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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [xmodem.c] - Rev 1776

Go to most recent revision | Compare with Previous | Blame | View Log

/* XMODEM support for GDB, the GNU debugger.
   Copyright 1995, 2000, 2001 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., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, 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 (struct serial *desc, int timeout)
{
  int c;
 
  c = serial_readchar (desc, timeout);
 
  if (remote_debug > 0)
    fputc_unfiltered (c, gdb_stdlog);
 
  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 (void)
{
  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 (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 (struct serial *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 (struct serial *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
    internal_error (__FILE__, __LINE__, "failed internal consistency check");			/* 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 (struct serial *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.");
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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