2 * (C) Copyright 2000-2004
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * Serial up- and download support
29 #define putc serial_putc
30 #define tstc serial_tstc
32 /*******************************************************
34 * Description: spinning delay to use before udelay works
35 ******************************************************/
36 static inline void delay(unsigned long loops)
38 __asm__ volatile ("1:\n" "subs %0, %1, #1\n"
39 "bne 1b":"=r" (loops):"0"(loops));
41 static inline void udelay(unsigned long us)
43 delay(us * 200); /* approximate */
47 extern void * memcpy(void * dest,const void *src,size_t count);
49 void * memcpy(void * dest,const void *src,size_t count)
51 char *tmp = (char *) dest, *s = (char *) src;
60 /* -------------------------------------------------------------------- */
64 #define START_CHAR 0x01
73 #define BREAK_TYPE 'B'
74 #define tochar(x) ((char) (((x) + SPACE) & 0xff))
75 #define untochar(x) ((int) (((x) - SPACE) & 0xff))
77 extern int os_data_count;
78 extern int os_data_header[8];
80 static void set_kerm_bin_mode(unsigned long *);
81 static int k_recv(void);
82 static ulong load_serial_bin (ulong offset);
85 char his_eol; /* character he needs at end of packet */
86 int his_pad_count; /* number of pad chars he needs */
87 char his_pad_char; /* pad chars he needs */
88 char his_quote; /* quote chars he'll use */
90 int do_load_serial_bin (ulong offset, int baudrate)
95 printf ("## Ready for binary (kermit) download "
96 "to 0x%08lX at %d bps...\n",
99 addr = load_serial_bin (offset);
101 printf ("## Binary (kermit) download aborted\n");
104 printf ("## Start Addr = 0x%08lX\n", addr);
111 static ulong load_serial_bin (ulong offset)
115 set_kerm_bin_mode ((ulong *) offset);
119 * Gather any trailing characters (for instance, the ^D which
120 * is sent by 'cu' after sending a file), and give the
121 * box some time (100 * 1 ms)
123 for (i=0; i<100; ++i) {
130 printf("## Total Size = 0x%08x = %d Bytes\n", size, size);
137 int count = his_pad_count;
143 /* converts escaped kermit char to binary char */
144 char ktrans (char in)
146 if ((in & 0x60) == 0x40) {
147 return (char) (in & ~0x40);
148 } else if ((in & 0x7f) == 0x3f) {
149 return (char) (in | 0x40);
154 int chk1 (char *buffer)
161 return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);
164 void s1_sendpacket (char *packet)
173 void send_ack (int n)
180 a_b[4] = tochar (chk1 (&a_b[1]));
186 void send_nack (int n)
193 a_b[4] = tochar (chk1 (&a_b[1]));
200 /* os_data_* takes an OS Open image and puts it into memory, and
201 puts the boot header in an array named os_data_header
203 if image is binary, no header is stored in os_data_header.
205 void (*os_data_init) (void);
206 void (*os_data_char) (char new_char);
207 static int os_data_state, os_data_state_saved;
209 static int os_data_count_saved;
210 static char *os_data_addr, *os_data_addr_saved;
211 static char *bin_start_address;
212 int os_data_header[8];
213 static void bin_data_init (void)
217 os_data_addr = bin_start_address;
219 static void os_data_save (void)
221 os_data_state_saved = os_data_state;
222 os_data_count_saved = os_data_count;
223 os_data_addr_saved = os_data_addr;
225 static void os_data_restore (void)
227 os_data_state = os_data_state_saved;
228 os_data_count = os_data_count_saved;
229 os_data_addr = os_data_addr_saved;
231 static void bin_data_char (char new_char)
233 switch (os_data_state) {
235 *os_data_addr++ = new_char;
240 static void set_kerm_bin_mode (unsigned long *addr)
242 bin_start_address = (char *) addr;
243 os_data_init = bin_data_init;
244 os_data_char = bin_data_char;
248 /* k_data_* simply handles the kermit escape translations */
249 static int k_data_escape, k_data_escape_saved;
250 void k_data_init (void)
255 void k_data_save (void)
257 k_data_escape_saved = k_data_escape;
260 void k_data_restore (void)
262 k_data_escape = k_data_escape_saved;
265 void k_data_char (char new_char)
268 /* last char was escape - translate this character */
269 os_data_char (ktrans (new_char));
272 if (new_char == his_quote) {
273 /* this char is escape - remember */
276 /* otherwise send this char as-is */
277 os_data_char (new_char);
282 #define SEND_DATA_SIZE 20
283 char send_parms[SEND_DATA_SIZE];
286 /* handle_send_packet interprits the protocol info and builds and
287 sends an appropriate ack for what we can do */
288 void handle_send_packet (int n)
293 /* initialize some protocol parameters */
294 his_eol = END_CHAR; /* default end of line character */
297 his_quote = K_ESCAPE;
299 /* ignore last character if it filled the buffer */
300 if (send_ptr == &send_parms[SEND_DATA_SIZE - 1])
302 bytes = send_ptr - send_parms; /* how many bytes we'll process */
306 /* handle MAXL - max length */
307 /* ignore what he says - most I'll take (here) is 94 */
308 a_b[++length] = tochar (94);
311 /* handle TIME - time you should wait for my packets */
312 /* ignore what he says - don't wait for my ack longer than 1 second */
313 a_b[++length] = tochar (1);
316 /* handle NPAD - number of pad chars I need */
317 /* remember what he says - I need none */
318 his_pad_count = untochar (send_parms[2]);
319 a_b[++length] = tochar (0);
322 /* handle PADC - pad chars I need */
323 /* remember what he says - I need none */
324 his_pad_char = ktrans (send_parms[3]);
325 a_b[++length] = 0x40; /* He should ignore this */
328 /* handle EOL - end of line he needs */
329 /* remember what he says - I need CR */
330 his_eol = untochar (send_parms[4]);
331 a_b[++length] = tochar (END_CHAR);
334 /* handle QCTL - quote control char he'll use */
335 /* remember what he says - I'll use '#' */
336 his_quote = send_parms[5];
340 /* handle QBIN - 8-th bit prefixing */
341 /* ignore what he says - I refuse */
345 /* handle CHKT - the clock check type */
346 /* ignore what he says - I do type 1 (for now) */
350 /* handle REPT - the repeat prefix */
351 /* ignore what he says - I refuse (for now) */
355 /* handle CAPAS - the capabilities mask */
356 /* ignore what he says - I only do long packets - I don't do windows */
357 a_b[++length] = tochar (2); /* only long packets */
358 a_b[++length] = tochar (0); /* no windows */
359 a_b[++length] = tochar (94); /* large packet msb */
360 a_b[++length] = tochar (94); /* large packet lsb */
364 a_b[1] = tochar (length);
367 a_b[++length] = '\0';
368 a_b[length] = tochar (chk1 (&a_b[1]));
369 a_b[++length] = his_eol;
370 a_b[++length] = '\0';
374 /* k_recv receives a OS Open image file over kermit line */
375 static int k_recv (void)
378 char k_state, k_state_saved;
386 /* initialize some protocol parameters */
387 his_eol = END_CHAR; /* default end of line character */
390 his_quote = K_ESCAPE;
392 /* initialize the k_recv and k_data state machine */
396 k_state_saved = k_state;
398 n = 0; /* just to get rid of a warning */
401 /* expect this "type" sequence (but don't check):
406 B: break transmission
409 /* enter main loop */
411 /* set the send packet pointer to begining of send packet parms */
412 send_ptr = send_parms;
414 /* With each packet, start summing the bytes starting with the length.
415 Save the current sequence number.
416 Note the type of the packet.
417 If a character less than SPACE (0x20) is received - error.
421 /* OLD CODE, Prior to checking sequence numbers */
422 /* first have all state machines save current states */
423 k_state_saved = k_state;
428 /* wait for the starting character or ^C */
431 case START_CHAR: /* start packet */
433 case ETX_CHAR: /* ^C waiting for packet */
440 /* get length of packet */
443 if ((new_char & 0xE0) == 0)
445 sum += new_char & 0xff;
446 length = untochar (new_char);
447 /* get sequence number */
449 if ((new_char & 0xE0) == 0)
451 sum += new_char & 0xff;
452 n = untochar (new_char);
455 /* NEW CODE - check sequence numbers for retried packets */
456 /* Note - this new code assumes that the sequence number is correctly
457 * received. Handling an invalid sequence number adds another layer
458 * of complexity that may not be needed - yet! At this time, I'm hoping
459 * that I don't need to buffer the incoming data packets and can write
460 * the data into memory in real time.
463 /* same sequence number, restore the previous state */
464 k_state = k_state_saved;
467 /* new sequence number, checkpoint the download */
469 k_state_saved = k_state;
474 /* get packet type */
476 if ((new_char & 0xE0) == 0)
478 sum += new_char & 0xff;
481 /* check for extended length */
483 /* (length byte was 0, decremented twice) */
484 /* get the two length bytes */
486 if ((new_char & 0xE0) == 0)
488 sum += new_char & 0xff;
489 len_hi = untochar (new_char);
491 if ((new_char & 0xE0) == 0)
493 sum += new_char & 0xff;
494 len_lo = untochar (new_char);
495 length = len_hi * 95 + len_lo;
496 /* check header checksum */
498 if ((new_char & 0xE0) == 0)
500 if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
502 sum += new_char & 0xff;
503 /* --length; */ /* new length includes only data and block check to come */
505 /* bring in rest of packet */
508 if ((new_char & 0xE0) == 0)
510 sum += new_char & 0xff;
512 if (k_state == DATA_TYPE) {
513 /* pass on the data if this is a data packet */
514 k_data_char (new_char);
515 } else if (k_state == SEND_TYPE) {
516 /* save send pack in buffer as is */
517 *send_ptr++ = new_char;
518 /* if too much data, back off the pointer */
519 if (send_ptr >= &send_parms[SEND_DATA_SIZE])
523 /* get and validate checksum character */
525 if ((new_char & 0xE0) == 0)
527 if (new_char != tochar ((sum + ((sum >> 6) & 0x03)) & 0x3f))
531 if (new_char != END_CHAR) {
533 /* restore state machines */
534 k_state = k_state_saved;
536 /* send a negative acknowledge packet in */
538 } else if (k_state == SEND_TYPE) {
539 /* crack the protocol parms, build an appropriate ack packet */
540 handle_send_packet (n);
542 /* send simple acknowledge packet in */
544 /* quit if end of transmission */
545 if (k_state == BREAK_TYPE)
550 return ((ulong) os_data_addr - (ulong) bin_start_address);