OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [xmodem.c] - Diff between revs 105 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 105 Rev 1765
/* XMODEM support for GDB, the GNU debugger.
/* XMODEM support for GDB, the GNU debugger.
   Copyright 1995 Free Software Foundation, Inc.
   Copyright 1995 Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
   Boston, MA 02111-1307, USA.  */
 
 
#include "defs.h"
#include "defs.h"
#include "serial.h"
#include "serial.h"
#include "target.h"
#include "target.h"
#include "xmodem.h"
#include "xmodem.h"
 
 
/* These definitions are for xmodem protocol. */
/* These definitions are for xmodem protocol. */
 
 
#define SOH     0x01
#define SOH     0x01
#define STX     0x02
#define STX     0x02
#define ACK     0x06
#define ACK     0x06
#define NAK     0x15
#define NAK     0x15
#define EOT     0x04
#define EOT     0x04
#define CANCEL  0x18
#define CANCEL  0x18
 
 
static int blknum;              /* XMODEM block number */
static int blknum;              /* XMODEM block number */
static int crcflag;             /* Sez we are using CRC's instead of cksums */
static int crcflag;             /* Sez we are using CRC's instead of cksums */
 
 
static int
static int
readchar (desc, timeout)
readchar (desc, timeout)
     serial_t desc;
     serial_t desc;
     int timeout;
     int timeout;
{
{
  int c;
  int c;
 
 
  c = SERIAL_READCHAR (desc, timeout);
  c = SERIAL_READCHAR (desc, timeout);
 
 
  if (remote_debug > 0)
  if (remote_debug > 0)
    fputc_unfiltered (c, gdb_stdlog);
    fputc_unfiltered (c, gdb_stdlog);
 
 
  if (c >= 0)
  if (c >= 0)
    return c;
    return c;
 
 
  if (c == SERIAL_TIMEOUT)
  if (c == SERIAL_TIMEOUT)
    error ("Timeout reading from remote system.");
    error ("Timeout reading from remote system.");
 
 
  perror_with_name ("xmodem.c:readchar()");
  perror_with_name ("xmodem.c:readchar()");
}
}
 
 
#define CRC16 0x1021            /* Generator polynomial (X^16 + X^12 + X^5 + 1) */
#define CRC16 0x1021            /* Generator polynomial (X^16 + X^12 + X^5 + 1) */
 
 
static unsigned short *crctab;
static unsigned short *crctab;
 
 
/* Call this to init the fast CRC-16 calculation table.  */
/* Call this to init the fast CRC-16 calculation table.  */
 
 
static void
static void
crcinit ()
crcinit ()
{
{
  static int crctab_inited = 0;
  static int crctab_inited = 0;
  int val;
  int val;
 
 
  if (crctab_inited == 1)
  if (crctab_inited == 1)
    return;
    return;
 
 
  crctab = xmalloc (256 * sizeof (short));
  crctab = xmalloc (256 * sizeof (short));
 
 
  for (val = 0; val <= 255; val++)
  for (val = 0; val <= 255; val++)
    {
    {
      int i;
      int i;
      unsigned int crc;
      unsigned int crc;
 
 
      crc = val << 8;
      crc = val << 8;
 
 
      for (i = 0; i < 8; ++i)
      for (i = 0; i < 8; ++i)
        {
        {
          crc <<= 1;
          crc <<= 1;
 
 
          if (crc & 0x10000)
          if (crc & 0x10000)
            crc ^= CRC16;
            crc ^= CRC16;
        }
        }
 
 
      crctab[val] = crc;
      crctab[val] = crc;
    }
    }
 
 
  crctab_inited = 1;
  crctab_inited = 1;
}
}
 
 
/* Calculate a CRC-16 for the LEN byte message pointed at by P.  */
/* Calculate a CRC-16 for the LEN byte message pointed at by P.  */
 
 
static unsigned short
static unsigned short
docrc (p, len)
docrc (p, len)
     unsigned char *p;
     unsigned char *p;
     int len;
     int len;
{
{
  unsigned short crc = 0;
  unsigned short crc = 0;
 
 
  while (len-- > 0)
  while (len-- > 0)
    crc = (crc << 8) ^ crctab[(crc >> 8) ^ *p++];
    crc = (crc << 8) ^ crctab[(crc >> 8) ^ *p++];
 
 
  return crc;
  return crc;
}
}
 
 
/* Start up the transmit process.  Reset state variables.  Wait for receiver to
/* Start up the transmit process.  Reset state variables.  Wait for receiver to
   send NAK or CRC request.  */
   send NAK or CRC request.  */
 
 
