From 872f75d4fbd938e77d3fa0350ea8168c875038c9 Mon Sep 17 00:00:00 2001
From: Joerg Wunsch <j@uriah.heep.sax.de>
Date: Tue, 10 May 2005 19:17:12 +0000
Subject: [PATCH] Mega-commit to bring in both, the STK500v2 support from Erik
 Walthinsen, as well as JTAG ICE mkII support (by me).

Erik's submission has been cleaned up a little bit, mostly to add his
name and the current year to the copyright of the new file, remove
trailing white space before importing the files, and fix the minor
syntax errors in his avrdude.conf.in additions (missing semicolons).

The JTAG ICE mkII support should be considered alpha to beta quality
at this point.  Few things are still to be done, like defering the
hfuse (OCDEN) tweaks until they are really required.  Also, for
reasons not yet known, the target MCU doesn't start to run after
signing off from the ICE, it needs a power-cycle first (at least on my
STK500).

Note that for the JTAG ICE, I did change a few things in the internal
API.  Notably I made the serial receive timeout configurable by the
backends via an exported variable (done in both the Posix and the
Win32 implementation), and I made the serial_recv() function return a
-1 instead of bailing out with exit(1) upon encountering a receive
timeout (currently only done in the Posix implementation).  Both
measures together allow me to receive a datastreem from the ICE at 115
kbps on a somewhat lossy PCI multi-UART card that occasionally drops a
character.  The JTAG ICE mkII protocol has enough of safety layers to
allow recovering from these events, but the previous code wasn't
prepared for any kind of recovery.  The Win32 change for this still
has to be done, and the traditional drivers need to be converted to
exit(1) upon encountering a timeout (as they're now getting a -1
returned they didn't see before in that case).


git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@451 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 avrdude/Makefile.am        |   8 +
 avrdude/avrdude.1          |  76 ++-
 avrdude/avrdude.conf.in    | 658 ++++++++++++++++++++++++-
 avrdude/avrpart.c          |  32 +-
 avrdude/avrpart.h          |  25 +
 avrdude/config_gram.y      | 186 ++++++++
 avrdude/doc/avrdude.texi   |  84 +++-
 avrdude/lexer.l            |  32 +-
 avrdude/main.c             |  27 +-
 avrdude/pgm.h              |   1 +
 avrdude/ser_posix.c        |  30 +-
 avrdude/ser_win32.c        |  38 +-
 avrdude/serial.h           |   3 +
 avrdude/stk500v2.c         | 949 +++++++++++++++++++++++++++++++++++++
 avrdude/stk500v2.h         |  29 ++
 avrdude/stk500v2_private.h | 134 ++++++
 16 files changed, 2227 insertions(+), 85 deletions(-)
 create mode 100644 avrdude/stk500v2.c
 create mode 100644 avrdude/stk500v2.h
 create mode 100644 avrdude/stk500v2_private.h

diff --git a/avrdude/Makefile.am b/avrdude/Makefile.am
index ad7643b0..8221f36b 100644
--- a/avrdude/Makefile.am
+++ b/avrdude/Makefile.am
@@ -63,8 +63,13 @@ avrdude_SOURCES = \
 	config.h \
 	confwin.c \
 	confwin.h \
+	crc16.c \
+	crc16.h \
 	fileio.c \
 	fileio.h \
+	jtagmkII.c \
+	jtagmkII.h \
+	jtagmkII_private.h \
 	linux_ppdev.h \
 	lists.c \
 	lists.h \
@@ -85,6 +90,9 @@ avrdude_SOURCES = \
 	stk500.c \
 	stk500.h \
 	stk500_private.h \
+	stk500v2.c \
+	stk500v2.h \
+	stk500v2_private.h \
 	term.c \
 	term.h
 
diff --git a/avrdude/avrdude.1 b/avrdude/avrdude.1
index f0e80c93..3e6d4bdb 100644
--- a/avrdude/avrdude.1
+++ b/avrdude/avrdude.1
@@ -1,6 +1,6 @@
 .\"
 .\" avrdude - A Downloader/Uploader for AVR device programmers
-.\" Copyright (C) 2001, 2002, 2003  Joerg Wunsch
+.\" Copyright (C) 2001, 2002, 2003, 2005  Joerg Wunsch
 .\"
 .\" This program is free software; you can redistribute it and/or modify
 .\" it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
 .\"
 .\" $Id$
 .\"
-.Dd DATE November 26, 2003
+.Dd DATE May 10, 2005
 .Os
 .Dt AVRDUDE 1
 .Sh NAME
@@ -28,6 +28,8 @@
 .Sh SYNOPSIS
 .Nm
 .Fl p Ar partno
+.Op Fl b Ar baudrate
+.Op Fl B Ar bitclock
 .Op Fl c Ar programmer-id
 .Op Fl C Ar config-file
 .Op Fl D
@@ -51,9 +53,13 @@
 is a program for downloading code and data to Atmel AVR
 microcontrollers.
 .Nm Avrdude
-supports Atmel's STK500 programmer as well as a simple hard-wired
+supports Atmel's STK500 programmer,
+Atmel's JTAG ICE mkII,
+as well as a simple hard-wired
 programmer connected directly to a
 .Xr ppi 4
+or
+.Xr parport 4
 parallel port.  In the simplest case, the hardware consists just of a
 cable connecting the respective AVR signal lines to the parallel port.
 .Pp
@@ -78,6 +84,11 @@ from the MCU when in-system programming is used.
 .Pp
 Atmel's STK500 programmer is also supported and connects to a serial
 port.
+Both, firmware versions 1.x and 2.x can be handled, but require a
+different programmer type specification (by now).
+.Pp
+Atmel's JTAG ICE mkII is supported as well to up- or download memory
+areas from/to an AVR target (no support for on-chip debugging).
 .Pp
 Input files can be provided, and output files can be written in
 different file formats, such as raw binary files containing the data
@@ -127,7 +138,7 @@ the format.  Currently, the following MCU types are understood:
 .TS
 ll.
 \fBOption tag\fP	\fBOfficial part name\fP
-t15	ATtiny15
+c128	AT90CAN128
 1200	AT90S1200
 2313	AT90S2313
 2333	AT90S2333
@@ -137,19 +148,43 @@ t15	ATtiny15
 4434	AT90S4434
 8515	AT90S8515
 8535	AT90S8535
-m163	ATMEGA163
-m169	ATMEGA169
-m128	ATMEGA128
-m103	ATMEGA103
-m16	ATMEGA16
-m48	ATMEGA48
-m8	ATMEGA8
-m88	ATMEGA88
+m103	ATmega103
+m128	ATmega128
+m16	ATmega16
+m161	ATmega161
+m162	ATmega162
+m163	ATmega163
+m169	ATmega169
+m32	ATmega32
+m48	ATmega48
+m64	ATmega64
+m8	ATmega8
+m8515	ATmega8515
+m8535	ATmega8535
+m88	ATmega88
+t12	ATtiny12
+t13	ATtiny13
+t15	ATtiny15
+t2313	ATtiny2313
+t26	ATtiny26
 .TE
 .Bl -tag -width "(*) "
 .It "(*)"
-The AT90S2323 uses the same algorithm.
+The AT90S2323 and ATtiny22 use the same algorithm.
 .El
+.It Fl b Ar baudrate
+Override the RS-232 connection baud rate specified in the respective
+programmer's entry of the configuration file.
+.It Fl B Ar bitclock
+Specify the bit clock period for the JTAG interface (JTAG ICE only).
+The value is a floating-point number in microseconds.
+The default value of the JTAG ICE results in about 1 microsecond bit
+clock period, suitable for target MCUs running at 4 MHz clock and
+above.
+Unlike certain parameters in the STK500, the JTAG ICE resets all its
+parameters to default values when the programming software signs
+off from the ICE, so for MCUs running at lower clock speeds, this
+parameter must be specified on the command-line.
 .It Fl c Ar programmer-id
 Use the pin configuration specified by the argument.  Pin
 configurations are read from the config file (see the
@@ -434,13 +469,24 @@ by 1E3.
 Turn the master oscillator off.
 .Em Only supported on the STK500 programmer.
 .It Ar sck period
+.Em STK500 programmer only:
 Set the SCK clock period to
 .Ar period
 microseconds.
-.Em Only supported on the STK500 programmer.
+.Pp
+.Em JTAG ICE only:
+Set the JTAG ICE bit clock period to
+.Ar period
+microseconds.
+Note that unlike STK500 settings, this setting will be reverted to
+its default value (approximately 1 microsecond) when the programming
+software signs off from the JTAG ICE.
 .It Ar parms
+.Em STK500 programmer only:
 Display the current voltage and master oscillator parameters.
-.Em Only supported on the STK500 programmer.
+.Pp
+.Em JTAG ICE only:
+Display the current target supply voltage and JTAG bit clock rate/period.
 .It Ar \&?
 .It Ar help
 Give a short on-line summary of the available commands.
diff --git a/avrdude/avrdude.conf.in b/avrdude/avrdude.conf.in
index 09f069a3..ec4c820f 100644
--- a/avrdude/avrdude.conf.in
+++ b/avrdude/avrdude.conf.in
@@ -15,7 +15,7 @@
 #   programmer
 #       id       = <id1> [, <id2> [, <id3>] ...] ;  # <idN> are quoted strings
 #       desc     = <description> ;                  # quoted string
-#       type     = par | stk500 | avr910;           # programmer type
+#       type     = par | stk500 | stk500v2 | avr910 | jtagmkii; # programmer type
 #       baudrate = <num> ;                          # baudrate for avr910-programmer
 #       vcc      = <num1> [, <num2> ... ] ;         # pin number(s)
 #       reset    = <num> ;                          # pin number
@@ -31,16 +31,43 @@
 #   part
 #       id               = <id> ;                 # quoted string
 #       desc             = <description> ;        # quoted string
+#       has_jtag         = <yes/no> ;             # part has JTAG i/f
 #       devicecode       = <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
 #       reset            = dedicated | io;
 #       retry_pulse      = reset | sck;
 #       pgm_enable       = <instruction format> ;
 #       chip_erase       = <instruction format> ;
+#       chip_erase_delay = <num> ;                # chip erase delay (us)
+#       # STK500 parameters (parallel programming IO lines)
+#       pagel            = <num> ;                # pin name in hex, i.e., 0xD7
+#       bs2              = <num> ;                # pin name in hex, i.e., 0xA0
+#       serial           = <yes/no> ;             # can use serial downloading
+#       parallel         = <yes/no/pseudo>;       # can use par. programming
+#       # STK500v2 parameters, to be taken from Atmel's XML files
+#       timeout          = <num> ;
+#       stabdelay        = <num> ;
+#       cmdexdelay       = <num> ;
+#       synchloops       = <num> ;
+#       bytedelay        = <num> ;
+#       pollvalue        = <num> ;
+#       pollindex        = <num> ;
+#       predelay         = <num> ;
+#       postdelay        = <num> ;
+#       pollmethod       = <num> ;
+#       mode             = <num> ;
+#       delay            = <num> ;
+#       blocksize        = <num> ;
+#       readsize         = <num> ;
+#       # JTAG ICE mkII parameters, also from XML files
+#       allowfullpagebitstream = <yes/no> ;
+#       enablepageprogramming = <yes/no> ;
+#       idr              = <num> ;                # IO addr of IDR (OCD) reg.
+#       rampz            = <num> ;                # IO addr of RAMPZ reg.
+#       spmcr            = <num> ;                # mem addr of SPMC[S]R reg.
+#
 #       memory <memtype>
 #           paged           = <yes/no> ;          # yes / no
 #           size            = <num> ;             # bytes
@@ -208,12 +235,24 @@ programmer
   type  = stk500;
 ;
 
+programmer
+  id    = "avrispv2";
+  desc  = "Atmel AVR ISP V2";
+  type  =  stk500v2;
+;
+
 programmer
   id    = "stk500";
   desc  = "Atmel STK500";
   type  = stk500;
 ;
 
+programmer
+  id    = "stk500v2";
+  desc  = "Atmel STK500 V2";
+  type  = stk500v2;
+;
+
 programmer
   id    = "avr910";
   desc  = "Atmel Low Cost Serial Programmer";
@@ -226,6 +265,21 @@ programmer
   type  = butterfly;
 ;
 
+programmer
+  id    = "jtagmkII";
+  desc  = "Atmel JTAG ICE mkII";
+  baudrate = 19200;    # default is 19200
+  type  = jtagmkii;
+;
+
+# easier to type
+programmer
+  id    = "jtag2";
+  desc  = "Atmel JTAG ICE mkII";
+  baudrate = 19200;    # default is 19200
+  type  = jtagmkii;
+;
+
 programmer
   id    = "pavr";
   desc  = "Jason Kyle's pAVR Serial Programmer";
@@ -377,6 +431,17 @@ part
     chip_erase          = "1 0 1 0  1 1 0 0   1 0 0 x  x x x x",
                           "x x x x  x x x x   x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 64;
         min_write_delay = 9000;
@@ -388,6 +453,11 @@ part
 
         write           = "1  1  0  0   0  0  0  0    x x x x  x x x x",
                           "x  x a5 a4  a3 a2 a1 a0    i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 8;
+	blocksize	= 64;
+	readsize	= 256;
     ;
 
     memory "flash"
@@ -415,6 +485,11 @@ part
                           "  x  x  x  x   x  x  x a8",
                           " a7 a6 a5 a4  a3 a2 a1 a0",
                           "  i  i  i  i   i  i  i  i";
+
+	mode		= 0x04;
+	delay		= 5;
+	blocksize	= 128;
+	readsize	= 256;
     ;
 
     memory "signature"
@@ -463,6 +538,17 @@ part
     chip_erase          = "1 0 1 0  1 1 0 0   1 0 0 x  x x x x",
                           "x x x x  x x x x   x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 1;
+
     memory "eeprom"
         size            = 64;
         min_write_delay = 4000;
@@ -474,6 +560,11 @@ part
 
         write           = "1  1  0  0   0  0  0  0    0 0 0 x  x x x x",
                           "x  x a5 a4  a3 a2 a1 a0    i i i i  i i i i";
+
+	mode		= 0x41;
+	delay		= 5;
+	blocksize	= 4;
+	readsize	= 256;
     ;
 
     memory "flash"
@@ -509,6 +600,11 @@ part
                           "  0  0  0  0   0  0  0 a8",
                           " a7 a6 a5 a4   x  x  x  x",
                           "  x  x  x  x   x  x  x  x";
+
+	mode		= 0x41;
+	delay		= 6;
+	blocksize	= 32;
+	readsize	= 256;
     ;
 
     memory "signature"
@@ -578,6 +674,17 @@ part
     chip_erase          = "1 0 1 0  1 1 0 0   1 0 0 x  x x x x",
                           "x x x x  x x x x   x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 64;
         min_write_delay = 8200;
@@ -589,6 +696,11 @@ part
 
         write           = "1  1  0  0   0  0  0  0    x x x x  x x x x",
                           "x  x a5 a4  a3 a2 a1 a0    i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 10;
+	blocksize	= 64;
+	readsize	= 256;
     ;
 
     memory "flash"
@@ -616,6 +728,11 @@ part
                           "  x  x  x  x   x  x  x a8",
                           " a7 a6 a5 a4  a3 a2 a1 a0",
                           "  i  i  i  i   i  i  i  i";
+
+	mode		= 0x04;
+	delay		= 5;
+	blocksize	= 128;
+	readsize	= 256;
     ;
 
     memory "signature"
@@ -649,7 +766,6 @@ part
     ;
 ;
 
-
 #------------------------------------------------------------
 # AT90s1200
 #------------------------------------------------------------
@@ -668,6 +784,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 1;
+    bytedelay		= 0;
+    pollindex		= 0;
+    pollvalue		= 0xFF;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 64;
         min_write_delay = 4000;
@@ -679,6 +806,11 @@ part
 
         write           = "1 1  0  0   0  0  0  0   x x x x  x x x x",
                           "x x a5 a4  a3 a2 a1 a0   i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 20;
+	blocksize	= 32;
+	readsize	= 256;
       ;
     memory "flash"
         size            = 1024;
@@ -705,6 +837,11 @@ part
                           "  x   x   x   x    x   x   x  a8",
                           " a7  a6  a5  a4   a3  a2  a1  a0",
                           "  i   i   i   i    i   i   i   i";
+
+	mode		= 0x02;
+	delay		= 15;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "signature"
         size            = 3;
@@ -749,6 +886,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 256;
         min_write_delay = 9000;
@@ -760,6 +908,11 @@ part
 
         write           = " 1  1  0  0   0  0  0  0   x x x x  x x x a8",
                           "a7 a6 a5 a4  a3 a2 a1 a0   i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 64;
+	readsize	= 256;
       ;
     memory "flash"
         size            = 4096;
@@ -786,6 +939,11 @@ part
                           "  x   x   x   x  a11 a10  a9  a8",
                           " a7  a6  a5  a4   a3  a2  a1  a0",
                           "  i   i   i   i    i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 64;
+	readsize	= 256;
       ;
     memory "signature"
         size            = 3;
@@ -810,6 +968,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 128;
         min_write_delay = 4000;
@@ -821,6 +990,11 @@ part
 
         write           = "1  1  0  0   0  0  0  0   x x x x  x x x x",
                           "x a6 a5 a4  a3 a2 a1 a0   i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 64;
+	readsize	= 256;
       ;
     memory "flash"
         size            = 2048;
@@ -847,6 +1021,11 @@ part
                           "  x   x   x   x    x   x  a9  a8",
                           " a7  a6  a5  a4   a3  a2  a1  a0",
                           "  i   i   i   i    i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "signature"
         size            = 3;
@@ -866,6 +1045,7 @@ part
 
 part
     id               = "2333";
+##### WARNING: No XML file for device 'AT90S2333'! #####
     desc             = "AT90S2333";
     stk500_devcode   = 0x42;
     avr910_devcode   = 0x34;
@@ -944,7 +1124,7 @@ part
 
 
 #------------------------------------------------------------
-# AT90s2343
+# AT90s2343 (also AT90s2323 and ATtiny22)
 #------------------------------------------------------------
 
 part
@@ -959,6 +1139,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 128;
         min_write_delay = 9000;
@@ -970,6 +1161,11 @@ part
 
         write           = "1  1  0  0   0  0  0  0   0 0 0 0  0 0 0 0",
                           "x a6 a5 a4  a3 a2 a1 a0   i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 64;
+	readsize	= 256;
       ;
     memory "flash"
         size            = 2048;
@@ -996,6 +1192,11 @@ part
                           "  x   x   x   x    x   x  a9  a8",
                           " a7  a6  a5  a4   a3  a2  a1  a0",
                           "  i   i   i   i    i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 128;
+	readsize	= 128;
       ;
     memory "signature"
         size            = 3;
@@ -1041,6 +1242,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 256;
         min_write_delay = 9000;
@@ -1052,6 +1264,11 @@ part
 
         write           = " 1  1  0  0   0  0  0  0   x x x x  x x x x",
                           "a7 a6 a5 a4  a3 a2 a1 a0   i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "flash"
         size            = 4096;
@@ -1078,6 +1295,11 @@ part
                           "  x   x   x   x    x a10  a9  a8",
                           " a7  a6  a5  a4   a3  a2  a1  a0",
                           "  i   i   i   i    i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "signature"
         size            = 3;
@@ -1113,6 +1335,7 @@ part
 
 part
     id               = "4434";
+##### WARNING: No XML file for device 'AT90S4434'! #####
     desc             = "AT90S4434";
     stk500_devcode   = 0x52;
     avr910_devcode   = 0x6c;
@@ -1204,6 +1427,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 512;
         min_write_delay = 4000;
@@ -1215,6 +1449,11 @@ part
 
         write           = " 1  1  0  0   0  0  0  0   x x x x  x x x a8",
                           "a7 a6 a5 a4  a3 a2 a1 a0   i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "flash"
         size            = 8192;
@@ -1241,6 +1480,11 @@ part
                           "  x   x   x   x  a11 a10  a9  a8",
                           " a7  a6  a5  a4   a3  a2  a1  a0",
                           "  i   i   i   i    i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "signature"
         size            = 3;
@@ -1279,6 +1523,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 512;
         min_write_delay = 9000;
@@ -1290,6 +1545,11 @@ part
 
         write           = " 1  1  0  0   0  0  0  0   x x x x  x x x a8",
                           "a7 a6 a5 a4  a3 a2 a1 a0   i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "flash"
         size            = 8192;
@@ -1316,6 +1576,11 @@ part
                           "  x   x   x   x  a11 a10  a9  a8",
                           " a7  a6  a5  a4   a3  a2  a1  a0",
                           "  i   i   i   i    i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "signature"
         size            = 3;
@@ -1354,6 +1619,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 4096;
         min_write_delay = 4000;
@@ -1369,6 +1645,11 @@ part
                           "  x   x   x   x    a11 a10  a9  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0", 
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "flash"
@@ -1404,6 +1685,11 @@ part
                           "a15 a14 a13 a12    a11 a10  a9  a8",
                           " a7   x   x   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x11;
+	delay		= 70;
+	blocksize	= 256;
+	readsize	= 256;
       ;
 
     memory "fuse"
@@ -1439,6 +1725,7 @@ part
 part
     id               = "m64";
     desc             = "ATMEGA64";
+    has_jtag         = yes;
     stk500_devcode   = 0xA0;
     chip_erase_delay = 9000;
     pagel            = 0xD7;
@@ -1450,6 +1737,20 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
+    idr                 = 0x22;
+    spmcr               = 0x68;
+
     memory "eeprom"
         paged           = no; /* leave this "no" */
         page_size       = 8;  /* for parallel programming */
@@ -1467,6 +1768,11 @@ part
                           "  x   x   x   x    a11 a10  a9  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0", 
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 20;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "flash"
@@ -1502,6 +1808,11 @@ part
                           "  x a14 a13 a12    a11 a10  a9  a8",
                           " a7   x   x   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x21;
+	delay		= 6;
+	blocksize	= 128;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -1563,6 +1874,7 @@ part
 part
     id               = "m128";
     desc             = "ATMEGA128";
+    has_jtag         = yes;
     stk500_devcode   = 0xB2;
     avr910_devcode   = 0x43;
     chip_erase_delay = 9000;
@@ -1575,6 +1887,21 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
+    idr                 = 0x22;
+    spmcr               = 0x68;
+    rampz               = 0x3b;
+
     memory "eeprom"
         paged           = no; /* leave this "no" */
         page_size       = 8;  /* for parallel programming */
@@ -1592,6 +1919,11 @@ part
                           "  x   x   x   x    a11 a10  a9  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0", 
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 12;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "flash"
@@ -1627,6 +1959,11 @@ part
                           "a15 a14 a13 a12    a11 a10  a9  a8",
                           " a7   x   x   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x21;
+	delay		= 6;
+	blocksize	= 128;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -1685,6 +2022,7 @@ part
 part
     id               = "c128";
     desc             = "AT90CAN128";
+    has_jtag         = yes;
     stk500_devcode   = 0xB3;
 #    avr910_devcode   = 0x43;
     chip_erase_delay = 9000;
@@ -1697,6 +2035,21 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 1;
+
+    idr                 = 0x31;
+    spmcr               = 0x57;
+    rampz               = 0x3b;
+
     memory "eeprom"
         paged           = no; /* leave this "no" */
         page_size       = 8;  /* for parallel programming */
@@ -1714,6 +2067,11 @@ part
                           "  0   0   0   x    a11 a10  a9  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0", 
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x41;
+	delay		= 20;
+	blocksize	= 8;
+	readsize	= 256;
       ;
 
     memory "flash"
@@ -1749,6 +2107,11 @@ part
                           "a15 a14 a13 a12    a11 a10  a9  a8",
                           " a7   x   x   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x41;
+	delay		= 6;
+	blocksize	= 256;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -1808,6 +2171,7 @@ part
 part
     id               = "m16";
     desc             = "ATMEGA16";
+    has_jtag         = yes;
     stk500_devcode   = 0x82;
     avr910_devcode   = 0x74;
     pagel            = 0xd7;
@@ -1819,7 +2183,23 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
+    idr                 = 0x31;
+    spmcr               = 0x57;
+
     memory "eeprom"
+        paged           = no; /* leave this "no" */
+        page_size       = 4;  /* for parallel programming */
         size            = 512;
         min_write_delay = 9000;
         max_write_delay = 9000;
@@ -1834,6 +2214,11 @@ part
                           "  0   0   x   x      x   x  a9  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0", 
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 10;
+	blocksize	= 128;
+	readsize	= 256;
       ;
 
     memory "flash"
@@ -1869,6 +2254,11 @@ part
                           "  0   0 a13 a12    a11 a10  a9  a8",
                           " a7  a6   x   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x21;
+	delay		= 6;
+	blocksize	= 128;
+	readsize	= 256;
       ;
 
     memory "lock"
@@ -1912,9 +2302,13 @@ part
 part
     id               = "m162";
     desc             = "ATMEGA162";
+    has_jtag         = yes;
     stk500_devcode   = 0x83;
     chip_erase_delay = 9000;
 
+    idr              = 0x04;
+    spmcr            = 0x57;
+
     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";
 
@@ -1957,7 +2351,20 @@ part
                           "  x   x   x   x      x   x   x   x";
       ;
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
+        paged           = no; /* leave this "no" */
+        page_size       = 4;  /* for parallel programming */
         size            = 512;
         min_write_delay = 9000;
         max_write_delay = 9000;
@@ -1973,6 +2380,11 @@ part
                           "  0   0   x   x      x   x  a9  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0",
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x41;
+	delay		= 20;
+	blocksize	= 4;
+	readsize	= 256;
         ;
 
     memory "lfuse"
@@ -2106,6 +2518,11 @@ part
                           "  x   x   x a12    a11 a10  a9  a8",
                           " a7  a6   x   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x41;
+	delay		= 6;
+	blocksize	= 128;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -2161,6 +2578,7 @@ part
 part
     id               = "m169";
     desc             = "ATMEGA169";
+    has_jtag         = yes;
     stk500_devcode   = 0x85;
     avr910_devcode   = 0x75;
     chip_erase_delay = 9000;
@@ -2169,7 +2587,23 @@ part
 
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 1;
+
+    idr                 = 0x31;
+    spmcr               = 0x57;
+
    memory "eeprom"
+        paged           = no; /* leave this "no" */
+        page_size       = 4;  /* for parallel programming */
         size            = 512;
         min_write_delay = 9000;
         max_write_delay = 9000;
@@ -2184,6 +2618,11 @@ part
                           "  x   x   x   x      x   x   x  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0", 
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x41;
+	delay		= 20;
+	blocksize	= 4;
+	readsize	= 256;
       ;
 
     memory "flash"
@@ -2219,6 +2658,11 @@ part
                           "  x   x   x a12    a11 a10  a9  a8",
                           " a7  a6   x   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x41;
+	delay		= 6;
+	blocksize	= 128;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -2283,6 +2727,7 @@ part
 part
     id               = "m32";
     desc             = "ATMEGA32";
+    has_jtag         = yes;
     stk500_devcode   = 0x91;
     avr910_devcode   = 0x72;
     chip_erase_delay = 9000;
@@ -2294,6 +2739,20 @@ part
 
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
+    idr                 = 0x31;
+    spmcr               = 0x57;
+
    memory "eeprom"
         paged           = no;   /* leave this "no" */
         page_size       = 4;    /* for parallel programming */
@@ -2311,6 +2770,11 @@ part
                           "  0   0   x   x      x   x  a9  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0",
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 10;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "flash"
@@ -2346,6 +2810,11 @@ part
                           "  0   0 a13 a12    a11 a10  a9  a8",
                           " a7  a6   x   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x21;
+	delay		= 6;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -2411,6 +2880,17 @@ part
 
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 0  0 0 0 0",
                        "x x x x  x x x x    x x x x  x x x x";
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
    memory "eeprom"
         size            = 512;
         min_write_delay = 3400;
@@ -2426,6 +2906,11 @@ part
                           "  x   x   x   x      x   x   x  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0",
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 5;
+	blocksize	= 128;
+	readsize	= 256;
       ;
 
     memory "flash"
@@ -2461,6 +2946,11 @@ part
                           "  x   x   x a12    a11 a10  a9  a8",
                           " a7  a6   x   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x21;
+	delay		= 16;
+	blocksize	= 128;
+	readsize	= 256;
       ;
 
     memory "fuse"
@@ -2503,13 +2993,24 @@ part
     avr910_devcode   = 0x76;
     pagel            = 0xd7;
     bs2              = 0xc2;
-    chip_erase_delay = 9000;
+    chip_erase_delay = 10000;
     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";
 
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 512;
         min_write_delay = 9000;
@@ -2525,6 +3026,11 @@ part
                           "  0   0   x   x      x   x   x  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0", 
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 10;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "flash"
         paged           = yes;
@@ -2534,7 +3040,7 @@ part
         min_write_delay = 4500;
         max_write_delay = 4500;
         readback_p1     = 0xff;
-        readback_p2     = 0xff;
+        readback_p2     = 0x00;
         read_lo         = "  0   0   1   0    0   0   0   0",
                           "  0   0   0   0  a11 a10  a9  a8",
                           " a7  a6  a5  a4   a3  a2  a1  a0",
@@ -2559,6 +3065,11 @@ part
                           "  0   0   0   0    a11 a10  a9  a8",
                           " a7  a6  a5   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x21;
+	delay		= 6;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -2625,6 +3136,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 512;
         min_write_delay = 9000;
@@ -2640,6 +3162,11 @@ part
                           "  0   0   x   x      x   x   x  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0",
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 10;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "flash"
         paged           = yes;
@@ -2674,6 +3201,11 @@ part
                           "  0   0   0   0    a11 a10  a9  a8",
                           " a7  a6  a5   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x21;
+	delay		= 6;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -2742,6 +3274,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 512;
         min_write_delay = 9000;
@@ -2757,6 +3300,11 @@ part
                           "  0   0   x   x      x   x   x  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0",
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x04;
+	delay		= 10;
+	blocksize	= 128;
+	readsize	= 256;
       ;
     memory "flash"
         paged           = yes;
@@ -2791,6 +3339,11 @@ part
                           "  0   0   0   0    a11 a10  a9  a8",
                           " a7  a6  a5   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x21;
+	delay		= 6;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -2858,6 +3411,17 @@ part
     chip_erase          = "1 0 1 0  1 1 0 0   1 0 0 x  x x x x",
                           "x x x x  x x x x   x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 0;
+
     memory "eeprom"
         size            = 128;
         min_write_delay = 9000;
@@ -2869,6 +3433,11 @@ part
 
         write           = "1  1  0  0   0  0  0  0    x x x x  x x x x",
                           "x a6 a5 a4  a3 a2 a1 a0    i i i i  i i i i";
+
+	mode		= 0x04;
+	delay		= 10;
+	blocksize	= 64;
+	readsize	= 256;
     ;
 
     memory "flash"
@@ -2904,6 +3473,11 @@ part
                           "  x  x  x  x   x  x a9 a8",
                           " a7 a6 a5 a4   x  x  x  x",
                           "  x  x  x  x   x  x  x  x";
+
+	mode		= 0x21;
+	delay		= 6;
+	blocksize	= 16;
+	readsize	= 256;
     ;
 
     memory "signature"
@@ -2959,13 +3533,24 @@ part
 #    avr910_devcode   = 0x;
     pagel            = 0xd7;
     bs2              = 0xc2;
-    chip_erase_delay = 9000;
+    chip_erase_delay = 45000;
     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";
 
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 1;
+
     memory "eeprom"
         size            = 256;
         min_write_delay = 3600;
@@ -2981,6 +3566,11 @@ part
                           "  0   0   0   x      x   x   x   x",
                           " a7  a6  a5  a4     a3  a2  a1  a0", 
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x41;
+	delay		= 5;
+	blocksize	= 4;
+	readsize	= 256;
       ;
     memory "flash"
         paged           = yes;
@@ -2989,8 +3579,8 @@ part
         num_pages       = 64;
         min_write_delay = 4500;
         max_write_delay = 4500;
-        readback_p1     = 0xff;
-        readback_p2     = 0xff;
+        readback_p1     = 0x00;
+        readback_p2     = 0x00;
         read_lo         = "  0   0   1   0    0   0   0   0",
                           "  0   0   0   0    0 a10  a9  a8",
                           " a7  a6  a5  a4   a3  a2  a1  a0",
@@ -3015,6 +3605,11 @@ part
                           "  0   0   0   0      0 a10  a9  a8",
                           " a7  a6  a5   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x41;
+	delay		= 6;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -3082,6 +3677,17 @@ part
     chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                        "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 1;
+
     memory "eeprom"
         size            = 512;
         min_write_delay = 3600;
@@ -3097,6 +3703,11 @@ part
                           "  0   0   0   x      x   x   x  a8",
                           " a7  a6  a5  a4     a3  a2  a1  a0", 
                           "  i   i   i   i      i   i   i   i";
+
+	mode		= 0x41;
+	delay		= 5;
+	blocksize	= 4;
+	readsize	= 256;
       ;
     memory "flash"
         paged           = yes;
@@ -3131,6 +3742,11 @@ part
                           "  0   0   0   0    a11 a10  a9  a8",
                           " a7  a6  a5   x      x   x   x   x",
                           "  x   x   x   x      x   x   x   x";
+
+	mode		= 0x41;
+	delay		= 6;
+	blocksize	= 64;
+	readsize	= 256;
       ;
 
     memory "lfuse"
@@ -3213,6 +3829,17 @@ part
      chip_erase       = "1 0 1 0  1 1 0 0    1 0 0 x  x x x x",
                         "x x x x  x x x x    x x x x  x x x x";
 
+    timeout		= 200;
+    stabdelay		= 100;
+    cmdexedelay		= 25;
+    synchloops		= 32;
+    bytedelay		= 0;
+    pollindex		= 3;
+    pollvalue		= 0x53;
+    predelay		= 1;
+    postdelay		= 1;
+    pollmethod		= 1;
+
      memory "eeprom"
          size            = 128;
          min_write_delay = 4000;
@@ -3224,6 +3851,11 @@ part
 
          write           = "1  1  0  0   0  0  0  0   0 0 0 x  x x x x",
                            "x a6 a5 a4  a3 a2 a1 a0   i i i i  i i i i";
+
+	mode		= 0x41;
+	delay		= 6;
+	blocksize	= 4;
+	readsize	= 256;
        ;
      memory "flash"
          paged           = yes;
@@ -3261,6 +3893,11 @@ part
                            "  0  0  0  0   0  0 a9 a8",
                            " a7 a6 a5 a4   x  x  x  x",
                            "  x  x  x  x   x  x  x  x";
+
+	mode		= 0x41;
+	delay		= 6;
+	blocksize	= 32;
+	readsize	= 256;
        ;
 #   ATtiny2313 has Signature Bytes: 0x1E 0x91 0x0A.
      memory "signature"
@@ -3309,3 +3946,4 @@ part
                            "0  0  0  0   0  0  0  a0   o o o o  o o o o";
      ;
   ;
+
diff --git a/avrdude/avrpart.c b/avrdude/avrpart.c
index a75d708c..78e112ce 100644
--- a/avrdude/avrpart.c
+++ b/avrdude/avrpart.c
@@ -292,23 +292,23 @@ void avr_mem_display(char * prefix, FILE * f, AVRMEM * m, int type,
   char * optr;
 
   if (m == NULL) {
-    fprintf(f,
-            "%s                          Page                       Polled\n"
-            "%sMemory Type Paged  Size   Size #Pages MinW  MaxW   ReadBack\n"
-            "%s----------- ------ ------ ---- ------ ----- ----- ---------\n",
+      fprintf(f,
+              "%s                       Block Poll               Page                       Polled\n"
+              "%sMemory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack\n"
+              "%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
             prefix, prefix, prefix);
   }
   else {
     if (verbose > 2) {
       fprintf(f,
-              "%s                          Page                       Polled\n"
-              "%sMemory Type Paged  Size   Size #Pages MinW  MaxW   ReadBack\n"
-              "%s----------- ------ ------ ---- ------ ----- ----- ---------\n",
+              "%s                       Block Poll               Page                       Polled\n"
+              "%sMemory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack\n"
+              "%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
               prefix, prefix, prefix);
     }
     fprintf(f,
-            "%s%-11s %-6s %6d %4d %5d %5d %5d 0x%02x 0x%02x\n",
-            prefix, m->desc,
+            "%s%-11s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
+            prefix, m->desc, m->mode, m->delay, m->blocksize, m->pollindex,
             m->paged ? "yes" : "no",
             m->size,
             m->page_size,
@@ -486,6 +486,13 @@ void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose)
           "%sRETRY pulse           : %s\n"
           "%sserial program mode   : %s\n"
           "%sparallel program mode : %s\n"
+          "%sTimeout               : %d\n"
+          "%sStabDelay             : %d\n"
+          "%sCmdexeDelay           : %d\n"
+          "%sSyncLoops             : %d\n"
+          "%sByteDelay             : %d\n"
+          "%sPollIndex             : %d\n"
+          "%sPollValue             : 0x%02x\n"
           "%sMemory Detail         :\n\n",
           prefix, p->desc,
           prefix, p->chip_erase_delay,
@@ -496,6 +503,13 @@ void avr_display(FILE * f, AVRPART * p, char * prefix, int verbose)
           prefix, (p->flags & AVRPART_SERIALOK) ? "yes" : "no",
           prefix, (p->flags & AVRPART_PARALLELOK) ?
             ((p->flags & AVRPART_PSEUDOPARALLEL) ? "psuedo" : "yes") : "no",
+          prefix, p->timeout,
+          prefix, p->stabdelay,
+          prefix, p->cmdexedelay,
+          prefix, p->synchloops,
+          prefix, p->bytedelay,
+          prefix, p->pollindex,
+          prefix, p->pollvalue,
           prefix);
 
   px = prefix;
diff --git a/avrdude/avrpart.h b/avrdude/avrpart.h
index 490f6325..138a6ebb 100644
--- a/avrdude/avrpart.h
+++ b/avrdude/avrpart.h
@@ -78,6 +78,9 @@ typedef struct opcode {
 #define AVRPART_SERIALOK       0x0001  /* part supports serial programming */
 #define AVRPART_PARALLELOK     0x0002  /* part supports parallel programming */
 #define AVRPART_PSEUDOPARALLEL 0x0004  /* part has pseudo parallel support */
+#define AVRPART_HAS_JTAG       0x0008  /* part has a JTAG i/f */
+#define AVRPART_ALLOWFULLPAGEBITSTREAM 0x0010 /* JTAG ICE mkII param. */
+#define AVRPART_ENABLEPAGEPROGRAMMING 0x0020 /* JTAG ICE mkII param. */
 
 #define AVR_DESCLEN 64
 #define AVR_IDLEN   32
@@ -94,6 +97,21 @@ typedef struct avrpart {
                                        this pin (PIN_AVR_*) */
   unsigned      flags;              /* see AVRPART_ masks */
 
+  int           timeout;            /* stk500 v2 xml file parameter */
+  int           stabdelay;          /* stk500 v2 xml file parameter */
+  int           cmdexedelay;        /* stk500 v2 xml file parameter */
+  int           synchloops;         /* stk500 v2 xml file parameter */
+  int           bytedelay;          /* stk500 v2 xml file parameter */
+  int           pollindex;          /* stk500 v2 xml file parameter */
+  unsigned char pollvalue;          /* stk500 v2 xml file parameter */
+  int           predelay;           /* stk500 v2 xml file parameter */
+  int           postdelay;          /* stk500 v2 xml file parameter */
+  int           pollmethod;         /* stk500 v2 xml file parameter */
+
+  unsigned char idr;                /* JTAG ICE mkII XML file parameter */
+  unsigned char rampz;              /* JTAG ICE mkII XML file parameter */
+  unsigned char spmcr;              /* JTAG ICE mkII XML file parameter */
+
   OPCODE      * op[AVR_OP_MAX];     /* opcodes */
 
   LISTID        mem;                /* avr memory definitions */
@@ -115,6 +133,13 @@ typedef struct avrmem {
                                  back on, see errata
                                  http://www.atmel.com/atmel/acrobat/doc1280.pdf */
   unsigned char readback[2];  /* polled read-back values */
+
+  int mode;                   /* stk500 v2 xml file parameter */
+  int delay;                  /* stk500 v2 xml file parameter */
+  int blocksize;              /* stk500 v2 xml file parameter */
+  int readsize;               /* stk500 v2 xml file parameter */
+  int pollindex;              /* stk500 v2 xml file parameter */
+
   unsigned char * buf;        /* pointer to memory buffer */
   OPCODE * op[AVR_OP_MAX];    /* opcodes */
 } AVRMEM;
diff --git a/avrdude/config_gram.y b/avrdude/config_gram.y
index a515c597..f7fe7713 100644
--- a/avrdude/config_gram.y
+++ b/avrdude/config_gram.y
@@ -33,9 +33,11 @@
 #include "ppi.h"
 #include "pgm.h"
 #include "stk500.h"
+#include "stk500v2.h"
 #include "avr910.h"
 #include "butterfly.h"
 #include "avr.h"
+#include "jtagmkII.h"
 
 #if defined(WIN32NATIVE)
 #define strtok_r( _s, _sep, _lasts ) \
@@ -87,6 +89,7 @@ static int parse_cmdbits(OPCODE * op);
 %token K_FLASH
 %token K_ID
 %token K_IO
+%token K_JTAG_MKII
 %token K_LOADPAGE
 %token K_MAX_WRITE_DELAY
 %token K_MIN_WRITE_DELAY
@@ -111,6 +114,7 @@ static int parse_cmdbits(OPCODE * op);
 %token K_SCK
 %token K_SIZE
 %token K_STK500
+%token K_STK500V2
 %token K_AVR910
 %token K_BUTTERFLY
 %token K_TYPE
@@ -121,6 +125,36 @@ static int parse_cmdbits(OPCODE * op);
 %token K_NO
 %token K_YES
 
+/* stk500 v2 xml file parameters */
+%token K_TIMEOUT
+%token K_STABDELAY
+%token K_CMDEXEDELAY
+%token K_SYNCHLOOPS
+%token K_BYTEDELAY
+%token K_POLLVALUE
+%token K_POLLINDEX
+%token K_PREDELAY
+%token K_POSTDELAY
+%token K_POLLMETHOD
+%token K_MODE
+%token K_DELAY
+%token K_BLOCKSIZE
+%token K_READSIZE
+
+/* JTAG ICE mkII specific parameters */
+%token K_ALLOWFULLPAGEBITSTREAM	/*
+				 * Internal parameter for the JTAG
+				 * ICE; describes the internal JTAG
+				 * streaming behaviour inside the MCU.
+				 * 1 for all older chips, 0 for newer
+				 * MCUs.
+				 */
+%token K_ENABLEPAGEPROGRAMMING	/* ? yes for mega256*, mega406 */
+%token K_HAS_JTAG		/* MCU has JTAG i/f. */
+%token K_IDR			/* address of OCD register in IO space */
+%token K_RAMPZ			/* address of RAMPZ reg. in IO space */
+%token K_SPMCR			/* address of SPMC[S]R in memory space */
+
 %token TKN_COMMA
 %token TKN_EQUAL
 %token TKN_SEMI
@@ -296,6 +330,12 @@ prog_parm :
     }
   } |
 
+  K_TYPE TKN_EQUAL K_STK500V2 {
+    {
+      stk500v2_initpgm(current_prog);
+    }
+  } |
+
   K_TYPE TKN_EQUAL K_AVR910 {
     { 
       avr910_initpgm(current_prog);
@@ -308,6 +348,12 @@ prog_parm :
     }
   } |
 
+  K_TYPE TKN_EQUAL K_JTAG_MKII {
+    {
+      jtagmkII_initpgm(current_prog);
+    }
+  } |
+
   K_DESC TKN_EQUAL TKN_STRING {
     strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN);
     current_prog->desc[PGM_DESCLEN-1] = 0;
@@ -483,6 +529,114 @@ part_parm :
       free_tokens(2, $1, $3);
     } |
 
+  K_TIMEOUT TKN_EQUAL TKN_NUMBER
+    {
+      current_part->timeout = $3->value.number;
+      free_token($3);
+    } |
+
+  K_STABDELAY TKN_EQUAL TKN_NUMBER
+    {
+      current_part->stabdelay = $3->value.number;
+      free_token($3);
+    } |
+
+  K_CMDEXEDELAY TKN_EQUAL TKN_NUMBER
+    {
+      current_part->cmdexedelay = $3->value.number;
+      free_token($3);
+    } |
+
+  K_SYNCHLOOPS TKN_EQUAL TKN_NUMBER
+    {
+      current_part->synchloops = $3->value.number;
+      free_token($3);
+    } |
+
+  K_BYTEDELAY TKN_EQUAL TKN_NUMBER
+    {
+      current_part->bytedelay = $3->value.number;
+      free_token($3);
+    } |
+
+  K_POLLVALUE TKN_EQUAL TKN_NUMBER
+    {
+      current_part->pollvalue = $3->value.number;
+      free_token($3);
+    } |
+
+  K_POLLINDEX TKN_EQUAL TKN_NUMBER
+    {
+      current_part->pollindex = $3->value.number;
+      free_token($3);
+    } |
+
+  K_PREDELAY TKN_EQUAL TKN_NUMBER
+    {
+      current_part->predelay = $3->value.number;
+      free_token($3);
+    } |
+
+  K_POSTDELAY TKN_EQUAL TKN_NUMBER
+    {
+      current_part->postdelay = $3->value.number;
+      free_token($3);
+    } |
+
+  K_POLLMETHOD TKN_EQUAL TKN_NUMBER
+    {
+      current_part->pollmethod = $3->value.number;
+      free_token($3);
+    } |
+
+  K_HAS_JTAG TKN_EQUAL yesno
+    {
+      if ($3->primary == K_YES)
+        current_part->flags |= AVRPART_HAS_JTAG;
+      else if ($3->primary == K_NO)
+        current_part->flags &= ~AVRPART_HAS_JTAG;
+
+      free_token($3);
+    } |
+
+  K_ALLOWFULLPAGEBITSTREAM TKN_EQUAL yesno
+    {
+      if ($3->primary == K_YES)
+        current_part->flags |= AVRPART_ALLOWFULLPAGEBITSTREAM;
+      else if ($3->primary == K_NO)
+        current_part->flags &= ~AVRPART_ALLOWFULLPAGEBITSTREAM;
+
+      free_token($3);
+    } |
+
+  K_ENABLEPAGEPROGRAMMING TKN_EQUAL yesno
+    {
+      if ($3->primary == K_YES)
+        current_part->flags |= AVRPART_ENABLEPAGEPROGRAMMING;
+      else if ($3->primary == K_NO)
+        current_part->flags &= ~AVRPART_ENABLEPAGEPROGRAMMING;
+
+      free_token($3);
+    } |
+
+  K_IDR TKN_EQUAL TKN_NUMBER
+    {
+      current_part->idr = $3->value.number;
+      free_token($3);
+    } |
+
+  K_RAMPZ TKN_EQUAL TKN_NUMBER
+    {
+      current_part->rampz = $3->value.number;
+      free_token($3);
+    } |
+
+  K_SPMCR TKN_EQUAL TKN_NUMBER
+    {
+      current_part->spmcr = $3->value.number;
+      free_token($3);
+    } |
+
   K_SERIAL TKN_EQUAL yesno
     {
       if ($3->primary == K_YES)
@@ -630,6 +784,38 @@ mem_spec :
       free_token($3);
     } |
 
+
+  K_MODE TKN_EQUAL TKN_NUMBER
+    {
+      current_mem->mode = $3->value.number;
+      free_token($3);
+    } |
+
+  K_DELAY TKN_EQUAL TKN_NUMBER
+    {
+      current_mem->delay = $3->value.number;
+      free_token($3);
+    } |
+
+  K_BLOCKSIZE TKN_EQUAL TKN_NUMBER
+    {
+      current_mem->blocksize = $3->value.number;
+      free_token($3);
+    } |
+
+  K_READSIZE TKN_EQUAL TKN_NUMBER
+    {
+      current_mem->readsize = $3->value.number;
+      free_token($3);
+    } |
+
+  K_POLLINDEX TKN_EQUAL TKN_NUMBER
+    {
+      current_mem->pollindex = $3->value.number;
+      free_token($3);
+    } |
+
+
   opcode TKN_EQUAL string_list {
     { 
       int opnum;
diff --git a/avrdude/doc/avrdude.texi b/avrdude/doc/avrdude.texi
index 4290453d..4cc305f1 100644
--- a/avrdude/doc/avrdude.texi
+++ b/avrdude/doc/avrdude.texi
@@ -28,7 +28,7 @@ This file documents the avrdude program.
 
 For avrdude version @value{VERSION}, @value{UPDATED}.
 
-Copyright @copyright{} 2003 Brian Dean
+Copyright @copyright{} 2003,2005 Brian Dean
 
 Permission is granted to make and distribute verbatim copies of
 this manual provided the copyright notice and this permission notice
@@ -63,7 +63,7 @@ by the Free Software Foundation.
 
 @vfill
 
-Copyright @copyright{} 2003 Brian S. Dean
+Copyright @copyright{} 2003,2005 Brian S. Dean
 @sp 2
 
 Permission is granted to make and distribute verbatim copies of
@@ -129,7 +129,8 @@ from the contents of a file, while interactive mode is useful for
 exploring memory contents, modifing individual bytes of eeprom,
 programming fuse/lock bits, etc.
 
-AVRDUDE supports three basic programmer types: Atmel's STK500, appnote
+AVRDUDE supports four basic programmer types: Atmel's STK500,
+Atmel's JTAG ICE mkII, appnote
 avr910 and the PPI (parallel port interface). PPI represents a class
 of simple programmers where the programming lines are directly
 connected to the PC parallel port. Several pin configurations exist
@@ -139,7 +140,7 @@ programmer on the command line or by creating a new entry in its
 configuration file. All that's usually required for a new entry is to
 tell AVRDUDE which pins to use for each programming function. 
 
-The STK500 and avr910 use the serial port to communicate with the PC
+The STK500, JTAG ICE and avr910 use the serial port to communicate with the PC
 and contains on-board logic to control the programming of the target
 device. The fundamental difference between the two types lies in the
 protocol used to control the programmer. The avr910 protocol is very
@@ -147,6 +148,14 @@ simplistic and can easily be used as the basis for a simple, home made
 programer since the firmware is available online. On the other hand,
 the STK500 protocol is more robust and complicated and the firmware is
 not openly available.
+The JTAG ICE also uses a serial communication protocol which is similar
+to the STK500 firmware version 2 one.  However, as the JTAG ICE is
+intented to allow on-chip debugging as well as memory programming, the
+protocol is more sophisticated.
+(This protocol can also be run on top of USB, but AVRDUDE by now only
+supports the RS-232-based option.)
+Only the memory programming functionality of the JTAG ICE is supported
+by AVRDUDE.
 
 @menu
 * History::                     
@@ -221,6 +230,9 @@ datasheet so that you can enter the programming specifications.
 Currently, the following MCU types are understood:
 
 @table @code
+@itemx c128
+AT90CAN128
+
 @itemx 1200
 AT90S1200
 
@@ -249,59 +261,80 @@ AT90S8515
 AT90S8535
 
 @itemx m103
-ATMEGA103
+ATmega103
 
 @itemx m128
-ATMEGA128
+ATmega128
 
 @itemx m16
-ATMEGA16
+ATmega16
 
 @itemx m161
-ATMEGA161
+ATmega161
 
 @itemx m162
-ATMEGA162
+ATmega162
 
 @itemx m163
-ATMEGA163
+ATmega163
 
 @itemx m169
-ATMEGA169
+ATmega169
 
 @itemx m32
-ATMEGA32
+ATmega32
 
 @itemx m48
-ATMEGA48
+ATmega48
 
 @itemx m64
-ATMEGA64
+ATmega64
 
 @itemx m8
-ATMEGA8
+ATmega8
 
 @itemx m8515
-ATMEGA8515
+ATmega8515
 
 @itemx m8535
-ATMEGA8535
+ATmega8535
 
 @itemx m88
-ATMEGA88
+ATmega88
 
 @itemx t12
 ATtiny12
 
+@itemx t13
+ATtiny13
+
 @itemx t15
 ATtiny15
 
+@itemx t2313
+ATtiny2313
+
 @itemx t26
-ATTINY26
+ATtiny26
 
 @end table
 
-(*)   The AT90S2323 uses the same algorithm.
+(*)   The AT90S2323 and ATtiny22 use the same algorithm.
+
+@item -b @var{baudrate}
+Override the RS-232 connection baud rate specified in the respective
+programmer's entry of the configuration file.
+
+@item -B @var{bitclock}
+Specify the bit clock period for the JTAG interface (JTAG ICE only).
+The value is a floating-point number in microseconds.
+The default value of the JTAG ICE results in about 1 microsecond bit
+clock period, suitable for target MCUs running at 4 MHz clock and
+above.
+Unlike certain parameters in the STK500, the JTAG ICE resets all its
+parameters to default values when the programming software signs
+off from the ICE, so for MCUs running at lower clock speeds, this
+parameter must be specified on the command-line.
 
 @item -c @var{programmer-id}
 Specify the programmer to be used.  AVRDUDE knows about several common
@@ -766,11 +799,22 @@ multiplies by 1E6, a trailing letter @var{k} by 1E3.
 Turn the master oscillator off.
 
 @item sck @var{period}
+@emph{STK500 only:}
 Set the SCK clock period to @var{period} microseconds.
 
+@emph{JTAG ICE only:}
+Set the JTAG ICE bit clock period to @var{period} microseconds.
+Note that unlike STK500 settings, this setting will be reverted to
+its default value (approximately 1 microsecond) when the programming
+software signs off from the JTAG ICE.
+
 @item parms
+@emph{STK500 only:}
 Display the current voltage and master oscillator parameters.
 
+@emph{JTAG ICE only:}
+Display the current target supply voltage and JTAG bit clock rate/period.
+
 @end table
 
 @c
diff --git a/avrdude/lexer.l b/avrdude/lexer.l
index d0b72e15..f240a9bd 100644
--- a/avrdude/lexer.l
+++ b/avrdude/lexer.l
@@ -115,23 +115,29 @@ SIGN     [+-]
          exit(1); }
 }
 
+allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
+avr910           { yylval=NULL; return K_AVR910; }
+avr910_devcode   { yylval=NULL; return K_AVR910_DEVCODE; }
 bank_size        { yylval=NULL; return K_PAGE_SIZE; }
 banked           { yylval=NULL; return K_PAGED; }
 baudrate         { yylval=NULL; return K_BAUDRATE; }
 bs2              { yylval=NULL; return K_BS2; }
 buff             { yylval=NULL; return K_BUFF; }
+butterfly        { yylval=NULL; return K_BUTTERFLY; }
 chip_erase_delay { yylval=NULL; return K_CHIP_ERASE_DELAY; }
 desc             { yylval=NULL; return K_DESC; }
 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; }
+enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; }
 errled           { yylval=NULL; return K_ERRLED; }
 flash            { yylval=NULL; return K_FLASH; }
+has_jtag         { yylval=NULL; return K_HAS_JTAG; }
 id               { yylval=NULL; return K_ID; }
+idr              { yylval=NULL; return K_IDR; }
+jtagmkii         { yylval=NULL; return K_JTAG_MKII; }
 max_write_delay  { yylval=NULL; return K_MAX_WRITE_DELAY; }
 memory           { yylval=NULL; return K_MEMORY; }
 min_write_delay  { yylval=NULL; return K_MIN_WRITE_DELAY; }
@@ -148,19 +154,37 @@ part             { yylval=NULL; return K_PART; }
 pgmled           { yylval=NULL; return K_PGMLED; }
 programmer       { yylval=NULL; return K_PROGRAMMER; }
 pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; }
