This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FYI/as-is: Patch to add support for atmel probe (avr).


From: Tristan Gingold <gingold@adacore.com>

Hello,

Below is a patch that Tristan wrote many months ago in order to allow
us to debug programs on AVR over the Atmel jtagice mkii probe.  There
were a couple of things that were interesting with this is patch:
  - A small layer to check for libusb - apparently a relatively
    portable API.
  - The code that uses libusb itself to talk to the probe over
    the usb port.

Unfortunately, Tristan never found the time to contribute this code,
and today, we no longer need it. I am sending it here, in case someone
else finds its useful.  It's been rebased to the current HEAD, but
is otherwise provided as is. I'm not even sure it compiles. But it was
known to work several months ago, and we did not make any change since
then.

-------------------------------------------------------------------

This patch adds support for the Atmel jtagice mkii probe - used by the avr.
As the probe is connected through USB, it adds an optionnal dependency to
libusb - which is a rather portable library.

FIXME: add documentation.

2011-01-25  Tristan Gingold  <gingold@adacore.com>

	* configure.ac: Check for libusb.
	* Makefile.in (LIBUSB): New variable.
	(CLIBS): Add LIBUSB.
	* configure: Regenerate.
	* config.in: Regenerate.
	* remote-atmel-mkii.c: New file.
	* configure.tgt: Add remote-atmel-mkii.c on avr.
---
 gdb/Makefile.in         |    5 +-
 gdb/config.in           |    3 +
 gdb/configure           |  498 +++++++++
 gdb/configure.ac        |   22 +
 gdb/configure.tgt       |    2 +-
 gdb/remote-atmel-mkii.c | 2722 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 3250 insertions(+), 2 deletions(-)
 create mode 100644 gdb/remote-atmel-mkii.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9f6f3a9..fa6847a 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -154,6 +154,9 @@ LIBEXPAT = @LIBEXPAT@
 # Where is lzma?  This will be empty if lzma was not available.
 LIBLZMA = @LIBLZMA@
 
+# Where is libusb?  This will be empty if expat was not available.
+LIBUSB = @LIBUSB@
+
 WARN_CFLAGS = @WARN_CFLAGS@
 WERROR_CFLAGS = @WERROR_CFLAGS@
 GDB_WARN_CFLAGS = $(WARN_CFLAGS)
