* monitor.c: Move all xmodem stuff into xmodem.[ch]. Remove
authorStu Grossman <grossman@cygnus>
Mon, 17 Apr 1995 06:31:39 +0000 (06:31 +0000)
committerStu Grossman <grossman@cygnus>
Mon, 17 Apr 1995 06:31:39 +0000 (06:31 +0000)
unnecessary remoteloadprotocol and remoteloadtype support.
* (expect expect_prompt):  Change names to monitor_expect and
monitor_expect_prompt.  Make them global.
* (printf_monitor):  Change name to monitor_printf.  Make global.
* (monitor_read_memory):  Flush command echo to avoid parsing
ambiguity with CPU32Bug monitor.
* (monitor_load):  Remove remoteloadprotocol and remoteloadtype
support.  Call target_ops->load_routine, default to
monitor_load_srec.
* (monitor_load_srec):  Remove everything but S-record support.
* monitor.h (monitor_ops):  Add load_routine to provide monitor
specific download capability.
* remote-est.c:  Clean up copyrights and comments.
* w89k-rom.c:  Use new xmodem support.
* xmodem.c xmodem.h:  New files to support xmodem downloads.
* rom68k-rom.c remote-est.c:  Fix copyrights, add load_routine
entry to monitor_ops.
* cpu32bug-rom.c:  New file to support Moto BCC debuggers.
* config/m68k/est.mt (TDEPFILES):  Add cpu32bug.o.
* config/pa/hppapro.mt (TDEPFILES):  Add xmodem.o.

gdb/.Sanitize
gdb/config/m68k/est.mt
gdb/config/pa/hppapro.mt
gdb/cpu32bug-rom.c [new file with mode: 0644]
gdb/monitor.h
gdb/remote-est.c
gdb/rom68k-rom.c
gdb/w89k-rom.c
gdb/xmodem.c [new file with mode: 0644]
gdb/xmodem.h [new file with mode: 0644]

index 0d0822cfe6207425d4751847b365d1a64569046b..004f681421297818bb41fc19b0e08c879413e716 100644 (file)
@@ -112,6 +112,7 @@ core.c
 coredep.c
 corelow.c
 cp-valprint.c
+cpu32bug-rom.c
 cxux-nat.c
 dbxread.c
 dcache.c
@@ -326,6 +327,8 @@ w89k-rom.c
 xcoffread.c
 xcoffsolib.c
 xcoffsolib.h
+xmodem.c
+xmodem.h
 z8k-tdep.c
 
 
index d93fb973a9ba88ea38688da4701eeaeb243c550a..84aae4d28ade71eb6ccffd220d51fc318fa28e32 100644 (file)
@@ -1,3 +1,3 @@
 # Target: m68k emulator EST-300
-TDEPFILES= m68k-tdep.o monitor.o remote-est.o
+TDEPFILES= m68k-tdep.o monitor.o remote-est.o cpu32bug-rom.o
 TM_FILE= tm-est.h
index 4cafd9516caaecfa160d8434cf1ae9d326fe1f79..b2786add4d656993c21d1b3ebe1ff6ca7fc92b9d 100644 (file)
@@ -1,4 +1,4 @@
 # Target: PA based debug monitor
-TDEPFILES= hppa-tdep.o op50-rom.o w89k-rom.o monitor.o
+TDEPFILES= hppa-tdep.o op50-rom.o w89k-rom.o monitor.o xmodem.o
 TM_FILE= tm-pro.h
 XDEPFILES= ser-tcp.o
