diff --git a/ChangeLog b/ChangeLog
index ae6dc7a8..93d56eff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2003-03-16  Theodore A. Roth  <troth@openavr.org>
+
+	* avr.c (avr_read): Use pgm->read_sig_bytes to read signature bytes if
+	available.
+	* avr910.c (avr910_vfy_cmd_sent): New function.
+	(avr910_chip_erase): Add support for chip erase.
+	(avr910_enter_prog_mode): New function.
+	(avr910_leave_prog_mode): New function.
+	(avr910_initialize): Add code to select device type and enter prog mode.
+	(avr910_close): Leave programming mode before closing serial port.
+	(avr910_read_sig_bytes): New function.
+	(avr910_initpgm): Add avr910_read_sig_bytes method to pgm initializer.
+	* avrdude.conf.in: Add note about deprecating devicecode.
+	Change all occurences of devicecode to stk500_devcode.
+	Add avr910_devcode to a few parts for testing.
+	* avrpart.h (struct avrpart): Change devicecode field to stk500_devcode.
+	(struct avrpart): Add avr910_devcode field.
+	* config_gram.y: Add K_STK500_DEVCODE and K_AVR910_DEVCODE tokens.
+	Generate an error if devicecode is found in the config file.
+	Handle parsing of avr910_devcode and stk500_devcode.
+	* lexer.l: Handle parsing of avr910_devcode and stk500_devcode.
+	* pgm.c: Initialize pgm->read_sig_bytes field.
+	* pgm.h: Add pgm->read_sig_bytes field.
+	* stk500.c: Use stk500_devcode instead of devicecode.
+
 2003-03-16  Theodore A. Roth  <troth@openavr.org>
 
 	* avrdude.conf.in: Add avr910 and pavr programmers.
diff --git a/avr.c b/avr.c
index 02207ea0..af5bc0f4 100644
--- a/avr.c
+++ b/avr.c
@@ -385,6 +385,11 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
     }
   }
 
+  if (strcmp(mem->desc, "signature") == 0) {
+    if (pgm->read_sig_bytes) {
+      return pgm->read_sig_bytes(pgm, p, mem);
+    }
+  }
 
   printed = 0;
 
diff --git a/avr910.c b/avr910.c
index 02c85327..2ab41e5d 100644
--- a/avr910.c
+++ b/avr910.c
@@ -39,14 +39,19 @@
 extern char * progname;
 extern int do_cycles;
 
-#define show_func_info() \
-  fprintf(stderr, "%s: %d: called %s()\n", __FILE__, __LINE__, __FUNCTION__)
+/* These two defines are only for debugging. Will remove them once it starts
+   working. */
 
+#define show_func_info() \
+  fprintf(stderr, "%s: line %d: called %s()\n", \
+          __FILE__, __LINE__, __FUNCTION__)
+
+#define no_show_func_info()
 
 
 static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len)
 {
-  show_func_info();
+  no_show_func_info();
 
   return serial_send(pgm->fd, buf, len);
 }
@@ -54,7 +59,7 @@ static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len)
 
 static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len)
 {
-  show_func_info();
+  no_show_func_info();
 
   return serial_recv(pgm->fd, buf, len);
 }
@@ -64,15 +69,26 @@ static int avr910_drain(PROGRAMMER * pgm, int display)
 {
   show_func_info();
 
-  /* Do nothing. */
-
   return serial_drain(pgm->fd, display);
 }
 
 
