* mn10300.igen (OP_F0F4): Need to load contents of register AN0
[platform/upstream/binutils.git] / gdb / xmodem.c
1 /* XMODEM support for GDB, the GNU debugger.
2    Copyright 1995 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, Boston, MA 02111-1307, USA.  */
19
20 #include "defs.h"
21 #include "serial.h"
22 #include "target.h"
23 #include "xmodem.h"
24
25 /* These definitions are for xmodem protocol. */
26
27 #define SOH     0x01
28 #define STX     0x02
29 #define ACK     0x06
30 #define NAK     0x15
31 #define EOT     0x04
32 #define CANCEL  0x18
33
34 static int blknum;              /* XMODEM block number */
35 static int crcflag;             /* Sez we are using CRC's instead of cksums */
36
37 static int
38 readchar (desc, timeout)
39      serial_t desc;
40      int timeout;
41 {
42   int c;
43
44   c = SERIAL_READCHAR (desc, timeout);
45
46   if (remote_debug > 0)
47     fputc_unfiltered (c, gdb_stderr);
48
49   if (c >= 0)
50     return c;
51
52   if (c == SERIAL_TIMEOUT)
53     error ("Timeout reading from remote system.");
54
55   perror_with_name ("xmodem.c:readchar()");
56 }
57
58 #define CRC16 0x1021            /* Generator polynomial (X^16 + X^12 + X^5 + 1) */
59
60 static unsigned short *crctab;
61
62 /* Call this to init the fast CRC-16 calculation table.  */
63
64 static void
65 crcinit ()
66 {
67   static int crctab_inited = 0;
68   int val;
69
70   if (crctab_inited == 1)
71     return;
72
73   crctab = xmalloc (256 * sizeof (short));
74
75   for (val = 0; val <= 255; val++)
76     {
77       int i;
78       unsigned int crc;
79
80       crc = val << 8;
81
82       for (i = 0; i < 8; ++i)
83         {
84           crc <<= 1;
85
86           if (crc & 0x10000)
87             crc ^= CRC16;
88         }
89
90       crctab [val] = crc;
91     }
92
93   crctab_inited = 1;
94 }
95
96 /* Calculate a CRC-16 for the LEN byte message pointed at by P.  */
97
98 static unsigned short
99 docrc (p, len)
100      unsigned char *p;
101      int len;
102 {
103   unsigned short crc = 0;
104
105   while (len-- > 0)
106     crc = (crc << 8) ^ crctab [(crc >> 8) ^ *p++];
107
108   return crc;
109 }
110
111 /* Start up the transmit process.  Reset state variables.  Wait for receiver to
112    send NAK or CRC request.  */
113
114 int
115 xmodem_init_xfer (desc)
116      serial_t desc;
117 {
118   int c;
119   int i;
120
121   blknum = 1;
122   crcflag = 0;
123   crcinit ();
124
125   for (i = 1; i <= 10; i++)
126     {
127       c = readchar (desc, 6);
128
129       switch (c)
130         {
131         case 'C':
132           crcflag = 1;
133         case NAK:
134           return 0;
135         default:
136           fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c);
137           continue;
138         case CANCEL:            /* target aborted load */
139           fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n");
140           continue;
141         }
142     }
143   error ("xmodem_init_xfer:  Too many unexpected characters.");
144 }
145
146 /* Take 128 bytes of data and make a packet out of it.
147  *
148  *      Each packet looks like this:
149  *      +-----+-------+-------+------+-----+
150  *      | SOH | Seq1. | Seq2. | data | SUM |
151  *      +-----+-------+-------+------+-----+
152  *      SOH  = 0x01
153  *      Seq1 = The sequence number.
154  *      Seq2 = The complement of the sequence number.
155  *      Data = A 128 bytes of data.
156  *      SUM  = Add the contents of the 128 bytes and use the low-order
157  *             8 bits of the result.
158  *
159  * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the
160  * remote system.  PACKET must be XMODEM_PACKETSIZE bytes long.  The data must
161  * start 3 bytes after the beginning of the packet to leave room for the
162  * XMODEM header.  LEN is the length of the data portion of the packet (and
163  * must be <= 128 bytes).  If it is < 128 bytes, ^Z padding will be added.
164  */
165
166 void
167 xmodem_send_packet (desc, packet, len, hashmark)
168      serial_t desc;
169      unsigned char *packet;
170      int len;
171      int hashmark;
172 {
173   int i;
174   int retries;
175   int pktlen;
176   int datasize;
177   
178   /* build the packet header */
179
180   packet[1] = blknum;
181   packet[2] = ~blknum;
182
183   blknum++;
184   
185   if (len <= XMODEM_DATASIZE)
186     {
187       packet[0] = SOH;
188       datasize = XMODEM_DATASIZE;
189     }
190   else if (len <= XMODEM_1KDATASIZE)
191     {
192       packet[0] = STX;
193       datasize = XMODEM_1KDATASIZE;
194     }
195   else
196     abort ();                   /* Packet way too large */
197
198   /* Add ^Z padding if packet < 128 (or 1024) bytes */
199
200   memset (packet + 3 + len, '\026', datasize - len);
201
202   if (crcflag)
203     {
204       int crc;
205
206       crc = docrc (packet + 3, datasize);
207
208       packet[3 + datasize] = crc >> 8;
209       packet[3 + datasize + 1] = crc;
210       pktlen = datasize + 5;
211     }
212   else
213     {
214       int sum;
215
216       sum = 0;
217       for (i = 3; i < datasize + 3; i++)
218         sum += packet[i];
219
220       packet[3 + datasize] = sum; /* add the checksum */
221       pktlen = datasize + 4;
222     }
223
224   for (retries = 3; retries >= 0; retries--)
225     {
226       int c;
227
228       SERIAL_WRITE (desc, packet, pktlen);
229
230       c = readchar (desc, 3);
231       switch (c)
232         {
233         case ACK:
234           return;
235         case NAK:
236           if (!hashmark)
237             continue;
238           putchar_unfiltered ('-');
239           gdb_flush (gdb_stdout);
240           continue;
241         case CANCEL:
242           error ("xmodem_send_packet: Transfer aborted by receiver.");
243         default:
244           fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
245           continue;
246         }
247     }
248
249   SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
250
251   error ("xmodem_send_packet:  Excessive retries.");
252 }
253
254 /* Finish off the transfer.  Send out the EOT, and wait for an ACK.  */
255
256 void
257 xmodem_finish_xfer (desc)
258      serial_t desc;
259 {
260   int retries;
261
262   for (retries = 10; retries >= 0; retries--)
263     {
264       int c;
265
266       SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
267
268       c = readchar (desc, 3);
269       switch (c)
270         {
271         case ACK:
272           return;
273         case NAK:
274           continue;
275         case CANCEL:
276           error ("xmodem_finish_xfer: Transfer aborted by receiver.");
277         default:
278           fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
279           continue;
280         }
281     }
282
283   error ("xmodem_finish_xfer:  Excessive retries.");
284 }