Commit a4773c5559867f8fc6b0c1a7eb8ab36cfd53756f

Authored by Lokesh Vutla
Committed by Tom Rini
1 parent 03e6151d5b

xyz-modem: Fix timeout loop waiting with WATCHDOG

Commit 2c77c0d6524eb ("xyz-modem: Change getc timeout loop waiting")
fixes the loop delay when using a hw watchdog, assuming that watchdog
kicking is taken care of by getc(). But the xyzmodem driver tries to
do a getc only after confirming that a character is available like below:
	while (!tstc()) {
		till timeout;
	}
	if (tstc())
		*c = getc();

and getc() does a watchdog reset only if it fails to see a character.
In this case, getc() always sees a character and never does a
watchdog reset. So to make sure that watchdog doesn't get reset
while loading the file, do a watchdog reset just before starting the
image loading.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Vignesh R <vigneshr@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 1 changed file with 2 additions and 0 deletions Inline Diff

1 // SPDX-License-Identifier: eCos-2.0 1 // SPDX-License-Identifier: eCos-2.0
2 /* 2 /*
3 *========================================================================== 3 *==========================================================================
4 * 4 *
5 * xyzModem.c 5 * xyzModem.c
6 * 6 *
7 * RedBoot stream handler for xyzModem protocol 7 * RedBoot stream handler for xyzModem protocol
8 * 8 *
9 *========================================================================== 9 *==========================================================================
10 *#####DESCRIPTIONBEGIN#### 10 *#####DESCRIPTIONBEGIN####
11 * 11 *
12 * Author(s): gthomas 12 * Author(s): gthomas
13 * Contributors: gthomas, tsmith, Yoshinori Sato 13 * Contributors: gthomas, tsmith, Yoshinori Sato
14 * Date: 2000-07-14 14 * Date: 2000-07-14
15 * Purpose: 15 * Purpose:
16 * Description: 16 * Description:
17 * 17 *
18 * This code is part of RedBoot (tm). 18 * This code is part of RedBoot (tm).
19 * 19 *
20 *####DESCRIPTIONEND#### 20 *####DESCRIPTIONEND####
21 * 21 *
22 *========================================================================== 22 *==========================================================================
23 */ 23 */
24 #include <common.h> 24 #include <common.h>
25 #include <xyzModem.h> 25 #include <xyzModem.h>
26 #include <stdarg.h> 26 #include <stdarg.h>
27 #include <u-boot/crc.h> 27 #include <u-boot/crc.h>
28 #include <watchdog.h>
28 29
29 /* Assumption - run xyzModem protocol over the console port */ 30 /* Assumption - run xyzModem protocol over the console port */
30 31
31 /* Values magic to the protocol */ 32 /* Values magic to the protocol */
32 #define SOH 0x01 33 #define SOH 0x01
33 #define STX 0x02 34 #define STX 0x02
34 #define EOT 0x04 35 #define EOT 0x04
35 #define ACK 0x06 36 #define ACK 0x06
36 #define BSP 0x08 37 #define BSP 0x08
37 #define NAK 0x15 38 #define NAK 0x15
38 #define CAN 0x18 39 #define CAN 0x18
39 #define EOF 0x1A /* ^Z for DOS officionados */ 40 #define EOF 0x1A /* ^Z for DOS officionados */
40 41
41 /* Data & state local to the protocol */ 42 /* Data & state local to the protocol */
42 static struct 43 static struct
43 { 44 {
44 int *__chan; 45 int *__chan;
45 unsigned char pkt[1024], *bufp; 46 unsigned char pkt[1024], *bufp;
46 unsigned char blk, cblk, crc1, crc2; 47 unsigned char blk, cblk, crc1, crc2;
47 unsigned char next_blk; /* Expected block */ 48 unsigned char next_blk; /* Expected block */
48 int len, mode, total_retries; 49 int len, mode, total_retries;
49 int total_SOH, total_STX, total_CAN; 50 int total_SOH, total_STX, total_CAN;
50 bool crc_mode, at_eof, tx_ack; 51 bool crc_mode, at_eof, tx_ack;
51 unsigned long file_length, read_length; 52 unsigned long file_length, read_length;
52 } xyz; 53 } xyz;
53 54
54 #define xyzModem_CHAR_TIMEOUT 2000 /* 2 seconds */ 55 #define xyzModem_CHAR_TIMEOUT 2000 /* 2 seconds */
55 #define xyzModem_MAX_RETRIES 20 56 #define xyzModem_MAX_RETRIES 20
56 #define xyzModem_MAX_RETRIES_WITH_CRC 10 57 #define xyzModem_MAX_RETRIES_WITH_CRC 10
57 #define xyzModem_CAN_COUNT 3 /* Wait for 3 CAN before quitting */ 58 #define xyzModem_CAN_COUNT 3 /* Wait for 3 CAN before quitting */
58 59
59 60
60 typedef int cyg_int32; 61 typedef int cyg_int32;
61 static int 62 static int
62 CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c) 63 CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c)
63 { 64 {
64 65
65 ulong now = get_timer(0); 66 ulong now = get_timer(0);
67 WATCHDOG_RESET();
66 while (!tstc ()) 68 while (!tstc ())
67 { 69 {
68 if (get_timer(now) > xyzModem_CHAR_TIMEOUT) 70 if (get_timer(now) > xyzModem_CHAR_TIMEOUT)
69 break; 71 break;
70 } 72 }
71 if (tstc ()) 73 if (tstc ())
72 { 74 {
73 *c = getc (); 75 *c = getc ();
74 return 1; 76 return 1;
75 } 77 }
76 return 0; 78 return 0;
77 } 79 }
78 80
79 static void 81 static void
80 CYGACC_COMM_IF_PUTC (char x, char y) 82 CYGACC_COMM_IF_PUTC (char x, char y)
81 { 83 {
82 putc (y); 84 putc (y);
83 } 85 }
84 86
85 /* Validate a hex character */ 87 /* Validate a hex character */
86 __inline__ static bool 88 __inline__ static bool
87 _is_hex (char c) 89 _is_hex (char c)
88 { 90 {
89 return (((c >= '0') && (c <= '9')) || 91 return (((c >= '0') && (c <= '9')) ||
90 ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f'))); 92 ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f')));
91 } 93 }
92 94
93 /* Convert a single hex nibble */ 95 /* Convert a single hex nibble */
94 __inline__ static int 96 __inline__ static int
95 _from_hex (char c) 97 _from_hex (char c)
96 { 98 {
97 int ret = 0; 99 int ret = 0;
98 100
99 if ((c >= '0') && (c <= '9')) 101 if ((c >= '0') && (c <= '9'))
100 { 102 {
101 ret = (c - '0'); 103 ret = (c - '0');
102 } 104 }
103 else if ((c >= 'a') && (c <= 'f')) 105 else if ((c >= 'a') && (c <= 'f'))
104 { 106 {
105 ret = (c - 'a' + 0x0a); 107 ret = (c - 'a' + 0x0a);
106 } 108 }
107 else if ((c >= 'A') && (c <= 'F')) 109 else if ((c >= 'A') && (c <= 'F'))
108 { 110 {
109 ret = (c - 'A' + 0x0A); 111 ret = (c - 'A' + 0x0A);
110 } 112 }
111 return ret; 113 return ret;
112 } 114 }
113 115
114 /* Convert a character to lower case */ 116 /* Convert a character to lower case */
115 __inline__ static char 117 __inline__ static char
116 _tolower (char c) 118 _tolower (char c)
117 { 119 {
118 if ((c >= 'A') && (c <= 'Z')) 120 if ((c >= 'A') && (c <= 'Z'))
119 { 121 {
120 c = (c - 'A') + 'a'; 122 c = (c - 'A') + 'a';
121 } 123 }
122 return c; 124 return c;
123 } 125 }
124 126
125 /* Parse (scan) a number */ 127 /* Parse (scan) a number */
126 static bool 128 static bool
127 parse_num (char *s, unsigned long *val, char **es, char *delim) 129 parse_num (char *s, unsigned long *val, char **es, char *delim)
128 { 130 {
129 bool first = true; 131 bool first = true;
130 int radix = 10; 132 int radix = 10;
131 char c; 133 char c;
132 unsigned long result = 0; 134 unsigned long result = 0;
133 int digit; 135 int digit;
134 136
135 while (*s == ' ') 137 while (*s == ' ')
136 s++; 138 s++;
137 while (*s) 139 while (*s)
138 { 140 {
139 if (first && (s[0] == '0') && (_tolower (s[1]) == 'x')) 141 if (first && (s[0] == '0') && (_tolower (s[1]) == 'x'))
140 { 142 {
141 radix = 16; 143 radix = 16;
142 s += 2; 144 s += 2;
143 } 145 }
144 first = false; 146 first = false;
145 c = *s++; 147 c = *s++;
146 if (_is_hex (c) && ((digit = _from_hex (c)) < radix)) 148 if (_is_hex (c) && ((digit = _from_hex (c)) < radix))
147 { 149 {
148 /* Valid digit */ 150 /* Valid digit */
149 result = (result * radix) + digit; 151 result = (result * radix) + digit;
150 } 152 }
151 else 153 else
152 { 154 {
153 if (delim != (char *) 0) 155 if (delim != (char *) 0)
154 { 156 {
155 /* See if this character is one of the delimiters */ 157 /* See if this character is one of the delimiters */
156 char *dp = delim; 158 char *dp = delim;
157 while (*dp && (c != *dp)) 159 while (*dp && (c != *dp))
158 dp++; 160 dp++;
159 if (*dp) 161 if (*dp)
160 break; /* Found a good delimiter */ 162 break; /* Found a good delimiter */
161 } 163 }
162 return false; /* Malformatted number */ 164 return false; /* Malformatted number */
163 } 165 }
164 } 166 }
165 *val = result; 167 *val = result;
166 if (es != (char **) 0) 168 if (es != (char **) 0)
167 { 169 {
168 *es = s; 170 *es = s;
169 } 171 }
170 return true; 172 return true;
171 } 173 }
172 174
173 175
174 #if defined(DEBUG) && !defined(CONFIG_USE_TINY_PRINTF) 176 #if defined(DEBUG) && !defined(CONFIG_USE_TINY_PRINTF)
175 /* 177 /*
176 * Note: this debug setup works by storing the strings in a fixed buffer 178 * Note: this debug setup works by storing the strings in a fixed buffer
177 */ 179 */
178 static char zm_debug_buf[8192]; 180 static char zm_debug_buf[8192];
179 static char *zm_out = zm_debug_buf; 181 static char *zm_out = zm_debug_buf;
180 static char *zm_out_start = zm_debug_buf; 182 static char *zm_out_start = zm_debug_buf;
181 183
182 static int 184 static int
183 zm_dprintf(char *fmt, ...) 185 zm_dprintf(char *fmt, ...)
184 { 186 {
185 int len; 187 int len;
186 va_list args; 188 va_list args;
187 189
188 va_start(args, fmt); 190 va_start(args, fmt);
189 len = diag_vsprintf(zm_out, fmt, args); 191 len = diag_vsprintf(zm_out, fmt, args);
190 va_end(args); 192 va_end(args);
191 zm_out += len; 193 zm_out += len;
192 return len; 194 return len;
193 } 195 }
194 196
195 static void 197 static void
196 zm_flush (void) 198 zm_flush (void)
197 { 199 {
198 zm_out = zm_out_start; 200 zm_out = zm_out_start;
199 } 201 }
200 202
201 static void 203 static void
202 zm_dump_buf (void *buf, int len) 204 zm_dump_buf (void *buf, int len)
203 { 205 {
204 206
205 } 207 }
206 208
207 static unsigned char zm_buf[2048]; 209 static unsigned char zm_buf[2048];
208 static unsigned char *zm_bp; 210 static unsigned char *zm_bp;
209 211
210 static void 212 static void
211 zm_new (void) 213 zm_new (void)
212 { 214 {
213 zm_bp = zm_buf; 215 zm_bp = zm_buf;
214 } 216 }
215 217
216 static void 218 static void
217 zm_save (unsigned char c) 219 zm_save (unsigned char c)
218 { 220 {
219 *zm_bp++ = c; 221 *zm_bp++ = c;
220 } 222 }
221 223
222 static void 224 static void
223 zm_dump (int line) 225 zm_dump (int line)
224 { 226 {
225 zm_dprintf ("Packet at line: %d\n", line); 227 zm_dprintf ("Packet at line: %d\n", line);
226 zm_dump_buf (zm_buf, zm_bp - zm_buf); 228 zm_dump_buf (zm_buf, zm_bp - zm_buf);
227 } 229 }
228 230
229 #define ZM_DEBUG(x) x 231 #define ZM_DEBUG(x) x
230 #else 232 #else
231 #define ZM_DEBUG(x) 233 #define ZM_DEBUG(x)
232 #endif 234 #endif
233 235
234 /* Wait for the line to go idle */ 236 /* Wait for the line to go idle */
235 static void 237 static void
236 xyzModem_flush (void) 238 xyzModem_flush (void)
237 { 239 {
238 int res; 240 int res;
239 char c; 241 char c;
240 while (true) 242 while (true)
241 { 243 {
242 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c); 244 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c);
243 if (!res) 245 if (!res)
244 return; 246 return;
245 } 247 }
246 } 248 }
247 249
248 static int 250 static int
249 xyzModem_get_hdr (void) 251 xyzModem_get_hdr (void)
250 { 252 {
251 char c; 253 char c;
252 int res; 254 int res;
253 bool hdr_found = false; 255 bool hdr_found = false;
254 int i, can_total, hdr_chars; 256 int i, can_total, hdr_chars;
255 unsigned short cksum; 257 unsigned short cksum;
256 258
257 ZM_DEBUG (zm_new ()); 259 ZM_DEBUG (zm_new ());
258 /* Find the start of a header */ 260 /* Find the start of a header */
259 can_total = 0; 261 can_total = 0;
260 hdr_chars = 0; 262 hdr_chars = 0;
261 263
262 if (xyz.tx_ack) 264 if (xyz.tx_ack)
263 { 265 {
264 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK); 266 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
265 xyz.tx_ack = false; 267 xyz.tx_ack = false;
266 } 268 }
267 while (!hdr_found) 269 while (!hdr_found)
268 { 270 {
269 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c); 271 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c);
270 ZM_DEBUG (zm_save (c)); 272 ZM_DEBUG (zm_save (c));
271 if (res) 273 if (res)
272 { 274 {
273 hdr_chars++; 275 hdr_chars++;
274 switch (c) 276 switch (c)
275 { 277 {
276 case SOH: 278 case SOH:
277 xyz.total_SOH++; 279 xyz.total_SOH++;
278 case STX: 280 case STX:
279 if (c == STX) 281 if (c == STX)
280 xyz.total_STX++; 282 xyz.total_STX++;
281 hdr_found = true; 283 hdr_found = true;
282 break; 284 break;
283 case CAN: 285 case CAN:
284 xyz.total_CAN++; 286 xyz.total_CAN++;
285 ZM_DEBUG (zm_dump (__LINE__)); 287 ZM_DEBUG (zm_dump (__LINE__));
286 if (++can_total == xyzModem_CAN_COUNT) 288 if (++can_total == xyzModem_CAN_COUNT)
287 { 289 {
288 return xyzModem_cancel; 290 return xyzModem_cancel;
289 } 291 }
290 else 292 else
291 { 293 {
292 /* Wait for multiple CAN to avoid early quits */ 294 /* Wait for multiple CAN to avoid early quits */
293 break; 295 break;
294 } 296 }
295 case EOT: 297 case EOT:
296 /* EOT only supported if no noise */ 298 /* EOT only supported if no noise */
297 if (hdr_chars == 1) 299 if (hdr_chars == 1)
298 { 300 {
299 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK); 301 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
300 ZM_DEBUG (zm_dprintf ("ACK on EOT #%d\n", __LINE__)); 302 ZM_DEBUG (zm_dprintf ("ACK on EOT #%d\n", __LINE__));
301 ZM_DEBUG (zm_dump (__LINE__)); 303 ZM_DEBUG (zm_dump (__LINE__));
302 return xyzModem_eof; 304 return xyzModem_eof;
303 } 305 }
304 default: 306 default:
305 /* Ignore, waiting for start of header */ 307 /* Ignore, waiting for start of header */
306 ; 308 ;
307 } 309 }
308 } 310 }
309 else 311 else
310 { 312 {
311 /* Data stream timed out */ 313 /* Data stream timed out */
312 xyzModem_flush (); /* Toss any current input */ 314 xyzModem_flush (); /* Toss any current input */
313 ZM_DEBUG (zm_dump (__LINE__)); 315 ZM_DEBUG (zm_dump (__LINE__));
314 CYGACC_CALL_IF_DELAY_US ((cyg_int32) 250000); 316 CYGACC_CALL_IF_DELAY_US ((cyg_int32) 250000);
315 return xyzModem_timeout; 317 return xyzModem_timeout;
316 } 318 }
317 } 319 }
318 320
319 /* Header found, now read the data */ 321 /* Header found, now read the data */
320 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.blk); 322 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.blk);
321 ZM_DEBUG (zm_save (xyz.blk)); 323 ZM_DEBUG (zm_save (xyz.blk));
322 if (!res) 324 if (!res)
323 { 325 {
324 ZM_DEBUG (zm_dump (__LINE__)); 326 ZM_DEBUG (zm_dump (__LINE__));
325 return xyzModem_timeout; 327 return xyzModem_timeout;
326 } 328 }
327 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.cblk); 329 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.cblk);
328 ZM_DEBUG (zm_save (xyz.cblk)); 330 ZM_DEBUG (zm_save (xyz.cblk));
329 if (!res) 331 if (!res)
330 { 332 {
331 ZM_DEBUG (zm_dump (__LINE__)); 333 ZM_DEBUG (zm_dump (__LINE__));
332 return xyzModem_timeout; 334 return xyzModem_timeout;
333 } 335 }
334 xyz.len = (c == SOH) ? 128 : 1024; 336 xyz.len = (c == SOH) ? 128 : 1024;
335 xyz.bufp = xyz.pkt; 337 xyz.bufp = xyz.pkt;
336 for (i = 0; i < xyz.len; i++) 338 for (i = 0; i < xyz.len; i++)
337 { 339 {
338 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c); 340 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, &c);
339 ZM_DEBUG (zm_save (c)); 341 ZM_DEBUG (zm_save (c));
340 if (res) 342 if (res)
341 { 343 {
342 xyz.pkt[i] = c; 344 xyz.pkt[i] = c;
343 } 345 }
344 else 346 else
345 { 347 {
346 ZM_DEBUG (zm_dump (__LINE__)); 348 ZM_DEBUG (zm_dump (__LINE__));
347 return xyzModem_timeout; 349 return xyzModem_timeout;
348 } 350 }
349 } 351 }
350 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.crc1); 352 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.crc1);
351 ZM_DEBUG (zm_save (xyz.crc1)); 353 ZM_DEBUG (zm_save (xyz.crc1));
352 if (!res) 354 if (!res)
353 { 355 {
354 ZM_DEBUG (zm_dump (__LINE__)); 356 ZM_DEBUG (zm_dump (__LINE__));
355 return xyzModem_timeout; 357 return xyzModem_timeout;
356 } 358 }
357 if (xyz.crc_mode) 359 if (xyz.crc_mode)
358 { 360 {
359 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.crc2); 361 res = CYGACC_COMM_IF_GETC_TIMEOUT (*xyz.__chan, (char *) &xyz.crc2);
360 ZM_DEBUG (zm_save (xyz.crc2)); 362 ZM_DEBUG (zm_save (xyz.crc2));
361 if (!res) 363 if (!res)
362 { 364 {
363 ZM_DEBUG (zm_dump (__LINE__)); 365 ZM_DEBUG (zm_dump (__LINE__));
364 return xyzModem_timeout; 366 return xyzModem_timeout;
365 } 367 }
366 } 368 }
367 ZM_DEBUG (zm_dump (__LINE__)); 369 ZM_DEBUG (zm_dump (__LINE__));
368 /* Validate the message */ 370 /* Validate the message */
369 if ((xyz.blk ^ xyz.cblk) != (unsigned char) 0xFF) 371 if ((xyz.blk ^ xyz.cblk) != (unsigned char) 0xFF)
370 { 372 {
371 ZM_DEBUG (zm_dprintf 373 ZM_DEBUG (zm_dprintf
372 ("Framing error - blk: %x/%x/%x\n", xyz.blk, xyz.cblk, 374 ("Framing error - blk: %x/%x/%x\n", xyz.blk, xyz.cblk,
373 (xyz.blk ^ xyz.cblk))); 375 (xyz.blk ^ xyz.cblk)));
374 ZM_DEBUG (zm_dump_buf (xyz.pkt, xyz.len)); 376 ZM_DEBUG (zm_dump_buf (xyz.pkt, xyz.len));
375 xyzModem_flush (); 377 xyzModem_flush ();
376 return xyzModem_frame; 378 return xyzModem_frame;
377 } 379 }
378 /* Verify checksum/CRC */ 380 /* Verify checksum/CRC */
379 if (xyz.crc_mode) 381 if (xyz.crc_mode)
380 { 382 {
381 cksum = crc16_ccitt(0, xyz.pkt, xyz.len); 383 cksum = crc16_ccitt(0, xyz.pkt, xyz.len);
382 if (cksum != ((xyz.crc1 << 8) | xyz.crc2)) 384 if (cksum != ((xyz.crc1 << 8) | xyz.crc2))
383 { 385 {
384 ZM_DEBUG (zm_dprintf ("CRC error - recvd: %02x%02x, computed: %x\n", 386 ZM_DEBUG (zm_dprintf ("CRC error - recvd: %02x%02x, computed: %x\n",
385 xyz.crc1, xyz.crc2, cksum & 0xFFFF)); 387 xyz.crc1, xyz.crc2, cksum & 0xFFFF));
386 return xyzModem_cksum; 388 return xyzModem_cksum;
387 } 389 }
388 } 390 }
389 else 391 else
390 { 392 {
391 cksum = 0; 393 cksum = 0;
392 for (i = 0; i < xyz.len; i++) 394 for (i = 0; i < xyz.len; i++)
393 { 395 {
394 cksum += xyz.pkt[i]; 396 cksum += xyz.pkt[i];
395 } 397 }
396 if (xyz.crc1 != (cksum & 0xFF)) 398 if (xyz.crc1 != (cksum & 0xFF))
397 { 399 {
398 ZM_DEBUG (zm_dprintf 400 ZM_DEBUG (zm_dprintf
399 ("Checksum error - recvd: %x, computed: %x\n", xyz.crc1, 401 ("Checksum error - recvd: %x, computed: %x\n", xyz.crc1,
400 cksum & 0xFF)); 402 cksum & 0xFF));
401 return xyzModem_cksum; 403 return xyzModem_cksum;
402 } 404 }
403 } 405 }
404 /* If we get here, the message passes [structural] muster */ 406 /* If we get here, the message passes [structural] muster */
405 return 0; 407 return 0;
406 } 408 }
407 409
408 int 410 int
409 xyzModem_stream_open (connection_info_t * info, int *err) 411 xyzModem_stream_open (connection_info_t * info, int *err)
410 { 412 {
411 int stat = 0; 413 int stat = 0;
412 int retries = xyzModem_MAX_RETRIES; 414 int retries = xyzModem_MAX_RETRIES;
413 int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC; 415 int crc_retries = xyzModem_MAX_RETRIES_WITH_CRC;
414 416
415 /* ZM_DEBUG(zm_out = zm_out_start); */ 417 /* ZM_DEBUG(zm_out = zm_out_start); */
416 #ifdef xyzModem_zmodem 418 #ifdef xyzModem_zmodem
417 if (info->mode == xyzModem_zmodem) 419 if (info->mode == xyzModem_zmodem)
418 { 420 {
419 *err = xyzModem_noZmodem; 421 *err = xyzModem_noZmodem;
420 return -1; 422 return -1;
421 } 423 }
422 #endif 424 #endif
423 425
424 /* TODO: CHECK ! */ 426 /* TODO: CHECK ! */
425 int dummy = 0; 427 int dummy = 0;
426 xyz.__chan = &dummy; 428 xyz.__chan = &dummy;
427 xyz.len = 0; 429 xyz.len = 0;
428 xyz.crc_mode = true; 430 xyz.crc_mode = true;
429 xyz.at_eof = false; 431 xyz.at_eof = false;
430 xyz.tx_ack = false; 432 xyz.tx_ack = false;
431 xyz.mode = info->mode; 433 xyz.mode = info->mode;
432 xyz.total_retries = 0; 434 xyz.total_retries = 0;
433 xyz.total_SOH = 0; 435 xyz.total_SOH = 0;
434 xyz.total_STX = 0; 436 xyz.total_STX = 0;
435 xyz.total_CAN = 0; 437 xyz.total_CAN = 0;
436 xyz.read_length = 0; 438 xyz.read_length = 0;
437 xyz.file_length = 0; 439 xyz.file_length = 0;
438 440
439 CYGACC_COMM_IF_PUTC (*xyz.__chan, (xyz.crc_mode ? 'C' : NAK)); 441 CYGACC_COMM_IF_PUTC (*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));
440 442
441 if (xyz.mode == xyzModem_xmodem) 443 if (xyz.mode == xyzModem_xmodem)
442 { 444 {
443 /* X-modem doesn't have an information header - exit here */ 445 /* X-modem doesn't have an information header - exit here */
444 xyz.next_blk = 1; 446 xyz.next_blk = 1;
445 return 0; 447 return 0;
446 } 448 }
447 449
448 while (retries-- > 0) 450 while (retries-- > 0)
449 { 451 {
450 stat = xyzModem_get_hdr (); 452 stat = xyzModem_get_hdr ();
451 if (stat == 0) 453 if (stat == 0)
452 { 454 {
453 /* Y-modem file information header */ 455 /* Y-modem file information header */
454 if (xyz.blk == 0) 456 if (xyz.blk == 0)
455 { 457 {
456 /* skip filename */ 458 /* skip filename */
457 while (*xyz.bufp++); 459 while (*xyz.bufp++);
458 /* get the length */ 460 /* get the length */
459 parse_num ((char *) xyz.bufp, &xyz.file_length, NULL, " "); 461 parse_num ((char *) xyz.bufp, &xyz.file_length, NULL, " ");
460 /* The rest of the file name data block quietly discarded */ 462 /* The rest of the file name data block quietly discarded */
461 xyz.tx_ack = true; 463 xyz.tx_ack = true;
462 } 464 }
463 xyz.next_blk = 1; 465 xyz.next_blk = 1;
464 xyz.len = 0; 466 xyz.len = 0;
465 return 0; 467 return 0;
466 } 468 }
467 else if (stat == xyzModem_timeout) 469 else if (stat == xyzModem_timeout)
468 { 470 {
469 if (--crc_retries <= 0) 471 if (--crc_retries <= 0)
470 xyz.crc_mode = false; 472 xyz.crc_mode = false;
471 CYGACC_CALL_IF_DELAY_US (5 * 100000); /* Extra delay for startup */ 473 CYGACC_CALL_IF_DELAY_US (5 * 100000); /* Extra delay for startup */
472 CYGACC_COMM_IF_PUTC (*xyz.__chan, (xyz.crc_mode ? 'C' : NAK)); 474 CYGACC_COMM_IF_PUTC (*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));
473 xyz.total_retries++; 475 xyz.total_retries++;
474 ZM_DEBUG (zm_dprintf ("NAK (%d)\n", __LINE__)); 476 ZM_DEBUG (zm_dprintf ("NAK (%d)\n", __LINE__));
475 } 477 }
476 if (stat == xyzModem_cancel) 478 if (stat == xyzModem_cancel)
477 { 479 {
478 break; 480 break;
479 } 481 }
480 } 482 }
481 *err = stat; 483 *err = stat;
482 ZM_DEBUG (zm_flush ()); 484 ZM_DEBUG (zm_flush ());
483 return -1; 485 return -1;
484 } 486 }
485 487
486 int 488 int
487 xyzModem_stream_read (char *buf, int size, int *err) 489 xyzModem_stream_read (char *buf, int size, int *err)
488 { 490 {
489 int stat, total, len; 491 int stat, total, len;
490 int retries; 492 int retries;
491 493
492 total = 0; 494 total = 0;
493 stat = xyzModem_cancel; 495 stat = xyzModem_cancel;
494 /* Try and get 'size' bytes into the buffer */ 496 /* Try and get 'size' bytes into the buffer */
495 while (!xyz.at_eof && (size > 0)) 497 while (!xyz.at_eof && (size > 0))
496 { 498 {
497 if (xyz.len == 0) 499 if (xyz.len == 0)
498 { 500 {
499 retries = xyzModem_MAX_RETRIES; 501 retries = xyzModem_MAX_RETRIES;
500 while (retries-- > 0) 502 while (retries-- > 0)
501 { 503 {
502 stat = xyzModem_get_hdr (); 504 stat = xyzModem_get_hdr ();
503 if (stat == 0) 505 if (stat == 0)
504 { 506 {
505 if (xyz.blk == xyz.next_blk) 507 if (xyz.blk == xyz.next_blk)
506 { 508 {
507 xyz.tx_ack = true; 509 xyz.tx_ack = true;
508 ZM_DEBUG (zm_dprintf 510 ZM_DEBUG (zm_dprintf
509 ("ACK block %d (%d)\n", xyz.blk, __LINE__)); 511 ("ACK block %d (%d)\n", xyz.blk, __LINE__));
510 xyz.next_blk = (xyz.next_blk + 1) & 0xFF; 512 xyz.next_blk = (xyz.next_blk + 1) & 0xFF;
511 513
512 if (xyz.mode == xyzModem_xmodem || xyz.file_length == 0) 514 if (xyz.mode == xyzModem_xmodem || xyz.file_length == 0)
513 { 515 {
514 /* Data blocks can be padded with ^Z (EOF) characters */ 516 /* Data blocks can be padded with ^Z (EOF) characters */
515 /* This code tries to detect and remove them */ 517 /* This code tries to detect and remove them */
516 if ((xyz.bufp[xyz.len - 1] == EOF) && 518 if ((xyz.bufp[xyz.len - 1] == EOF) &&
517 (xyz.bufp[xyz.len - 2] == EOF) && 519 (xyz.bufp[xyz.len - 2] == EOF) &&
518 (xyz.bufp[xyz.len - 3] == EOF)) 520 (xyz.bufp[xyz.len - 3] == EOF))
519 { 521 {
520 while (xyz.len 522 while (xyz.len
521 && (xyz.bufp[xyz.len - 1] == EOF)) 523 && (xyz.bufp[xyz.len - 1] == EOF))
522 { 524 {
523 xyz.len--; 525 xyz.len--;
524 } 526 }
525 } 527 }
526 } 528 }
527 529
528 /* 530 /*
529 * See if accumulated length exceeds that of the file. 531 * See if accumulated length exceeds that of the file.
530 * If so, reduce size (i.e., cut out pad bytes) 532 * If so, reduce size (i.e., cut out pad bytes)
531 * Only do this for Y-modem (and Z-modem should it ever 533 * Only do this for Y-modem (and Z-modem should it ever
532 * be supported since it can fall back to Y-modem mode). 534 * be supported since it can fall back to Y-modem mode).
533 */ 535 */
534 if (xyz.mode != xyzModem_xmodem && 0 != xyz.file_length) 536 if (xyz.mode != xyzModem_xmodem && 0 != xyz.file_length)
535 { 537 {
536 xyz.read_length += xyz.len; 538 xyz.read_length += xyz.len;
537 if (xyz.read_length > xyz.file_length) 539 if (xyz.read_length > xyz.file_length)
538 { 540 {
539 xyz.len -= (xyz.read_length - xyz.file_length); 541 xyz.len -= (xyz.read_length - xyz.file_length);
540 } 542 }
541 } 543 }
542 break; 544 break;
543 } 545 }
544 else if (xyz.blk == ((xyz.next_blk - 1) & 0xFF)) 546 else if (xyz.blk == ((xyz.next_blk - 1) & 0xFF))
545 { 547 {
546 /* Just re-ACK this so sender will get on with it */ 548 /* Just re-ACK this so sender will get on with it */
547 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK); 549 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
548 continue; /* Need new header */ 550 continue; /* Need new header */
549 } 551 }
550 else 552 else
551 { 553 {
552 stat = xyzModem_sequence; 554 stat = xyzModem_sequence;
553 } 555 }
554 } 556 }
555 if (stat == xyzModem_cancel) 557 if (stat == xyzModem_cancel)
556 { 558 {
557 break; 559 break;
558 } 560 }
559 if (stat == xyzModem_eof) 561 if (stat == xyzModem_eof)
560 { 562 {
561 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK); 563 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
562 ZM_DEBUG (zm_dprintf ("ACK (%d)\n", __LINE__)); 564 ZM_DEBUG (zm_dprintf ("ACK (%d)\n", __LINE__));
563 if (xyz.mode == xyzModem_ymodem) 565 if (xyz.mode == xyzModem_ymodem)
564 { 566 {
565 CYGACC_COMM_IF_PUTC (*xyz.__chan, 567 CYGACC_COMM_IF_PUTC (*xyz.__chan,
566 (xyz.crc_mode ? 'C' : NAK)); 568 (xyz.crc_mode ? 'C' : NAK));
567 xyz.total_retries++; 569 xyz.total_retries++;
568 ZM_DEBUG (zm_dprintf ("Reading Final Header\n")); 570 ZM_DEBUG (zm_dprintf ("Reading Final Header\n"));
569 stat = xyzModem_get_hdr (); 571 stat = xyzModem_get_hdr ();
570 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK); 572 CYGACC_COMM_IF_PUTC (*xyz.__chan, ACK);
571 ZM_DEBUG (zm_dprintf ("FINAL ACK (%d)\n", __LINE__)); 573 ZM_DEBUG (zm_dprintf ("FINAL ACK (%d)\n", __LINE__));
572 } 574 }
573 xyz.at_eof = true; 575 xyz.at_eof = true;
574 break; 576 break;
575 } 577 }
576 CYGACC_COMM_IF_PUTC (*xyz.__chan, (xyz.crc_mode ? 'C' : NAK)); 578 CYGACC_COMM_IF_PUTC (*xyz.__chan, (xyz.crc_mode ? 'C' : NAK));
577 xyz.total_retries++; 579 xyz.total_retries++;
578 ZM_DEBUG (zm_dprintf ("NAK (%d)\n", __LINE__)); 580 ZM_DEBUG (zm_dprintf ("NAK (%d)\n", __LINE__));
579 } 581 }
580 if (stat < 0) 582 if (stat < 0)
581 { 583 {
582 *err = stat; 584 *err = stat;
583 xyz.len = -1; 585 xyz.len = -1;
584 return total; 586 return total;
585 } 587 }
586 } 588 }
587 /* Don't "read" data from the EOF protocol package */ 589 /* Don't "read" data from the EOF protocol package */
588 if (!xyz.at_eof) 590 if (!xyz.at_eof)
589 { 591 {
590 len = xyz.len; 592 len = xyz.len;
591 if (size < len) 593 if (size < len)
592 len = size; 594 len = size;
593 memcpy (buf, xyz.bufp, len); 595 memcpy (buf, xyz.bufp, len);
594 size -= len; 596 size -= len;
595 buf += len; 597 buf += len;
596 total += len; 598 total += len;
597 xyz.len -= len; 599 xyz.len -= len;
598 xyz.bufp += len; 600 xyz.bufp += len;
599 } 601 }
600 } 602 }
601 return total; 603 return total;
602 } 604 }
603 605
604 void 606 void
605 xyzModem_stream_close (int *err) 607 xyzModem_stream_close (int *err)
606 { 608 {
607 diag_printf 609 diag_printf
608 ("xyzModem - %s mode, %d(SOH)/%d(STX)/%d(CAN) packets, %d retries\n", 610 ("xyzModem - %s mode, %d(SOH)/%d(STX)/%d(CAN) packets, %d retries\n",
609 xyz.crc_mode ? "CRC" : "Cksum", xyz.total_SOH, xyz.total_STX, 611 xyz.crc_mode ? "CRC" : "Cksum", xyz.total_SOH, xyz.total_STX,
610 xyz.total_CAN, xyz.total_retries); 612 xyz.total_CAN, xyz.total_retries);
611 ZM_DEBUG (zm_flush ()); 613 ZM_DEBUG (zm_flush ());
612 } 614 }
613 615
614 /* Need to be able to clean out the input buffer, so have to take the */ 616 /* Need to be able to clean out the input buffer, so have to take the */
615 /* getc */ 617 /* getc */
616 void 618 void
617 xyzModem_stream_terminate (bool abort, int (*getc) (void)) 619 xyzModem_stream_terminate (bool abort, int (*getc) (void))
618 { 620 {
619 int c; 621 int c;
620 622
621 if (abort) 623 if (abort)
622 { 624 {
623 ZM_DEBUG (zm_dprintf ("!!!! TRANSFER ABORT !!!!\n")); 625 ZM_DEBUG (zm_dprintf ("!!!! TRANSFER ABORT !!!!\n"));
624 switch (xyz.mode) 626 switch (xyz.mode)
625 { 627 {
626 case xyzModem_xmodem: 628 case xyzModem_xmodem:
627 case xyzModem_ymodem: 629 case xyzModem_ymodem:
628 /* The X/YMODEM Spec seems to suggest that multiple CAN followed by an equal */ 630 /* The X/YMODEM Spec seems to suggest that multiple CAN followed by an equal */
629 /* number of Backspaces is a friendly way to get the other end to abort. */ 631 /* number of Backspaces is a friendly way to get the other end to abort. */
630 CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN); 632 CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN);
631 CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN); 633 CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN);
632 CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN); 634 CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN);
633 CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN); 635 CYGACC_COMM_IF_PUTC (*xyz.__chan, CAN);
634 CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP); 636 CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP);
635 CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP); 637 CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP);
636 CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP); 638 CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP);
637 CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP); 639 CYGACC_COMM_IF_PUTC (*xyz.__chan, BSP);
638 /* Now consume the rest of what's waiting on the line. */ 640 /* Now consume the rest of what's waiting on the line. */
639 ZM_DEBUG (zm_dprintf ("Flushing serial line.\n")); 641 ZM_DEBUG (zm_dprintf ("Flushing serial line.\n"));
640 xyzModem_flush (); 642 xyzModem_flush ();
641 xyz.at_eof = true; 643 xyz.at_eof = true;
642 break; 644 break;
643 #ifdef xyzModem_zmodem 645 #ifdef xyzModem_zmodem
644 case xyzModem_zmodem: 646 case xyzModem_zmodem:
645 /* Might support it some day I suppose. */ 647 /* Might support it some day I suppose. */
646 #endif 648 #endif
647 break; 649 break;
648 } 650 }
649 } 651 }
650 else 652 else
651 { 653 {
652 ZM_DEBUG (zm_dprintf ("Engaging cleanup mode...\n")); 654 ZM_DEBUG (zm_dprintf ("Engaging cleanup mode...\n"));
653 /* 655 /*
654 * Consume any trailing crap left in the inbuffer from 656 * Consume any trailing crap left in the inbuffer from
655 * previous received blocks. Since very few files are an exact multiple 657 * previous received blocks. Since very few files are an exact multiple
656 * of the transfer block size, there will almost always be some gunk here. 658 * of the transfer block size, there will almost always be some gunk here.
657 * If we don't eat it now, RedBoot will think the user typed it. 659 * If we don't eat it now, RedBoot will think the user typed it.
658 */ 660 */
659 ZM_DEBUG (zm_dprintf ("Trailing gunk:\n")); 661 ZM_DEBUG (zm_dprintf ("Trailing gunk:\n"));
660 while ((c = (*getc) ()) > -1) 662 while ((c = (*getc) ()) > -1)
661 ; 663 ;
662 ZM_DEBUG (zm_dprintf ("\n")); 664 ZM_DEBUG (zm_dprintf ("\n"));
663 /* 665 /*
664 * Make a small delay to give terminal programs like minicom 666 * Make a small delay to give terminal programs like minicom
665 * time to get control again after their file transfer program 667 * time to get control again after their file transfer program
666 * exits. 668 * exits.
667 */ 669 */
668 CYGACC_CALL_IF_DELAY_US ((cyg_int32) 250000); 670 CYGACC_CALL_IF_DELAY_US ((cyg_int32) 250000);
669 } 671 }
670 } 672 }
671 673
672 char * 674 char *
673 xyzModem_error (int err) 675 xyzModem_error (int err)
674 { 676 {
675 switch (err) 677 switch (err)
676 { 678 {
677 case xyzModem_access: 679 case xyzModem_access:
678 return "Can't access file"; 680 return "Can't access file";
679 break; 681 break;
680 case xyzModem_noZmodem: 682 case xyzModem_noZmodem:
681 return "Sorry, zModem not available yet"; 683 return "Sorry, zModem not available yet";
682 break; 684 break;
683 case xyzModem_timeout: 685 case xyzModem_timeout:
684 return "Timed out"; 686 return "Timed out";
685 break; 687 break;
686 case xyzModem_eof: 688 case xyzModem_eof:
687 return "End of file"; 689 return "End of file";
688 break; 690 break;
689 case xyzModem_cancel: 691 case xyzModem_cancel:
690 return "Cancelled"; 692 return "Cancelled";
691 break; 693 break;
692 case xyzModem_frame: 694 case xyzModem_frame:
693 return "Invalid framing"; 695 return "Invalid framing";
694 break; 696 break;
695 case xyzModem_cksum: 697 case xyzModem_cksum:
696 return "CRC/checksum error"; 698 return "CRC/checksum error";
697 break; 699 break;
698 case xyzModem_sequence: 700 case xyzModem_sequence:
699 return "Block sequence error"; 701 return "Block sequence error";
700 break; 702 break;
701 default: 703 default:
702 return "Unknown error"; 704 return "Unknown error";
703 break; 705 break;
704 } 706 }
705 } 707 }
706 708
707 /* 709 /*
708 * RedBoot interface 710 * RedBoot interface
709 */ 711 */
710 712