+static void avr910_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg)
+{
+  char c;
+
+  avr910_recv(pgm, &c, 1);
+  if (c != '\r') {
+    fprintf(stderr, "%s: error: programmer did not respond to command: %s\n",
+            progname, errmsg);
+    exit(1);
+  }
+}
+
+
 static int avr910_rdy_led(PROGRAMMER * pgm, int value)
 {
-  show_func_info();
+  no_show_func_info();
 
   /* Do nothing. */
 
@@ -82,7 +98,7 @@ static int avr910_rdy_led(PROGRAMMER * pgm, int value)
 
 static int avr910_err_led(PROGRAMMER * pgm, int value)
 {
-  show_func_info();
+  no_show_func_info();
 
   /* Do nothing. */
 
@@ -92,7 +108,7 @@ static int avr910_err_led(PROGRAMMER * pgm, int value)
 
 static int avr910_pgm_led(PROGRAMMER * pgm, int value)
 {
-  show_func_info();
+  no_show_func_info();
 
   /* Do nothing. */
 
@@ -102,7 +118,7 @@ static int avr910_pgm_led(PROGRAMMER * pgm, int value)
 
 static int avr910_vfy_led(PROGRAMMER * pgm, int value)
 {
-  show_func_info();
+  no_show_func_info();
 
   /* Do nothing. */
 
@@ -115,7 +131,10 @@ static int avr910_vfy_led(PROGRAMMER * pgm, int value)
  */
 static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p)
 {
-  show_func_info();
+  no_show_func_info();
+
+  avr910_send(pgm, "e", 1);
+  avr910_vfy_cmd_sent(pgm, "chip erase");
 
   return 0;
 }
@@ -136,7 +155,7 @@ static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p)
  */
 static void avr910_powerup(PROGRAMMER * pgm)
 {
-  show_func_info();
+  no_show_func_info();
 
   /* Do nothing. */
 
@@ -149,7 +168,7 @@ static void avr910_powerup(PROGRAMMER * pgm)
  */
 static void avr910_powerdown(PROGRAMMER * pgm)
 {
-  show_func_info();
+  no_show_func_info();
 
   /* Do nothing. */
 
@@ -157,23 +176,41 @@ static void avr910_powerdown(PROGRAMMER * pgm)
 }
 
 
+static void avr910_enter_prog_mode(PROGRAMMER * pgm)
+{
+  avr910_send(pgm, "P", 1);
+  avr910_vfy_cmd_sent(pgm, "enter prog mode");
+}
+
+
+static void avr910_leave_prog_mode(PROGRAMMER * pgm)
+{
+  avr910_send(pgm, "L", 1);
+  avr910_vfy_cmd_sent(pgm, "leave prog mode");
+}
+
+
 /*
  * initialize the AVR device and prepare it to accept commands
  */
 static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
 {
-  char pn[8];
+  char id[8];
   char sw[2];
   char hw[2];
+  char buf[10];
+  char type;
   unsigned char c;
+  int dev_supported = 0;
 
   show_func_info();
 
-  /* Programmer returns exactly 7 chars _without_ the null.*/
+  /* Get the programmer identifier. Programmer returns exactly 7 chars
+     _without_ the null.*/
 
   avr910_send(pgm, "S", 1);
-  memset (pn, 0, sizeof(pn));
-  avr910_recv(pgm, pn, sizeof(pn)-1);
+  memset (id, 0, sizeof(id));
+  avr910_recv(pgm, id, sizeof(id)-1);
 
   /* Get the HW and SW versions to see if the programmer is present. */
 
@@ -183,19 +220,48 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
   avr910_send(pgm, "v", 1);
   avr910_recv(pgm, hw, sizeof(hw));
 
-  fprintf(stderr, "Found programmer: %s\n", pn);
+  /* Get the programmer type (serial or parallel). Expect serial. */
+
+  avr910_send(pgm, "p", 1);
+  avr910_recv(pgm, &type, 1);
+
+  fprintf(stderr, "Found programmer: Id = \"%s\"; type = %c\n", id, type);
   fprintf(stderr, "    Software Version = %c.%c; "
           "Hardware Version = %c.%c\n", sw[0], sw[1], hw[0], hw[1]);
 
   /* Get list of devices that the programmer supports. */
 
   avr910_send(pgm, "t", 1);
+  fprintf(stderr, "\nProgrammer supports the following devices:\n");
   while (1) {
     avr910_recv(pgm, &c, 1);
     if (c == 0)
       break;
-    fprintf(stderr, "Device code: 0x%02x\n", c);
+    fprintf(stderr, "    Device code: 0x%02x\n", c);
+
+    /* FIXME: Need to lookup devcode and report the device. */
+
+    if (p->avr910_devcode == c)
+      dev_supported = 1;
   };
+  fprintf(stderr,"\n");
+
+  if (!dev_supported) {
+    fprintf(stderr,
+            "%s: error: selected device is not supported by programmer: %s\n",
+            progname, p->id);
+    exit(1);
+  }
+
+  /* Tell the programmer which part we selected. */
+
+  buf[0] = 'T';
+  buf[1] = p->avr910_devcode;
+
+  avr910_send(pgm, buf, 2);
+  avr910_vfy_cmd_sent(pgm, "select device");
+
+  avr910_enter_prog_mode(pgm);
 
   return 0;
 }
@@ -203,7 +269,7 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
 
 static int avr910_save(PROGRAMMER * pgm)
 {
-  show_func_info();
+  no_show_func_info();
 
   /* Do nothing. */
 
@@ -213,7 +279,7 @@ static int avr910_save(PROGRAMMER * pgm)
 
 static void avr910_restore(PROGRAMMER * pgm)
 {
-  show_func_info();
+  no_show_func_info();
 
   /* Do nothing. */
 
@@ -223,7 +289,9 @@ static void avr910_restore(PROGRAMMER * pgm)
 
 static void avr910_disable(PROGRAMMER * pgm)
 {
-  show_func_info();
+  no_show_func_info();
+
+  /* Do nothing. */
 
   return;
 }
@@ -231,7 +299,7 @@ static void avr910_disable(PROGRAMMER * pgm)
 
 static void avr910_enable(PROGRAMMER * pgm)
 {
-  show_func_info();
+  no_show_func_info();
 
   /* Do nothing. */
 
@@ -246,15 +314,21 @@ static void avr910_enable(PROGRAMMER * pgm)
 static int avr910_cmd(PROGRAMMER * pgm, unsigned char cmd[4], 
                       unsigned char res[4])
 {
+  int i;
+
   show_func_info();
 
+  for (i=0; i<4; i++) {
+    fprintf(stderr, "cmd[%d] = 0x%02x\n", i, cmd[i]);
+  }
+
   return 0;
 }
 
 
 static void avr910_open(PROGRAMMER * pgm, char * port)
 {
-  show_func_info();
+  no_show_func_info();
 
   strcpy(pgm->port, port);
   pgm->fd = serial_open(port, 19200);
@@ -267,7 +341,9 @@ static void avr910_open(PROGRAMMER * pgm, char * port)
 
 static void avr910_close(PROGRAMMER * pgm)
 {
-  show_func_info();
+  no_show_func_info();
+
+  avr910_leave_prog_mode(pgm);
 
   serial_close(pgm->fd);
   pgm->fd = -1;
@@ -281,10 +357,27 @@ static void avr910_display(PROGRAMMER * pgm, char * p)
   return;
 }
 
+/* Signature byte reads are always 3 bytes. */
+
+static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
+{
+  no_show_func_info();
+
+  if (m->size < 3) {
+    fprintf(stderr, "%s: memsize too small for sig byte read", progname);
+    return -1;
+  }
+
+  avr910_send(pgm, "s", 1);
+  avr910_recv(pgm, m->buf, 3);
+
+  return 3;
+}
+
 
 void avr910_initpgm(PROGRAMMER * pgm)
 {
-  show_func_info();
+  no_show_func_info();
 
   strcpy(pgm->type, "avr910");
 
@@ -312,4 +405,6 @@ void avr910_initpgm(PROGRAMMER * pgm)
   /*
    * optional functions
    */
+
+  pgm->read_sig_bytes = avr910_read_sig_bytes;
 }
diff --git a/avrdude.conf.in b/avrdude.conf.in
index dad2337f..77bc28ca 100644
--- a/avrdude.conf.in
+++ b/avrdude.conf.in
@@ -30,7 +30,9 @@
 #   part
 #       id               = <id> ;                 # quoted string
 #       desc             = <description> ;        # quoted string
-#       devicecode       = <num> ;                # numeric
+#       devcode          = <num> ;            # deprecated, use stk500_devcode
+#       stk500_devcode   = <num> ;                # numeric
+#       avr910_devcode   = <num> ;                # numeric
 #       chip_erase_delay = <num> ;                # micro-seconds
 #       pagel            = <num> ;                # pin name in hex, i.e., 0xD7
 #       bs2              = <num> ;                # pin name in hex, i.e., 0xA0
@@ -284,7 +286,7 @@ programmer
 part
     id                  = "t15";
     desc                = "ATtiny15";
-    devicecode          = 0x13;
+    stk500_devcode      = 0x13;
     chip_erase_delay    = 20000;
     pgm_enable          = "1 0 1 0  1 1 0 0   0 1 0 1  0 0 1 1",
                           "x x x x  x x x x   x x x x  x x x x";
@@ -371,7 +373,8 @@ part
 part
     id               = "1200";
     desc             = "AT90S1200";
-    devicecode       = 0x33;
+    stk500_devcode   = 0x33;
+    avr910_devcode   = 0x13;
     chip_erase_delay = 20000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -451,7 +454,7 @@ part
 part
     id               = "4414";
     desc             = "AT90S4414";
-    devicecode       = 0x50;
+    stk500_devcode   = 0x50;
     chip_erase_delay = 20000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -511,7 +514,7 @@ part
 part
     id               = "2313";
     desc             = "AT90S2313";
-    devicecode       = 0x40;
+    stk500_devcode   = 0x40;
     chip_erase_delay = 20000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -576,7 +579,7 @@ part
 part
     id               = "2333";
     desc             = "AT90S2333";
-    devicecode       = 0x42;
+    stk500_devcode   = 0x42;
     chip_erase_delay = 20000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -738,7 +741,7 @@ part
 part
     id               = "4433";
     desc             = "AT90S4433";
-    devicecode       = 0x51;
+    stk500_devcode   = 0x51;
     chip_erase_delay = 20000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -819,7 +822,7 @@ part
 part
     id               = "4434";
     desc             = "AT90S4434";
-    devicecode       = 0x52;
+    stk500_devcode   = 0x52;
     chip_erase_delay = 20000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -899,7 +902,8 @@ part
 part
     id               = "8515";
     desc             = "AT90S8515";
-    devicecode       = 0x60;
+    stk500_devcode   = 0x60;
+    avr910_devcode   = 0x38;
     chip_erase_delay = 20000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -973,7 +977,7 @@ part
 part
     id               = "8535";
     desc             = "AT90S8535";
-    devicecode       = 0x61;
+    stk500_devcode   = 0x61;
     chip_erase_delay = 20000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -1033,7 +1037,7 @@ part
 part
     id               = "m103";
     desc             = "ATMEGA103";
-    devicecode       = 0xB1;
+    stk500_devcode   = 0xB1;
     chip_erase_delay = 112000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -1126,7 +1130,7 @@ part
 part
     id               = "m128";
     desc             = "ATMEGA128";
-    devicecode       = 0xB2;
+    stk500_devcode   = 0xB2;
     chip_erase_delay = 9000;
     pagel            = 0xD7;
     bs2              = 0xA0;
@@ -1247,7 +1251,7 @@ part
 part
     id               = "m16";
     desc             = "ATMEGA16";
-    devicecode       = 0x82;
+    stk500_devcode   = 0x82;
     pagel            = 0xd7;
     bs2              = 0xa0;
     chip_erase_delay = 9000;
@@ -1351,7 +1355,7 @@ part
 part
     id               = "m163";
     desc             = "ATMEGA163";
-    devicecode       = 0x81;
+    stk500_devcode   = 0x81;
     chip_erase_delay = 32000;
     pagel            = 0xd7;
     bs2              = 0xa0;
@@ -1465,7 +1469,7 @@ part
 part
     id               = "m169";
     desc             = "ATMEGA169";
-    devicecode       = 0x85;
+    stk500_devcode   = 0x85;
     chip_erase_delay = 32000;
     pgm_enable       = "1 0 1 0  1 1 0 0    0 1 0 1  0 0 1 1",
                        "x x x x  x x x x    x x x x  x x x x";
@@ -1586,7 +1590,7 @@ part
 part
     id               = "m8";
     desc             = "ATMEGA8";
-    devicecode       = 0x70;
+    stk500_devcode   = 0x70;
     pagel            = 0xd7;
     bs2              = 0xc2;
     chip_erase_delay = 9000;
diff --git a/avrpart.h b/avrpart.h
index b8c01c0b..11275978 100644
--- a/avrpart.h
+++ b/avrpart.h
@@ -81,7 +81,8 @@ typedef struct opcode {
 typedef struct avrpart {
   char          desc[AVR_DESCLEN];  /* long part name */
   char          id[AVR_IDLEN];      /* short part name */
-  int           devicecode;         /* Atmel STK500 device code */
+  int           stk500_devcode;     /* stk500 device code */
+  int           avr910_devcode;     /* avr910 device code */
   int           chip_erase_delay;   /* microseconds */
   unsigned char pagel;              /* for parallel programming */
   unsigned char bs2;                /* for parallel programming */
diff --git a/config_gram.y b/config_gram.y
index a1213509..c4d3ea17 100644
--- a/config_gram.y
+++ b/config_gram.y
@@ -73,6 +73,8 @@ static int parse_cmdbits(OPCODE * op);
 %token K_DEFAULT_SERIAL
 %token K_DESC
 %token K_DEVICECODE
+%token K_STK500_DEVCODE
+%token K_AVR910_DEVCODE
 %token K_EEPROM
 %token K_ERRLED
 %token K_FLASH
@@ -411,7 +413,24 @@ part_parm :
 
   K_DEVICECODE TKN_EQUAL TKN_NUMBER {
     {
-      current_part->devicecode = $3->value.number;
+      fprintf(stderr, 
+              "%s: error at %s:%d: devicecode is deprecated, use "
+              "stk500_devcode instead\n",
+              progname, infile, lineno);
+      exit(1);
+    }
+  } |
+
+  K_STK500_DEVCODE TKN_EQUAL TKN_NUMBER {
+    {
+      current_part->stk500_devcode = $3->value.number;
+      free_token($3);
+    }
+  } |
+
+  K_AVR910_DEVCODE TKN_EQUAL TKN_NUMBER {
+    {
+      current_part->avr910_devcode = $3->value.number;
       free_token($3);
     }
   } |
diff --git a/lexer.l b/lexer.l
index 64df0a95..83160cd2 100644
--- a/lexer.l
+++ b/lexer.l
@@ -125,6 +125,8 @@ default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
 default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
 default_serial   { yylval=NULL; return K_DEFAULT_SERIAL; }
 devicecode       { yylval=NULL; return K_DEVICECODE; }
+stk500_devcode   { yylval=NULL; return K_STK500_DEVCODE; }
+avr910_devcode   { yylval=NULL; return K_AVR910_DEVCODE; }
 eeprom           { yylval=NULL; return K_EEPROM; }
 errled           { yylval=NULL; return K_ERRLED; }
 flash            { yylval=NULL; return K_FLASH; }
diff --git a/pgm.c b/pgm.c
index b65da69e..c369cead 100644
--- a/pgm.c
+++ b/pgm.c
@@ -89,6 +89,7 @@ PROGRAMMER * pgm_new(void)
    */
   pgm->paged_write    = NULL;
   pgm->paged_load     = NULL;
+  pgm->read_sig_bytes = NULL;
 
   return pgm;
 }
diff --git a/pgm.h b/pgm.h
index 5dcde7be..f18a8ff2 100644
--- a/pgm.h
+++ b/pgm.h
@@ -66,6 +66,7 @@ typedef struct programmer_t {
                           int page_size, int n_bytes);
   int  (*paged_load)     (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
                           int page_size, int n_bytes);
+  int  (*read_sig_bytes) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m);
   char config_file[PATH_MAX]; /* config file where defined */
   int  lineno;                /* config file line number */
 } PROGRAMMER;
diff --git a/stk500.c b/stk500.c
index c570c8a5..723315b6 100644
--- a/stk500.c
+++ b/stk500.c
@@ -383,7 +383,7 @@ static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p)
    */
   buf[0] = Cmnd_STK_SET_DEVICE;
 
-  buf[1] = p->devicecode;
+  buf[1] = p->stk500_devcode;
   buf[2] = 0; /* device revision */
 
   if ((p->flags & AVRPART_SERIALOK) && (p->flags & AVRPART_PARALLELOK))