int
int
xmodem_init_xfer (desc)
xmodem_init_xfer (desc)
     serial_t desc;
     serial_t desc;
{
{
  int c;
  int c;
  int i;
  int i;
 
 
  blknum = 1;
  blknum = 1;
  crcflag = 0;
  crcflag = 0;
  crcinit ();
  crcinit ();
 
 
  for (i = 1; i <= 10; i++)
  for (i = 1; i <= 10; i++)
    {
    {
      c = readchar (desc, 6);
      c = readchar (desc, 6);
 
 
      switch (c)
      switch (c)
        {
        {
        case 'C':
        case 'C':
          crcflag = 1;
          crcflag = 1;
        case NAK:
        case NAK:
          return 0;
          return 0;
        default:
        default:
          fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c);
          fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c);
          continue;
          continue;
        case CANCEL:            /* target aborted load */
        case CANCEL:            /* target aborted load */
          fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n");
          fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n");
          continue;
          continue;
        }
        }
    }
    }
  error ("xmodem_init_xfer:  Too many unexpected characters.");
  error ("xmodem_init_xfer:  Too many unexpected characters.");
}
}
 
 
/* Take 128 bytes of data and make a packet out of it.
/* Take 128 bytes of data and make a packet out of it.
 
 
 *      Each packet looks like this:
 *      Each packet looks like this:
 *      +-----+-------+-------+------+-----+
 *      +-----+-------+-------+------+-----+
 *      | SOH | Seq1. | Seq2. | data | SUM |
 *      | SOH | Seq1. | Seq2. | data | SUM |
 *      +-----+-------+-------+------+-----+
 *      +-----+-------+-------+------+-----+
 *      SOH  = 0x01
 *      SOH  = 0x01
 *      Seq1 = The sequence number.
 *      Seq1 = The sequence number.
 *      Seq2 = The complement of the sequence number.
 *      Seq2 = The complement of the sequence number.
 *      Data = A 128 bytes of data.
 *      Data = A 128 bytes of data.
 *      SUM  = Add the contents of the 128 bytes and use the low-order
 *      SUM  = Add the contents of the 128 bytes and use the low-order
 *             8 bits of the result.
 *             8 bits of the result.
 *
 *
 * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the
 * 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
 * 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
 * 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
 * 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.
 * must be <= 128 bytes).  If it is < 128 bytes, ^Z padding will be added.
 */
 */
 
 
