diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
commit | c906108c21474dfb4ed285bcc0ac6fe02cd400cc (patch) | |
tree | a0015aa5cedc19ccbab307251353a41722a3ae13 /gdb/xmodem.c | |
parent | cd946cff9ede3f30935803403f06f6ed30cad136 (diff) | |
download | gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.zip gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.gz gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.bz2 |
Initial creation of sourceware repositorygdb-4_18-branchpoint
Diffstat (limited to 'gdb/xmodem.c')
-rw-r--r-- | gdb/xmodem.c | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/gdb/xmodem.c b/gdb/xmodem.c new file mode 100644 index 0000000..dd13b87 --- /dev/null +++ b/gdb/xmodem.c @@ -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., 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 (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."); +} |