b164243b7d4225bae809139502fb9ccba606767f
[uccvend-snackrom.git] / ROM2 / xmodem.c
1 /* XMODEM support for GDB, the GNU debugger.
2    Copyright 1995, 2000, 2001 Free Software Foundation, Inc.
3
4    This file is part of GDB.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include "chime.h"
22 #include "sci.h"
23 #include "xmodem.h"
24 #include "crctab.h"
25
26 /* These definitions are for xmodem protocol. */
27
28 #define SOH     0x01
29 #define STX     0x02
30 #define ACK     0x06
31 #define NAK     0x15
32 #define EOT     0x04
33 #define CANCEL  0x18
34
35 static int blknum;              /* XMODEM block number */
36 static int crcflag;             /* Sez we are using CRC's instead of cksums */
37
38 static int
39 readchar (int timeout)
40 {
41   int c;
42
43   c = serial_readchar (timeout);
44
45   if (c >= 0)
46     return c;
47
48   if (c == SERIAL_TIMEOUT)
49           chime_for(0xff);
50     /*error ("Timeout reading from remote system.")*/;
51
52   return 0;
53 }
54
55 /* Calculate a CRC-16 for the LEN byte message pointed at by P.  */
56 /* Pads with ^Z up to 128 bytes if told to */
57
58 static unsigned short
59 docrc (unsigned char *p, int len, bool pad)
60 {
61   int len2 = len;
62   unsigned short crc = 0;
63
64   while (len-- > 0)
65     crc = (crc << 8) ^ crctab[(crc >> 8) ^ *p++];
66   if (pad && len2 < 128) {
67     len = 128-len;
68     while (len-- > 0)
69       crc = (crc << 8) ^ crctab[(crc >> 8) ^ 0x1a];
70   }
71
72   return crc;
73 }
74
75 /* Start up the transmit process.  Reset state variables.  Wait for receiver to
76    send NAK or CRC request.  */
77
78 int
79 xmodem_init_xfer ()
80 {
81   int c;
82   int i;
83
84   blknum = 1;
85   crcflag = 0;
86
87   for (i = 1; i <= 10; i++)
88     {
89       c = readchar (6);
90
91       switch (c)
92         {
93         case 'C':
94           crcflag = 1;
95           /* fall through */
96         case NAK:
97           return 1;
98         default:
99           chime_for(0x7f);
100           /* fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c); */
101           continue;
102         case CANCEL:            /* target aborted load */
103           /* fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n"); */
104           return 0;
105         }
106     }
107   chime_for(0xff);
108   /*error ("xmodem_init_xfer:  Too many unexpected characters.");*/
109   return 0;
110 }
111
112 /* Take 128 bytes of data and make a packet out of it.
113
114  *      Each packet looks like this:
115  *      +-----+-------+-------+------+-----+
116  *      | SOH | Seq1. | Seq2. | data | SUM |
117  *      +-----+-------+-------+------+-----+
118  *      SOH  = 0x01
119  *      Seq1 = The sequence number.
120  *      Seq2 = The complement of the sequence number.
121  *      Data = A 128 bytes of data.
122  *      SUM  = Add the contents of the 128 bytes and use the low-order
123  *             8 bits of the result.
124  *
125  * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the
126  * remote system.  PACKET must be XMODEM_PACKETSIZE bytes long.  The data must
127  * start 3 bytes after the beginning of the packet to leave room for the
128  * XMODEM header.  LEN is the length of the data portion of the packet (and
129  * must be <= 128 bytes).  If it is < 128 bytes, ^Z padding will be added.
130  */
131
132 bool
133 xmodem_send_packet (const unsigned char *packet, int len)
134 {
135   int i;
136   int retries;
137   char p;
138   char s[3];
139
140   if (len > XMODEM_DATASIZE) {
141     chime_for(0xff);
142     return 0;
143   }
144
145   for (retries = 3; retries >= 0; retries--) {
146     int c;
147     /* send the packet header */
148     send_string("\x01"); /* SOH */
149     p = blknum; serial_write(&p, 1);
150     p = ~blknum; serial_write(&p, 1);
151
152     serial_write(packet, len); /* Send data bytes */
153
154     char *ptr, *end;
155     ptr = (char*)(packet+len);
156     end = (char*)(packet+128);
157     for (; ptr < end; ptr++) {
158       send_string("\x1A"); /* pad with ^Z */
159     }
160
161     /* Add ^Z padding if packet < 128 (or 1024) bytes */
162     if (crcflag) {
163       u16 crc;
164
165       crc = docrc ((unsigned char*)packet, len, 1);
166
167       s[0] = crc >> 8;
168       s[1] = crc & 0xff;
169       s[2] = '\0';
170       send_string(s);
171     } else {
172       int sum;
173
174       sum = 0;
175       for (i = 0; i < len; i++)
176         sum += packet[i];
177       for (; i < 128; i++)
178         sum += 0x1a;
179
180       s[0] = sum;
181       s[1] = '\0';
182       send_string(s);
183     }
184
185     c = readchar (3);
186     switch (c)
187       {
188       case ACK:
189         goto out;
190       case NAK:
191         continue;
192       case CANCEL:
193         /* error ("xmodem_send_packet: Transfer aborted by receiver."); */
194         chime_for(0xff);
195         return 0;
196       default:
197         /*fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);*/
198         /* mtearle is evil */
199         chime_for(c);
200         continue;
201       }
202   }
203
204   //serial_write ("\004", 1);   /* Send an EOT */
205
206   /* error ("xmodem_send_packet:  Excessive retries."); */
207   chime_for(0xff);
208   return 0;
209 out:
210   blknum++;
211   return 1;
212 }
213
214 /* Finish off the transfer.  Send out the EOT, and wait for an ACK.  */
215
216 void
217 xmodem_finish_xfer ()
218 {
219   int retries;
220
221   for (retries = 10; retries >= 0; retries--)
222     {
223       int c;
224
225       serial_write ("\004", 1); /* Send an EOT */
226
227       c = readchar (3);
228       switch (c)
229         {
230         case ACK:
231           return;
232         case NAK:
233           continue;
234         case CANCEL:
235           chime_for(0xff);
236           /* error ("xmodem_finish_xfer: Transfer aborted by receiver."); */
237         default:
238           /* fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c); */
239           chime_for(c);
240           continue;
241         }
242     }
243
244   chime_for(0xff);
245   /* error ("xmodem_finish_xfer:  Excessive retries."); */
246 }

UCC git Repository :: git.ucc.asn.au