@@ -472,7 +475,7 @@ INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(MH_LDFLAGS) $(LDFLAGS) $(CONFIG_
 # LIBIBERTY appears twice on purpose.
 CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \
 	$(XM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ @PYTHON_LIBS@ \
-	$(LIBEXPAT) $(LIBLZMA) \
+	$(LIBEXPAT) $(LIBLZMA) $(LIBUSB) \
 	$(LIBIBERTY) $(WIN32LIBS) $(LIBGNU)
 CDEPS = $(XM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \
 	$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU)
diff --git a/gdb/config.in b/gdb/config.in
index 9e21325..8b0dc3b 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -213,6 +213,9 @@
 /* Define to 1 if you have the <libunwind-ia64.h> header file. */
 #undef HAVE_LIBUNWIND_IA64_H
 
+/* Define if you have the usb library. */
+#undef HAVE_LIBUSB
+
 /* Define to 1 if you have the `w' library (-lw). */
 #undef HAVE_LIBW
 
diff --git a/gdb/configure b/gdb/configure
index fdfd17c..8089d78 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -653,6 +653,9 @@ TARGET_SYSTEM_ROOT
 CONFIG_LDFLAGS
 RDYNAMIC
 ALLOCA
+LTLIBUSB
+LIBUSB
+HAVE_LIBUSB
 PYTHON_LIBS
 PYTHON_CPPFLAGS
 PYTHON_CFLAGS
@@ -805,6 +808,8 @@ enable_rpath
 with_libexpat_prefix
 with_python
 enable_libmcheck
+with_libusb
+with_libusb_prefix
 with_included_regex
 with_sysroot
 with_system_gdbinit
@@ -1519,6 +1524,9 @@ Optional Packages:
   --without-libexpat-prefix     don't search for libexpat in includedir and libdir
   --with-python[=PYTHON]  include python support
                           (auto/yes/no/<python-program>)
+  --with-libusb           include libusb support (auto/yes/no)
+  --with-libusb-prefix[=DIR]  search for libusb in DIR/include and DIR/lib
+  --without-libusb-prefix     don't search for libusb in includedir and libdir
   --without-included-regex
                           don't use included regex; this is the default on
                           systems with version 2 of the GNU C library (use
@@ -8609,6 +8617,496 @@ fi
 
 fi
 
+
+# Check whether --with-libusb was given.
+if test "${with_libusb+set}" = set; then :
+  withval=$with_libusb;
+else
+  with_libusb=auto
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libusb" >&5
+$as_echo_n "checking whether to use libusb... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_libusb" >&5
+$as_echo "$with_libusb" >&6; }
+
+if test "${with_libusb}" = no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libusb support disabled; some features may be unavailable." >&5
+$as_echo "$as_me: WARNING: libusb support disabled; some features may be unavailable." >&2;}
+  HAVE_LIBUSB=no
+else
+
+
+
+
+
+
+
+
+    use_additional=yes
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+    eval additional_includedir=\"$includedir\"
+    eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+
+# Check whether --with-libusb-prefix was given.
+if test "${with_libusb_prefix+set}" = set; then :
+  withval=$with_libusb_prefix;
+    if test "X$withval" = "Xno"; then
+      use_additional=no
+    else
+      if test "X$withval" = "X"; then
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+
+          eval additional_includedir=\"$includedir\"
+          eval additional_libdir=\"$libdir\"
+
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      else
+        additional_includedir="$withval/include"
+        additional_libdir="$withval/lib"
+      fi
+    fi
+
+fi
+
+      LIBUSB=
+  LTLIBUSB=
+  INCUSB=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='usb '
+  while test -n "$names_next_round"; do
+    names_this_round="$names_next_round"
+    names_next_round=
+    for name in $names_this_round; do
+      already_handled=
+      for n in $names_already_handled; do
+        if test "$n" = "$name"; then
+          already_handled=yes
+          break
+        fi
+      done
+      if test -z "$already_handled"; then
+        names_already_handled="$names_already_handled $name"
+                        uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+        eval value=\"\$HAVE_LIB$uppername\"
+        if test -n "$value"; then
+          if test "$value" = yes; then
+            eval value=\"\$LIB$uppername\"
+            test -z "$value" || LIBUSB="${LIBUSB}${LIBUSB:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIBUSB="${LTLIBUSB}${LTLIBUSB:+ }$value"
+          else
+                                    :
+          fi
+        else
+                              found_dir=
+          found_la=
+          found_so=
+          found_a=
+          if test $use_additional = yes; then
+            if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
+              found_dir="$additional_libdir"
+              found_so="$additional_libdir/lib$name.$shlibext"
+              if test -f "$additional_libdir/lib$name.la"; then
+                found_la="$additional_libdir/lib$name.la"
+              fi
+            else
+              if test -f "$additional_libdir/lib$name.$libext"; then
+                found_dir="$additional_libdir"
+                found_a="$additional_libdir/lib$name.$libext"
+                if test -f "$additional_libdir/lib$name.la"; then
+                  found_la="$additional_libdir/lib$name.la"
+                fi
+              fi
+            fi
+          fi
+          if test "X$found_dir" = "X"; then
+            for x in $LDFLAGS $LTLIBUSB; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+              case "$x" in
+                -L*)
+                  dir=`echo "X$x" | sed -e 's/^X-L//'`
+                  if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
+                    found_dir="$dir"
+                    found_so="$dir/lib$name.$shlibext"
+                    if test -f "$dir/lib$name.la"; then
+                      found_la="$dir/lib$name.la"
+                    fi
+                  else
+                    if test -f "$dir/lib$name.$libext"; then
+                      found_dir="$dir"
+                      found_a="$dir/lib$name.$libext"
+                      if test -f "$dir/lib$name.la"; then
+                        found_la="$dir/lib$name.la"
+                      fi
+                    fi
+                  fi
+                  ;;
+              esac
+              if test "X$found_dir" != "X"; then
+                break
+              fi
+            done
+          fi
+          if test "X$found_dir" != "X"; then
+                        LTLIBUSB="${LTLIBUSB}${LTLIBUSB:+ }-L$found_dir -l$name"
+            if test "X$found_so" != "X"; then
+                                                        if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
+                                LIBUSB="${LIBUSB}${LIBUSB:+ }$found_so"
+              else
+                                                                                haveit=
+                for x in $ltrpathdirs; do
+                  if test "X$x" = "X$found_dir"; then
+                    haveit=yes
+                    break
+                  fi
+                done
+                if test -z "$haveit"; then
+                  ltrpathdirs="$ltrpathdirs $found_dir"
+                fi
+                                if test "$hardcode_direct" = yes; then
+                                                      LIBUSB="${LIBUSB}${LIBUSB:+ }$found_so"
+                else
+                  if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+                                                            LIBUSB="${LIBUSB}${LIBUSB:+ }$found_so"
+                                                            haveit=
+                    for x in $rpathdirs; do
+                      if test "X$x" = "X$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      rpathdirs="$rpathdirs $found_dir"
+                    fi
+                  else
+                                                                                haveit=
+                    for x in $LDFLAGS $LIBUSB; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                      if test "X$x" = "X-L$found_dir"; then
+                        haveit=yes
+                        break
+                      fi
+                    done
+                    if test -z "$haveit"; then
+                      LIBUSB="${LIBUSB}${LIBUSB:+ }-L$found_dir"
+                    fi
+                    if test "$hardcode_minus_L" != no; then
+                                                                                        LIBUSB="${LIBUSB}${LIBUSB:+ }$found_so"
+                    else
+                                                                                                                                                                                LIBUSB="${LIBUSB}${LIBUSB:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                                LIBUSB="${LIBUSB}${LIBUSB:+ }$found_a"
+              else
+                                                LIBUSB="${LIBUSB}${LIBUSB:+ }-L$found_dir -l$name"
+              fi
+            fi
+                        additional_includedir=
+            case "$found_dir" in
+              */lib | */lib/)
+                basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+                additional_includedir="$basedir/include"
+                ;;
+            esac
+            if test "X$additional_includedir" != "X"; then
+                                                                                                                if test "X$additional_includedir" != "X/usr/include"; then
+                haveit=
+                if test "X$additional_includedir" = "X/usr/local/include"; then
+                  if test -n "$GCC"; then
+                    case $host_os in
+                      linux*) haveit=yes;;
+                    esac
+                  fi
+                fi
+                if test -z "$haveit"; then
+                  for x in $CPPFLAGS $INCUSB; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                    if test "X$x" = "X-I$additional_includedir"; then
+                      haveit=yes
+                      break
+                    fi
+                  done
+                  if test -z "$haveit"; then
+                    if test -d "$additional_includedir"; then
+                                            INCUSB="${INCUSB}${INCUSB:+ }-I$additional_includedir"
+                    fi
+                  fi
+                fi
+              fi
+            fi
+                        if test -n "$found_la"; then
+                                                        save_libdir="$libdir"
+              case "$found_la" in
+                */* | *\\*) . "$found_la" ;;
+                *) . "./$found_la" ;;
+              esac
+              libdir="$save_libdir"
+                            for dep in $dependency_libs; do
+                case "$dep" in
+                  -L*)
+                    additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+                                                                                                                                                                if test "X$additional_libdir" != "X/usr/lib"; then
+                      haveit=
+                      if test "X$additional_libdir" = "X/usr/local/lib"; then
+                        if test -n "$GCC"; then
+                          case $host_os in
+                            linux*) haveit=yes;;
+                          esac
+                        fi
+                      fi
+                      if test -z "$haveit"; then
+                        haveit=
+                        for x in $LDFLAGS $LIBUSB; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LIBUSB="${LIBUSB}${LIBUSB:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIBUSB; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+                          if test "X$x" = "X-L$additional_libdir"; then
+                            haveit=yes
+                            break
+                          fi
+                        done
+                        if test -z "$haveit"; then
+                          if test -d "$additional_libdir"; then
+                                                        LTLIBUSB="${LTLIBUSB}${LTLIBUSB:+ }-L$additional_libdir"
+                          fi
+                        fi
+                      fi
+                    fi
+                    ;;
+                  -R*)
+                    dir=`echo "X$dep" | sed -e 's/^X-R//'`
+                    if test "$enable_rpath" != no; then
+                                                                  haveit=
+                      for x in $rpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        rpathdirs="$rpathdirs $dir"
+                      fi
+                                                                  haveit=
+                      for x in $ltrpathdirs; do
+                        if test "X$x" = "X$dir"; then
+                          haveit=yes
+                          break
+                        fi
+                      done
+                      if test -z "$haveit"; then
+                        ltrpathdirs="$ltrpathdirs $dir"
+                      fi
+                    fi
+                    ;;
+                  -l*)
+                                        names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+                    ;;
+                  *.la)
+                                                                                names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+                    ;;
+                  *)
+                                        LIBUSB="${LIBUSB}${LIBUSB:+ }$dep"
+                    LTLIBUSB="${LTLIBUSB}${LTLIBUSB:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+                                                            LIBUSB="${LIBUSB}${LIBUSB:+ }-l$name"
+            LTLIBUSB="${LTLIBUSB}${LTLIBUSB:+ }-l$name"
+          fi
+        fi
+      fi
+    done
+  done
+  if test "X$rpathdirs" != "X"; then
+    if test -n "$hardcode_libdir_separator"; then
+                        alldirs=
+      for found_dir in $rpathdirs; do
+        alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+      done
+            acl_save_libdir="$libdir"
+      libdir="$alldirs"
+      eval flag=\"$hardcode_libdir_flag_spec\"
+      libdir="$acl_save_libdir"
+      LIBUSB="${LIBUSB}${LIBUSB:+ }$flag"
+    else
+            for found_dir in $rpathdirs; do
+        acl_save_libdir="$libdir"
+        libdir="$found_dir"
+        eval flag=\"$hardcode_libdir_flag_spec\"
+        libdir="$acl_save_libdir"
+        LIBUSB="${LIBUSB}${LIBUSB:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+            for found_dir in $ltrpathdirs; do
+      LTLIBUSB="${LTLIBUSB}${LTLIBUSB:+ }-R$found_dir"
+    done
+  fi
+
+
+        ac_save_CPPFLAGS="$CPPFLAGS"
+
+  for element in $INCUSB; do
+    haveit=
+    for x in $CPPFLAGS; do
+
+  acl_save_prefix="$prefix"
+  prefix="$acl_final_prefix"
+  acl_save_exec_prefix="$exec_prefix"
+  exec_prefix="$acl_final_exec_prefix"
+  eval x=\"$x\"
+  exec_prefix="$acl_save_exec_prefix"
+  prefix="$acl_save_prefix"
+
+      if test "X$x" = "X$element"; then
+        haveit=yes
+        break
+      fi
+    done
+    if test -z "$haveit"; then
+      CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+    fi
+  done
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libusb" >&5
+$as_echo_n "checking for libusb... " >&6; }
+if test "${ac_cv_libusb+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    ac_save_LIBS="$LIBS"
+    LIBS="$LIBS $LIBUSB"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "usb.h"
+int
+main ()
+{
+usb_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_libusb=yes
+else
+  ac_cv_libusb=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LIBS="$ac_save_LIBS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libusb" >&5
+$as_echo "$ac_cv_libusb" >&6; }
+  if test "$ac_cv_libusb" = yes; then
+    HAVE_LIBUSB=yes
+
+$as_echo "#define HAVE_LIBUSB 1" >>confdefs.h
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libusb" >&5
+$as_echo_n "checking how to link with libusb... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBUSB" >&5
+$as_echo "$LIBUSB" >&6; }
+  else
+    HAVE_LIBUSB=no
+            CPPFLAGS="$ac_save_CPPFLAGS"
+    LIBUSB=
+    LTLIBUSB=
+  fi
+
+
+
+
+
+
+  if test "$HAVE_LIBUSB" != yes; then
+    if test "$with_libusb" = yes; then
+      as_fn_error "libusb is missing or unusable" "$LINENO" 5
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libusb is missing or unusable; some features may be unavailable." >&5
+$as_echo "$as_me: WARNING: libusb is missing or unusable; some features may be unavailable." >&2;}
+    fi
+  fi
+fi
+
 # ------------------------- #
 # Checks for header files.  #
 # ------------------------- #
diff --git a/gdb/configure.ac b/gdb/configure.ac
index db52804..68c14e4 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1067,6 +1067,28 @@ if test "$ENABLE_LIBMCHECK" = "yes" ; then
   AC_CHECK_LIB(mcheck, main)
 fi
 
+dnl libusb
+AC_ARG_WITH(libusb,
+  AS_HELP_STRING([--with-libusb], [include libusb support (auto/yes/no)]),
+  [], [with_libusb=auto])
+AC_MSG_CHECKING([whether to use libusb])
+AC_MSG_RESULT([$with_libusb])
+
+if test "${with_libusb}" = no; then
+  AC_MSG_WARN([libusb support disabled; some features may be unavailable.])
+  HAVE_LIBUSB=no
+else
+  AC_LIB_HAVE_LINKFLAGS([usb], [], [#include "usb.h"],
+			[usb_init ();])
+  if test "$HAVE_LIBUSB" != yes; then
+    if test "$with_libusb" = yes; then
+      AC_MSG_ERROR([libusb is missing or unusable])
+    else
+      AC_MSG_WARN([libusb is missing or unusable; some features may be unavailable.])
+    fi
+  fi
+fi
+
 # ------------------------- #
 # Checks for header files.  #
 # ------------------------- #
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 36d4304..115c415 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -100,7 +100,7 @@ arm*-*-*)
 
 avr-*-*)
 	# Target: AVR
-	gdb_target_obs="avr-tdep.o"
+	gdb_target_obs="avr-tdep.o remote-atmel-mkii.o"
 	gdb_sim=../sim/avr/libsim.a
 	;;
 
diff --git a/gdb/remote-atmel-mkii.c b/gdb/remote-atmel-mkii.c
new file mode 100644
index 0000000..1259bbb
--- /dev/null
+++ b/gdb/remote-atmel-mkii.c
@@ -0,0 +1,2722 @@
+/* Remote debugging interface for Atmel JTAGICE mkII.
+
+   Copyright (C) 2009, 2010
+   Free Software Foundation, Inc.
+
+   Contributed by AdaCore.
+   Written by Tristan Gingold <gingold@adacore.com>
+
+   This file is part of GDB.
+
+   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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+/* Note: the protocol is fully described by the document AVR067 available
+   from Atmel web site.  */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "inferior.h"
+#include "target.h"
+#include "regcache.h"
+#include "xml-support.h"
+#include "completer.h"
+#include "readline/tilde.h"
+#include "gdbthread.h"
+
+#ifdef HAVE_LIBUSB
+
+#include <usb.h>
+
+/* Magic numbers used to identify the probe.  */
+#define ID_VENDOR_ATMEL   0x03eb
+#define ID_PRODUCT_MKII   0x2103
+#define ID_DEVICE_RELEASE 0x0200
+
+/* Endpoints.  */
+#define MKII_EP_WRITE 0x02
+#define MKII_EP_READ  0x82
+
+/* Memory type.  */
+#define MEMORY_TYPE_IO_SHADOW 0x30
+#define MEMORY_TYPE_SRAM 0x20
+#define MEMORY_TYPE_EEPROM 0x22
+#define MEMORY_TYPE_EVENT 0x60
+#define MEMORY_TYPE_SPM 0xA0
+#define MEMORY_TYPE_FLASH_PAGE 0xB0
+#define MEMORY_TYPE_EEPROM_PAGE 0xB1
+#define MEMORY_TYPE_FUSE_BITS 0xB2
+#define MEMORY_TYPE_LOCK_BITS 0xB3
+#define MEMORY_TYPE_SIGN_JTAG 0xB4
+#define MEMORY_TYPE_OSCCAL_BYTE 0xB5
+#define MEMORY_TYPE_CAN 0xB6
+
+#define MKII_WRITE_TIMEOUT 500
+#define MKII_READ_TIMEOUT 5000
+#define MKII_EVENT_TIMEOUT 200
+#define MKII_EVENT_SEQNUM 0xffff
+
+/* Max packet size.  Defined by USB.  */
+#define MKII_PKT_SIZE 64
+
+/* Packet header size: start(1) + seq(2) + len(4) + token(1).  */
+#define MKII_HDR_SIZE 8
+
+#define MKII_ESC      0x1b
+#define MKII_TOKEN    0x0e
+
+#define DEVICE_DESCRIPTOR_LEN 298
+
+/* JTAGICE commands.  */
+#define CMND_GET_SIGN_OFF  0x00
+#define CMND_GET_SIGN_ON   0x01
+#define CMND_SET_PARAMETER 0x02
+#define CMND_GET_PARAMETER 0x03
+#define CMND_WRITE_MEMORY  0x04
+#define CMND_READ_MEMORY   0x05
+#define CMND_WRITE_PC      0x06
+#define CMND_READ_PC       0x07
+#define CMND_GO            0x08
+#define CMND_SINGLE_STEP   0x09
+#define CMND_FORCED_STOP   0x0a
+#define CMND_RESET         0x0b
+#define CMND_SET_DEVICE_DESCRIPTOR 0x0c
+#define CMND_ERASEPAGE_SPM  0x0d
+#define CMND_GET_SYNC       0x0f
+#define CMND_SELFTEST       0x10
+#define CMND_SET_BREAK      0x11
+#define CMND_GET_BREAK      0x12
+#define CMND_CHIP_ERASE     0x13
+#define CMND_ENTER_PROGMODE 0x14
+#define CMND_LEAVE_PROGMODE 0x15
+#define CMND_CLR_BREAK      0x1a
+#define CMND_RESTORE_TARGET 0x23
+
+/* JTAGICE replies.  */
+#define RSP_SUCCESS(v) ((v) >= 0x80 && (v) <= 0x9f)
+#define RSP_OK 0x80
+#define RSP_PARAMETER 0x81
+#define RSP_MEMORY 0x82
+#define RSP_GET_BREAK 0x83
+#define RSP_PC 0x84
+#define RSP_SELFTEST 0x85
+#define RSP_SIGN_ON  0x86
+
+#define RSP_FAILURE(v) ((v) >= 0xa0 && (v) <= 0xbf)
+#define RSP_FAILED                0xa0
+#define RSP_ILLEGAL_PARAMETER     0xa1
+#define RSP_ILLEGAL_MEMORY_TYPE   0xa2
+#define RSP_ILLEGAL_MEMORY_RANGE  0xa3
+#define RSP_ILLEGAL_EMULATOR_MODE 0xa4
+
+/* JTAGICE events.  */
+#define EVT_BREAK            0xe0
+#define EVT_RUN              0xe1
+#define EVT_TARGET_POWER_ON  0xe4
+#define EVT_TARGET_POWER_OFF 0xe5
+#define EVT_DEBUG	     0xe6
+#define EVT_EXT_RESET	     0xe7
+#define EVT_TARGET_SLEEP     0xe8
+#define EVT_TARGET_WAKEUP    0xe9
+
+/* Argument of CMND_FORCED_STOP.  */
+#define FLAG_LOW_LEVEL 0x01
+#define FLAG_HIGH_LEVEL 0x02
+
+/* Argument of CMND_SINGLE_STEP.  */
+#define SINGLE_STEP_OVER 0x00
+#define SINGLE_STEP_INTO 0x01
+#define SINGLE_STEP_OUT 0x02
+
+/* Emulator parameters.  */
+#define PARAM_HARDWARE_VERSION 0x01
+#define PARAM_FW_VERSION 0x02
+#define PARAM_EMULATOR_MODE 0x03
+#define PARAM_IREG 0x04
+#define PARAM_BAUDRATE 0x05
+#define PARAM_OCD_VTARGET 0x06
+#define PARAM_OCD_JTAG_CLOCK 0x07
+#define PARAM_OCD_BREAK_CAUSE 0x08
+#define PARAM_TIMERS_RUNNNING 0x09
+#define PARAM_BREAK_ON_FLOW 0x0a
+#define PARAM_BREAK_ADDR1 0x0b
+#define PARAM_BREAK_ADDR2 0x0c
+#define PARAM_COMB_BREAK_CTRL 0x0d
+#define PARAM_JTAGID_STRING 0x0e
+#define PARAM_FLASH_PAGE_SIZE 0x14
+#define PARAM_EEPROM_PAGE_SIZE 0x15
+#define PARAM_TARGET_MCU_STATE 0x1a
+#define PARAM_DAISY_CHAIN_INFO 0x1b
+#define PARAM_BOOT_ADDRESS 0x1c
+#define PARAM_TARGET_SIGNATURE 0x1d
+#define PARAM_PACKET_PARSING_ERROR 0x40
+#define PARAM_VALID_PACKET_RECEIVED 0x41
+#define PARAM_COMM_TX_FAILURE 0x42
+#define PARAM_COMM_RX_FAILURE 0x43
+#define PARAM_CRC_ERRORS 0x44
+#define PARAM_POWER_SOURCE 0x45
+
+enum mkii_emulator_mode { MODE_DEBUGWIRE, MODE_JTAG, MODE_UNKNOWN, MODE_SPI };
+
+/* Device descriptor fields.  Extracted from AVR067 document, keeping
+   names.
+   This table is used to configure the probe so that it can manage the target.
+   Data is available from Atmel AVRStudio in XML format.  */
+struct device_descriptor_data
+{
+  unsigned char ucReadIO[8];           /* LSB = IOloc  0, MSB = IOloc63.  */
+  unsigned char ucReadIOShadow[8];     /* LSB = IOloc  0, MSB = IOloc63.  */
+  unsigned char ucWriteIO[8];          /* LSB = IOloc  0, MSB = IOloc63.  */
+  unsigned char ucWriteIOShadow[8];    /* LSB = IOloc  0, MSB = IOloc63.  */
+  unsigned char ucReadExtIO[52];       /* LSB = IOloc  96, MSB = IOloc511.  */
+  unsigned char ucReadIOExtShadow[52]; /* LSB = IOloc  96, MSB = IOloc511.  */
+  unsigned char ucWriteExtIO[52];      /* LSB = IOloc  96, MSB = IOloc511.  */
+  unsigned char ucWriteIOExtShadow[52];/* LSB = IOloc  96, MSB = IOloc511.  */
+  unsigned char ucIDRAddress[1];       /* IDR address.  */
+  unsigned char ucSPMCRAddress[1];     /* SPMCR address and dW BasePC.  */
+  unsigned char ucRAMPZAddress[1];     /* RAMPZ address in SRAM I/O space.  */
+  unsigned char uiFlashPageSize[2];    /* Log2 of device Flash page size.  */
+  unsigned char ucEepromPageSize[1];   /* Device Eeprom Page Size in bytes.  */
+  unsigned char ulBootAddress[4];      /* Device Boot Loader Start Address.  */
+  unsigned char uiUpperExtIOLoc[2];/* Topmost extended I/O loc (0 if none).  */
+  unsigned char ulFlashSize[4];   /* Device Flash Size.  */
+  unsigned char ucEepromInst[20]; /* Instructions for W/R EEPROM.  */
+  unsigned char ucFlashInst[3];   /* Instructions for W/R FLASH.  */
+  unsigned char ucSPHaddr[1];     /* Stack pointer high.  */
+  unsigned char ucSPLaddr[1];     /* Stack pointer low.  */
+  unsigned char uiFlashpages[2];  /* number of pages in flash.  */
+  unsigned char ucDWDRAddress[1]; /* DWDR register address.  */
+  unsigned char ucDWBasePC[1];    /* Base/mask value of the PC.  */
+  unsigned char ucAllowFullPageBitstream[1]; /* FALSE on ALL new parts.  */
+  unsigned char uiStartSmallestBootLoaderSection[2];
+  unsigned char EnablePageProgramming[1]; /* For JTAG parts, default 1.  */
+  unsigned char ucCacheType[1];   /* CacheType_Normal 0x00, CacheType_CAN 0x01,
+                                     CacheType_HEIMDALL 0x02.  */
+  unsigned char uiSramStartAddr[2];/* Start of SRAM.  */
+  unsigned char ucResetType[1];    /* Selects reset type. ResetNormal = 0x00
+                                      ResetAT76CXXX = 0x01.  */
+  unsigned char ucPCMaskExtended[1]; /* For parts with extended PC.  */
+  unsigned char ucPCMaskHigh[1];     /* PC high mask.  */
+  unsigned char ucEindAddress[1];    /* Selects reset type.  */
+  unsigned char EECRAddress[2];      /* EECR IO address.  */
+};
+
+struct device_descriptor
+{
+  /* Name of the part as seen to the user.  */
+  const char *name;
+
+  /* Device ID, as reported by the device.  */
+  unsigned int id;
+
+  /* Parameters.  */
+  struct device_descriptor_data data;
+
+  /* Simply linked list.  */
+  const struct device_descriptor *next;
+};
+
+enum param_kind
+ {
+   PARAM_KIND_HW_VERSION,
+   PARAM_KIND_FW_VERSION,
+   PARAM_KIND_BYTE,
+   PARAM_KIND_WORD,
+   PARAM_KIND_LONG,
+   PARAM_KIND_4BYTES,
+   PARAM_KIND_JTAGID,
+   PARAM_KIND_VOLT
+ };
+
+struct param_description
+{
+  unsigned char id;
+  const char *name;
+  enum param_kind kind;
+};
+
+static const struct param_description param_descs[] =
+  {
+    /* 0x00 */
+    { PARAM_HARDWARE_VERSION, "Hardware Version",  PARAM_KIND_HW_VERSION },
+    { PARAM_FW_VERSION, "Firmware Version", PARAM_KIND_FW_VERSION },
+    { PARAM_EMULATOR_MODE, "Emulator Mode", PARAM_KIND_BYTE },
+    { PARAM_IREG, "Ireg", PARAM_KIND_WORD },
+    { PARAM_BAUDRATE, "Baud rate", PARAM_KIND_BYTE },
+    { PARAM_OCD_VTARGET, "OCD Vtarget", PARAM_KIND_VOLT },
+    { PARAM_OCD_JTAG_CLOCK, "OCD JTAG Clock", PARAM_KIND_BYTE },
+    { PARAM_OCD_BREAK_CAUSE, "OCD Break cause", PARAM_KIND_BYTE },
+    { PARAM_TIMERS_RUNNNING, "Timers running", PARAM_KIND_BYTE },
+    { PARAM_BREAK_ON_FLOW, "Break on change of flow", PARAM_KIND_BYTE },
+    { PARAM_BREAK_ADDR1, "Break Addr1", PARAM_KIND_WORD },
+    { PARAM_BREAK_ADDR2, "Break Addr2", PARAM_KIND_WORD },
+    { PARAM_COMB_BREAK_CTRL, "Comb break ctrl", PARAM_KIND_BYTE },
+    { PARAM_JTAGID_STRING, "JTAG ID", PARAM_KIND_JTAGID },
+    /* 0x10  */
+    { PARAM_FLASH_PAGE_SIZE, "Flash page size", PARAM_KIND_WORD },
+    { PARAM_EEPROM_PAGE_SIZE, "Flash page size", PARAM_KIND_BYTE },
+    { PARAM_TARGET_MCU_STATE, "MCU State", PARAM_KIND_BYTE },
+    { PARAM_DAISY_CHAIN_INFO, "Daisy chain info", PARAM_KIND_4BYTES },
+    { PARAM_BOOT_ADDRESS, "Boot address", PARAM_KIND_LONG },
+    { PARAM_TARGET_SIGNATURE, "Target signature", PARAM_KIND_WORD },
+    { PARAM_PACKET_PARSING_ERROR, "Packet parsing errors", PARAM_KIND_LONG },
+    { PARAM_VALID_PACKET_RECEIVED, "Valid packets received", PARAM_KIND_LONG },
+    { PARAM_COMM_TX_FAILURE, "Comm TX failures", PARAM_KIND_LONG },
+    { PARAM_COMM_RX_FAILURE, "Comm RX failures", PARAM_KIND_LONG },
+    { PARAM_CRC_ERRORS, "CRC errors", PARAM_KIND_LONG },
+    { PARAM_POWER_SOURCE, "Power source", PARAM_KIND_BYTE },
+    { 0, NULL, 0 }
+  };
+
+/* Probe state.  */
+
+struct mkii_probe
+{
+  /* USB handle.  */
+  usb_dev_handle *udev;
+
+  /* Device descriptor.  */
+  const struct device_descriptor *dev_data;
+
+  /* Interface number claimed by gdb.  */
+  int usb_interface;
+
+  /* Sequence number for the next command.  */
+  unsigned short seq_num;
+
+  /* Emulator mode (how is the target connected to the emulator).  */
+  enum mkii_emulator_mode emulator_mode;
+
+  /* OCD jtag clock parameter.  */
+  unsigned char jtagclock;
+
+  /* True if the target is powered.  */
+  unsigned char power;
+
+  /* True if the target is stopped.  */
+  unsigned char stopped;
+
+  /* Events to be handled.  */
+  unsigned int events_mask;
+#define MKII_EVENT_POWER (1 << 0)	/* Target power has changed.  */
+#define MKII_EVENT_RUN   (1 << 1)	/* Running/stop event.  */
+#define MKII_EVENT_SLEEP (1 << 2)	/* Sleep/wakeup event.  */
+
+  /* Hardware breakpoints address, -1 if not used.  */
+#define MKII_MAX_NBR_BP 3
+#define MKII_BP_UNUSED ((CORE_ADDR)-1)
+  CORE_ADDR bp_addrs[MKII_MAX_NBR_BP];
+};
+
+struct avr_memdesc {
+  CORE_ADDR base;
+  CORE_ADDR size;
+  unsigned char memtype;
+};
+
+static const struct avr_memdesc avr_memdescs[] =
+  {
+    { 0x000000, 0x800000, MEMORY_TYPE_SPM },
+    { 0x800000, 0x010000, MEMORY_TYPE_SRAM },
+    { 0x810000, 0x010000, MEMORY_TYPE_EEPROM },
+    { 0x820000, 0x010000, MEMORY_TYPE_FUSE_BITS },
+    { 0x830000, 0x010000, MEMORY_TYPE_LOCK_BITS },
+    { 0x000000, 0x000000, 0 }
+  };
+
+static struct mkii_probe probe1;
+
+static struct target_ops mkii_ops;
+
+static ptid_t mkii_ptid;
+
+static const struct device_descriptor builtin_devices[] =
+{
+  {
+    "AT90USB1287",
+    0x0978203f,
+    {
+      { 0xff, 0xff, 0xe3, 0xf9, 0xff, 0x3f, 0xb9, 0xf8 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0xb6, 0x6d, 0x03, 0xe0, 0xff, 0x1f, 0xb8, 0xf8 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x73, 0xcf, 0x33, 0xdf, 0xf7, 0x3f, 0xf7, 0xff, 0xff, 0x7f, 0x5f,
+        0x3f, 0x00, 0x37, 0x80, 0xe7, 0x7f, 0xff, 0xfd, 0x03, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x73, 0xcf, 0x33, 0xd8, 0xf7, 0x3f, 0xf7, 0xff, 0xf3, 0x7f, 0x5f,
+        0x2f, 0x00, 0x36, 0x80, 0xe5, 0x0f, 0x7f, 0x31, 0x03, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x31 },
+      { 0x57 },
+      { 0x00 },
+      { 0x00, 0x01 },
+      { 0x08 },
+      { 0x00, 0xfe, 0x00, 0x00 },
+      { 0xff, 0x00 },
+      { 0x00, 0x00 },
+      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      { 0x00, 0x00, 0x00 },
+      { 0x00 },
+      { 0x00 },
+      { 0x00, 0x00 },
+      { 0x00 },
+      { 0x00 },
+      { 0x00 },
+      { 0x00, 0x00 },
+      { 0x01 },
+      { 0x00 },
+      { 0x00, 0x00 },
+      { 0x00 },
+      { 0x00 },
+      { 0x00 },
+      { 0x00 },
+      { 0x3f, 0x00 }
+    }
+  },
+  { NULL, 0}
+};
+
+static const struct device_descriptor *loaded_devices;
+
+static void
+write_le2 (unsigned char *buf, unsigned int val)
+{
+  buf[0] = val >> 0;
+  buf[1] = val >> 8;
+}
+
+static void
+write_le4 (unsigned char *buf, unsigned int val)
+{
+  buf[0] = val >> 0;
+  buf[1] = val >> 8;
+  buf[2] = val >> 16;
+  buf[3] = val >> 24;
+}
+
+static unsigned int
+read_le2 (const unsigned char *buf)
+{
+  return (buf[0] << 0) | (buf[1] << 8);
+}
+
+static unsigned int
+read_le4 (const unsigned char *buf)
+{
+  return (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
+}
+
+/* Get the avr_memdesc for ADDR.  Return NULL if ADDR is invalid.  */
+
+static const struct avr_memdesc *
+get_avr_memdesc (CORE_ADDR first, CORE_ADDR last)
+{
+  int i;
+
+  for (i = 0; avr_memdescs[i].size; i++)
+    {
+      const struct avr_memdesc *desc = &avr_memdescs[i];
+      if (first >= desc->base && last < desc->base + desc->size)
+        return desc;
+    }
+  printf_filtered (_("No AVR memory type at %s\n"),
+                   paddress (target_gdbarch, first));
+  return NULL;
+}
+
+static void
+parse_char_array (struct gdb_xml_parser *parser,
+                  const struct gdb_xml_element *element,
+                  unsigned char *dest, const char *text, int num)
+{
+  char *p = (char *)text;
+
+  while (num > 0)
+    {
+      unsigned long val;
+
+      val = strtoul (p, &p, 0);
+      if (val > 255)
+        gdb_xml_error (parser, _("bad value in element %s"), element->name);
+      *dest++ = val;
+      num--;
+      if (*p == 0)
+        break;
+      if (num == 0 && *p != 0)
+        gdb_xml_error (parser, _("too many values for element %s"),
+                       element->name);
+      if (*p != ',')
+        gdb_xml_error (parser, _("invalid character for element %s"),
+                       element->name);
+      /* Skip ','.  */
+      p++;
+    }
+}
+
+static void
+parse_long (struct gdb_xml_parser *parser,
+            const struct gdb_xml_element *element,
+            unsigned char *dest, const char *text)
+{
+  char *p = (char *)text;
+  unsigned long val;
+
+  val = strtoul (p, &p, 0);
+  write_le4 (dest, val);
+  if (*p != 0)
+    gdb_xml_error (parser, _("not enough values for element %s"),
+                   element->name);
+}
+
+static void
+parse_int (struct gdb_xml_parser *parser,
+            const struct gdb_xml_element *element,
+            unsigned char *dest, const char *text)
+{
+  char *p = (char *)text;
+  unsigned long val;
+
+  val = strtoul (p, &p, 0);
+  if (val > 0xffff)
+    gdb_xml_error (parser, _("bad value in element %s"), element->name);
+  write_le2 (dest, val);
+  if (*p != 0)
+    gdb_xml_error (parser, _("not enough values for element %s"),
+                   element->name);
+}
+
+#define FIELD_HANDLER_CHAR(NAME)                                \
+static void                                                     \
+NAME##_end_handler (struct gdb_xml_parser *parser,              \
+                    const struct gdb_xml_element *element,      \
+                    void *user_data, const char *body_text)     \
+{                                                               \
+  struct device_descriptor *desc = user_data;                   \
+                                                                \
+  parse_char_array (parser, element, desc->data.NAME,           \
+                    body_text, sizeof (desc->data.NAME));       \
+}
+
+#define FIELD_HANDLER_LONG(NAME)                                \
+static void                                                     \
+NAME##_end_handler (struct gdb_xml_parser *parser,              \
+                    const struct gdb_xml_element *element,      \
+                    void *user_data, const char *body_text)     \
+{                                                               \
+  struct device_descriptor *desc = user_data;                   \
+                                                                \
+  gdb_assert (sizeof (desc->data.NAME) == 4);                   \
+  parse_long (parser, element, desc->data.NAME, body_text);     \
+}
+
+#define FIELD_HANDLER_INT(NAME)                                 \
+static void                                                     \
+NAME##_end_handler (struct gdb_xml_parser *parser,              \
+                    const struct gdb_xml_element *element,      \
+                    void *user_data, const char *body_text)     \
+{                                                               \
+  struct device_descriptor *desc = user_data;                   \
+                                                                \
+  gdb_assert (sizeof (desc->data.NAME) == 2);                   \
+  parse_int (parser, element, desc->data.NAME, body_text);      \
+}
+
+FIELD_HANDLER_CHAR (ucReadIO)
+FIELD_HANDLER_CHAR (ucWriteIO)
+FIELD_HANDLER_CHAR (ucReadIOShadow)
+FIELD_HANDLER_CHAR (ucWriteIOShadow)
+FIELD_HANDLER_CHAR (ucReadExtIO)
+FIELD_HANDLER_CHAR (ucWriteExtIO)
+FIELD_HANDLER_CHAR (ucReadIOExtShadow)
+FIELD_HANDLER_CHAR (ucWriteIOExtShadow)
+FIELD_HANDLER_CHAR (ucIDRAddress)
+FIELD_HANDLER_CHAR (ucSPMCRAddress)
+FIELD_HANDLER_CHAR (ucRAMPZAddress)
+FIELD_HANDLER_INT  (uiFlashPageSize)
+FIELD_HANDLER_CHAR (ucEepromPageSize)
+FIELD_HANDLER_LONG (ulBootAddress)
+FIELD_HANDLER_INT  (uiUpperExtIOLoc)
+FIELD_HANDLER_LONG (ulFlashSize)
+FIELD_HANDLER_CHAR (ucEepromInst)
+FIELD_HANDLER_CHAR (ucFlashInst)
+FIELD_HANDLER_CHAR (ucSPHaddr)
+FIELD_HANDLER_CHAR (ucSPLaddr)
+/* FIELD_HANDLER_CHAR (uiFlashpages) - Not in XML ? */
+FIELD_HANDLER_CHAR (ucDWDRAddress)
+FIELD_HANDLER_CHAR (ucDWBasePC)
+FIELD_HANDLER_CHAR (ucAllowFullPageBitstream)
+FIELD_HANDLER_CHAR (uiStartSmallestBootLoaderSection)
+FIELD_HANDLER_CHAR (EnablePageProgramming)
+FIELD_HANDLER_CHAR (ucCacheType)
+/* FIELD_HANDLER_INT (uiSramStartAddr) - Not in XML ? */
+FIELD_HANDLER_CHAR (ucResetType)
+FIELD_HANDLER_CHAR (ucPCMaskExtended)
+FIELD_HANDLER_CHAR (ucPCMaskHigh)
+FIELD_HANDLER_INT  (EECRAddress)
+#undef FIELD_HANDLER
+
+static void
+part_name_end_handler (struct gdb_xml_parser *parser,
+                       const struct gdb_xml_element *element,
+                       void *user_data, const char *body_text)
+{
+  struct device_descriptor *desc = user_data;
+
+  desc->name = xstrdup (body_text);
+  make_cleanup (xfree, (char *)desc->name);
+}
+
+static void
+id_end_handler (struct gdb_xml_parser *parser,
+                       const struct gdb_xml_element *element,
+                       void *user_data, const char *body_text)
+{
+  struct device_descriptor *desc = user_data;
+
+  desc->id = strtoul (body_text, NULL, 0);
+}
+
+const struct gdb_xml_element admin_children[] = {
+  { "PART_NAME", NULL, NULL, GDB_XML_EF_NONE,
+    NULL, part_name_end_handler },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element jtagicemkii_children[] = {
+  { "ID", NULL, NULL, GDB_XML_EF_NONE, NULL, id_end_handler },
+#define FIELD_ELEMENT(XML_NAME, NAME)                                \
+  { #XML_NAME, NULL, NULL, GDB_XML_EF_OPTIONAL, NULL, NAME##_end_handler }
+  FIELD_ELEMENT (ucRead, ucReadIO),
+  FIELD_ELEMENT (ucWrite, ucWriteIO),
+  FIELD_ELEMENT (ucReadShadow, ucReadIOShadow),
+  FIELD_ELEMENT (ucWriteShadow, ucWriteIOShadow),
+  FIELD_ELEMENT (ucExtRead, ucReadExtIO),
+  FIELD_ELEMENT (ucExtWrite, ucWriteExtIO),
+  FIELD_ELEMENT (ucExtReadShadow, ucReadIOExtShadow),
+  FIELD_ELEMENT (ucExtWriteShadow, ucWriteIOExtShadow),
+  FIELD_ELEMENT (ucIDRAddress, ucIDRAddress),
+  FIELD_ELEMENT (ucSPMCAddress, ucSPMCRAddress),
+  FIELD_ELEMENT (ucRAMPZAddress, ucRAMPZAddress),
+  FIELD_ELEMENT (ulFlashPageSize, uiFlashPageSize),
+  FIELD_ELEMENT (ulEepromPageSize, ucEepromPageSize),
+  FIELD_ELEMENT (ulBootAddress, ulBootAddress),
+  FIELD_ELEMENT (ucUpperExtIOLoc, uiUpperExtIOLoc),
+  FIELD_ELEMENT (ulFlashSize, ulFlashSize),
+  FIELD_ELEMENT (ucEepromInst, ucEepromInst),
+  FIELD_ELEMENT (ucFlashInst, ucFlashInst),
+  FIELD_ELEMENT (ucSPHaddr, ucSPHaddr),
+  FIELD_ELEMENT (ucSPLaddr, ucSPLaddr),
+  FIELD_ELEMENT (DWdatareg, ucDWDRAddress),
+  FIELD_ELEMENT (DWbasePC, ucDWBasePC),
+  FIELD_ELEMENT (ucAllowFullPageBitstream, ucAllowFullPageBitstream),
+  FIELD_ELEMENT (uiStartSmallestBootLoaderSection,
+                 uiStartSmallestBootLoaderSection),
+  FIELD_ELEMENT (EnablePageProgramming, EnablePageProgramming),
+  FIELD_ELEMENT (CacheType, ucCacheType),
+  FIELD_ELEMENT (ResetType, ucResetType),
+  FIELD_ELEMENT (PCMaskExtended, ucPCMaskExtended),
+  FIELD_ELEMENT (PCMaskHigh, ucPCMaskHigh),
+  FIELD_ELEMENT (EECRAddress, EECRAddress),
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element ice_settings_children[] = {
+  { "JTAGICEmkII", NULL, jtagicemkii_children, GDB_XML_EF_NONE,
+    NULL, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element avrpart_children[] = {
+  { "ADMIN", NULL, admin_children, GDB_XML_EF_NONE, NULL, NULL },
+  { "ICE_SETTINGS", NULL, ice_settings_children, GDB_XML_EF_NONE, NULL, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element avrpart_elements[] = {
+  { "AVRPART", NULL, avrpart_children, GDB_XML_EF_NONE,
+    NULL, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static void
+mkii_print_device_descriptor (const struct device_descriptor *desc,
+                              int verbose)
+{
+#define FIELD(NAME) { #NAME, sizeof (desc->data.NAME) }
+  struct field_desc
+  {
+    const char *name;
+    unsigned int len;
+  };
+  static const struct field_desc fields[] =
+    {
+      FIELD (ucReadIO),
+      FIELD (ucReadIOShadow),
+      FIELD (ucWriteIO),
+      FIELD (ucWriteIOShadow),
+      FIELD (ucReadExtIO),
+      FIELD (ucReadIOExtShadow),
+      FIELD (ucWriteExtIO),
+      FIELD (ucWriteIOExtShadow),
+      FIELD (ucIDRAddress),
+      FIELD (ucSPMCRAddress),
+      FIELD (ucRAMPZAddress),
+      FIELD (uiFlashPageSize),
+      FIELD (ucEepromPageSize),
+      FIELD (ulBootAddress),
+      FIELD (uiUpperExtIOLoc),
+      FIELD (ulFlashSize),
+      FIELD (ucEepromInst),
+      FIELD (ucFlashInst),
+      FIELD (ucSPHaddr),
+      FIELD (ucSPLaddr),
+      FIELD (uiFlashpages),
+      FIELD (ucDWDRAddress),
+      FIELD (ucDWBasePC),
+      FIELD (ucAllowFullPageBitstream),
+      FIELD (uiStartSmallestBootLoaderSection),
+      FIELD (EnablePageProgramming),
+      FIELD (ucCacheType),
+      FIELD (uiSramStartAddr),
+      FIELD (ucResetType),
+      FIELD (ucPCMaskExtended),
+      FIELD (ucPCMaskHigh),
+      FIELD (ucEindAddress),
+      FIELD (EECRAddress),
+      { NULL, 0 }
+    };
+#undef FIELD
+  const struct field_desc *d = fields;
+  const unsigned char *p;
+  printf_unfiltered ("  {\n");
+  printf_unfiltered ("    \"%s\",\n", desc->name);
+  printf_unfiltered ("    0x%08x,\n", desc->id);
+  printf_unfiltered ("    {\n");
+  p = (const unsigned char *)&desc->data;
+  while (1)
+    {
+      int i = 0;
+      if (verbose)
+        printf_unfiltered ("      /* %s */\n", d->name);
+      printf_unfiltered ("      { ");
+      while (1)
+        {
+          printf_unfiltered ("0x%02x", *p++);
+          i++;
+          if (i != d->len)
+            printf_unfiltered (",");
+          else
+            break;
+          printf_unfiltered ((i % 12 == 11) ? "\n        " : " ");
+
+        }
+      printf_unfiltered (" }");
+      d++;
+      if (d->len == 0)
+        break;
+      printf_unfiltered (",\n");
+    }
+  printf_unfiltered ("\n"
+                     "    }\n"
+                     "  }\n");
+}
+
+static void
+mkii_load_xml_command (char *args, int from_tty)
+{
+#if !defined(HAVE_LIBEXPAT)
+  error (_("command not available; XML support was disabled at compile time"));
+#else
+  char *filename;
+  char *content;
+  struct gdb_xml_parser *parser;
+  struct cleanup *back_to;
+  struct device_descriptor desc;
+
+  if (args == 0)
+    error (_("filename expected"));
+
+  filename = tilde_expand (args);
+  make_cleanup (xfree, filename);
+  content = xml_fetch_content_from_file (filename, NULL);
+  if (content == NULL)
+    error (_("can't read %s"), args);
+  memset (&desc, 0, sizeof (desc));
+  back_to = make_cleanup (xfree, content);
+  parser = gdb_xml_create_parser_and_cleanup (_("Atmel AVR Parts"),
+					      avrpart_elements, &desc);
+
+  if (gdb_xml_parse (parser, content) == 0)
+    {
+      struct device_descriptor *res;
+
+      /* Parsed successfully.  */
+      printf_filtered ("Found '%s': id=%08x\n", desc.name, desc.id);
+      mkii_print_device_descriptor (&desc, 0);
+
+      /* Prepend to the list of known devices.  */
+      res = XNEW (struct device_descriptor);
+      res->name = xstrdup (desc.name);
+      res->id = desc.id;
+      res->data = desc.data;
+      res->next = loaded_devices;
+      loaded_devices = res;
+    }
+
+  do_cleanups (back_to);
+#endif
+}
+
+/* CRC16 definitions - from Atmel AVR067 document.  */
+static const unsigned short crc_table[256] =
+  {
+    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+  };
+
+/* CRC calculation macros.  */
+#define CRC_INIT 0xFFFF
+
+static unsigned short
+mkii_checksum (const unsigned char *message, unsigned long length,
+               unsigned short crc)
+{
+  unsigned long i;
+
+  for (i = 0; i < length; i++)
+    crc = (crc >> 8) ^ crc_table[(crc ^ message[i]) & 0x00ff];
+  return crc;
+}
+
+/* Send a packet to the probe.  */
+
+static void
+mkii_send (struct mkii_probe *probe,
+           const unsigned char *cmd, unsigned long cmd_len,
+           const unsigned char *data, unsigned long data_len)
+{
+  int i;
+  unsigned long pos;
+  unsigned short crc;
+  int crc_done;
+  char buf[MKII_PKT_SIZE];
+
+  if (remote_debug > 1)
+    {
+      const char *cmd_name = "unknown";
+      switch (cmd[0])
+        {
+        case CMND_GET_SIGN_OFF:
+          cmd_name = "get_sign_off";
+          break;
+        case CMND_GET_SIGN_ON:
+          cmd_name = "get_sign_on";
+          break;
+        case CMND_SET_PARAMETER:
+          cmd_name = "set_parameter";
+          break;
+        case CMND_GET_PARAMETER:
+          cmd_name = "get_parameter";
+          break;
+        case CMND_WRITE_MEMORY:
+          cmd_name = "write_memory";
+          break;
+        case CMND_READ_MEMORY:
+          cmd_name = "read_memory";
+          break;
+        case CMND_WRITE_PC:
+          cmd_name = "write_PC";
+          break;
+        case CMND_READ_PC:
+          cmd_name = "read_PC";
+          break;
+        case CMND_GO:
+          cmd_name = "go";
+          break;
+        case CMND_SINGLE_STEP:
+          cmd_name = "single_step";
+          break;
+        case CMND_FORCED_STOP:
+          cmd_name = "forced_stop";
+          break;
+        case CMND_RESET:
+          cmd_name = "reset";
+          break;
+        case CMND_SET_DEVICE_DESCRIPTOR:
+          cmd_name = "set_device_descriptor";
+          break;
+        case CMND_ERASEPAGE_SPM:
+          cmd_name = "erasepage_spm";
+          break;
+        case CMND_GET_SYNC:
+          cmd_name = "get_sync";
+          break;
+        case CMND_SELFTEST:
+          cmd_name = "selftest";
+          break;
+        case CMND_SET_BREAK:
+          cmd_name = "set_break";
+          break;
+        case CMND_GET_BREAK:
+          cmd_name = "get_break";
+          break;
+        case CMND_CHIP_ERASE:
+          cmd_name = "chip_erase";
+          break;
+        case CMND_ENTER_PROGMODE:
+          cmd_name = "enter_progmode";
+          break;
+        case CMND_LEAVE_PROGMODE:
+          cmd_name = "leave_progmode";
+          break;
+        case CMND_CLR_BREAK:
+          cmd_name = "clr break";
+          break;
+        case CMND_RESTORE_TARGET:
+          cmd_name = "restore_target";
+          break;
+        default:
+          break;
+        }
+      fprintf_unfiltered (gdb_stdlog,
+                          "atmel-mkii: send cmd=0x%02x len=%ld (%s)\n",
+                          cmd[0], data_len, cmd_name);
+    }
+
+  /* Build packet header.  */
+  buf[0] = MKII_ESC;
+  write_le2 (buf + 1, probe->seq_num);
+  write_le4 (buf + 3, cmd_len + data_len);
+  buf[7] = MKII_TOKEN;
+
+  /* Increment seq number.  */
+  probe->seq_num++;
+  if (probe->seq_num == MKII_EVENT_SEQNUM)
+    probe->seq_num = 0;
+
+  /* Copy command.  */
+  gdb_assert (cmd_len + MKII_HDR_SIZE < MKII_PKT_SIZE);
+  memcpy (buf + MKII_HDR_SIZE, cmd, cmd_len);
+  pos = MKII_HDR_SIZE + cmd_len;
+
+  crc = CRC_INIT;
+  crc_done = 0;
+
+  while (1)
+    {
+      unsigned long chunk_len;
+      int res;
+
+      chunk_len = MKII_PKT_SIZE - pos;
+      chunk_len = min (chunk_len, data_len);
+      memcpy (buf + pos, data, chunk_len);
+      pos += chunk_len;
+      data_len -= chunk_len;
+      data += chunk_len;
+
+      crc = mkii_checksum (buf, pos, crc);
+
+      if (data_len == 0 && pos + 2 <= MKII_PKT_SIZE)
+        {
+          write_le2 (buf + pos, crc);
+          pos += 2;
+          crc_done = 1;
+        }
+
+      if (remote_debug > 2)
+        {
+          int j;
+
+          fprintf_unfiltered (gdb_stdlog, "atmel-mkii: send");
+          for (j = 0; j < pos; j++)
+            fprintf_unfiltered (gdb_stdlog, " %02x", (unsigned char)buf[j]);
+          fprintf_unfiltered (gdb_stdlog, "\n");
+        }
+
+      res = usb_bulk_write (probe->udev, MKII_EP_WRITE,
+                            buf, pos, MKII_WRITE_TIMEOUT);
+      if (res < 0)
+        error (_("atmel-mkii write error %d (%s)."), res, usb_strerror ());
+      if (crc_done)
+        break;
+      pos = 0;
+    }
+}
+
+/* Return the length.  */
+static unsigned long
+mkii_recv (struct mkii_probe *probe,
+           unsigned short *seq, unsigned char *msg, unsigned long maxlen,
+           unsigned int timeout)
+{
+  char buf[MKII_PKT_SIZE];
+  unsigned long len = 0;
+  unsigned long l = 0;
+  int state = 0;
+  unsigned short id = 0;
+  unsigned short crc = CRC_INIT;
+
+  while (1)
+    {
+      int res;
+      int i;
+
+      res = usb_bulk_read (probe->udev, MKII_EP_READ,
+                           buf, MKII_PKT_SIZE, timeout);
+      if (res < 0)
+        {
+          warning (_("atmel-mkii read error (%d): %s."), res, usb_strerror ());
+          return 0;
+        }
+      if (res == 0 || quit_flag)
+        return 0;
+      if (remote_debug > 2)
+        {
+          int j;
+
+          fprintf_unfiltered (gdb_stdlog, "atmel-mkii: recv");
+          for (j = 0; j < res; j++)
+            fprintf_unfiltered
+              (gdb_stdlog, "%c%02x",
+               (j == 8 || j == res - 2) ? '-' : ' ', (unsigned char)buf[j]);
+          fprintf_unfiltered (gdb_stdlog, "\n");
+        }
+
+      for (i = 0; i < res; i++)
+        {
+          unsigned char b = buf[i];
+
+          crc = mkii_checksum (&b, 1, crc);
+          switch (state)
+            {
+            case 0:
+              if (b == MKII_ESC)
+                state = 1;
+              else
+                crc = CRC_INIT;
+              break;
+            case 1:
+              id = b;
+              state = 2;
+              break;
+            case 2:
+              id = id | (b << 8);
+              *seq = id;
+              state = 3;
+              break;
+            case 3:
+              len = b;
+              state = 4;
+              break;
+            case 4:
+              len = len | (b << 8);
+              state = 5;
+              break;
+            case 5:
+              len = len | (b << 16);
+              state = 6;
+              break;
+            case 6:
+              len = len | (b << 24);
+              state = 7;
+              break;
+            case 7:
+              l = 0;
+              if (b == MKII_TOKEN && len > 0)
+                state = 8;
+              else
+                {
+                  crc = CRC_INIT;
+                  state = 0;
+                }
+              break;
+            case 8:
+              if (l < maxlen)
+                msg[l] = b;
+              l++;
+              if (l == len)
+                state = 9;
+              break;
+            case 9:
+              state = 10;
+              break;
+            case 10:
+              if (crc != 0)
+                {
+                  warning (_("atmel-mkii: bad crc"));
+                  state = 0;
+                  crc = CRC_INIT;
+                }
+              else
+                {
+                  if (remote_debug > 1)
+                    {
+                      const char *rsp_name;
+                      switch (msg[0])
+                        {
+                        case RSP_OK:
+                          rsp_name = "ok";
+                          break;
+                        case RSP_PARAMETER:
+                          rsp_name = "parameter";
+                          break;
+                        case RSP_MEMORY:
+                          rsp_name = "memory";
+                          break;
+                        case RSP_GET_BREAK:
+                          rsp_name = "get_break";
+                          break;
+                        case RSP_PC:
+                          rsp_name = "pc";
+                          break;
+                        case RSP_SELFTEST:
+                          rsp_name = "selftest";
+                          break;
+                        case RSP_SIGN_ON:
+                          rsp_name = "sign_on";
+                          break;
+                        case EVT_BREAK:
+                          rsp_name = "break";
+                          break;
+                        case EVT_RUN:
+                          rsp_name = "run";
+                          break;
+                        case EVT_TARGET_POWER_ON:
+                          rsp_name = "target_power_on";
+                          break;
+                        case EVT_TARGET_POWER_OFF:
+                          rsp_name = "target_power_off";
+                          break;
+                        case EVT_DEBUG:
+                          rsp_name = "debug";
+                          break;
+                        case EVT_EXT_RESET:
+                          rsp_name = "ext_reset";
+                          break;
+                        case EVT_TARGET_SLEEP:
+                          rsp_name = "target_sleep";
+                          break;
+                        case EVT_TARGET_WAKEUP:
+                          rsp_name = "target_wakeup";
+                          break;
+                        default:
+                          rsp_name = "unknown";
+                          break;
+                        }
+                      fprintf_unfiltered
+                        (gdb_stdlog,
+                         "atmel-mkii: recv rsp=0x%02x len=%ld (%s)\n",
+                         msg[0], len, rsp_name);
+                    }
+                  return len;
+                }
+              break;
+            default:
+              abort ();
+            }
+        }
+    }
+}
+
+static void
+mkii_event_msg (struct mkii_probe *probe, unsigned char *msg, int len)
+{
+  if (remote_debug > 1)
+    fprintf_unfiltered (gdb_stdlog, "atmel-mkii: got event %02x\n", msg[0]);
+
+  switch (msg[0])
+    {
+    case EVT_TARGET_POWER_ON:
+      probe->events_mask |= MKII_EVENT_POWER;
+      probe->power = 1;
+      break;
+    case EVT_TARGET_POWER_OFF:
+      probe->events_mask |= MKII_EVENT_POWER;
+      probe->power = 0;
+      break;
+    case EVT_BREAK:
+      probe->events_mask |= MKII_EVENT_RUN;
+      probe->stopped = 1;
+      break;
+    case EVT_RUN:
+      probe->events_mask |= MKII_EVENT_RUN;
+      probe->stopped = 0;
+      break;
+    case EVT_TARGET_SLEEP:
+      probe->events_mask |= MKII_EVENT_SLEEP;
+      probe->stopped = 1;
+      break;
+    case EVT_TARGET_WAKEUP:
+      /* Currently ignored.  */
+      break;
+    default:
+      fprintf_unfiltered
+        (gdb_stdlog, "atmel-mkii: unhandled event %02x\n", msg[0]);
+      break;
+    }
+}
+
+static int
+mkii_wait_event (struct mkii_probe *probe)
+{
+  unsigned char buf[8];
+  unsigned short seq, r_seq;
+  int res;
+
+  while (1)
+    {
+      res = mkii_recv (probe, &r_seq, buf, sizeof (buf), MKII_EVENT_TIMEOUT);
+      if (res <= 0)
+        return res;
+      if (r_seq == MKII_EVENT_SEQNUM)
+        {
+          mkii_event_msg (probe, buf, res);
+          return 1;
+        }
+      else
+        warning (_("atmel-mkii: unexpected packet\n"));
+    }
+}
+
+/* Send a command to a probe and wait for the reply.
+   The command is composed of two part: CMD which is the command bytes
+   and DATA which is its associated data.  The length of the command, CMD_LEN,
+   shouldn't be longer than an USB packet size.  This is OK with all
+   known commands.
+   The reply is put into REPLY.
+   Return the length of the reply.  */
+
+static int
+mkii_cmd_with_data (struct mkii_probe *probe,
+                    const unsigned char *cmd, unsigned long cmd_len,
+                    const unsigned char *data, unsigned long data_len,
+                    unsigned char *reply, unsigned long reply_maxlen)
+{
+  unsigned short seq, r_seq;
+  int res;
+
+  /* First, send the message.  */
+  seq = probe->seq_num;
+  mkii_send (probe, cmd, cmd_len, data, data_len);
+
+  while (1)
+    {
+      res = mkii_recv (probe, &r_seq, reply, reply_maxlen, MKII_READ_TIMEOUT);
+
+      if (res == 0)
+        return 0;
+
+      if (r_seq == MKII_EVENT_SEQNUM)
+        {
+          mkii_event_msg (probe, reply, res);
+          continue;
+        }
+      if (r_seq != seq)
+        warning (_("atmel-mkii: synchro lost\n"));
+      else
+        return res;
+    }
+}
+
+/* Same as mkii_cmd_with_data but without data.  Just send a command
+   and wait for the reply.  */
+
+static int
+mkii_cmd (struct mkii_probe *probe,
+          const unsigned char *cmd, unsigned long cmd_len,
+          unsigned char *reply, unsigned long reply_maxlen)
+{
+  return mkii_cmd_with_data (probe, cmd, cmd_len, NULL, 0,
+                             reply, reply_maxlen);
+}
+
+/* Send a command, wait for the reply and return 0 in case of success.
+   Return the status byte in case of failure.  */
+
+static int
+mkii_cmd_status (struct mkii_probe *probe,
+                 const unsigned char *cmd, unsigned long cmd_len)
+{
+  unsigned char reply[16];
+  int res;
+
+  res = mkii_cmd (probe, cmd, cmd_len, reply, sizeof (reply));
+  if (res != 1)
+    return 1;
+  if (!RSP_SUCCESS (reply[0]))
+    return reply[0];
+  else
+    return 0;
+}
+
+/* Single byte command.  */
+
+static int
+mkii_cmd_simple (struct mkii_probe *probe, unsigned char c)
+{
+  unsigned char cmd[2];
+
+  cmd[0] = c;
+  return mkii_cmd_status (probe, cmd, 1);
+}
+
+static void
+mkii_ping (struct mkii_probe *probe)
+{
+  int res;
+
+  res = mkii_cmd_simple (probe, CMND_GET_SYNC);
+  if (res != 0)
+    error (_("ping to target atmel-mkii failed (err=%02x)"), res);
+}
+
+static const struct device_descriptor *
+mkii_find_device_descriptor (unsigned int id)
+{
+  const struct device_descriptor *d;
+
+  for (d = loaded_devices; d; d = d->next)
+    if (d->id == id)
+      return d;
+
+  for (d = builtin_devices; d->name; d++)
+    if (d->id == id)
+      return d;
+
+  return NULL;
+}
+
+static void
+mkii_stop_now (struct mkii_probe *probe, int reset)
+{
+  int ret;
+  unsigned char cmd[4];
+
+  /* Stop now.  */
+  cmd[0] = reset ? CMND_RESET : CMND_FORCED_STOP;
+  cmd[1] = FLAG_LOW_LEVEL;
+  ret = mkii_cmd_status (probe, cmd, 2);
+  if (ret != 0)
+    {
+      fprintf_unfiltered (gdb_stdlog, "atmel-mkii: stop: got 0x%02x\n", ret);
+      return;
+    }
+
+  mkii_ping (probe);
+  if (!probe->stopped)
+    {
+      fprintf_unfiltered (gdb_stdlog, "atmel-mkii: target not stopped\n");
+      return;
+    }
+  probe->events_mask &= ~MKII_EVENT_RUN;
+}
+
+static void
+mkii_handle_power_on (struct mkii_probe *probe)
+{
+  /* The device has been powered-up.  */
+  const struct device_descriptor *dev;
+  int ret;
+  unsigned char cmd[4], msg[32];
+  unsigned int id;
+
+  /* Set emulator mode.  */
+  cmd[0] = CMND_SET_PARAMETER;
+  cmd[1] = PARAM_EMULATOR_MODE;
+  cmd[2] = probe->emulator_mode;
+  ret = mkii_cmd_status (probe, cmd, 3);
+  if (ret != 0)
+    {
+      fprintf_unfiltered
+        (gdb_stdlog, "atmel-mkii: set emulator mode: got 0x%02x\n", ret);
+      probe->power = 0;
+      return;
+    }
+
+  if (probe->emulator_mode == MODE_JTAG)
+    {
+      /* Set JTAG clock.  */
+      cmd[0] = CMND_SET_PARAMETER;
+      cmd[1] = PARAM_OCD_JTAG_CLOCK;
+      cmd[2] = probe->jtagclock;
+      ret = mkii_cmd_status (probe, cmd, 3);
+      if (ret != 0)
+        {
+          fprintf_unfiltered
+            (gdb_stdlog, "atmel-mkii: set jtag clock: got %02x\n", ret);
+          probe->power = 0;
+          return;
+        }
+    }
+
+  /* Read JTAG-ID.  */
+  cmd[0] = CMND_GET_PARAMETER;
+  cmd[1] = PARAM_JTAGID_STRING;
+  ret = mkii_cmd (probe, cmd, 2, msg, sizeof (msg));
+  if (ret != 5 || msg[0] != RSP_PARAMETER)
+    {
+      fprintf_unfiltered (gdb_stdlog, "atmel-mkii: get jtag-id: got %d %02x\n",
+                          ret, msg[0]);
+      probe->power = 0;
+      return;
+    }
+
+  id = read_le4 (msg + 1);
+
+  dev = mkii_find_device_descriptor (id);
+  if (dev == NULL)
+    {
+      warning (_("Atmel device id 0x%08x is not known"), id);
+      return;
+    }
+  fprintf_unfiltered (gdb_stdlog, "atmel-mkii: found device 0x%08x - %s\n",
+                      id, dev->name);
+  probe->dev_data = dev;
+
+  /* Set device descriptor.  */
+  cmd[0] = CMND_SET_DEVICE_DESCRIPTOR;
+  ret = mkii_cmd_with_data
+    (probe, cmd, 1, (const unsigned char *)&dev->data, DEVICE_DESCRIPTOR_LEN,
+     msg, sizeof (msg));
+  if (ret != 1 || msg[0] != RSP_OK)
+    {
+      fprintf_unfiltered
+        (gdb_stdlog, "atmel-mkii: set device descriptor: got %d %02x\n",
+         ret, msg[0]);
+      probe->power = 0;
+      return;
+    }
+}
+
+static void
+mkii_handle_events (struct mkii_probe *probe)
+{
+  if (probe->events_mask & MKII_EVENT_POWER)
+    {
+      probe->events_mask &= ~MKII_EVENT_POWER;
+      if (probe->power)
+        mkii_handle_power_on (probe);
+    }
+}
+
+/* Return true if DEV represents an Atmel mkII probe.  */
+
+static int
+is_atmel_mkii (const struct usb_device *dev)
+{
+  return dev->descriptor.idVendor == ID_VENDOR_ATMEL
+    && dev->descriptor.idProduct == ID_PRODUCT_MKII
+    && dev->descriptor.bcdDevice == ID_DEVICE_RELEASE;
+}
+
+/* Initialize libusb if not already initialized.
+   We don't initialize during gdb initialization to avoid overhead if usb
+   is not used.  */
+
+static void
+maybe_usb_init (void)
+{
+  static int done;
+
+  if (!done)
+    {
+      done = 1;
+      usb_init ();
+    }
+}
+
+/* The list of available "info atmel-mkii " commands.  */
+static struct cmd_list_element *info_atmel_mkii_cmdlist = NULL;
+
+static void
+info_atmel_mkii_command (char *args, int from_tty)
+{
+  printf_unfiltered (_("\"info atmel-mkii\" must be followed by a subcommand name.\n"));
+  help_list (info_atmel_mkii_cmdlist, "info atmel-mkii ", -1, gdb_stdout);
+}
+
+/* List probes found.  */
+
+static void
+info_atmel_mkii_probes_command (char *args, int from_tty)
+{
+  struct usb_bus *bus;
+  struct usb_device *dev;
+  struct cleanup *old_chain;
+  int count = 0;
+
+  maybe_usb_init ();
+  usb_find_busses ();
+  usb_find_devices ();
+
+  for (bus = usb_get_busses (); bus; bus = bus->next)
+    for (dev = bus->devices; dev; dev = dev->next)
+      if (is_atmel_mkii (dev))
+        count++;
+
+  if (count == 0)
+    {
+      ui_out_message (uiout, 0, "No probe found (check power-on).\n");
+      return;
+    }
+
+  old_chain = make_cleanup_ui_out_table_begin_end (uiout, 2, count,
+                                                   "devices");
+
+  ui_out_table_header (uiout, 16, ui_left, "sn", "S/N");
+  ui_out_table_header (uiout, 60, ui_left, "file", "Filename");
+  ui_out_table_body (uiout);
+
+  for (bus = usb_get_busses (); bus; bus = bus->next)
+    for (dev = bus->devices; dev; dev = dev->next)
+      if (is_atmel_mkii (dev))
+        {
+          char serial_num[16];
+          int ret;
+          struct cleanup *chain2;
+          usb_dev_handle *udev;
+
+          udev = usb_open(dev);
+          if (!udev)
+            ret = -1;
+          else
+            {
+              ret = usb_get_string_simple (udev, dev->descriptor.iSerialNumber,
+                                           serial_num, sizeof (serial_num));
+              usb_close(udev);
+            }
+
+          chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+
+          if (ret > 0)
+            ui_out_field_string (uiout, "sn", serial_num);
+          else
+            ui_out_field_string (uiout, "sn", "?");
+
+          ui_out_field_string (uiout, "file", dev->filename);
+
+          ui_out_text (uiout, "\n");
+          do_cleanups (chain2);
+        }
+
+  do_cleanups (old_chain);
+}
+
+/* The list of available "mainenance atmel-mkii " commands.  */
+static struct cmd_list_element *maintenance_atmel_mkii_cmdlist = NULL;
+
+static void
+maintenance_atmel_mkii_command (char *args, int from_tty)
+{
+  printf_unfiltered
+    (_("\"maintenance atmel-mkii\" must be followed by a subcommand name.\n"));
+  help_list (maintenance_atmel_mkii_cmdlist, "maintenance atmel-mkii ",
+             -1, gdb_stdout);
+}
+
+static void
+mkii_ping_command (char *args, int from_tty)
+{
+  struct mkii_probe *probe = &probe1;
+
+  if (probe->udev == NULL)
+    error (_("target atmel-mkii not selected"));
+
+  mkii_handle_events (probe);
+
+  mkii_ping (probe);
+
+  mkii_handle_events (probe);
+}
+
+static void
+info_atmel_mkii_parameters_command (char *args, int from_tty)
+{
+  struct mkii_probe *probe = &probe1;
+  unsigned char cmd[2];
+  unsigned char msg[32];
+  int res;
+  const struct param_description *param;
+
+  if (probe->udev == NULL)
+    error (_("target atmel-mkii not selected"));
+
+  mkii_handle_events (probe);
+
+  for (param = param_descs; param->name; param++)
+    {
+      int len;
+
+      ui_out_text (uiout, param->name);
+      ui_out_text (uiout, ": ");
+
+      cmd[0] = CMND_GET_PARAMETER;
+      cmd[1] = param->id;
+      res = mkii_cmd (probe, cmd, 2, msg, sizeof (msg));
+
+      if (msg[0] == RSP_ILLEGAL_EMULATOR_MODE)
+        {
+          ui_out_text (uiout, "not available\n");
+          continue;
+        }
+      if (msg[0] != RSP_PARAMETER)
+        {
+          ui_out_field_fmt (uiout, "value", "error 0x%02x\n", msg[0]);
+          continue;
+        }
+
+      switch (param->kind)
+        {
+        case PARAM_KIND_HW_VERSION:
+        case PARAM_KIND_WORD:
+        case PARAM_KIND_VOLT:
+          len = 2;
+          break;
+        case PARAM_KIND_FW_VERSION:
+        case PARAM_KIND_LONG:
+        case PARAM_KIND_4BYTES:
+        case PARAM_KIND_JTAGID:
+          len = 4;
+          break;
+        case PARAM_KIND_BYTE:
+          len = 1;
+          break;
+        default:
+          len = 0;
+          break;
+        }
+
+      if (res != len + 1)
+        {
+          ui_out_field_fmt (uiout, "value", "bad len (%d)\n", res);
+          continue;
+        }
+
+      switch (param->kind)
+        {
+        case PARAM_KIND_HW_VERSION:
+          ui_out_field_fmt (uiout, "value",
+                            "M_MCU ver: %02x, S_MCU ver: %02x",
+                            msg[2], msg[1]);
+          break;
+        case PARAM_KIND_WORD:
+          ui_out_field_fmt (uiout, "value", "%02x%02x", msg[2], msg[1]);
+          break;
+        case PARAM_KIND_VOLT:
+          {
+            int val = (msg[2] << 8) | msg[1];
+            ui_out_field_fmt (uiout, "value", "%d.%03d mV",
+                              val / 1000, val % 1000);
+          }
+          break;
+        case PARAM_KIND_FW_VERSION:
+          ui_out_field_fmt (uiout, "value",
+                            "M_MCU ver: %02x.%02x, S_MCU ver: %02x.%02x",
+                            msg[2], msg[1], msg[4], msg[3]);
+          break;
+
+        case PARAM_KIND_LONG:
+          {
+            unsigned int val;
+            val = read_le4 (msg + 1);
+            ui_out_field_fmt (uiout, "value", "%08x", val);
+          }
+          break;
+        case PARAM_KIND_4BYTES:
+        case PARAM_KIND_JTAGID:
+          ui_out_field_fmt (uiout, "value", "%02x %02x %02x %02x",
+                            msg[4], msg[3], msg[2], msg[1]);
+          break;
+        case PARAM_KIND_BYTE:
+          ui_out_field_fmt (uiout, "value", "%02x", msg[1]);
+          break;
+        default:
+          len = 0;
+          break;
+        }
+      ui_out_text (uiout, "\n");
+    }
+}
+
+static void
+info_atmel_mkii_devices_command (char *args, int from_tty)
+{
+  const struct device_descriptor *d;
+
+  ui_out_text (uiout, "Loaded descriptions:\n");
+  for (d = loaded_devices; d; d = d->next)
+    ui_out_field_fmt (uiout, "name", " %s\n", d->name);
+
+  ui_out_text (uiout, "Builtin descriptions:\n");
+  for (d = builtin_devices; d->name; d++)
+    ui_out_field_fmt (uiout, "name", " %s\n", d->name);
+}
+
+static void
+check_power (struct mkii_probe *probe)
+{
+  int ret;
+  unsigned char cmd[2], msg[32];
+
+  /* Read OCD Vtarget.  */
+  cmd[0] = CMND_GET_PARAMETER;
+  cmd[1] = PARAM_OCD_VTARGET;
+  ret = mkii_cmd (probe, cmd, 2, msg, sizeof (msg));
+  if (ret == 3 && msg[0] == RSP_PARAMETER && msg[1] != 0)
+    {
+      /* If more than .256 V, we assume the target is powered.  */
+      probe->power = 1;
+      probe->events_mask |= MKII_EVENT_POWER;
+    }
+
+  mkii_handle_events (probe);
+}
+
+static int
+mkii_sign_on (struct mkii_probe *probe)
+{
+  int ret;
+  unsigned char cmd[1], msg[32];
+
+  cmd[0] = CMND_GET_SIGN_ON;
+  ret = mkii_cmd (probe, cmd, 1, msg, sizeof (msg));
+
+  if (ret < 1)
+    return ret;
+
+  if (remote_debug && ret > 0)
+    {
+      fprintf_unfiltered
+        (gdb_stdlog, "Communication protocol: %02x\n", msg[1]);
+      fprintf_unfiltered
+        (gdb_stdlog, "M_MCU Boot Loader FW version: 0x%02x\n", msg[2]);
+      fprintf_unfiltered
+        (gdb_stdlog, "M_MCU Firmware version: %02x.%02x\n", msg[4], msg[3]);
+      fprintf_unfiltered
+        (gdb_stdlog, "M_MCU Hardware version: %02x\n", msg[5]);
+      fprintf_unfiltered
+        (gdb_stdlog, "S_MCU Boot Loader FW version: 0x%02x\n", msg[6]);
+      fprintf_unfiltered
+        (gdb_stdlog, "S_MCU Firmware version: %02x.%02x\n", msg[8], msg[7]);
+      fprintf_unfiltered
+        (gdb_stdlog, "S_MCU Hardware version: %02x\n", msg[9]);
+      fprintf_unfiltered
+        (gdb_stdlog, "Serial Number: %02x %02x %02x %02x %02x %02x\n",
+         msg[10], msg[11], msg[12], msg[13], msg[14], msg[15]);
+      msg[sizeof(msg)-1] = 0;
+      fprintf_unfiltered (gdb_stdlog,
+                          "Device Id string: %s\n", msg + 16);
+    }
+  return 1;
+}
+
+/* Open a connection to a remote debugger.
+   NAME is the filename used for communication.  */
+
+static void
+mkii_open (char *args, int from_tty)
+{
+  struct usb_bus *bus;
+  struct usb_device *dev;
+  struct usb_device *dev1;
+  struct cleanup *old_chain;
+  usb_dev_handle *udev;
+  struct mkii_probe *probe = &probe1;
+  int usb_interface;
+  char *ser_num = NULL;
+  int i;
+  int res;
+  int timeout = 3;
+
+  /* Just in case it was already open.  This will close the target.  */
+  unpush_target (&mkii_ops);
+
+  probe->emulator_mode = MODE_JTAG;
+  probe->jtagclock = 16;
+
+  if (remote_debug)
+    fprintf_unfiltered (gdb_stdlog, "mkii_open(%d)\n", from_tty);
+
+  if (args)
+    {
+      char **argv;
+
+      argv = gdb_buildargv (args);
+      make_cleanup_freeargv (argv);
+
+      for (i = 0; argv[i]; i++)
+        {
+          if (argv[i][0] != '-')
+            break;
+          if (strcmp (argv[i], "-jtag") == 0)
+            probe->emulator_mode = MODE_JTAG;
+          else if (strcmp (argv[i], "-debugwire") == 0)
+            probe->emulator_mode = MODE_DEBUGWIRE;
+          else if (strcmp (argv[i], "-spi") == 0)
+            probe->emulator_mode = MODE_SPI;
+          else if (strncmp (argv[i], "--clock=", 8) == 0)
+            {
+              char *e;
+              unsigned long clk;
+
+              clk = strtoul (argv[i] + 8, &e, 0);
+              if (*e == 'M')
+                {
+                  clk *= 1000000;
+                  e++;
+                }
+              else if (*e == 'k')
+                {
+                  clk *= 1000;
+                  e++;
+                }
+              if (strcmp (e, "hz") == 0)
+                e += 2;
+              if (!*e || e == argv[i] + 8)
+                error (_("atmel-mkii: cannot parse --clock option"));
+              if (clk >= 4000000)
+                probe->jtagclock = 0;
+              else if (clk == 0)
+                probe->jtagclock = 255;
+              else
+                probe->jtagclock = 4000000 / clk;
+            }
+          else
+            error (_("atmel-mkii: unknown option '%s'"), argv[i]);
+        }
+      if (argv[i])
+        {
+          ser_num = argv[i];
+          i++;
+        }
+      if (argv[i])
+        error (_("atmel-mkii: too many arguments"));
+    }
+
+  maybe_usb_init ();
+
+ retry:
+  usb_find_busses ();
+  usb_find_devices ();
+
+  udev = NULL;
+  dev1 = NULL;
+  for (bus = usb_get_busses (); bus; bus = bus->next)
+    for (dev = bus->devices; dev; dev = dev->next)
+      if (is_atmel_mkii (dev))
+        {
+          int ret;
+          char serial_num[16];
+
+          if (ser_num == NULL && udev != NULL)
+            {
+              usb_close (udev);
+              error (_("Several probes found.  Please specify serial number."));
+            }
+
+          udev = usb_open (dev);
+          dev1 = dev;
+          if (!udev)
+            continue;
+          if (ser_num != NULL)
+            {
+              ret = usb_get_string_simple
+                (udev, dev->descriptor.iSerialNumber,
+                 serial_num, sizeof (serial_num));
+              if (ret < 0 || strcmp (ser_num, serial_num) != 0)
+                {
+                  usb_close (udev);
+                  udev = NULL;
+                }
+              else
+                goto found;
+            }
+        }
+ found:
+  dev = dev1;
+  if (udev == NULL)
+    error (_("Probe not found."));
+
+  if (dev->config == NULL)
+    {
+      usb_close (udev);
+      error (_("Probe has no configuration."));
+    }
+  if (usb_set_configuration (udev, dev->config[0].bConfigurationValue))
+    {
+      usb_close (udev);
+      error (_("Cannot configure the probe (%s).  Please power cycle it."),
+             usb_strerror ());
+    }
+  usb_interface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber;
+  if (usb_claim_interface (udev, usb_interface))
+    {
+      usb_close (udev);
+      error (_("Cannot claim interface (%s)."), usb_strerror ());
+    }
+
+  probe->udev = udev;
+  probe->usb_interface = usb_interface;
+  probe->seq_num = 0;
+  probe->dev_data = NULL;
+
+  for (i = 0; i < MKII_MAX_NBR_BP; i++)
+    probe->bp_addrs[i] = -1;
+
+  res = mkii_sign_on (probe);
+  if (res == 0)
+    {
+      /* Timeout.  Reset the device.  */
+      usb_release_interface (udev, usb_interface);
+      usb_reset (udev);
+      if (--timeout > 0)
+        {
+          warning (_("atmel-mkii: timeout while signing-on.  Retry"));
+          goto retry;
+        }
+    }
+  if (res <= 0)
+    {
+      probe->udev = NULL;
+      usb_close (udev);
+      error (_("atmel-mkii: sign-on error %d."), res);
+    }
+
+  probe->power = 0;
+  probe->events_mask = 0;
+
+  check_power (probe);
+
+  target_preopen (from_tty);
+
+  push_target (&mkii_ops);
+
+  inferior_ptid = null_ptid;
+}
+
+static void
+mkii_create_inferior (struct target_ops *ops, char *exec_file,
+                      char *args, char **env, int from_tty)
+{
+  struct mkii_probe *probe = &probe1;
+
+  if (args && (*args != '\000'))
+    error (_("Args are not supported by atmel-mkii."));
+
+  if (!probe->power)
+    check_power (probe);
+  if (!probe->power)
+    error (_("target is not powered."));
+
+  mkii_stop_now (probe, 1);
+
+  clear_proceed_status ();
+
+  inferior_ptid = mkii_ptid;
+  inferior_appeared (current_inferior (), ptid_get_pid (inferior_ptid));
+  add_thread_silent (inferior_ptid);
+}
+
+static void
+mkii_stop (ptid_t ptid)
+{
+  struct mkii_probe *probe = &probe1;
+
+  printf_unfiltered ("mkii_stop\n");
+}
+
+static void
+mkii_kill (struct target_ops *ops)
+{
+  struct mkii_probe *probe = &probe1;
+  int res;
+
+  /* Best effort.  */
+  res = mkii_cmd_simple (probe, CMND_RESTORE_TARGET);
+  if (res != 0)
+    warning (_("atmel-mkii: can't restore target (err=%02x)"), res);
+
+  target_mourn_inferior ();
+}
+
+static void
+mkii_close (int quitting)
+{
+  struct mkii_probe *probe = &probe1;
+
+  if (remote_debug)
+    fprintf_unfiltered (gdb_stdlog, "mkii_close(%d)\n", quitting);
+
+  if (probe->udev)
+    {
+      int res;
+
+      /* Best effort...  */
+      mkii_cmd_simple (probe, CMND_GET_SIGN_OFF);
+
+      res = usb_release_interface (probe->udev, probe->usb_interface);
+      if (res < 0)
+        warning (_("atmel-mkii release usb interface error %d (%s)."),
+                 res, usb_strerror ());
+      res = usb_close (probe->udev);
+      if (res < 0)
+        warning (_("atmel-mkii close usb interface error %d (%s)."),
+                 res, usb_strerror ());
+      probe->udev = NULL;
+    }
+
+  generic_mourn_inferior ();
+  delete_thread_silent (mkii_ptid);
+  delete_inferior_silent (ptid_get_pid (mkii_ptid));
+}
+
+static void
+mkii_mourn_inferior (struct target_ops *target)
+{
+  if (remote_debug)
+    fprintf_filtered (gdb_stdlog, "mkii_mourn_inferior:\n");
+
+  remove_breakpoints ();
+  generic_mourn_inferior ();
+  delete_thread_silent (mkii_ptid);
+}
+
+#define MKII_XFER_SIZE (MKII_PKT_SIZE - MKII_HDR_SIZE - 2 - 10)
+
+static LONGEST
+mkii_read_mem (struct mkii_probe *probe,
+               int memory_type,
+               ULONGEST addr,
+               unsigned char *buf,
+               LONGEST len)
+{
+  gdb_byte buf_data[MKII_PKT_SIZE];
+  gdb_byte buf_cmd[10];
+  int ret;
+  LONGEST res;
+
+  if (remote_debug)
+    fprintf_unfiltered
+      (gdb_stdlog, "atmel-mkii: read %u bytes at 0x%08lx in space %02x\n",
+       (unsigned) len, (unsigned long) addr, memory_type);
+
+  res = 0;
+  while (len > 0)
+    {
+      int l = (len > MKII_XFER_SIZE) ? MKII_XFER_SIZE : len;
+      int off = 0;
+      int extra = 0;
+
+      buf_cmd[0] = CMND_READ_MEMORY;
+      buf_cmd[1] = memory_type;
+      if (memory_type == MEMORY_TYPE_SPM && ((addr & 1) || (l & 1)))
+        {
+          if (addr & 1)
+            off = 1;
+          if ((l + off) & 1)
+            extra = 1;
+        }
+      if (l + off + extra > MKII_XFER_SIZE)
+        l -= 2;
+      write_le4 (buf_cmd + 2, l + off + extra);
+      write_le4 (buf_cmd + 6, addr - off);
+      ret = mkii_cmd (probe, buf_cmd, 10, buf_data, sizeof (buf_data));
+      if (ret < 1 || buf_data[0] != RSP_MEMORY)
+        return res;
+      ret--;
+      ret -= off + extra;
+      memcpy (buf, buf_data + 1 + off, ret);
+      buf += ret;
+      len -= ret;
+      res += ret;
+      addr += ret;
+    }
+  return res;
+}
+
+static LONGEST
+mkii_write_mem (struct mkii_probe *probe,
+                int memory_type,
+                ULONGEST addr,
+                const unsigned char *buf,
+                LONGEST len)
+{
+  gdb_byte buf_reply[10];
+  int ret;
+  gdb_byte cmd[10];
+
+  if (remote_debug)
+    fprintf_unfiltered
+      (gdb_stdlog, "atmel-mkii: write %u bytes at 0x%08lx in space %02x\n",
+       (unsigned) len, (unsigned long) addr, memory_type);
+
+  cmd[0] = CMND_WRITE_MEMORY;
+  cmd[1] = memory_type;
+  write_le4 (cmd + 2, len);
+  write_le4 (cmd + 6, addr);
+  ret = mkii_cmd_with_data (probe, cmd, 10, buf, len,
+                            buf_reply, sizeof (buf_reply));
+  if (ret < 1 || buf_reply[0] != RSP_OK)
+    return 0;
+  return len;
+}
+
+static LONGEST
+mkii_xfer_partial (struct target_ops *ops,
+                   enum target_object object, const char *annex,
+                   gdb_byte *readbuf, const gdb_byte *writebuf,
+                   ULONGEST offset, LONGEST len)
+{
+  struct mkii_probe *probe = &probe1;
+  const struct avr_memdesc *mdesc;
+
+  gdb_assert ((readbuf == NULL) ^ (writebuf == NULL));
+
+  if (object != TARGET_OBJECT_MEMORY)
+    return -1;
+
+  mdesc = get_avr_memdesc (offset, offset + len - 1);
+  if (mdesc == NULL)
+    return -1;
+
+  if (readbuf != NULL)
+    return mkii_read_mem (probe, mdesc->memtype, offset, readbuf, len);
+  else
+    return mkii_write_mem (probe, mdesc->memtype, offset, writebuf, len);
+}
+
+#define AVR_SREG_REGNUM 32
+#define AVR_SP_REGNUM 33
+#define AVR_PC_REGNUM 34
+
+static void
+mkii_fetch_registers (struct target_ops *ops,
+                      struct regcache *regcache, int regnum)
+{
+  struct mkii_probe *probe = &probe1;
+  unsigned char buf[8];
+  int res;
+  int reg;
+  int len;
+
+  if (regnum == AVR_PC_REGNUM)
+    {
+      unsigned char cmd[2];
+
+      cmd[0] = CMND_READ_PC;
+      res = mkii_cmd (probe, cmd, 1, buf, sizeof (buf));
+      if (res == 5 && buf[0] == RSP_PC)
+        {
+          /* Convert word address to byte address.  */
+          CORE_ADDR pc = read_le4 (buf + 1) << 1;
+          write_le4 (buf + 1, pc);
+          regcache_raw_supply (regcache, AVR_PC_REGNUM, buf + 1);
+        }
+      else
+        warning (_("atmel-mkii read_pc failed (res=%d err=%02x)"), res, buf[0]);
+      return;
+    }
+
+  len = 1;
+  if (regnum == AVR_SP_REGNUM)
+    {
+      reg = 0x5d;
+      len = 2;
+    }
+  else if (regnum == AVR_SREG_REGNUM)
+    reg = 0x5F;
+  else
+    reg = regnum;
+
+  if (mkii_read_mem (probe, MEMORY_TYPE_SRAM, reg, buf, len) != len)
+    warning (_("atmel-mkii fetch registers failed"));
+  else
+    regcache_raw_supply (regcache, regnum, buf);
+}
+
+static void
+mkii_prepare_to_store (struct regcache *regcache)
+{
+}
+
+static void
+mkii_store_registers (struct target_ops *ops,
+                      struct regcache *regcache, int regnum)
+{
+  struct mkii_probe *probe = &probe1;
+  unsigned char buf[8];
+  int res;
+  int reg;
+  int len;
+
+  if (regnum == AVR_PC_REGNUM)
+    {
+      CORE_ADDR pc;
+
+      buf[0] = CMND_WRITE_PC;
+      regcache_raw_collect (regcache, AVR_PC_REGNUM, buf + 1);
+      /* Convert byte to word.  */
+      pc = read_le4 (buf + 1) >> 1;
+      write_le4 (buf + 1, pc);
+      res = mkii_cmd_status (probe, buf, 5);
+      if (res != 0)
+        warning (_("atmel-mkii write_pc failed (err=%02x)"), res);
+      return;
+    }
+
+  len = 1;
+  if (regnum == AVR_SP_REGNUM)
+    {
+      reg = 0x5d;
+      len = 2;
+    }
+  else if (regnum == AVR_SREG_REGNUM)
+    reg = 0x5F;
+  else
+    reg = regnum;
+
+  regcache_raw_collect (regcache, regnum, buf);
+
+  if (mkii_write_mem (probe, MEMORY_TYPE_SRAM, reg, buf, len) != len)
+    warning (_("atmel-mkii write registers failed"));
+}
+
+static int
+mkii_insert_breakpoint (struct gdbarch *gdbarch, struct bp_target_info *bp)
+{
+  struct mkii_probe *probe = &probe1;
+  CORE_ADDR addr = bp->placed_address;
+  int i;
+
+  for (i = 0; i < MKII_MAX_NBR_BP; i++)
+    if (probe->bp_addrs[i] == MKII_BP_UNUSED)
+      {
+        unsigned char cmd[8];
+        int res;
+
+        cmd[0] = CMND_SET_BREAK;
+        cmd[1] = 0x01; /* Program memory breakpoint.  */
+        cmd[2] = i + 1;
+        write_le4 (cmd + 3, addr >> 1);
+        cmd[7] = 0x03; /* Program breakpoint.  */
+        res = mkii_cmd_status (probe, cmd, 8);
+        if (res != 0)
+          error (_("mkii: cannot insert breakpoint (rsp=%02x)"), res);
+        else
+          probe->bp_addrs[i] = addr;
+        return 0;
+      }
+
+  error (_("Too many breakpoints (> %d) for mkii."), MKII_MAX_NBR_BP);
+}
+
+static int
+mkii_remove_breakpoint (struct gdbarch *gdbarch, struct bp_target_info *bp)
+{
+  struct mkii_probe *probe = &probe1;
+  CORE_ADDR addr = bp->placed_address;
+  int i;
+
+  for (i = 0; i < MKII_MAX_NBR_BP; i++)
+    if (probe->bp_addrs[i] == addr)
+      {
+        unsigned char cmd[8];
+        int res;
+
+        cmd[0] = CMND_CLR_BREAK;
+        cmd[1] = i + 1;
+        write_le4 (cmd + 2, addr >> 1);
+        res = mkii_cmd_status (probe, cmd, 6);
+        if (res != 0)
+          error (_("mkii: cannot clear breakpoint (rsp=%02x)"), res);
+        else
+          probe->bp_addrs[i] = MKII_BP_UNUSED;
+        return 0;
+      }
+
+  fprintf_unfiltered (gdb_stderr,
+		      "Can't find breakpoint associated with %s\n",
+		      paddress (gdbarch, addr));
+  return 1;
+}
+
+static void
+mkii_resume (struct target_ops *ops,
+             ptid_t ptid, int step, enum target_signal signal)
+{
+  struct mkii_probe *probe = &probe1;
+  unsigned char cmd[4];
+  unsigned char msg[2];
+  int ret;
+
+  gdb_assert (probe->stopped);
+
+  if (signal != TARGET_SIGNAL_0)
+    printf_unfiltered ("atmel-mkii: posting signal %d is not implemented\n",
+                       signal);
+
+  if (step)
+    {
+      cmd[0] = CMND_SINGLE_STEP;
+      cmd[1] = FLAG_LOW_LEVEL;
+      cmd[2] = SINGLE_STEP_INTO;
+
+      ret = mkii_cmd_status (probe, cmd, 3);
+      if (ret != 0)
+        fprintf_unfiltered
+          (gdb_stdlog, "atmel-mkii: single step: got 0x%02x\n", ret);
+    }
+  else
+    {
+      ret = mkii_cmd_simple (probe, CMND_GO);
+      if (ret != 0)
+        fprintf_unfiltered (gdb_stdlog, "atmel-mkii: go: got %02x\n", ret);
+    }
+
+  probe->stopped = 0;
+}
+
+static ptid_t
+mkii_wait (struct target_ops *ops,
+           ptid_t ptid, struct target_waitstatus *status, int options)
+{
+  struct mkii_probe *probe = &probe1;
+
+  do
+    {
+      mkii_wait_event (probe);
+      if (quit_flag)
+        {
+          unsigned char cmd[2];
+          unsigned char msg[4];
+          int ret;
+
+          quit_flag = 0;
+          cmd[0] = CMND_FORCED_STOP;
+          cmd[1] = FLAG_LOW_LEVEL;
+          ret = mkii_cmd_status (probe, cmd, 2);
+          if (ret != 0)
+            fprintf_unfiltered
+              (gdb_stdlog, "atmel-mkii: forced stop: got 0x%02x\n", ret);
+        }
+    }
+  while (!probe->stopped);
+
+  if (probe->events_mask & MKII_EVENT_SLEEP)
+    {
+      probe->events_mask &= ~MKII_EVENT_SLEEP;
+      status->kind = TARGET_WAITKIND_EXITED;
+      status->value.integer = 0;
+    }
+  else
+    {
+      status->kind = TARGET_WAITKIND_STOPPED;
+      status->value.sig = TARGET_SIGNAL_TRAP;
+    }
+  return mkii_ptid;
+}
+
+static void
+mkii_load (char *args, int from_tty)
+{
+  struct mkii_probe *probe = &probe1;
+  const struct device_descriptor *desc = probe->dev_data;
+  struct cleanup *old_chain;
+  asection *section;
+  char *filename;
+  int i;
+  int erase;
+  int quiet;
+  int res;
+  char **argv;
+  bfd *abfd = NULL;
+
+  dont_repeat ();
+
+  if (args == NULL)
+    error_no_arg (_("file to load"));
+
+  if (probe->udev == NULL || desc == NULL)
+    error (_("target atmel-mkii not selected"));
+
+  argv = gdb_buildargv (args);
+  old_chain = make_cleanup_freeargv (argv);
+  filename = NULL;
+  quiet = 0;
+  erase = 1;
+
+  for (i = 0; argv[i]; i++)
+    {
+      if (*argv[i] == '-')
+        {
+          if (strcmp (argv[i], "--no-erase") == 0)
+            erase = 0;
+          else if (strcmp (argv[i], "--erase") == 0)
+            erase = 2;
+          else
+            error (_("Invalid option: %s"), argv[i]);
+        }
+      else if (argv[i + 1] != NULL)
+        {
+          error (_("filename must be the latest parameter"));
+        }
+      else
+        filename = argv[i];
+    }
+  if (filename == NULL && erase != 2)
+    error_no_arg (_("file to load"));
+
+  if (!probe->stopped)
+    mkii_stop_now (probe, 1);
+  if (!probe->stopped)
+    error (_("cannot stop target"));
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (xfree, filename);
+
+      abfd = bfd_openr (filename, gnutarget);
+      if (abfd == NULL)
+        {
+          perror_with_name (filename);
+          return;
+        }
+      make_cleanup_bfd_close (abfd);
+
+      if (!bfd_check_format (abfd, bfd_object))
+        error (_("\"%s\" is not an object file: %s"), filename,
+               bfd_errmsg (bfd_get_error ()));
+    }
+
+  mkii_handle_events (probe);
+
+  res = mkii_cmd_simple (probe, CMND_ENTER_PROGMODE);
+  if (res != 0)
+    error (_("atmel-mkii: cannot enter prog-mode: %02x\n"), res);
+
+  if (erase)
+    {
+      res = mkii_cmd_simple (probe, CMND_CHIP_ERASE);
+      if (res != 0)
+        {
+          mkii_cmd_simple (probe, CMND_LEAVE_PROGMODE);
+          error (_("atmel-mkii: cannot erase chip: %02x\n"), res);
+        }
+    }
+
+  if (filename)
+    {
+      for (section = abfd->sections; section; section = section->next)
+        {
+          bfd_vma section_address;
+          bfd_size_type section_size;
+          file_ptr fptr;
+          int n;
+          const struct avr_memdesc *mdesc;
+          int page_size;
+          unsigned char memtype;
+          unsigned char *buf;
+
+          if (!(bfd_get_section_flags (abfd, section) & SEC_LOAD))
+            continue;
+
+          section_address = bfd_section_lma (pbfd, section);
+          section_size = bfd_get_section_size (section);
+
+          if (!quiet)
+            printf_filtered ("[Loading section %s at 0x%lx (%d bytes)]\n",
+                             bfd_get_section_name (abfd, section),
+                             (unsigned long) section_address,
+                             (int) section_size);
+
+          mdesc = get_avr_memdesc (section_address,
+                                   section_address + section_size - 1);
+          if (mdesc == NULL)
+            continue;
+
+          switch (mdesc->memtype)
+            {
+            case MEMORY_TYPE_SPM:
+              page_size = read_le2 (desc->data.uiFlashPageSize);
+              if (page_size == 0)
+                page_size = 256;
+              memtype = MEMORY_TYPE_FLASH_PAGE;
+              break;
+            default:
+              printf_filtered (_("Unhandled memtype 0x%x\n"), mdesc->memtype);
+              continue;
+            }
+
+          buf = xmalloc (page_size);
+          fptr = 0;
+          while (section_size > 0)
+            {
+              int count;
+              int off = section_address % page_size;
+              int res;
+
+              count = min (section_size, page_size - off);
+
+              if (off != 0 || count != page_size)
+                memset (buf, 0xff, page_size);
+
+              bfd_get_section_contents (abfd, section, buf + off, fptr, count);
+
+              if (off || count != page_size)
+                section_address -= off;
+              res = mkii_write_mem
+                (probe, memtype, section_address, buf, page_size);
+              if (res != page_size)
+                {
+                  printf_unfiltered (_("Error while downloading %s section.\n"),
+                                     bfd_get_section_name (abfd, section));
+                  break;
+                }
+
+              section_address += page_size;
+              fptr += count;
+              section_size -= count;
+            }
+          xfree (buf);
+        }
+
+      /* This is necessary because many things were based on the PC at
+         the time that we attached to the monitor, which is no longer
+         valid now that we have loaded new code (and just changed the
+         PC).  Another way to do this might be to call normal_stop,
+         except that the stack may not be valid, and things would get
+         horribly confused... */
+
+      clear_symtab_users (0);
+    }
+
+  res = mkii_cmd_simple (probe, CMND_LEAVE_PROGMODE);
+  if (res != 0)
+    error (_("atmel-mkii: cannot leave prog-mode: %02x\n"), res);
+
+  /* Reset now.  */
+  {
+    unsigned char cmd[2];
+    cmd[0] = CMND_RESET;
+    cmd[1] = FLAG_LOW_LEVEL;
+    res = mkii_cmd_status (probe, cmd, 2);
+    if (res != 0)
+      fprintf_unfiltered (gdb_stdlog, "atmel-mkii: reset: got 0x%02x\n", res);
+  }
+
+  mkii_ping (probe);
+  if (!probe->stopped)
+    fprintf_unfiltered (gdb_stdlog, "atmel-mkii: target not stopped\n");
+  probe->events_mask &= ~MKII_EVENT_RUN;
+
+  do_cleanups (old_chain);
+}
+
+static void
+info_atmel_mkii_fuse_command (char *args, int from_tty)
+{
+  struct mkii_probe *probe = &probe1;
+  unsigned char buf[4];
+  int res;
+  const struct param_description *param;
+
+  if (probe->udev == NULL)
+    error (_("target atmel-mkii not selected"));
+
+  mkii_handle_events (probe);
+
+  res = mkii_cmd_simple (probe, CMND_ENTER_PROGMODE);
+  if (res != 0)
+    error (_("atmel-mkii: cannot enter prog-mode: %02x\n"), res);
+
+  res = mkii_read_mem (probe, MEMORY_TYPE_LOCK_BITS, 0, buf, 1);
+  if (res == 1)
+    ui_out_field_fmt (uiout, "locks", "Lock bits: 0x%02x\n", buf[0]);
+
+  res = mkii_read_mem (probe, MEMORY_TYPE_FUSE_BITS, 0, buf, 3);
+  if (res == 3)
+    ui_out_field_fmt (uiout, "fuse", "Fuse bits: %02x %02x %02x\n",
+                      buf[0], buf[1], buf[2]);
+
+  res = mkii_cmd_simple (probe, CMND_LEAVE_PROGMODE);
+  if (res != 0)
+    error (_("atmel-mkii: cannot leave prog-mode: %02x\n"), res);
+}
+
+static void
+info_atmel_mkii_flash_command (char *args, int from_tty)
+{
+  struct mkii_probe *probe = &probe1;
+  const struct device_descriptor *desc = probe->dev_data;
+  unsigned char buf[4];
+  int res;
+  const struct param_description *param;
+
+  if (probe->udev == NULL || desc == NULL)
+    error (_("target atmel-mkii not selected"));
+  printf_unfiltered ("flash page size: %u bytes\n",
+                     read_le2 (desc->data.uiFlashPageSize));
+  printf_unfiltered ("flash size: %u bytes\n",
+                     read_le4 (desc->data.ulFlashSize));
+}
+
+/* Define the target subroutine names */
+
+static void
+init_mkii_ops (void)
+{
+  mkii_ops.to_shortname = "atmel-mkii";
+  mkii_ops.to_longname = "Atmel JTAGICE mkII probe";
+  mkii_ops.to_doc = "Use an Atmel JTAGICE mkII probe on USB";
+  mkii_ops.to_open = mkii_open;
+  mkii_ops.to_close = mkii_close;
+
+  mkii_ops.to_xfer_partial = mkii_xfer_partial;
+  mkii_ops.to_fetch_registers = mkii_fetch_registers;
+  mkii_ops.to_store_registers = mkii_store_registers;
+  mkii_ops.to_prepare_to_store = mkii_prepare_to_store;
+
+  mkii_ops.to_kill = mkii_kill;
+  mkii_ops.to_resume = mkii_resume;
+  mkii_ops.to_wait = mkii_wait;
+
+  mkii_ops.to_load = mkii_load;
+  mkii_ops.to_stop = mkii_stop;
+
+  mkii_ops.to_insert_breakpoint = mkii_insert_breakpoint;
+  mkii_ops.to_remove_breakpoint = mkii_remove_breakpoint;
+
+  mkii_ops.to_create_inferior = mkii_create_inferior;
+  mkii_ops.to_mourn_inferior = mkii_mourn_inferior;
+
+#if 0
+  mkii_ops.deprecated_xfer_memory = mkii_xfer_memory;
+  mkii_ops.to_files_info = mkii_files_info;
+  mkii_ops.to_can_use_hw_breakpoint = mkii_can_use_hw_watchpoint;
+  mkii_ops.to_insert_watchpoint = mkii_insert_watchpoint;
+  mkii_ops.to_remove_watchpoint = mkii_remove_watchpoint;
+  mkii_ops.to_stopped_by_watchpoint = mkii_stopped_by_watchpoint;
+  mkii_ops.to_stopped_data_address = mkii_stopped_data_address;
+  mkii_ops.to_log_command = serial_log_command;
+  mkii_ops.to_thread_alive = mkii_thread_alive;
+  mkii_ops.to_pid_to_str = mkii_pid_to_str;
+#endif
+  mkii_ops.to_has_all_memory = default_child_has_all_memory;
+  mkii_ops.to_has_memory = default_child_has_memory;
+  mkii_ops.to_has_stack = default_child_has_stack;
+  mkii_ops.to_has_registers = default_child_has_registers;
+  mkii_ops.to_has_execution = default_child_has_execution;
+  mkii_ops.to_stratum = process_stratum;
+  mkii_ops.to_magic = OPS_MAGIC;
+};
+
+extern initialize_file_ftype _initialize_remote_atmel_mkii;
+
+#endif /* HAVE_LIBUSB */
+
+void
+_initialize_remote_atmel_mkii (void)
+{
+#ifdef HAVE_LIBUSB
+  struct cmd_list_element *c;
+
+  gdb_assert (sizeof (struct device_descriptor_data) == DEVICE_DESCRIPTOR_LEN);
+
+  init_mkii_ops ();
+  add_target (&mkii_ops);
+  mkii_ptid = ptid_build (42000, 0, 1);
+
+  /* Add root prefix command for all "info atmel-mkii" commands.  */
+  add_prefix_cmd ("atmel-mkii", class_info, info_atmel_mkii_command,
+		  _("Various Atmel mkii specific commands."),
+		  &info_atmel_mkii_cmdlist, "info atmel-mkii ", 0, &infolist);
+
+  add_cmd ("probes", class_info, info_atmel_mkii_probes_command,
+           _("Get list of Atmel JTAGICE mkii probes.\n"),
+           &info_atmel_mkii_cmdlist);
+  add_cmd ("devices", class_info, info_atmel_mkii_devices_command,
+           _("Get list of known Atmel devices.\n"),
+           &info_atmel_mkii_cmdlist);
+  add_cmd ("parameters", class_info, info_atmel_mkii_parameters_command,
+           _("Display atmel JTAGICE mkii parameters.\n"),
+           &info_atmel_mkii_cmdlist);
+  add_cmd ("fuse", class_info, info_atmel_mkii_fuse_command,
+           _("Display AVR fuse and lock bits.\n"),
+           &info_atmel_mkii_cmdlist);
+  add_cmd ("flash", class_info, info_atmel_mkii_flash_command,
+           _("Display AVR flash state.\n"),
+           &info_atmel_mkii_cmdlist);
+
+  add_prefix_cmd ("atmel-mkii", class_maintenance,
+                  maintenance_atmel_mkii_command,
+                  _("Various Atmel mkii maintainance commands"),
+		  &maintenance_atmel_mkii_cmdlist, "maintenance atmel-mkii ",
+		  0/*allow-unknown*/,
+		  &maintenancelist);
+
+  c = add_cmd ("load-xml", class_obscure, mkii_load_xml_command,
+               _("Load Atmel part description file for JTAGICE mkII."),
+               &maintenance_atmel_mkii_cmdlist);
+  set_cmd_completer (c, filename_completer);
+  add_cmd ("ping", class_obscure, mkii_ping_command,
+           _("Ping Atmel JTAGICE mkII probe."),
+           &maintenance_atmel_mkii_cmdlist);
+#endif /* HAVE_LIBUSB */
+}
-- 
1.7.10.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]