void
void
xmodem_send_packet (desc, packet, len, hashmark)
xmodem_send_packet (desc, packet, len, hashmark)
     serial_t desc;
     serial_t desc;
     unsigned char *packet;
     unsigned char *packet;
     int len;
     int len;
     int hashmark;
     int hashmark;
{
{
  int i;
  int i;
  int retries;
  int retries;
  int pktlen;
  int pktlen;
  int datasize;
  int datasize;
 
 
  /* build the packet header */
  /* build the packet header */
 
 
  packet[1] = blknum;
  packet[1] = blknum;
  packet[2] = ~blknum;
  packet[2] = ~blknum;
 
 
  blknum++;
  blknum++;
 
 
  if (len <= XMODEM_DATASIZE)
  if (len <= XMODEM_DATASIZE)
    {
    {
      packet[0] = SOH;
      packet[0] = SOH;
      datasize = XMODEM_DATASIZE;
      datasize = XMODEM_DATASIZE;
    }
    }
  else if (len <= XMODEM_1KDATASIZE)
  else if (len <= XMODEM_1KDATASIZE)
    {
    {
      packet[0] = STX;
      packet[0] = STX;
      datasize = XMODEM_1KDATASIZE;
      datasize = XMODEM_1KDATASIZE;
    }
    }
  else
  else
    abort ();                   /* Packet way too large */
    abort ();                   /* Packet way too large */
 
 
  /* Add ^Z padding if packet < 128 (or 1024) bytes */
  /* Add ^Z padding if packet < 128 (or 1024) bytes */
 
 
  memset (packet + 3 + len, '\026', datasize - len);
  memset (packet + 3 + len, '\026', datasize - len);
 
 
  if (crcflag)
  if (crcflag)
    {
    {
      int crc;
      int crc;
 
 
      crc = docrc (packet + 3, datasize);
      crc = docrc (packet + 3, datasize);
 
 
      packet[3 + datasize] = crc >> 8;
      packet[3 + datasize] = crc >> 8;
      packet[3 + datasize + 1] = crc;
      packet[3 + datasize + 1] = crc;
      pktlen = datasize + 5;
      pktlen = datasize + 5;
    }
    }
  else
  else
    {
    {
      int sum;
      int sum;
 
 
      sum = 0;
      sum = 0;
      for (i = 3; i < datasize + 3; i++)
      for (i = 3; i < datasize + 3; i++)
        sum += packet[i];
        sum += packet[i];
 
 
      packet[3 + datasize] = sum;       /* add the checksum */
      packet[3 + datasize] = sum;       /* add the checksum */
      pktlen = datasize + 4;
      pktlen = datasize + 4;
    }
    }
 
 
  for (retries = 3; retries >= 0; retries--)
  for (retries = 3; retries >= 0; retries--)
    {
    {
      int c;
      int c;
 
 
      SERIAL_WRITE (desc, packet, pktlen);
      SERIAL_WRITE (desc, packet, pktlen);
 
 
      c = readchar (desc, 3);
      c = readchar (desc, 3);
      switch (c)
      switch (c)
        {
        {
        case ACK:
        case ACK:
          return;
          return;
        case NAK:
        case NAK:
          if (!hashmark)
          if (!hashmark)
            continue;
            continue;
          putchar_unfiltered ('-');
          putchar_unfiltered ('-');
          gdb_flush (gdb_stdout);
          gdb_flush (gdb_stdout);
          continue;
          continue;
        case CANCEL:
        case CANCEL:
          error ("xmodem_send_packet: Transfer aborted by receiver.");
          error ("xmodem_send_packet: Transfer aborted by receiver.");
        default:
        default:
          fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
          fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
          continue;
          continue;
        }
        }
    }
    }
 
 
  SERIAL_WRITE (desc, "\004", 1);       /* Send an EOT */
  SERIAL_WRITE (desc, "\004", 1);       /* Send an EOT */
 
 
  error ("xmodem_send_packet:  Excessive retries.");
  error ("xmodem_send_packet:  Excessive retries.");
}
}
 
 
/* Finish off the transfer.  Send out the EOT, and wait for an ACK.  */
/* Finish off the transfer.  Send out the EOT, and wait for an ACK.  */
 
 
void
void
xmodem_finish_xfer (desc)
xmodem_finish_xfer (desc)
     serial_t desc;
     serial_t desc;
{
{
  int retries;
  int retries;
 
 
  for (retries = 10; retries >= 0; retries--)
  for (retries = 10; retries >= 0; retries--)
    {
    {
      int c;
      int c;
 
 
      SERIAL_WRITE (desc, "\004", 1);   /* Send an EOT */
      SERIAL_WRITE (desc, "\004", 1);   /* Send an EOT */
 
 
      c = readchar (desc, 3);
      c = readchar (desc, 3);
      switch (c)
      switch (c)
        {
        {
        case ACK:
        case ACK:
          return;
          return;
        case NAK:
        case NAK:
          continue;
          continue;
        case CANCEL:
        case CANCEL:
          error ("xmodem_finish_xfer: Transfer aborted by receiver.");
          error ("xmodem_finish_xfer: Transfer aborted by receiver.");
        default:
        default:
          fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
          fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
          continue;
          continue;
        }
        }
    }
    }
 
 
  error ("xmodem_finish_xfer:  Excessive retries.");
  error ("xmodem_finish_xfer:  Excessive retries.");
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.