diff --git a/gdb/cpu32bug-rom.c b/gdb/cpu32bug-rom.c
new file mode 100644 (file)
index 0000000..5deefbb
--- /dev/null
@@ -0,0 +1,177 @@
+/* Remote debugging interface for CPU32Bug Rom monitor for GDB, the GNU debugger.
+   Copyright 1995 Free Software Foundation, Inc.
+
+   Written by Stu Grossman of Cygnus Support
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void cpu32bug_open PARAMS ((char *args, int from_tty));
+
+static void
+cpu32bug_supply_register (regname, regnamelen, val, vallen)
+     char *regname;
+     int regnamelen;
+     char *val;
+     int vallen;
+{
+  int regno;
+
+  if (regnamelen != 2)
+    return;
+
+  switch (regname[0])
+    {
+    case 'S':
+      if (regname[1] != 'R')
+       return;
+      regno = PS_REGNUM;
+      break;
+    case 'P':
+      if (regname[1] != 'C')
+       return;
+      regno = PC_REGNUM;
+      break;
+    case 'D':
+      if (regname[1] < '0' || regname[1] > '7')
+       return;
+      regno = regname[1] - '0' + D0_REGNUM;
+      break;
+    case 'A':
+      if (regname[1] < '0' || regname[1] > '7')
+       return;
+      regno = regname[1] - '0' + A0_REGNUM;
+      break;
+    default:
+      return;
+    }
+
+  monitor_supply_register (regno, val);
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes an "A7".
+ */
+
+static char *cpu32bug_regnames[NUM_REGS] =
+{
+  "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+  "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
+  "SR", "PC",
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops cpu32bug_ops;
+
+static char *cpu32bug_loadtypes[] = {"srec", NULL};
+static char *cpu32bug_loadprotos[] = {"none", NULL};
+
+static char *cpu32bug_inits[] = {"\r", NULL};
+
+static struct monitor_ops cpu32bug_cmds =
+{
+  MO_CLR_BREAK_USES_ADDR,
+  cpu32bug_inits,              /* Init strings */
+  "g\r",                       /* continue command */
+  "t\r",                       /* single step */
+  NULL,                                /* interrupt command */
+  "br %x\r",                   /* set a breakpoint */
+  "nobr %x\r",                 /* clear a breakpoint */
+  "nobr\r",                    /* clear all breakpoints */
+  "bf %x:%x %x;b\r",           /* fill (start count val) */
+  {
+    "ms %x %02x\r",            /* setmem.cmdb (addr, value) */
+    "ms %x %04x\r",            /* setmem.cmdw (addr, value) */
+    "ms %x %08x\r",            /* setmem.cmdl (addr, value) */
+    NULL,                      /* setmem.cmdll (addr, value) */
+    NULL,                      /* setreg.resp_delim */
+    NULL,                      /* setreg.term */
+    NULL,                      /* setreg.term_cmd */
+  },
+  {
+    "md %x:%x;b\r",            /* getmem.cmdb (addr, len) */
+    "md %x:%x;b\r",            /* getmem.cmdw (addr, len) */
+    "md %x:%x;b\r",            /* getmem.cmdl (addr, len) */
+    NULL,                      /* getmem.cmdll (addr, len) */
+    " ",                       /* getmem.resp_delim */
+    NULL,                      /* getmem.term */
+    NULL,                      /* getmem.term_cmd */
+  },
+  {
+    "rs %s %x\r",              /* setreg.cmd (name, value) */
+    NULL,                      /* setreg.resp_delim */
+    NULL,                      /* setreg.term */
+    NULL                       /* setreg.term_cmd */
+  },
+  {
+    "rs %s\r",                 /* getreg.cmd (name) */
+    "=",                       /* getreg.resp_delim */
+    NULL,                      /* getreg.term */
+    NULL                       /* getreg.term_cmd */
+  },
+  "rd\r",                      /* dump_registers */
+  "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)", /* register_pattern */
+  cpu32bug_supply_register,    /* supply_register */
+  NULL,                                /* load_routine (defaults to SRECs) */
+  "lo\r",                      /* download command */
+  "lo\r\n",                    /* load response */
+  "CPU32Bug>",                 /* monitor command prompt */
+  NULL,                                /* end-of-command delimitor */
+  NULL,                                /* optional command terminator */
+  &cpu32bug_ops,               /* target operations */
+  cpu32bug_loadtypes,          /* loadtypes */
+  cpu32bug_loadprotos,         /* loadprotos */
+  "9600",                      /* supported baud rates */
+  SERIAL_1_STOPBITS,           /* number of stop bits */
+  cpu32bug_regnames,           /* registers names */
+  MONITOR_OPS_MAGIC            /* magic */
+  };
+
+void
+cpu32bug_open(args, from_tty)
+     char *args;
+     int from_tty;
+{
+  monitor_open (args, &cpu32bug_cmds, from_tty);
+}
+
+void
+_initialize_cpu32bug_rom ()
+{
+  init_monitor_ops (&cpu32bug_ops);
+
+  cpu32bug_ops.to_shortname = "cpu32bug";
+  cpu32bug_ops.to_longname = "CPU32Bug monitor";
+  cpu32bug_ops.to_doc = "Debug via the CPU32Bug monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+  cpu32bug_ops.to_open = cpu32bug_open;
+
+  add_target (&cpu32bug_ops);
+}
index e752345d6b00c3bc646364689a7eb4a0381db7e3..d4e99621569a63a4334d0cd07d20657b11df9d8f 100644 (file)
@@ -22,6 +22,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "serial.h"
+
 struct rom_cmd_data {
   char *cmd;                   /* command to send */
   char *delim;                 /* the delimiter */
@@ -98,6 +100,7 @@ struct monitor_ops
   char *dump_registers;                /* Command to dump all regs at once */
   char *register_pattern;      /* Pattern that picks out register from reg dump */
   void (*supply_register) PARAMS ((char *name, int namelen, char *val, int vallen));
+  void (*load_routine) PARAMS ((serial_t desc, char *file, int hashmark)); /* Download routine */
   char *load;                  /* load command */
   char *loadresp;              /* Response to load command */
   char *prompt;                        /* monitor command prompt */
@@ -167,8 +170,9 @@ extern struct monitor_ops        *current_monitor;
 #define MEM_DIS_CMD            (current_monitor->getmem)
 #define REG_DELIM               (current_monitor->regset.delim)
 
+extern void monitor_open PARAMS ((char *args, struct monitor_ops *ops, int from_tty));
+extern char *monitor_supply_register PARAMS ((int regno, char *valstr));
+extern int monitor_expect PARAMS ((char *prompt, char *buf, int buflen));
+extern int monitor_expect_prompt PARAMS ((char *buf, int buflen));
+extern void monitor_printf ();
 extern void init_monitor_ops PARAMS ((struct target_ops *));
-
-extern void monitor_open PARAMS ((char *, struct monitor_ops *, int));
-
-extern char *monitor_supply_register PARAMS ((int, char *));
index 83866591ebf25d778cba4af39c89c85c127b176a..b8d5f5a8baf7846e49d9d6dd80739b19bdea1f92 100644 (file)
@@ -1,25 +1,25 @@
 /* Remote debugging interface for EST-300 ICE, for GDB
-   Copyright 1994 Free Software Foundation, Inc.
+   Copyright 1995 Free Software Foundation, Inc.
    Contributed by Cygnus Support.
 
    Written by Steve Chamberlain for Cygnus Support.
    Re-written by Stu Grossman of Cygnus Support
 
-   This file is part of GDB.
+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 2 of the License, or
-   (at your option) any later version.
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "defs.h"
 #include "gdbcore.h"
@@ -142,6 +142,7 @@ static struct monitor_ops est_cmds =
   "dr\r",                      /* dump_registers */
   "\\(\\w+\\) = \\([0-9a-fA-F]+\\)", /* register_pattern */
   est_supply_register,         /* supply_register */
+  NULL,                                /* load_routine (defaults to SRECs) */
   "dl\r",                      /* download command */
   "+",                         /* load response */
   ">BKM>",                     /* monitor command prompt */
index 220a049c4b64b4f908cdffe88359a5d695a0e020..ca1d41d6f5f8a82313b0512b6b2440d7dfe39122 100644 (file)
@@ -23,7 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "monitor.h"
 #include "serial.h"
 
-static void rom68k_open PARAMS ((char *, int));
+static void rom68k_open PARAMS ((char *args, int from_tty));
 
 static void
 rom68k_supply_register (regname, regnamelen, val, vallen)
@@ -39,40 +39,36 @@ rom68k_supply_register (regname, regnamelen, val, vallen)
   regno = -1;
 
   if (regnamelen == 2)
-    {
-      switch (regname[0])
-       {
-       case 'S':
-         if (regname[1] == 'R')
-           regno = PS_REGNUM;
+    switch (regname[0])
+      {
+      case 'S':
+       if (regname[1] == 'R')
+         regno = PS_REGNUM;
+       break;
+      case 'P':
+       if (regname[1] == 'C')
+         regno = PC_REGNUM;
+       break;
+      case 'D':
+       if (regname[1] != 'R')
          break;
-       case 'P':
-         if (regname[1] == 'C')
-           regno = PC_REGNUM;
+       regno = D0_REGNUM;
+       numregs = 8;
+       break;
+      case 'A':
+       if (regname[1] != 'R')
          break;
-       case 'D':
-         if (regname[1] != 'R')
-           break;
-         regno = D0_REGNUM;
-         numregs = 8;
-         break;
-       case 'A':
-         if (regname[1] != 'R')
-           break;
-         regno = A0_REGNUM;
-         numregs = 7;
-         break;
-       }
-    }
+       regno = A0_REGNUM;
+       numregs = 7;
+       break;
+      }
   else if (regnamelen == 3)
-    {
-      switch (regname[0])
-       {
-       case 'I':
-         if (regname[1] == 'S' && regname[2] == 'P')
-           regno = SP_REGNUM;
-       }
-    }
+    switch (regname[0])
+      {
+      case 'I':
+       if (regname[1] == 'S' && regname[2] == 'P')
+         regno = SP_REGNUM;
+      }
 
   if (regno >= 0)
     while (numregs-- > 0)
@@ -145,6 +141,7 @@ static struct monitor_ops rom68k_cmds =
                                /* register_pattern */
   "\\(\\w+\\)=\\([0-9a-fA-F]+\\( +[0-9a-fA-F]+\\b\\)*\\)",
   rom68k_supply_register,      /* supply_register */
+  NULL,                                /* load_routine (defaults to SRECs) */
   "dc\r",                      /* download command */
   "Waiting for S-records from host... ", /* Load response */
   "ROM68K :->",                        /* monitor command prompt */
index 5023e3120343c0ebf50e61cf0dc2702ada82d3a8..aedd739c69b14ec00b3a99cac9457ee8fbd9d138 100644 (file)
@@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "target.h"
 #include "monitor.h"
 #include "serial.h"
+#include "xmodem.h"
 
 static void w89k_open PARAMS ((char *args, int from_tty));
 
@@ -154,6 +155,82 @@ w89k_supply_register (regname, regnamelen, val, vallen)
       val = monitor_supply_register (regno++, val);
 }
 
+static int hashmark = 1;       /* flag set by "set hash" */
+
+extern struct monitor_ops w89k_cmds; /* fwd decl */
+
+static void
+w89k_load (desc, file, hashmark)
+     serial_t desc;
+     char *file;
+     int hashmark;
+{
+  bfd *abfd;
+  asection *s;
+  char *buffer;
+  int i;
+
+  buffer = alloca (XMODEM_PACKETSIZE);
+
+  abfd = bfd_openr (file, 0);
+  if (!abfd)
+    {
+      printf_filtered ("Unable to open file %s\n", file);
+      return;
+    }
+
+  if (bfd_check_format (abfd, bfd_object) == 0)
+    {
+      printf_filtered ("File is not an object file\n");
+      return;
+    }
+  
+  for (s = abfd->sections; s; s = s->next)
+    if (s->flags & SEC_LOAD)
+      {
+       bfd_size_type section_size;
+
+       printf_filtered ("%s\t: 0x%4x .. 0x%4x  ", s->name, s->vma,
+                        s->vma + s->_raw_size);
+       gdb_flush (gdb_stdout);
+
+       monitor_printf (w89k_cmds.load, s->vma);
+       if (w89k_cmds.loadresp)
+         monitor_expect (w89k_cmds.loadresp, NULL, 0);
+
+       xmodem_init_xfer (desc);
+
+       section_size = bfd_section_size (abfd, s);
+
+       for (i = 0; i < section_size; i += XMODEM_DATASIZE)
+         {
+           int numbytes;
+
+           numbytes = min (XMODEM_DATASIZE, section_size - i);
+
+           bfd_get_section_contents (abfd, s, buffer + XMODEM_DATAOFFSET, i,
+                                     numbytes);
+
+           xmodem_send_packet (desc, buffer, numbytes, hashmark);
+
+           if (hashmark)
+             {
+               putchar_unfiltered ('#');
+               gdb_flush (gdb_stdout);
+             }
+         }                     /* Per-packet (or S-record) loop */
+
+       xmodem_finish_xfer (desc);
+
+       monitor_expect_prompt (NULL, 0);
+
+       putchar_unfiltered ('\n');
+      }                                /* Loadable sections */
+  
+  if (hashmark) 
+    putchar_unfiltered ('\n');
+}
+
 /*
  * Define the monitor command strings. Since these are passed directly
  * through to a printf style function, we need can include formatting
@@ -162,7 +239,7 @@ w89k_supply_register (regname, regnamelen, val, vallen)
 
 static struct target_ops w89k_ops;
 
-static char *w89k_loadtypes[] = {"srec", NULL};
+static char *w89k_loadtypes[] = {"binary", NULL};
 static char *w89k_loadprotos[] = {"xmodem", NULL};
 
 static char *w89k_inits[] = {"\r", NULL};
@@ -211,8 +288,9 @@ static struct monitor_ops w89k_cmds =
   "r\r",                       /* dump_registers */
   "\\(\\w+\\)\\( +[0-9a-fA-F]+\\b\\)+",
   w89k_supply_register,                /* supply_register */
-  "u\r",                       /* download command */
-  "u\n\r",                     /* load response */
+  w89k_load,                   /* load routine */
+  "u %x\r",                    /* download command */
+  "\r",                                /* load response */
   "ROM>",                      /* monitor command prompt */
   NULL,                                /* end-of-command delimitor */
   NULL,                                /* optional command terminator */
diff --git a/gdb/xmodem.c b/gdb/xmodem.c
new file mode 100644 (file)
index 0000000..a854c9f
--- /dev/null
@@ -0,0 +1,284 @@
+/* XMODEM support for GDB, the GNU debugger.
+   Copyright 1995 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "serial.h"
+#include "target.h"
+#include "xmodem.h"
+
+/* These definitions are for xmodem protocol. */
+
+#define SOH    0x01
+#define STX    0x02
+#define ACK    0x06
+#define NAK    0x15
+#define EOT    0x04
+#define CANCEL 0x18
+
+static int blknum;             /* XMODEM block number */
+static int crcflag;            /* Sez we are using CRC's instead of cksums */
+
+static int
+readchar (desc, timeout)
+     serial_t desc;
+     int timeout;
+{
+  int c;
+
+  c = SERIAL_READCHAR (desc, timeout);
+
+  if (remote_debug > 0)
+    fputc_unfiltered (c, gdb_stderr);
+
+  if (c >= 0)
+    return c;
+
+  if (c == SERIAL_TIMEOUT)
+    error ("Timeout reading from remote system.");
+
+  perror_with_name ("xmodem.c:readchar()");
+}
+
+#define CRC16 0x1021           /* Generator polynomial (X^16 + X^12 + X^5 + 1) */
+
+static unsigned short *crctab;
+
+/* Call this to init the fast CRC-16 calculation table.  */
+
+static void
+crcinit ()
+{
+  static int crctab_inited = 0;
+  int val;
+
+  if (crctab_inited == 1)
+    return;
+
+  crctab = xmalloc (256 * sizeof (short));
+
+  for (val = 0; val <= 255; val++)
+    {
+      int i;
+      unsigned int crc;
+
+      crc = val << 8;
+
+      for (i = 0; i < 8; ++i)
+       {
+         crc <<= 1;
+
+         if (crc & 0x10000)
+           crc ^= CRC16;
+       }
+
+      crctab [val] = crc;
+    }
+
+  crctab_inited = 1;
+}
+
+/* Calculate a CRC-16 for the LEN byte message pointed at by P.  */
+
+static unsigned short
+docrc (p, len)
+     unsigned char *p;
+     int len;
+{
+  unsigned short crc = 0;
+
+  while (len-- > 0)
+    crc = (crc << 8) ^ crctab [(crc >> 8) ^ *p++];
+
+  return crc;
+}
+
+/* Start up the transmit process.  Reset state variables.  Wait for receiver to
+   send NAK or CRC request.  */
+
+int
+xmodem_init_xfer (desc)
+     serial_t desc;
+{
+  int c;
+  int i;
+
+  blknum = 1;
+  crcflag = 0;
+  crcinit ();
+
+  for (i = 1; i <= 10; i++)
+    {
+      c = readchar (desc, 6);
+
+      switch (c)
+       {
+       case 'C':
+         crcflag = 1;
+       case NAK:
+         return 0;
+       default:
+         fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c);
+         continue;
+       case CANCEL:            /* target aborted load */
+         fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n");
+         continue;
+       }
+    }
+  error ("xmodem_init_xfer:  Too many unexpected characters.");
+}
+
+/* Take 128 bytes of data and make a packet out of it.
+ *
+ *     Each packet looks like this:
+ *     +-----+-------+-------+------+-----+
+ *     | SOH | Seq1. | Seq2. | data | SUM |
+ *     +-----+-------+-------+------+-----+
+ *     SOH  = 0x01
+ *     Seq1 = The sequence number.
+ *     Seq2 = The complement of the sequence number.
+ *     Data = A 128 bytes of data.
+ *     SUM  = Add the contents of the 128 bytes and use the low-order
+ *            8 bits of the result.
+ *
+ * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the
+ * remote system.  PACKET must be XMODEM_PACKETSIZE bytes long.  The data must
+ * start 3 bytes after the beginning of the packet to leave room for the
+ * XMODEM header.  LEN is the length of the data portion of the packet (and
+ * must be <= 128 bytes).  If it is < 128 bytes, ^Z padding will be added.
+ */
+
+void
+xmodem_send_packet (desc, packet, len, hashmark)
+     serial_t desc;
+     unsigned char *packet;
+     int len;
+     int hashmark;
+{
+  int i;
+  int retries;
+  int pktlen;
+  int datasize;
+  
+  /* build the packet header */
+
+  packet[1] = blknum;
+  packet[2] = ~blknum;
+
+  blknum++;
+  
+  if (len <= XMODEM_DATASIZE)
+    {
+      packet[0] = SOH;
+      datasize = XMODEM_DATASIZE;
+    }
+  else if (len <= XMODEM_1KDATASIZE)
+    {
+      packet[0] = STX;
+      datasize = XMODEM_1KDATASIZE;
+    }
+  else
+    abort ();                  /* Packet way too large */
+
+  /* Add ^Z padding if packet < 128 (or 1024) bytes */
+
+  memset (packet + 3 + len, '\026', datasize - len);
+
+  if (crcflag)
+    {
+      int crc;
+
+      crc = docrc (packet + 3, datasize);
+
+      packet[3 + datasize] = crc >> 8;
+      packet[3 + datasize + 1] = crc;
+      pktlen = datasize + 5;
+    }
+  else
+    {
+      int sum;
+
+      sum = 0;
+      for (i = 3; i < datasize + 3; i++)
+       sum += packet[i];
+
+      packet[3 + datasize] = sum; /* add the checksum */
+      pktlen = datasize + 4;
+    }
+
+  for (retries = 3; retries >= 0; retries--)
+    {
+      int c;
+
+      SERIAL_WRITE (desc, packet, pktlen);
+
+      c = readchar (desc, 3);
+      switch (c)
+       {
+       case ACK:
+         return;
+       case NAK:
+         if (!hashmark)
+           continue;
+         putchar_unfiltered ('-');
+         gdb_flush (gdb_stdout);
+         continue;
+       case CANCEL:
+         error ("xmodem_send_packet: Transfer aborted by receiver.");
+       default:
+         fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
+         continue;
+       }
+    }
+
+  SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
+
+  error ("xmodem_send_packet:  Excessive retries.");
+}
+
+/* Finish off the transfer.  Send out the EOT, and wait for an ACK.  */
+
+void
+xmodem_finish_xfer (desc)
+     serial_t desc;
+{
+  int retries;
+
+  for (retries = 10; retries >= 0; retries--)
+    {
+      int c;
+
+      SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
+
+      c = readchar (desc, 3);
+      switch (c)
+       {
+       case ACK:
+         return;
+       case NAK:
+         continue;
+       case CANCEL:
+         error ("xmodem_finish_xfer: Transfer aborted by receiver.");
+       default:
+         fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
+         continue;
+       }
+    }
+
+  error ("xmodem_finish_xfer:  Excessive retries.");
+}
diff --git a/gdb/xmodem.h b/gdb/xmodem.h
new file mode 100644 (file)
index 0000000..8f1b749
--- /dev/null
@@ -0,0 +1,29 @@
+/* XMODEM support for GDB, the GNU debugger.
+   Copyright 1995 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+int xmodem_init_xfer PARAMS ((serial_t desc));
+void send_xmodem_packet PARAMS ((serial_t desc, unsigned char *packet, int len,
+                                int hashmark));
+void xmodem_finish_xfer PARAMS ((serial_t desc));
+
+#define XMODEM_DATASIZE        128     /* The data size is ALWAYS 128 */
+#define XMODEM_1KDATASIZE 1024 /* Unless it's 1024!!! */
+#define XMODEM_PACKETSIZE 133  /* data + packet headers and crc */
+#define XMODEM_1KPACKETSIZE 1024 + 5 /* data + packet headers and crc */
+#define XMODEM_DATAOFFSET 3    /* Offset to start of actual data */