+rampz            { yylval=NULL; return K_RAMPZ; }
 rdyled           { yylval=NULL; return K_RDYLED; }
 readback_p1      { yylval=NULL; return K_READBACK_P1; }
 readback_p2      { yylval=NULL; return K_READBACK_P2; }
 retry_pulse      { yylval=NULL; return K_RETRY_PULSE; }
 serial           { yylval=NULL; return K_SERIAL; }
 size             { yylval=NULL; return K_SIZE; }
+spmcr            { yylval=NULL; return K_SPMCR; }
 stk500           { yylval=NULL; return K_STK500; }
-avr910           { yylval=NULL; return K_AVR910; }
-butterfly        { yylval=NULL; return K_BUTTERFLY; }
+stk500v2         { yylval=NULL; return K_STK500V2; }
+stk500_devcode   { yylval=NULL; return K_STK500_DEVCODE; }
 type             { yylval=NULL; return K_TYPE; }
 vcc              { yylval=NULL; return K_VCC; }
 vfyled           { yylval=NULL; return K_VFYLED; }
 
+timeout          { yylval=NULL; return K_TIMEOUT; }
+stabdelay        { yylval=NULL; return K_STABDELAY; }
+cmdexedelay      { yylval=NULL; return K_CMDEXEDELAY; }
+synchloops       { yylval=NULL; return K_SYNCHLOOPS; }
+bytedelay        { yylval=NULL; return K_BYTEDELAY; }
+pollvalue        { yylval=NULL; return K_POLLVALUE; }
+pollindex        { yylval=NULL; return K_POLLINDEX; }
+predelay         { yylval=NULL; return K_PREDELAY; }
+postdelay        { yylval=NULL; return K_POSTDELAY; }
+pollmethod       { yylval=NULL; return K_POLLMETHOD; }
+mode             { yylval=NULL; return K_MODE; }
+delay            { yylval=NULL; return K_DELAY; }
+blocksize        { yylval=NULL; return K_BLOCKSIZE; }
+readsize        { yylval=NULL; return K_READSIZE; }
+
+
 
 dedicated        { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
 io               { yylval=new_token(K_IO); return K_IO; }
diff --git a/avrdude/main.c b/avrdude/main.c
index 9827d378..c222595e 100644
--- a/avrdude/main.c
+++ b/avrdude/main.c
@@ -1,6 +1,6 @@
 /*
  * avrdude - A Downloader/Uploader for AVR device programmers
- * Copyright (C) 2000-2004  Brian S. Dean <bsd@bsdhome.com>
+ * Copyright (C) 2000-2005  Brian S. Dean <bsd@bsdhome.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,7 +20,8 @@
 /* $Id$ */
 
 /*
- * Code to program an Atmel AVR AT90S device using the parallel port.
+ * Code to program an Atmel AVR device through one of the supported
+ * programmers.
  *
  * For parallel port connected programmers, the pin definitions can be
  * changed via a config file.  See the config file for instructions on
@@ -98,6 +99,8 @@ void usage(void)
  "Usage: %s [options]\n"
  "Options:\n"
  "  -p <partno>                Required. Specify AVR device.\n"
+ "  -b <baudrate>              Override RS-232 baud rate.\n"
+ "  -B <bitclock>              Specify JTAG bit clock period (us).\n"
  "  -C <config-file>           Specify location of configuration file.\n"
  "  -c <programmer>            Specify programmer type.\n"
  "  -D                         Disable auto erase for flash memory\n"
@@ -115,6 +118,8 @@ void usage(void)
  "                             recovered if they change\n"
  "  -t                         Enter terminal mode.\n"
  "  -E <exitspec>[,<exitspec>] List programmer exit specifications.\n"
+ "  -y                         Count # erase cycles in EEPROM.\n"
+ "  -Y <number>                Initialize erase cycle # in EEPROM.\n"
  "  -v                         Verbose output. -v -v for more.\n"
  "  -q                         Quell progress output.\n"
  "  -?                         Display this usage.\n"
@@ -707,6 +712,7 @@ int main(int argc, char * argv [])
   char  * e;           /* for strtol() error checking */
   int     quell_progress;
   int     baudrate;    /* override default programmer baud rate */
+  double  bitclock;    /* Specify programmer bit clock (JTAG ICE) */
   int     safemode;    /* Enable safemode, 1=safemode on, 0=normal */
   unsigned char safemode_lfuse = 0xff;
   unsigned char safemode_hfuse = 0xff;
@@ -759,6 +765,7 @@ int main(int argc, char * argv [])
   do_cycles     = 0;
   set_cycles    = -1;
   baudrate      = 0;
+  bitclock      = 0.0;
   safemode      = 1;       /* Safemode enabled by default */
 
 
@@ -816,6 +823,15 @@ int main(int argc, char * argv [])
         }
         break;
 
