source: svn/trunk/newcon3bcm2_21bu/dta/src/xmodem.c @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 11.4 KB
Line 
1/*************************************************************************
2**
3**      Broadcom Corp. Confidential
4**      Copyright 1999, 2000 Broadcom Corp.  All Rights Reserved.
5**
6**  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7**  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8**  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9**
10**      File:           xmodem.c
11**      Description:    XModem download code
12**      REVISION:
13**
14****************************************************************************/
15
16#include "xmodem.h"
17#include "bcmuart.h"
18
19struct bserial
20{
21        volatile UartChannel *uart;
22}bserial;
23
24#if 0
25        extern void print_string(char *str);
26        #define XDEBUG(x) print_string x
27#else
28        #define XDEBUG(x)
29
30#endif
31
32
33#ifndef TRUE
34        #define TRUE 1
35#endif
36#ifndef FALSE
37        #define FALSE 0
38#endif
39
40/* Common ASCII code */
41
42#define ASC_CR      0x0d            /* Carriage return */
43#define ASC_LF      0x0a            /* Line feed */
44#define ASC_ESC     0x1b            /* Escape */
45#define ASC_BS      0x08            /* Back space */
46#define ASC_SP      0x20            /* Space */
47
48////////////////////////////////////////////////////////
49
50
51#define MODEM_SOH   0x01
52#define MODEM_STX   0x02
53#define MODEM_EOT   0x04
54#define MODEM_ACK   0x06
55#define MODEM_NCK   0x15
56#define MODEM_CAN   0x18
57#define MODEM_C     0x43
58
59#define XMODEM_MAX_ERROR    100
60
61
62/* Time constants (unit is 54.918 ms) */
63#define C_TIMEOUT     75*CLOCK_FACTOR // Time period of sending C out at startup
64#define DATA_TIMEOUT  10*CLOCK_FACTOR // Time out of data/control char receiving
65#define SOH_TIMEOUT   30*CLOCK_FACTOR // Time out of waiting for SOH
66
67// X Modem error condition
68enum XM_ERROR
69{
70
71        No_Error,
72        User_Abort,
73        Block_Number_Timeout,
74        Non_Sequential_Block_Number,
75        Complement_Block_Number_Timeout,
76        Block_Number_Unmatch,
77        Data_Timeout,
78        Checksum_High_Timeout,
79        Checksum_Low_Timeout,
80        Bad_Checksum,
81        SOH_Timeout,
82        EOT_received
83
84}XM_ERROR;
85
86/* Static vars */
87
88static int crc_computed;
89static unsigned char blockCount;
90static unsigned int blockSize;
91static unsigned int lastBlockSize;
92static unsigned char * blockPtr;
93static unsigned char * target_buffer;
94static int modemError;
95static unsigned int errCount;
96
97/* Forward Dec */
98
99int RxData(volatile UartChannel *uart, unsigned char *inData );
100void AddCRC( unsigned char data );
101int WaitStart(volatile UartChannel *uart);
102int WaitBlockNumber(volatile UartChannel *uart);
103int WaitData(volatile UartChannel *uart);
104int WaitCRC(volatile UartChannel *uart);
105int WaitSOH(volatile UartChannel *uart);
106
107#if (BCHP_CHIP==7550) || (BCHP_CHIP==7552)
108#define TxData(uart,x) \
109while(!(uart->sdw_lsr & THRE)); \
110   uart->sdw_rbr_thr_dll = (unsigned char)x;
111#else
112#define TxData(uart,x) \
113while(!(uart->txstat & TXDREGEMT)); \
114   uart->txdata = x;
115#endif
116void ClrCRC(void){crc_computed=0;}
117int GetCRC(void){return crc_computed & 0xffff;}
118void AssertXMError(int er)
119{
120        XDEBUG(("AssertXMError\n"));
121        modemError = er;
122        errCount++;
123};
124
125// Reset XModem
126void ResetXModem()
127{
128        XDEBUG(("ResetXModem\n"));
129        blockPtr = target_buffer;
130        blockCount = 1;
131        modemError = No_Error;
132};
133
134/*****************************************************************
135  int RxData( unsigned char *inData ) Checks for incoming data
136
137  Return: TRUE  - Incoming data received
138                  FALSE - No incoming data
139
140 *****************************************************************/
141#define RXRDA          0x01
142#define RXOVFERR       0x02
143#define RXPARERR       0x04
144#define RXFRAMERR      0x08
145
146int RxData(volatile UartChannel *uart, unsigned char *inData )
147{
148        volatile unsigned char Status;
149        volatile unsigned char junk;
150
151        //XDEBUG(("RxData\n"));
152#if (BCHP_CHIP==7550) || (BCHP_CHIP==7552)
153        Status = uart->sdw_lsr;
154        if (Status & RXRDA)
155        {
156                if (Status & RXOVFERR)
157                {
158                        XDEBUG(("OVERRUNERR\n"));
159                        junk = uart->sdw_rbr_thr_dll & 0xFF;
160                        TxData(uart,MODEM_C);
161                }
162                else if (Status & RXPARERR)
163                {
164                        XDEBUG(("PARERR\n"));
165                        junk = uart->sdw_rbr_thr_dll & 0xFF;
166                        TxData(uart,MODEM_C);
167                }
168                else if (Status & RXFRAMERR)
169                {
170                        XDEBUG(("FRAMEERR\n"));
171                        junk = uart->sdw_rbr_thr_dll & 0xFF;
172                        TxData(uart,MODEM_C);
173                }
174
175                *inData = uart->sdw_rbr_thr_dll & 0xFF;
176                return TRUE;
177        }
178#else
179        Status = uart->rxstat;
180        if (Status & RXDATARDY)
181        {
182                if (Status & OVERRUNERR)
183                {
184                        XDEBUG(("OVERRUNERR\n"));
185                        junk = uart->rxdata;
186                        TxData(uart,MODEM_C);
187                }
188                else if (Status & PARERR)
189                {
190                        XDEBUG(("PARERR\n"));
191                        junk = uart->rxdata;
192                        TxData(uart,MODEM_C);
193                }
194                else if (Status & FRAMEERR)
195                {
196                        XDEBUG(("FRAMEERR\n"));
197                        junk = uart->rxdata;
198                        TxData(uart,MODEM_C);
199                }
200
201                *inData = uart->rxdata;
202                return TRUE;
203        }
204#endif
205        return FALSE;
206}
207
208
209
210/*****************************************************************
211   void AddCRC( unsigned char data ) Adds data into CRC
212 *****************************************************************/
213void AddCRC( unsigned char data )
214{
215        int i;
216
217//      XDEBUG(("AddCRC\n"));
218        crc_computed = crc_computed ^ (int)data << 8;
219        for (i=0; i<8; ++i)
220        {
221                if ( crc_computed & 0x8000 )
222                {
223                        crc_computed = crc_computed << 1 ^ 0x1021;
224                }
225                else
226                {
227                        crc_computed = crc_computed << 1;
228                }
229        }
230}
231
232#define TEN_SECOND 10000000
233//#define TEN_SECOND 1000000
234
235/*****************************************************************
236  WaitStart() Waits for XMODEM receiving to start
237
238  Return: TRUE  - XMODEM downloading started
239                  FALSE - XMODEM downloading aborted
240
241  Note: User can press ESC to abort the downloading.
242
243 *****************************************************************/
244int WaitStart(volatile UartChannel *uart)
245{
246        unsigned char data;
247        unsigned int delay;
248
249        XDEBUG(("WaitStart\n"));
250        ResetXModem();
251        delay = 0;
252
253        while (1)
254        {
255                /* Generate C every 10 seconds if SOH has not received. */
256                if (delay == TEN_SECOND)
257                {
258                        delay = 0;
259                        TxData(uart,MODEM_C);
260                }
261
262                delay++;
263
264                /* Wait for hand shake ack */
265                if ( RxData(uart, &data) )
266                {
267                        if ( data == MODEM_SOH )
268                        {
269                                XDEBUG(("MODEM_SOH\n"));
270                                blockSize = 128;
271                                lastBlockSize = blockSize;
272
273                                return TRUE;
274                        }
275                        else if ( data == MODEM_STX )
276                        {
277
278                                XDEBUG(("MODEM_STX\n"));
279                                blockSize = 1024;
280                                lastBlockSize = blockSize;
281                                return TRUE;
282                        }
283                        else if ( data == ASC_ESC )
284                        {
285                                XDEBUG(("ASC_ESC\n"));
286
287                                AssertXMError( User_Abort );
288                                return FALSE;
289                        }
290                }
291        }
292}
293
294
295
296/*****************************************************************
297  WaitBlockNumber() Wait for XMODEM receiving the block number
298         complement
299
300  Return: TRUE  - XMODEM received block number complement
301                                         (May not be correct)
302                  FALSE - Timeout, should restart the XModem
303 *****************************************************************/
304int WaitBlockNumber(volatile UartChannel *uart)
305{
306        unsigned char data;
307        unsigned char receivedblockCount;
308
309        XDEBUG(("WaitBlockNumber\n"));
310        /* Wait for block number */
311        while (1)
312        {
313                /* Check if block number is received */
314                if ( RxData(uart,&receivedblockCount) )
315                {
316                        break;
317                }
318        }
319
320        /* Wait for block number complement */
321        while (1)
322        {
323                /* Check block number */
324                if ( RxData(uart,&data) )
325                {
326
327                        /* Check if complement matches */
328                        if ( (data + receivedblockCount) != 0xff )
329                        {
330                                XDEBUG(("Block_Number_Unmatch\n"));
331
332                                AssertXMError( Block_Number_Unmatch );
333                        }
334
335                        /* Check if it is re-doing the last block */
336                        /* or reciving the very first block       */
337                        if ( receivedblockCount == blockCount)
338                        {
339                                XDEBUG(("re-doing the last block or first"));
340                                ClrCRC();
341                                return TRUE;
342                        }
343
344                        /* Check if it is a new block */
345                        if ( (receivedblockCount == blockCount+1) ||
346                                 ((receivedblockCount==0) && (blockCount==0xff)) )
347                        {
348                                blockCount = receivedblockCount;
349                                blockPtr += lastBlockSize;
350                                lastBlockSize = blockSize;
351                                ClrCRC();
352                                return TRUE;
353                        }
354
355                        /* Error: the block number doesn't make sense */
356
357                        AssertXMError( Non_Sequential_Block_Number );
358                        return TRUE;
359                }
360        }
361}
362
363
364/*****************************************************************
365  WaitData() Wait for data
366
367  Return: TRUE  - XMODEM received data block
368                  FALSE - Timeout, should restart the XModem
369 *****************************************************************/
370int WaitData(volatile UartChannel *uart)
371{
372        unsigned char data;
373        unsigned int   i,cnt;
374        unsigned long timeout = 0;
375        cnt = 0;
376        XDEBUG(("WaitData "));
377
378        for (i = 0; i < blockSize; i++)
379        {
380                while (1)
381                {
382                        if ( RxData(uart,&data) )
383                        {   
384                                *(unsigned char*)(blockPtr+i) = data; 
385                                AddCRC( data );
386                                cnt++;
387                                if (cnt == blockSize)
388                                {
389                                        return TRUE;
390                                }
391                                break;
392                        }
393                        timeout++;
394                        if (timeout > TEN_SECOND)
395                        {
396                                XDEBUG(("WaitData - TIMEOUT\n"));
397                                return FALSE;
398                        }
399                }
400        }
401
402        return TRUE;
403}
404
405
406/*****************************************************************
407  WaitCRC() Wait for CRC check sum
408
409  Return: TRUE  - XMODEM received check sum
410                  FALSE - Timeout, should restart the XModem
411 *****************************************************************/
412int WaitCRC(volatile UartChannel *uart)
413{
414
415        unsigned char data;
416        int   crc_received;
417        XDEBUG(("WaitCRC\n"));
418
419        /* Wait CRC check sum high byte */
420        while (1)
421        {
422                /* Wait for CRC check sum high byte */
423                if ( RxData(uart,&data) )
424                {
425                        crc_received = data << 8;
426                        break;
427                }
428        }
429
430
431        /* Wait CRC check sum low byte */
432        while (1)
433        {
434                /* Wait for CRC check sum low byte */
435                if ( RxData(uart,&data) )
436                {
437                        crc_received |= data ;
438                        break;
439                }
440        }
441
442        if ( crc_received != GetCRC() )
443                AssertXMError( Bad_Checksum );
444
445        return TRUE;
446
447}
448
449
450
451/*****************************************************************
452  WaitSOH() Waits for SOH control character
453
454  Return: TRUE  - SOH or STX or EOT recived
455                  FALSE - Timeout
456 *****************************************************************/
457int WaitSOH(volatile UartChannel *uart)
458{
459        unsigned char data;
460
461        XDEBUG(("WaitSOH\n"));
462        while (1)
463        {
464                /* Wait for hand shake (SOH or EOT) */
465                if ( RxData(uart,&data) )
466                {
467                        if ( data == MODEM_SOH )
468                        {
469                                blockSize = 128;
470                                return TRUE;
471                        }
472
473                        if ( data == MODEM_STX )
474                        {
475                                blockSize = 1024;
476                                return TRUE;
477                        }
478
479                        if ( data == MODEM_EOT )
480                        {
481                                TxData(uart,MODEM_ACK);
482                                AssertXMError( EOT_received );
483                                return TRUE;
484                        }
485                }
486        }
487}
488
489
490
491
492/*****************************************************************
493  XModemReceive( volatile UartChannel *uart, char* buf ) Starts XModem receive
494
495  Return: The number of bytes received
496                  If it is zero, an error condition has occurred.
497 *****************************************************************/
498unsigned int XModemReceive(volatile UartChannel *uart, unsigned char* buf )
499{
500
501        /* Initialize the buffer pointer */
502        target_buffer = buf;
503
504        /* Clear error count */
505        errCount   = 0;
506
507        /* Wait X Modem start */
508        if ( !WaitStart(uart) )
509        {
510                return 0;
511        }
512
513        /* X Modem main loop */
514        do
515        {
516                if ( !WaitBlockNumber(uart) )
517                {
518                        if ( !WaitStart(uart) )
519                                return 0;
520                }
521                else if ( !WaitData(uart) )
522                {
523                        if ( !WaitStart(uart) )
524                                return 0;
525                }
526                else if ( !WaitCRC(uart) )
527                {
528                        if ( !WaitStart(uart) )
529                                return 0;
530                }
531                else
532                {
533                        if ( modemError == No_Error )
534                        {
535                                TxData(uart,MODEM_ACK);
536                                if ( !WaitSOH(uart) )
537                                        if ( !WaitStart(uart) ) return 0;
538                        }
539                        else
540                        {
541                                modemError = No_Error;
542
543                                if ( errCount > XMODEM_MAX_ERROR )
544                                {
545                                        TxData(uart,MODEM_CAN);
546                                        errCount = 0;
547                                        if ( !WaitStart(uart) ) return 0;
548                                }
549                                else
550                                {
551                                        TxData(uart,MODEM_NCK);
552                                        if ( !WaitSOH(uart) )
553                                                if ( !WaitStart(uart) ) return 0;
554                                }
555                        }
556                }
557        } while ( modemError != EOT_received );
558
559        return(unsigned int)(blockPtr - target_buffer + blockSize);
560}
561
562unsigned int xmodem_receive(volatile UartChannel *uart, unsigned char* buf )
563{
564        return XModemReceive(uart,buf);
565}
566
Note: See TracBrowser for help on using the repository browser.