Index: avr910.c
===================================================================
RCS file: /cvsroot/avrdude/avrdude/avr910.c,v
retrieving revision 1.17
diff -u -r1.17 avr910.c
--- avr910.c	17 Apr 2004 19:37:14 -0000	1.17
+++ avr910.c	6 Jun 2004 11:20:25 -0000
@@ -40,6 +40,7 @@
 extern int do_cycles;
 
 static char has_auto_incr_addr;
+static char has_enhanced_mode;
 
 
 static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len)
@@ -158,6 +159,13 @@
   if (has_auto_incr_addr == 'Y')
       fprintf(stderr, "Programmer supports auto addr increment.\n");
 
+  /* See if programmer supports enhanced mode. */
+
+  avr910_send(pgm, "M", 1);
+  avr910_recv(pgm, &has_enhanced_mode, 1);
+  if (has_enhanced_mode == 'Y')
+      fprintf(stderr, "Programmer supports enhanced mode.\n");
+
   /* Get list of devices that the programmer supports. */
 
   avr910_send(pgm, "t", 1);
@@ -440,6 +448,76 @@
 }
 
 
+static int avr910_paged_write_flash_enhanced(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
+                                    int page_size, int n_bytes)
+{
+  unsigned char buf[2];
+  unsigned int addr = 0;
+  unsigned int max_addr = n_bytes;
+  unsigned int page_addr;
+  int page_bytes = page_size;
+  unsigned int block_size = page_size;
+  int page_wr_cmd_pending = 0;
+
+  page_addr = addr;
+
+  if ((!m->paged) || (block_size > 120)) {
+    block_size = 120;
+  }
+  
+  /* Set address */
+  avr910_set_addr(pgm, addr>>1);
+
+  while (addr < max_addr) {
+
+    /* Check if full blocksize is possible; if not, correct it */
+    if ((addr + block_size) > max_addr) {
+      block_size = max_addr - addr;
+    }
+    if (m->paged && (page_bytes < block_size)) {
+      block_size = page_bytes;
+    }
+
+    /* Send command and blockdata */
+    buf[0] = 'N';
+    buf[1] = block_size;
+    avr910_send(pgm, buf, sizeof(buf));
+    avr910_send(pgm, &m->buf[addr], block_size);
+    avr910_vfy_cmd_sent(pgm, "write block");
+        
+    addr += block_size;
+
+    /* In paged mode: flush page after full page was written */
+    if (m->paged) {
+      page_bytes -= block_size;
+      page_wr_cmd_pending = 1;
+
+      if (page_bytes == 0) {
+
+	avr910_send(pgm, "m", 1);
+	avr910_vfy_cmd_sent(pgm, "flush page");
+
+	page_addr = addr;
+	page_bytes = page_size;
+	page_wr_cmd_pending = 0;
+      }
+    }
+
+    report_progress (addr, max_addr, NULL);
+  }
+
+  /* If we didn't send the page wr cmd after the last byte written in the
+     loop, send it now. */
+
+  if (page_wr_cmd_pending != 0) {
+    avr910_send(pgm, "m", 1);
+    avr910_vfy_cmd_sent(pgm, "flush final page");
+  }
+
+  return addr;
+}
+
+
 static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p,
                                      AVRMEM * m, int page_size, int n_bytes)
 {
@@ -473,7 +551,12 @@
                               int page_size, int n_bytes)
 {
   if (strcmp(m->desc, "flash") == 0) {
-    return avr910_paged_write_flash(pgm, p, m, page_size, n_bytes);
+    if (has_enhanced_mode == 'Y') {
+      return avr910_paged_write_flash_enhanced(pgm, p, m, page_size, n_bytes);
+    }
+    else {
+      return avr910_paged_write_flash(pgm, p, m, page_size, n_bytes);
+    }
   }
   else if (strcmp(m->desc, "eeprom") == 0) {
     return avr910_paged_write_eeprom(pgm, p, m, page_size, n_bytes);
@@ -484,7 +567,7 @@
 }
 
 
-static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
+static int avr910_paged_load_normal(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
                              int page_size, int n_bytes)
 {
   unsigned char cmd;
@@ -533,6 +616,71 @@
 
   return addr * rd_size;
 }
+
+
+static int avr910_paged_load_flash_enhanced(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
+                             int page_size, int n_bytes)
+{
+  unsigned int addr = 0;
+  unsigned int wordcount;
+  unsigned int bytes_left;
+  unsigned char temp;
+  unsigned char cmd[3];
+  int i;
+
+  avr910_set_addr(pgm, addr);
+
+  while (addr < n_bytes) {
+
+    if ((n_bytes - addr) > (0xffff * 2)) {
+      wordcount = 0xffff;
+    } else {
+      wordcount = (n_bytes - addr) / 2;
+    }
+
+    cmd[0] = 'n';
+    cmd[1] = (wordcount >> 8) & 0xff;
+    cmd[2] = wordcount & 0xff;
+    avr910_send(pgm, cmd, sizeof(cmd));
+
+    bytes_left = wordcount * 2;
+    while (bytes_left > 0) {
+      if (bytes_left > 0xff) {
+	temp = 0xff;
+      } else {
+	temp = bytes_left;
+      }
+      avr910_recv(pgm, &m->buf[addr], temp);
+      bytes_left -= temp;
+      addr += temp;
+      report_progress (addr, n_bytes, NULL);
+    }
+
+
+  }
+
+  // swap MSB and LSB
+  for (i = 0; i < n_bytes; i+=2) {
+    temp = m->buf[i];
+    m->buf[i] = m->buf[i+1];
+    m->buf[i+1] = temp;
+  }
+ 
+  return n_bytes;
+}
+
+
+static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
+                             int page_size, int n_bytes)
+{
+  if ((strcmp(m->desc, "flash") == 0) && (has_enhanced_mode == 'Y')) {
+    return avr910_paged_load_flash_enhanced(pgm, p, m, page_size, n_bytes);
+  }
+  else {
+    return avr910_paged_load_normal(pgm, p, m, page_size, n_bytes);
+  }
+}
+
 
 /* Signature byte reads are always 3 bytes. */
 