+      case 'B':	/* specify JTAG ICE bit clock period */
+	bitclock = strtod(optarg, &e);
+	if ((e == optarg) || (*e != 0) || bitclock == 0.0) {
+	  fprintf(stderr, "%s: invalid bit clock period specified '%s'\n",
+                  progname, optarg);
+          exit(1);
+        }
+        break;
+
       case 'c': /* programmer id */
         programmer = optarg;
         break;
@@ -1112,6 +1128,13 @@ int main(int argc, char * argv [])
     pgm->baudrate = baudrate;
   }
 
+  if (bitclock != 0.0) {
+    if (verbose) {
+      fprintf(stderr, "%sSetting bit clk period: %.1f\n", progbuf, bitclock);
+    }
+    pgm->bitclock = bitclock;
+  }
+
   rc = pgm->open(pgm, port);
   if (rc < 0) {
     exitrc = 1;
diff --git a/avrdude/pgm.h b/avrdude/pgm.h
index 52ec9baa..75f6cf0d 100644
--- a/avrdude/pgm.h
+++ b/avrdude/pgm.h
@@ -47,6 +47,7 @@ typedef struct programmer_t {
   int ppidata;
   int ppictrl;
   int baudrate;
+  double bitclock;    /* JTAG ICE clock period in microseconds */
   int fd;
   int  page_size;  /* page size if the programmer supports paged write/load */
   int  (*rdy_led)        (struct programmer_t * pgm, int value);
diff --git a/avrdude/ser_posix.c b/avrdude/ser_posix.c
index 18a60eec..39947b8c 100644
--- a/avrdude/ser_posix.c
+++ b/avrdude/ser_posix.c
@@ -41,6 +41,8 @@
 extern char *progname;
 extern int verbose;
 
+long serial_recv_timeout = 5000; /* ms */
+
 struct baud_mapping {
   long baud;
   speed_t speed;
@@ -76,7 +78,7 @@ static speed_t serial_baud_lookup(long baud)
   exit(1);
 }
 
-static int serial_setattr(int fd, long baud)
+int serial_setspeed(int fd, long baud)
 {
   int rc;
   struct termios termios;
@@ -90,7 +92,7 @@ static int serial_setattr(int fd, long baud)
    */
   rc = tcgetattr(fd, &termios);
   if (rc < 0) {
-    fprintf(stderr, "%s: serial_setattr(): tcgetattr() failed, %s", 
+    fprintf(stderr, "%s: serial_setspeed(): tcgetattr() failed, %s", 
             progname, strerror(errno));
     return -errno;
   }
@@ -108,7 +110,7 @@ static int serial_setattr(int fd, long baud)
   
   rc = tcsetattr(fd, TCSANOW, &termios);
   if (rc < 0) {
-    fprintf(stderr, "%s: serial_setattr(): tcsetattr() failed, %s", 
+    fprintf(stderr, "%s: serial_setspeed(): tcsetattr() failed, %s", 
             progname, strerror(errno));
     return -errno;
   }
@@ -135,7 +137,7 @@ int serial_open(char * port, int baud)
   /*
    * set serial line attributes
    */
-  rc = serial_setattr(fd, baud);
+  rc = serial_setspeed(fd, baud);
   if (rc) {
     fprintf(stderr, 
             "%s: serial_open(): can't set attributes for device \"%s\"\n",
@@ -199,9 +201,10 @@ int serial_send(int fd, char * buf, size_t buflen)
   reselect:
     nfds = select(fd+1, NULL, &wfds, NULL, &timeout);
     if (nfds == 0) {
-      fprintf(stderr,
-              "%s: serial_send(): programmer is not responding\n",
-              progname);
+      if (verbose >= 1)
+	fprintf(stderr,
+		"%s: serial_send(): programmer is not responding\n",
+		progname);
       exit(1);
     }
     else if (nfds == -1) {
@@ -239,8 +242,8 @@ int serial_recv(int fd, char * buf, size_t buflen)
   char * p = buf;
   size_t len = 0;
 
-  timeout.tv_sec  = 5;
-  timeout.tv_usec = 0;
+  timeout.tv_sec  = serial_recv_timeout / 1000L;
+  timeout.tv_usec = (serial_recv_timeout % 1000L) * 1000;
 
   while (len < buflen) {
     FD_ZERO(&rfds);
@@ -249,10 +252,11 @@ int serial_recv(int fd, char * buf, size_t buflen)
   reselect:
     nfds = select(fd+1, &rfds, NULL, NULL, &timeout);
     if (nfds == 0) {
-      fprintf(stderr, 
-              "%s: serial_recv(): programmer is not responding\n",
-              progname);
-      exit(1);
+      if (verbose > 1)
+	fprintf(stderr,
+		"%s: serial_recv(): programmer is not responding\n",
+		progname);
+      return -1;
     }
     else if (nfds == -1) {
       if (errno == EINTR) {
diff --git a/avrdude/ser_win32.c b/avrdude/ser_win32.c
index 72f0b33f..2bd72ef5 100644
--- a/avrdude/ser_win32.c
+++ b/avrdude/ser_win32.c
@@ -33,6 +33,8 @@
 extern char *progname;
 extern int verbose;
 
+long serial_recv_timeout = 5000; /* ms */
+
 #define W32SERBUFSIZE 1024
 
 struct baud_mapping {
@@ -81,9 +83,30 @@ BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms
 	return SetCommTimeouts(hComPort, &ctmo);
 }
 
-int serial_open(char * port, long baud)
+int serial_setspeed(int fd, long baud)
 {
 	DCB dcb;
+	HANDLE hComPort = (HANDLE)fd;
+
+	ZeroMemory (&dcb, sizeof(DCB));
+	dcb.DCBlength = sizeof(DCB);
+	dcb.BaudRate = serial_baud_lookup (baud);
+	dcb.fBinary = 1;
+	dcb.fDtrControl = DTR_CONTROL_DISABLE;
+	dcb.fRtsControl = RTS_CONTROL_DISABLE;
+	dcb.ByteSize = 8;
+	dcb.Parity = NOPARITY;
+	dcb.StopBits = ONESTOPBIT;
+
+	if (!SetCommState(hComPort, &dcb))
+		return -1;
+
+	return 0;
+}
+
+
+int serial_open(char * port, long baud)
+{
 	LPVOID lpMsgBuf;
 	HANDLE hComPort=INVALID_HANDLE_VALUE;
 
@@ -120,17 +143,8 @@ int serial_open(char * port, long baud)
 		exit(1);
 	}
 
-	ZeroMemory (&dcb, sizeof(DCB));
-	dcb.DCBlength = sizeof(DCB);
-	dcb.BaudRate = serial_baud_lookup (baud);
-	dcb.fBinary = 1;
-	dcb.fDtrControl = DTR_CONTROL_DISABLE;
-	dcb.fRtsControl = RTS_CONTROL_DISABLE;
-	dcb.ByteSize = 8;
-	dcb.Parity = NOPARITY;
-	dcb.StopBits = ONESTOPBIT;
 
-	if (!SetCommState(hComPort, &dcb))
+	if (serial_setspeed((int)hComPort, baud) != 0)
 	{
 		CloseHandle(hComPort);
 		fprintf(stderr, "%s: serial_open(): can't set com-state for \"%s\"\n",
@@ -229,7 +243,7 @@ int serial_recv(int fd, char * buf, size_t buflen)
 		exit(1);
 	}
 	
-	serial_w32SetTimeOut(hComPort,5000);
+	serial_w32SetTimeOut(hComPort, serial_recv_timeout);
 	
 	if (!ReadFile(hComPort, buf, buflen, &read, NULL)) {
 		LPVOID lpMsgBuf;
diff --git a/avrdude/serial.h b/avrdude/serial.h
index 4d8f4a67..8fbef14b 100644
--- a/avrdude/serial.h
+++ b/avrdude/serial.h
@@ -30,7 +30,10 @@
 #ifndef __serial_h__
 #define __serial_h__
 
+extern long serial_recv_timeout;
+
 extern int serial_open(char * port, long baud);
+extern int serial_setattr(int fd, long baud);
 extern void serial_close(int fd);
 
 extern int serial_send(int fd, char * buf, size_t buflen);
diff --git a/avrdude/stk500v2.c b/avrdude/stk500v2.c
new file mode 100644
index 00000000..aca3a6cc
--- /dev/null
+++ b/avrdude/stk500v2.c
@@ -0,0 +1,949 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2005 Erik Walthinsen
+ * Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* $Id$
+/* Based on Id: stk500.c,v 1.46 2004/12/22 01:52:45 bdean Exp */
+
+/*
+ * avrdude interface for Atmel STK500V2 programmer
+ *
+ * Note: most commands use the "universal command" feature of the
+ * programmer in a "pass through" mode, exceptions are "program
+ * enable", "paged read", and "paged write".
+ *
+ */
+
+#include "ac_cfg.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "avr.h"
+#include "pgm.h"
+#include "stk500_private.h"	// temp until all code converted
+#include "stk500v2_private.h"
+#include "serial.h"
+
+#define STK500V2_XTAL 7372800U
+
+#if 0
+#define DEBUG(format,args...) fprintf(stderr, format, ## args)
+#else
+#define DEBUG(format,args...)
+#endif
+
+#if 0
+#define DEBUGRECV(format,args...) fprintf(stderr, format, ## args)
+#else
+#define DEBUGRECV(format,args...)
+#endif
+
+
+extern int    verbose;
+extern char * progname;
+extern int do_cycles;
+
+static unsigned char command_sequence = 1;
+
+
+static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value);
+static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value);
+static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p);
+static int stk500v2_is_page_empty(unsigned int address, int page_size,
+                                  const unsigned char *buf);
+
+
+static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
+{
+  unsigned char buf[275 + 6];		// max MESSAGE_BODY of 275 bytes, 6 bytes overhead
+  int i;
+
+  buf[0] = MESSAGE_START;
+  buf[1] = command_sequence;
+  buf[2] = len / 256;
+  buf[3] = len % 256;
+  buf[4] = TOKEN;
+  memcpy(buf+5, data, len);
+
+  // calculate the XOR checksum
+  buf[5+len] = 0;
+  for (i=0;i<5+len;i++)
+    buf[5+len] ^= buf[i];
+
+  DEBUG("STK500V2: stk500v2_send(");
+  for (i=0;i<len+6;i++) DEBUG("0x%02x ",buf[i]);
+  DEBUG(", %d)\n",len+6);
+
+  if (serial_send(pgm->fd, buf, len+6) != 0) {
+    fprintf(stderr,"%s: stk500_send(): failed to send command to serial port\n",progname);
+    exit(1);
+  }
+
+  return 0;
+}
+
+
+static int stk500v2_drain(PROGRAMMER * pgm, int display)
+{
+  return serial_drain(pgm->fd, display);
+}
+
+
+static int stk500v2_recv(PROGRAMMER * pgm, unsigned char msg[], size_t maxsize) {
+  enum states { sINIT, sSTART, sSEQNUM, sSIZE1, sSIZE2, sTOKEN, sDATA, sCSUM, sDONE }  state = sSTART;
+  int msglen = 0;
+  int curlen = 0;
+  int timeout = 0;
+  unsigned char c, checksum = 0;
+
+  long timeoutval = 5;		// seconds
+  struct timeval tv;
+  double tstart, tnow;
+
+  DEBUG("STK500V2: stk500v2_recv(): ");
+
+  gettimeofday(&tv, NULL);
+  tstart = tv.tv_sec;
+
+  while ( (state != sDONE ) && (!timeout) ) {
+    serial_recv(pgm->fd, &c, 1);
+    DEBUG("0x%02x ",c);
+    checksum ^= c;
+
+    switch (state) {
+      case sSTART:
+        DEBUGRECV("hoping for start token...");
+        if (c == MESSAGE_START) {
+          DEBUGRECV("got it\n");
+          checksum = MESSAGE_START;
+          state = sSEQNUM;
+        } else
+          DEBUGRECV("sorry\n");
+        break;
+      case sSEQNUM:
+        DEBUGRECV("hoping for sequence...\n");
+        if (c == command_sequence) {
+          DEBUGRECV("got it, incrementing\n");
+          state = sSIZE1;
+          command_sequence++;
+        } else {
+          DEBUGRECV("sorry\n");
+          state = sSTART;
+        }
+        break;
+      case sSIZE1:
+        DEBUGRECV("hoping for size LSB\n");
+        msglen = c*256;
+        state = sSIZE2;
+        break;
+      case sSIZE2:
+        DEBUGRECV("hoping for size MSB...");
+        msglen += c;
+        DEBUG(" msg is %d bytes\n",msglen);
+        state = sTOKEN;
+        break;
+      case sTOKEN:
+        if (c == TOKEN) state = sDATA;
+        else state = sSTART;
+        break;
+      case sDATA:
+        if (curlen < maxsize) {
+          msg[curlen] = c;
+        } else {
+          fprintf(stderr, "%s: stk500v2_recv(): buffer too small, received %d byte into %d byte buffer\n",
+                  progname,curlen,maxsize);
+          return -2;
+        }
+        if ((curlen == 0) && (msg[0] == ANSWER_CKSUM_ERROR)) {
+          fprintf(stderr, "%s: stk500v2_recv(): previous packet sent with wrong checksum\n",
+                  progname);
+          return -3;
+        }
+        curlen++;
+        if (curlen == msglen) state = sCSUM;
+        break;
+      case sCSUM:
+        if (checksum == 0) {
+          state = sDONE;
+        } else {
+          state = sSTART;
+          fprintf(stderr, "%s: stk500v2_recv(): checksum error\n",
+                  progname);
+          return -4;
+        }
+        break;
+      default:
+        fprintf(stderr, "%s: stk500v2_recv(): unknown state\n",
+                progname);
+        return -5;
+     } /* switch */
+
+     gettimeofday(&tv, NULL);
+     tnow = tv.tv_sec;
+     if (tnow-tstart > timeoutval) {			// wuff - signed/unsigned/overflow
+       fprintf(stderr, "%s: stk500_2_ReceiveMessage(): timeout\n",
+               progname);
+       return -1;
+     }
+
+  } /* while */
+  DEBUG("\n");
+
+  return msglen+6;
+}
+
+
+
+static int stk500v2_getsync(PROGRAMMER * pgm) {
+  int tries = 0;
+  unsigned char buf[1], resp[32];
+  int status;
+
+  DEBUG("STK500V2: stk500v2_getsync()\n");
+
+retry:
+  tries++;
+
+  // send the sync command and see if we can get there
+  buf[0] = CMD_SIGN_ON;
+  stk500v2_send(pgm, buf, 1);
+
+  // try to get the response back and see where we got
+  status = stk500v2_recv(pgm, resp, sizeof(resp));
+
+  // if we got bytes returned, check to see what came back
+  if (status > 0) {
+    if (resp[0] == STATUS_CMD_OK) {
+      // success!
+      return 0;
+    } else {
+      if (tries > 33) {
+        fprintf(stderr,
+                "%s: stk500v2_getsync(): can't communicate with device: resp=0x%02x\n",
+                progname, resp[0]);
+        return -6;
+      } else
+        goto retry;
+    }
+
+  // or if we got a timeout
+  } else if (status == -1) {
+    if (tries > 33) {
+      fprintf(stderr,"%s: stk500v2_getsync(): timeout communicating with programmer\n",
+              progname);
+      return -1;
+    } else
+      goto retry;
+
+  // or any other error
+  } else {
+    if (tries > 33) {
+      fprintf(stderr,"%s: stk500v2_getsync(): error communicating with programmer: (%d)\n",
+              progname,status);
+    } else
+      goto retry;
+  }
+
+  return 0;
+}
+
+static int stk500v2_command(PROGRAMMER * pgm, char * buf, size_t len, size_t maxlen) {
+  int i;
+  int tries = 0;
+  int status;
+
+  DEBUG("STK500V2: stk500v2_command(");
+  for (i=0;i<len;i++) DEBUG("0x%02hhx ",buf[i]);
+  DEBUG(", %d)\n",len);
+
+retry:
+  tries++;
+
+  // send the command to the programmer
+  stk500v2_send(pgm,buf,len);
+
+  // attempt to read the status back
+  status = stk500v2_recv(pgm,buf,maxlen);
+
+  // if we got a successful readback, return
+  if (status > 0) {
+    DEBUG(" = %d\n",status);
+    return status;
+  }
+
+  // otherwise try to sync up again
+  status = stk500v2_getsync(pgm);
+  if (status != 0) {
+    if (tries > 33) {
+      fprintf(stderr,"%s: stk500v2_command(): failed miserably to execute command 0x%02x\n",
+              progname,buf[0]);
+      return -1;
+    } else
+      goto retry;
+  }
+
+  DEBUG(" = 0\n");
+  return 0;
+}
+
+static int stk500v2_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
+                        unsigned char res[4])
+{
+  unsigned char buf[8];
+  int result;
+
+  DEBUG("STK500V2: stk500v2_cmd(%02x,%02x,%02x,%02x)\n",cmd[0],cmd[1],cmd[2],cmd[3]);
+
+  buf[0] = CMD_SPI_MULTI;
+  buf[1] = 4;
+  buf[2] = 4;
+  buf[3] = 0;
+  buf[4] = cmd[0];
+  buf[5] = cmd[1];
+  buf[6] = cmd[2];
+  buf[7] = cmd[3];
+
+  result = stk500v2_command(pgm, buf, 8, sizeof(buf));
+  if (buf[1] != STATUS_CMD_OK) {
+    fprintf(stderr, "%s: stk500v2_cmd(): failed to send command\n",
+            progname);
+    return -1;
+  }
+
+  res[0] = buf[2];
+  res[1] = buf[3];
+  res[2] = buf[4];
+  res[3] = buf[5];
+
+  return 0;
+}
+
+
+/*
+ * issue the 'chip erase' command to the AVR device
+ */
+static int stk500v2_chip_erase(PROGRAMMER * pgm, AVRPART * p)
+{
+  int result;
+  unsigned char buf[16];
+
+  if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
+    fprintf(stderr, "%s: stk500v2_chip_erase: chip erase instruction not defined for part \"%s\"\n",
+            progname, p->desc);
+    return -1;
+  }
+
+  pgm->pgm_led(pgm, ON);
+
+  buf[0] = CMD_CHIP_ERASE_ISP;
+  buf[1] = p->chip_erase_delay / 1000;
+  buf[2] = 0;	// use delay (?)
+  avr_set_bits(p->op[AVR_OP_CHIP_ERASE], buf+3);
+  result = stk500v2_command(pgm, buf, 7, sizeof(buf));
+  usleep(p->chip_erase_delay);
+  pgm->initialize(pgm, p);
+
+  pgm->pgm_led(pgm, OFF);
+
+  return result;
+}
+
+/*
+ * issue the 'program enable' command to the AVR device
+ */
+static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p)
+{
+  unsigned char buf[16];
+
+  if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
+    fprintf(stderr, "%s: stk500v2_program_enable(): program enable instruction not defined for part \"%s\"\n",
+            progname, p->desc);
+    return -1;
+  }
+
+  buf[0] = CMD_ENTER_PROGMODE_ISP;
+  buf[1] = p->timeout;
+  buf[2] = p->stabdelay;
+  buf[3] = p->cmdexedelay;
+  buf[4] = p->synchloops;
+  buf[5] = p->bytedelay;
+  buf[6] = p->pollvalue;
+  buf[7] = p->pollindex;
+  avr_set_bits(p->op[AVR_OP_PGM_ENABLE], buf+8);
+
+  return stk500v2_command(pgm, buf, 12, sizeof(buf));
+}
+
+
+
+/*
+ * initialize the AVR device and prepare it to accept commands
+ */
+static int stk500v2_initialize(PROGRAMMER * pgm, AVRPART * p)
+{
+  return pgm->program_enable(pgm, p);
+}
+
+
+static void stk500v2_disable(PROGRAMMER * pgm)
+{
+  unsigned char buf[16];
+  int result;
+
+  buf[0] = CMD_LEAVE_PROGMODE_ISP;
+  buf[1] = 1; // preDelay;
+  buf[2] = 1; // postDelay;
+
+  result = stk500v2_command(pgm, buf, 3, sizeof(buf));
+
+  if (buf[1] != STATUS_CMD_OK) {
+    fprintf(stderr, "%s: stk500v2_disable(): failed to leave programming mode, got 0x%02x\n",
+            progname,buf[1]);
+    exit(1);
+  }
+
+  return;
+}
+
+static void stk500v2_enable(PROGRAMMER * pgm)
+{
+  return;
+}
+
+
+static int stk500v2_open(PROGRAMMER * pgm, char * port)
+{
+  DEBUG("STK500V2: stk500v2_open()\n");
+
+  strcpy(pgm->port, port);
+  if (pgm->baudrate)
+    pgm->fd = serial_open(port, pgm->baudrate);
+  else
+    pgm->fd = serial_open(port, 115200);
+
+  /*
+   * drain any extraneous input
+   */
+  stk500v2_drain(pgm, 0);
+
+  stk500v2_getsync(pgm);
+
+  stk500v2_drain(pgm, 0);
+
+  return 0;
+}
+
+
+static void stk500v2_close(PROGRAMMER * pgm)
+{
+  DEBUG("STK500V2: stk500v2_close()\n");
+
+  serial_close(pgm->fd);
+  pgm->fd = -1;
+}
+
+
+static int stk500v2_loadaddr(PROGRAMMER * pgm, unsigned int addr)
+{
+  unsigned char buf[16];
+  int result;
+
+  DEBUG("STK500V2: stk500v2_loadaddr(%d)\n",addr);
+
+  buf[0] = CMD_LOAD_ADDRESS;
+  buf[1] = (addr >> 24) & 0xff;
+  buf[2] = (addr >> 16) & 0xff;
+  buf[3] = (addr >> 8) & 0xff;
+  buf[4] = addr & 0xff;
+
+  result = stk500v2_command(pgm, buf, 5, sizeof(buf));
+
+  if (buf[1] != STATUS_CMD_OK) {
+    fprintf(stderr, "%s: stk500v2_loadaddr(): failed to set load address, got 0x%02x\n",
+            progname,buf[1]);
+    return -1;
+  }
+
+  return 0;
+}
+
+
+static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, 
+                              int page_size, int n_bytes)
+{
+  int addr, block_size;
+  unsigned char commandbuf[10];
+  unsigned char buf[266];
+  unsigned char cmds[4];
+  int result;
+
+  DEBUG("STK500V2: stk500v2_paged_write(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
+
+  if (page_size == 0) page_size = 256;
+
+  // determine which command is to be used
+  if (strcmp(m->desc, "flash") == 0) {
+    commandbuf[0] = CMD_PROGRAM_FLASH_ISP;
+  } else if (strcmp(m->desc, "eeprom") == 0) {
+    commandbuf[0] = CMD_PROGRAM_EEPROM_ISP;
+  }
+  commandbuf[4] = m->delay;
+
+  // if the memory is paged, load the appropriate commands into the buffer
+  if (m->mode & 0x01) {
+    commandbuf[3] = m->mode | 0x80;		// yes, write the stupid page to flash
+
+    if (m->op[AVR_OP_LOADPAGE_LO] == NULL) {
+      fprintf(stderr, "%s: stk500v2_paged_write: loadpage instruction not defined for part \"%s\"\n",
+              progname, p->desc);
+      return -1;
+    }
+    avr_set_bits(m->op[AVR_OP_LOADPAGE_LO], cmds);
+    commandbuf[5] = cmds[0];
+
+    if (m->op[AVR_OP_WRITEPAGE] == NULL) {
+      fprintf(stderr, "%s: stk500v2_paged_write: write page instruction not defined for part \"%s\"\n",
+              progname, p->desc);
+      return -1;
+    }
+    avr_set_bits(m->op[AVR_OP_WRITEPAGE], cmds);
+    commandbuf[6] = cmds[0];
+
+  // otherwise, we need to load different commands in
+  } else {
+    commandbuf[3] = m->mode | 0x80;		// yes, write the stupid words to flash
+
+    if (m->op[AVR_OP_WRITE_LO] == NULL) {
+      fprintf(stderr, "%s: stk500v2_paged_write: write instruction not defined for part \"%s\"\n",
+              progname, p->desc);
+      return -1;
+    }
+    avr_set_bits(m->op[AVR_OP_WRITE_LO], cmds);
+    commandbuf[6] = cmds[0];
+  }
+
+  // the read command is common to both methods
+  if (m->op[AVR_OP_READ_LO] == NULL) {
+    fprintf(stderr, "%s: stk500v2_paged_write: read instruction not defined for part \"%s\"\n",
+            progname, p->desc);
+    return -1;
+  }
+  avr_set_bits(m->op[AVR_OP_READ_LO], cmds);
+  commandbuf[7] = cmds[0];
+
+  commandbuf[8] = m->readback[0];
+  commandbuf[9] = m->readback[1];
+
+  stk500v2_loadaddr(pgm, 0);
+
+  for (addr=0; addr < n_bytes; addr += page_size) {
+    report_progress(addr,n_bytes,NULL);
+
+    if ((n_bytes-addr) < page_size)
+      block_size = n_bytes - addr;
+    else
+      block_size = page_size;
+    DEBUG("block_size at addr %d is %d\n",addr,block_size);
+
+    memcpy(buf,commandbuf,sizeof(commandbuf));
+
+    buf[1] = block_size >> 8;
+    buf[2] = block_size & 0xff;
+
+    memcpy(buf+10,m->buf+addr, block_size);
+
+    result = stk500v2_command(pgm,buf,block_size+10, sizeof(buf));
+    if (buf[1] != STATUS_CMD_OK) {
+      fprintf(stderr,"%s: stk500v2_paged_write: write command failed with %d\n",
+              progname,buf[1]);
+      return -1;
+    }
+  }
+
+  return n_bytes;
+}
+
+static int stk500v2_is_page_empty(unsigned int address, int page_size,
+                                const unsigned char *buf)
+{
+    int i;
+    for(i = 0; i < page_size; i++) {
+        if(buf[address + i] != 0xFF) {
+            /* Page is not empty. */
+            return(0);
+        }
+    }
+
+    /* Page is empty. */
+    return(1);
+}
+
+static int stk500v2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
+                             int page_size, int n_bytes)
+{
+  int addr, block_size;
+  unsigned char commandbuf[4];
+  unsigned char buf[275];	// max buffer size for stk500v2 at this point
+  unsigned char cmds[4];
+  int result, i;
+
+  DEBUG("STK500V2: stk500v2_paged_load(..,%s,%d,%d)\n",m->desc,page_size,n_bytes);
+
+  page_size = m->readsize;
+
+  // determine which command is to be used
+  if (strcmp(m->desc, "flash") == 0) {
+    commandbuf[0] = CMD_READ_FLASH_ISP;
+  } else if (strcmp(m->desc, "eeprom") == 0) {
+    commandbuf[0] = CMD_READ_EEPROM_ISP;
+  }
+
+  // the read command is common to both methods
+  if (m->op[AVR_OP_READ_LO] == NULL) {
+    fprintf(stderr, "%s: stk500v2_paged_write: read instruction not defined for part \"%s\"\n",
+            progname, p->desc);
+    return -1;
+  }
+  avr_set_bits(m->op[AVR_OP_READ_LO], cmds);
+  commandbuf[3] = cmds[0];
+
+  stk500v2_loadaddr(pgm, 0);
+
+  for (addr=0; addr < n_bytes; addr += page_size) {
+    report_progress(addr, n_bytes,NULL);
+
+    if ((n_bytes-addr) < page_size)
+      block_size = n_bytes - addr;
+    else
+      block_size = page_size;
+    DEBUG("block_size at addr %d is %d\n",addr,block_size);
+
+    memcpy(buf,commandbuf,sizeof(commandbuf));
+
+    buf[1] = block_size >> 8;
+    buf[2] = block_size & 0xff;
+
+    result = stk500v2_command(pgm,buf,4,sizeof(buf));
+    if (buf[1] != STATUS_CMD_OK) {
+      fprintf(stderr,"%s: stk500v2_paged_write: read command failed with %d\n",
+              progname,buf[1]);
+      return -1;
+    }
+#if 0
+    for (i=0;i<page_size;i++) {
+      fprintf(stderr,"%02X",buf[2+i]);
+      if (i%16 == 15) fprintf(stderr,"\n");
+    }
+#endif
+
+    memcpy(&m->buf[addr], &buf[2], block_size);
+  }
+
+  return 0;
+}
+
+
+static int stk500v2_set_vtarget(PROGRAMMER * pgm, double v)
+{
+  unsigned char uaref, utarg;
+
+  utarg = (unsigned)((v + 0.049) * 10);
+
+  if (stk500v2_getparm(pgm, PARAM_VADJUST, &uaref) != 0) {
+    fprintf(stderr,
+	    "%s: stk500v2_set_vtarget(): cannot obtain V[aref]\n",
+	    progname);
+    return -1;
+  }
+
+  if (uaref > utarg) {
+    fprintf(stderr,
+	    "%s: stk500v2_set_vtarget(): reducing V[aref] from %.1f to %.1f\n",
+	    progname, uaref / 10.0, v);
+    if (stk500v2_setparm(pgm, PARAM_VADJUST, utarg)
+	!= 0)
+      return -1;
+  }
+  return stk500v2_setparm(pgm, PARAM_VTARGET, utarg);
+}
+
+
+static int stk500v2_set_varef(PROGRAMMER * pgm, double v)
+{
+  unsigned char uaref, utarg;
+
+  uaref = (unsigned)((v + 0.049) * 10);
+
+  if (stk500v2_getparm(pgm, PARAM_VTARGET, &utarg) != 0) {
+    fprintf(stderr,
+	    "%s: stk500v2_set_varef(): cannot obtain V[target]\n",
+	    progname);
+    return -1;
+  }
+
+  if (uaref > utarg) {
+    fprintf(stderr,
+	    "%s: stk500v2_set_varef(): V[aref] must not be greater than "
+	    "V[target] = %.1f\n",
+	    progname, utarg / 10.0);
+    return -1;
+  }
+  return stk500v2_setparm(pgm, PARAM_VADJUST, uaref);
+}
+
+
+static int stk500v2_set_fosc(PROGRAMMER * pgm, double v)
+{
+  int fosc;
+  unsigned char prescale, cmatch;
+  static unsigned ps[] = {
+    1, 8, 32, 64, 128, 256, 1024
+  };
+  int idx, rc;
+
+  prescale = cmatch = 0;
+  if (v > 0.0) {
+    if (v > STK500V2_XTAL / 2) {
+      const char *unit;
+      if (v > 1e6) {
+        v /= 1e6;
+        unit = "MHz";
+      } else if (v > 1e3) {
+        v /= 1e3;
+        unit = "kHz";
+      } else
+        unit = "Hz";
+      fprintf(stderr,
+          "%s: stk500v2_set_fosc(): f = %.3f %s too high, using %.3f MHz\n",
+          progname, v, unit, STK500V2_XTAL / 2e6);
+      fosc = STK500V2_XTAL / 2;
+    } else
+      fosc = (unsigned)v;
+
+    for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) {
+      if (fosc >= STK500V2_XTAL / (256 * ps[idx] * 2)) {
+        /* this prescaler value can handle our frequency */
+        prescale = idx + 1;
+        cmatch = (unsigned)(STK500V2_XTAL / (2 * fosc * ps[idx])) - 1;
+        break;
+      }
+    }
+    if (idx == sizeof(ps) / sizeof(ps[0])) {
+      fprintf(stderr, "%s: stk500v2_set_fosc(): f = %u Hz too low, %u Hz min\n",
+          progname, fosc, STK500V2_XTAL / (256 * 1024 * 2));
+      return -1;
+    }
+  }
+
+  if ((rc = stk500v2_setparm(pgm, PARAM_OSC_PSCALE, prescale)) != 0
+      || (rc = stk500v2_setparm(pgm, PARAM_OSC_CMATCH, cmatch)) != 0)
+    return rc;
+
+  return 0;
+}
+
+
+/* This code assumes that each count of the SCK duration parameter
+   represents 8/f, where f is the clock frequency of the STK500V2 master
+   processors (not the target).  This number comes from Atmel
+   application note AVR061.  It appears that the STK500V2 bit bangs SCK.
+   For small duration values, the actual SCK width is larger than
+   expected.  As the duration value increases, the SCK width error
+   diminishes. */
+static int stk500v2_set_sck_period(PROGRAMMER * pgm, double v)
+{
+  unsigned char dur;
+  double min, max;
+
+  min = 8.0 / STK500V2_XTAL;
+  max = 255 * min;
+  dur = v / min + 0.5;
+
+  if (v < min) {
+      dur = 1;
+      fprintf(stderr,
+	      "%s: stk500v2_set_sck_period(): p = %.1f us too small, using %.1f us\n",
+	      progname, v / 1e-6, dur * min / 1e-6);
+  } else if (v > max) {
+      dur = 255;
+      fprintf(stderr,
+	      "%s: stk500v2_set_sck_period(): p = %.1f us too large, using %.1f us\n",
+	      progname, v / 1e-6, dur * min / 1e-6);
+  }
+
+  return stk500v2_setparm(pgm, PARAM_SCK_DURATION, dur);
+}
+
+
+static int stk500v2_getparm(PROGRAMMER * pgm, unsigned char parm, unsigned char * value)
+{
+  unsigned char buf[32];
+
+  buf[0] = CMD_GET_PARAMETER;
+  buf[1] = parm;
+
+  if (stk500v2_command(pgm, buf, 2, sizeof(buf)) < 0) {
+    fprintf(stderr,"%s: stk500v2_getparm(): failed to get parameter 0x%02x\n",
+            progname, parm);
+    return -1;
+  }
+
+  *value = buf[2];
+
+  return 0;
+}
+
+
+static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value)
+{
+  unsigned char buf[32];
+
+  buf[0] = CMD_SET_PARAMETER;
+  buf[1] = parm;
+  buf[2] = value;
+
+  if (stk500v2_command(pgm, buf, 3, sizeof(buf)) < 0) {
+    fprintf(stderr, "\n%s: stk500v2_setparm(): failed to set parameter 0x%02x\n",
+            progname, parm);
+    return -1;
+  }
+
+  return 0;
+}
+
+
+static void stk500v2_display(PROGRAMMER * pgm, char * p)
+{
+  unsigned char maj, min, hdw, topcard;
+  const char *topcard_name;
+
+  stk500v2_getparm(pgm, PARAM_HW_VER, &hdw);
+  stk500v2_getparm(pgm, PARAM_SW_MAJOR, &maj);
+  stk500v2_getparm(pgm, PARAM_SW_MINOR, &min);
+  stk500v2_getparm(pgm, PARAM_TOPCARD_DETECT, &topcard);
+
+  fprintf(stderr, "%sHardware Version: %d\n", p, hdw);
+  fprintf(stderr, "%sFirmware Version: %d.%d\n", p, maj, min);
+
+  if (1) {			// should check to see if it's a stk500 first
+    switch (topcard) {
+      case 0xAA: topcard_name = "STK501"; break;
+      case 0x55: topcard_name = "STK502"; break;
+      case 0xFA: topcard_name = "STK503"; break;
+      case 0xEE: topcard_name = "STK504"; break;
+      case 0xE4: topcard_name = "STK505"; break;
+      case 0xDD: topcard_name = "STK520"; break;
+      default: topcard_name = "Unknown"; break;
+    }
+    fprintf(stderr, "%sTopcard         : %s\n", p, topcard_name);
+  }
+  stk500v2_print_parms1(pgm, p);
+
+  return;
+}
+
+
+static void stk500v2_print_parms1(PROGRAMMER * pgm, char * p)
+{
+  unsigned char vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration;
+
+  stk500v2_getparm(pgm, PARAM_VTARGET, &vtarget);
+  stk500v2_getparm(pgm, PARAM_VADJUST, &vadjust);
+  stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale);
+  stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch);
+  stk500v2_getparm(pgm, PARAM_SCK_DURATION, &sck_duration);
+
+  fprintf(stderr, "%sVtarget         : %.1f V\n", p, vtarget / 10.0);
+  fprintf(stderr, "%sVaref           : %.1f V\n", p, vadjust / 10.0);
+  fprintf(stderr, "%sOscillator      : ", p);
+  if (osc_pscale == 0)
+    fprintf(stderr, "Off\n");
+  else {
+    int prescale = 1;
+    double f = STK500V2_XTAL / 2;
+    const char *unit;
+
+    switch (osc_pscale) {
+      case 2: prescale = 8; break;
+      case 3: prescale = 32; break;
+      case 4: prescale = 64; break;
+      case 5: prescale = 128; break;
+      case 6: prescale = 256; break;
+      case 7: prescale = 1024; break;
+    }
+    f /= prescale;
+    f /= (osc_cmatch + 1);
+    if (f > 1e6) {
+      f /= 1e6;
+      unit = "MHz";
+    } else if (f > 1e3) {
+      f /= 1000;
+      unit = "kHz";
+    } else
+      unit = "Hz";
+    fprintf(stderr, "%.3f %s\n", f, unit);
+  }
+  fprintf(stderr, "%sSCK period      : %.1f us\n", p,
+	  sck_duration * 8.0e6 / STK500V2_XTAL + 0.05);
+
+  return;
+}
+
+
+static void stk500v2_print_parms(PROGRAMMER * pgm)
+{
+  stk500v2_print_parms1(pgm, "");
+}
+
+
+void stk500v2_initpgm(PROGRAMMER * pgm)
+{
+  strcpy(pgm->type, "STK500V2");
+
+  /*
+   * mandatory functions
+   */
+  pgm->initialize     = stk500v2_initialize;
+  pgm->display        = stk500v2_display;
+  pgm->enable         = stk500v2_enable;
+  pgm->disable        = stk500v2_disable;
+  pgm->program_enable = stk500v2_program_enable;
+  pgm->chip_erase     = stk500v2_chip_erase;
+  pgm->cmd            = stk500v2_cmd;
+  pgm->open           = stk500v2_open;
+  pgm->close          = stk500v2_close;
+
+  /*
+   * optional functions
+   */
+  pgm->paged_write    = stk500v2_paged_write;
+  pgm->paged_load     = stk500v2_paged_load;
+  pgm->print_parms    = stk500v2_print_parms;
+  pgm->set_vtarget    = stk500v2_set_vtarget;
+  pgm->set_varef      = stk500v2_set_varef;
+  pgm->set_fosc       = stk500v2_set_fosc;
+  pgm->set_sck_period = stk500v2_set_sck_period;
+  pgm->page_size      = 256;
+}
diff --git a/avrdude/stk500v2.h b/avrdude/stk500v2.h
new file mode 100644
index 00000000..715136a0
--- /dev/null
+++ b/avrdude/stk500v2.h
@@ -0,0 +1,29 @@
+/*
+ * avrdude - A Downloader/Uploader for AVR device programmers
+ * Copyright (C) 2002-2005  Brian S. Dean <bsd@bsdhome.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* $Id$ */
+
+#ifndef stk500v2_h__
+#define stk500v2_h__
+
+void stk500v2_initpgm (PROGRAMMER * pgm);
+
+#endif
+
+
diff --git a/avrdude/stk500v2_private.h b/avrdude/stk500v2_private.h
new file mode 100644
index 00000000..69eb7edf
--- /dev/null
+++ b/avrdude/stk500v2_private.h
@@ -0,0 +1,134 @@
+//**** ATMEL AVR - A P P L I C A T I O N   N O T E  ************************
+//*
+//* Title:		AVR068 - STK500 Communication Protocol
+//* Filename:		command.h
+//* Version:		1.0
+//* Last updated:	10.01.2005
+//*
+//* Support E-mail:	avr@atmel.com
+//*
+//**************************************************************************
+
+// *****************[ STK message constants ]***************************
+
+#define MESSAGE_START                       0x1B        //= ESC = 27 decimal
+#define TOKEN                               0x0E
+
+// *****************[ STK general command constants ]**************************
+
+#define CMD_SIGN_ON                         0x01
+#define CMD_SET_PARAMETER                   0x02
+#define CMD_GET_PARAMETER                   0x03
+#define CMD_SET_DEVICE_PARAMETERS           0x04
+#define CMD_OSCCAL                          0x05
+#define CMD_LOAD_ADDRESS                    0x06
+#define CMD_FIRMWARE_UPGRADE                0x07
+
+
+// *****************[ STK ISP command constants ]******************************
+
+#define CMD_ENTER_PROGMODE_ISP              0x10
+#define CMD_LEAVE_PROGMODE_ISP              0x11
+#define CMD_CHIP_ERASE_ISP                  0x12
+#define CMD_PROGRAM_FLASH_ISP               0x13
+#define CMD_READ_FLASH_ISP                  0x14
+#define CMD_PROGRAM_EEPROM_ISP              0x15
+#define CMD_READ_EEPROM_ISP                 0x16
+#define CMD_PROGRAM_FUSE_ISP                0x17
+#define CMD_READ_FUSE_ISP                   0x18
+#define CMD_PROGRAM_LOCK_ISP                0x19
+#define CMD_READ_LOCK_ISP                   0x1A
+#define CMD_READ_SIGNATURE_ISP              0x1B
+#define CMD_READ_OSCCAL_ISP                 0x1C
+#define CMD_SPI_MULTI                       0x1D
+
+// *****************[ STK PP command constants ]*******************************
+
+#define CMD_ENTER_PROGMODE_PP               0x20
+#define CMD_LEAVE_PROGMODE_PP               0x21
+#define CMD_CHIP_ERASE_PP                   0x22
+#define CMD_PROGRAM_FLASH_PP                0x23
+#define CMD_READ_FLASH_PP                   0x24
+#define CMD_PROGRAM_EEPROM_PP               0x25
+#define CMD_READ_EEPROM_PP                  0x26
+#define CMD_PROGRAM_FUSE_PP                 0x27
+#define CMD_READ_FUSE_PP                    0x28
+#define CMD_PROGRAM_LOCK_PP                 0x29
+#define CMD_READ_LOCK_PP                    0x2A
+#define CMD_READ_SIGNATURE_PP               0x2B
+#define CMD_READ_OSCCAL_PP                  0x2C
+
+#define CMD_SET_CONTROL_STACK               0x2D
+
+// *****************[ STK HVSP command constants ]*****************************
+
+#define CMD_ENTER_PROGMODE_HVSP             0x30
+#define CMD_LEAVE_PROGMODE_HVSP             0x31
+#define CMD_CHIP_ERASE_HVSP                 0x32
+#define CMD_PROGRAM_FLASH_HVSP              0x33
+#define CMD_READ_FLASH_HVSP                 0x34
+#define CMD_PROGRAM_EEPROM_HVSP             0x35
+#define CMD_READ_EEPROM_HVSP                0x36
+#define CMD_PROGRAM_FUSE_HVSP               0x37
+#define CMD_READ_FUSE_HVSP                  0x38
+#define CMD_PROGRAM_LOCK_HVSP               0x39
+#define CMD_READ_LOCK_HVSP                  0x3A
+#define CMD_READ_SIGNATURE_HVSP             0x3B
+#define CMD_READ_OSCCAL_HVSP                0x3C
+
+// *****************[ STK test command constants ]***************************
+
+#define CMD_ENTER_TESTMODE                  0x60
+#define CMD_LEAVE_TESTMODE                  0x61
+#define CMD_CHIP_WRITE                      0x62
+#define CMD_PROGRAM_FLASH_PARTIAL           0x63
+#define CMD_PROGRAM_EEPROM_PARTIAL          0x64
+#define CMD_PROGRAM_SIGNATURE_ROW           0x65
+#define CMD_READ_FLASH_MARGIN               0x66
+#define CMD_READ_EEPROM_MARGIN              0x67
+#define CMD_READ_SIGNATURE_ROW_MARGIN       0x68
+#define CMD_PROGRAM_TEST_FUSE               0x69
+#define CMD_READ_TEST_FUSE                  0x6A
+#define CMD_PROGRAM_HIDDEN_FUSE_LOW         0x6B
+#define CMD_READ_HIDDEN_FUSE_LOW            0x6C
+#define CMD_PROGRAM_HIDDEN_FUSE_HIGH        0x6D
+#define CMD_READ_HIDDEN_FUSE_HIGH           0x6E
+#define CMD_PROGRAM_HIDDEN_FUSE_EXT         0x6F
+#define CMD_READ_HIDDEN_FUSE_EXT            0x70
+
+// *****************[ STK status constants ]***************************
+
+// Success
+#define STATUS_CMD_OK                       0x00
+
+// Warnings
+#define STATUS_CMD_TOUT                     0x80
+#define STATUS_RDY_BSY_TOUT                 0x81
+#define STATUS_SET_PARAM_MISSING            0x82
+
+// Errors
+#define STATUS_CMD_FAILED                   0xC0
+#define STATUS_CKSUM_ERROR                  0xC1
+#define STATUS_CMD_UNKNOWN                  0xC9
+
+// *****************[ STK parameter constants ]***************************
+#define PARAM_BUILD_NUMBER_LOW              0x80
+#define PARAM_BUILD_NUMBER_HIGH             0x81
+#define PARAM_HW_VER                        0x90
+#define PARAM_SW_MAJOR                      0x91
+#define PARAM_SW_MINOR                      0x92
+#define PARAM_VTARGET                       0x94
+#define PARAM_VADJUST                       0x95
+#define PARAM_OSC_PSCALE                    0x96
+#define PARAM_OSC_CMATCH                    0x97
+#define PARAM_SCK_DURATION                  0x98
+#define PARAM_TOPCARD_DETECT                0x9A
+#define PARAM_STATUS                        0x9C
+#define PARAM_DATA                          0x9D
+#define PARAM_RESET_POLARITY                0x9E
+#define PARAM_CONTROLLER_INIT               0x9F
+
+// *****************[ STK answer constants ]***************************
+
+#define ANSWER_CKSUM_ERROR                  0xB0
+