enable start-stop-daemon by default, i want to use this to clean up a few init script...
[15.05/openwrt.git] / target / linux / at91-2.6 / image / dfboot / src / main.c
1 /*----------------------------------------------------------------------------
2  *         ATMEL Microcontroller Software Support  -  ROUSSET  -
3  *----------------------------------------------------------------------------
4  * The software is delivered "AS IS" without warranty or condition of any
5  * kind, either express, implied or statutory. This includes without
6  * limitation any warranty or condition with respect to merchantability or
7  * fitness for any particular purpose, or against the infringements of
8  * intellectual property rights of others.
9  *----------------------------------------------------------------------------
10  * File Name            : main.c
11  * Object               : 
12  * Creation             : HIi   10/10/2003
13  * Modif                : HIi   15/06/2004 :    add crc32 to verify the download
14  *                                              from dataflash
15  *                      : HIi   21/09/2004 :    Set first PLLA to 180Mhz and MCK to
16  *                                              60Mhz to speed up dataflash boot (15Mhz)
17  *                      : MLC   12/04/2005 :    Modify SetPLL() to avoid errata
18  *                      : USA   30/12/2005 :    Change to page Size 1056
19  *                                              Change startaddress to C0008400
20  *                                              Change SPI Speed to ~4 Mhz
21  *                                              Add retry on CRC Error
22  *----------------------------------------------------------------------------
23  */
24 #include "config.h"
25 #include "stdio.h"
26 #include "AT91RM9200.h"
27 #include "lib_AT91RM9200.h"
28 #include "com.h"
29 #include "main.h"
30 #include "dataflash.h"
31 #include "AT91C_MCI_Device.h"
32
33 #define DEBUGOUT
34 #define XMODEM
35 #define MEMDISP
36
37 #ifdef  PAGESZ_1056
38 #define PAGESIZE        1056
39 #else
40 #define PAGESIZE        1024
41 #endif
42
43 #define AT91C_SDRAM_START 0x20000000
44 #define AT91C_BOOT_ADDR 0x21F00000
45 #define AT91C_BOOT_SIZE 128*PAGESIZE
46 #ifdef  PAGESZ_1056
47 #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008400
48 #else
49 #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008000
50 #endif
51 #define AT91C_PLLA_VALUE 0x237A3E5A  // crystal= 18.432MHz - fixes BRG error at 115kbps
52 //#define AT91C_PLLA_VALUE 0x2026BE04   // crystal= 18.432MHz
53 //#define AT91C_PLLA_VALUE 0x202CBE01   // crystal= 4MHz
54
55
56
57 #define DISP_LINE_LEN 16
58
59 // Reason for boot failure
60 #define IMAGE_BAD_SIZE                  0
61 #define IMAGE_READ_FAILURE      1
62 #define IMAGE_CRC_ERROR         2
63 #define IMAGE_ERROR                     3
64 #define SUCCESS                         -1
65
66 /* prototypes*/
67 extern void AT91F_ST_ASM_HANDLER(void);
68 extern void Jump(unsigned int addr);
69
70 const char *menu_dataflash[] = {
71 #ifdef XMODEM
72         "1: P DFboot\n",
73         "2: P U-Boot\n",
74 #endif
75         "3: P SDCard\n",
76 #ifdef  PAGESZ_1056
77         "4: R UBOOT\n",
78 #else
79         "4: R UBOOT\n",
80 #endif
81 #ifdef XMODEM
82         "5: P DF [addr]\n",
83 #endif
84         "6: RD DF [addr]\n",
85         "7: E DF\n"
86 };
87 #ifdef XMODEM
88 #define MAXMENU 7
89 #else
90 #define MAXMENU 4
91 #endif
92
93 char message[20];
94 #ifdef XMODEM
95 volatile char XmodemComplete = 0;
96 #endif
97 unsigned int StTick = 0;
98
99 AT91S_RomBoot const *pAT91;
100 #ifdef XMODEM
101 AT91S_SBuffer sXmBuffer;
102 AT91S_SvcXmodem svcXmodem;
103 AT91S_Pipe xmodemPipe;
104 #endif
105 AT91S_CtlTempo ctlTempo;
106
107
108 //*--------------------------------------------------------------------------------------
109 //* Function Name       : GetTickCount()
110 //* Object              : Return the number of systimer tick 
111 //* Input Parameters    :
112 //* Output Parameters   :
113 //*--------------------------------------------------------------------------------------
114 unsigned int GetTickCount(void)
115 {
116         return StTick;
117 }
118
119 #ifdef XMODEM
120 //*--------------------------------------------------------------------------------------
121 //* Function Name       : AT91_XmodemComplete()
122 //* Object              : Perform the remap and jump to appli in RAM
123 //* Input Parameters    :
124 //* Output Parameters   :
125 //*--------------------------------------------------------------------------------------
126 static void AT91_XmodemComplete(AT91S_PipeStatus status, void *pVoid)
127 {
128         /* stop the Xmodem tempo */
129         svcXmodem.tempo.Stop(&(svcXmodem.tempo));
130         XmodemComplete = 1;
131 }
132
133
134 //*--------------------------------------------------------------------------------------
135 //* Function Name       : AT91F_XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
136 //* Object              : Xmodem dispatcher
137 //* Input Parameters    :
138 //* Output Parameters   :
139 //*--------------------------------------------------------------------------------------
140 static void XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
141 {
142         AT91PS_SBuffer pSBuffer = (AT91PS_SBuffer) xmodemPipe.pBuffer->pChild;
143         AT91PS_USART   pUsart     = svcXmodem.pUsart;
144                         
145         if (pSBuffer->szRdBuffer == 0) {
146                 /* Start a tempo to wait the Xmodem protocol complete */
147                 svcXmodem.tempo.Start(&(svcXmodem.tempo), 10, 0, AT91_XmodemComplete, pUsart);                                                          
148         }
149 }
150 #endif
151
152 //*--------------------------------------------------------------------------------------
153 //* Function Name       : irq1_c_handler()
154 //* Object              : C Interrupt handler for Interrutp source 1
155 //* Input Parameters    : none
156 //* Output Parameters   : none
157 //*--------------------------------------------------------------------------------------
158 void AT91F_ST_HANDLER(void)
159 {
160         volatile unsigned int csr = *AT91C_DBGU_CSR;
161 #ifdef XMODEM
162         unsigned int error;
163 #endif
164         
165         if (AT91C_BASE_ST->ST_SR & 0x01) {
166                 StTick++;
167                 ctlTempo.CtlTempoTick(&ctlTempo);
168                 return;
169         }
170
171 #ifdef XMODEM
172         error = AT91F_US_Error((AT91PS_USART)AT91C_BASE_DBGU);
173         if (csr & error) {
174                 /* Stop previous Xmodem transmition*/
175                 *(AT91C_DBGU_CR) = AT91C_US_RSTSTA;
176                 AT91F_US_DisableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_ENDRX);
177                 AT91F_US_EnableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_RXRDY);
178
179         }
180         
181         else if (csr & (AT91C_US_TXRDY | AT91C_US_ENDTX | AT91C_US_TXEMPTY | 
182                         AT91C_US_RXRDY | AT91C_US_ENDRX | AT91C_US_TIMEOUT | 
183                         AT91C_US_RXBUFF)) {
184                 if ( !(svcXmodem.eot) )
185                         svcXmodem.Handler(&svcXmodem, csr);
186         }
187 #endif
188 }
189
190
191 //*-----------------------------------------------------------------------------
192 //* Function Name       : AT91F_DisplayMenu()
193 //* Object              : 
194 //* Input Parameters    : 
195 //* Return value                : 
196 //*-----------------------------------------------------------------------------
197 static int AT91F_DisplayMenu(void)
198 {
199         int i, mci_present = 0;
200         printf("\nDF LOADER %s %s %s\n",AT91C_VERSION,__DATE__,__TIME__);
201         AT91F_DataflashPrintInfo();
202         mci_present = AT91F_MCI_Init();
203         for(i = 0; i < MAXMENU; i++) {
204                 puts(menu_dataflash[i]);
205         }
206         return mci_present;
207 }       
208
209
210 //*-----------------------------------------------------------------------------
211 //* Function Name       : AsciiToHex()
212 //* Object              : ascii to hexa conversion
213 //* Input Parameters    : 
214 //* Return value                : 
215 //*-----------------------------------------------------------------------------
216 static unsigned int AsciiToHex(char *s, unsigned int *val)
217 {
218         int n;
219
220         *val=0;
221         
222         if(s[0] == '0' && ((s[1] == 'x') || (s[1] == 'X')))
223                 s+=2;
224         n = 0;  
225         while((n < 8) && (s[n] !=0))
226         {
227                 *val <<= 4;
228                 if ( (s[n] >= '0') && (s[n] <='9'))
229                         *val += (s[n] - '0');
230                 else    
231                         if ((s[n] >= 'a') && (s[n] <='f'))
232                                 *val += (s[n] - 0x57);
233                         else
234                                 if ((s[n] >= 'A') && (s[n] <='F'))
235                                         *val += (s[n] - 0x37);
236                         else
237                                 return 0;
238                 n++;
239         }
240
241         return 1;                               
242 }
243
244
245 #ifdef MEMDISP
246 //*-----------------------------------------------------------------------------
247 //* Function Name       : AT91F_MemoryDisplay()
248 //* Object              : Display the content of the dataflash
249 //* Input Parameters    : 
250 //* Return value                : 
251 //*-----------------------------------------------------------------------------
252 static int AT91F_MemoryDisplay(unsigned int addr, unsigned int length)
253 {
254         unsigned long   i, nbytes, linebytes;
255         char    *cp;
256 //      unsigned int    *uip;
257 //      unsigned short  *usp;
258         unsigned char   *ucp;
259         char linebuf[DISP_LINE_LEN];
260
261 //      nbytes = length * size;
262         nbytes = length;
263         do
264         {
265 //              uip = (unsigned int *)linebuf;
266 //              usp = (unsigned short *)linebuf;
267                 ucp = (unsigned char *)linebuf;
268                 
269                 printf("%08x:", addr);
270                 linebytes = (nbytes > DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
271                 if((addr & 0xF0000000) == 0x20000000) {
272                         for(i = 0; i < linebytes; i ++) {
273                                 linebuf[i] =  *(char *)(addr+i);
274                         }
275                 } else {
276                         read_dataflash(addr, linebytes, linebuf);
277                 }
278                 for (i=0; i<linebytes; i++)
279                 {
280 /*                      if (size == 4) 
281                                 printf(" %08x", *uip++);
282                         else if (size == 2)
283                                 printf(" %04x", *usp++);
284                         else
285 */
286                                 printf(" %02x", *ucp++);
287 //                      addr += size;
288                         addr++;
289                 }
290                 printf("    ");
291                 cp = linebuf;
292                 for (i=0; i<linebytes; i++) {
293                         if ((*cp < 0x20) || (*cp > 0x7e))
294                                 printf(".");
295                         else
296                                 printf("%c", *cp);
297                         cp++;
298                 }
299                 printf("\n");
300                 nbytes -= linebytes;
301         } while (nbytes > 0);
302         return 0;
303 }
304 #endif
305
306 //*--------------------------------------------------------------------------------------
307 //* Function Name       : AT91F_SetPLL
308 //* Object              : Set the PLLA to 180Mhz and Master clock to 60 Mhz
309 //* Input Parameters    :
310 //* Output Parameters   :
311 //*--------------------------------------------------------------------------------------
312 static unsigned int AT91F_SetPLL(void)
313 {
314         AT91_REG tmp;
315         AT91PS_PMC pPmc = AT91C_BASE_PMC;
316         AT91PS_CKGR pCkgr = AT91C_BASE_CKGR;
317
318         pPmc->PMC_IDR = 0xFFFFFFFF;
319
320         /* -Setup the PLL A */
321         pCkgr->CKGR_PLLAR = AT91C_PLLA_VALUE;
322
323         while (!(*AT91C_PMC_SR & AT91C_PMC_LOCKA));
324         
325         /* - Switch Master Clock from PLLB to PLLA/3 */
326         tmp = pPmc->PMC_MCKR;
327         /* See Atmel Errata #27 and #28 */
328         if (tmp & 0x0000001C) {
329                 tmp = (tmp & ~0x0000001C);
330                 pPmc->PMC_MCKR = tmp;
331                 while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
332         }
333         if (tmp != 0x00000202) {
334                 pPmc->PMC_MCKR = 0x00000202;
335                 if ((tmp & 0x00000003) != 0x00000002)
336                         while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
337         }
338
339         return 1;       
340 }
341
342
343 //*--------------------------------------------------------------------------------------
344 //* Function Name       : AT91F_ResetRegisters
345 //* Object              : Restore the initial state to registers
346 //* Input Parameters    :
347 //* Output Parameters   :
348 //*--------------------------------------------------------------------------------------
349 static unsigned int AT91F_ResetRegisters(void)
350 {
351         volatile int i = 0;
352
353         /* set the PIOs in input*/
354         /* This disables the UART output, so dont execute for now*/
355
356 #ifndef DEBUGOUT
357         *AT91C_PIOA_ODR = 0xFFFFFFFF;   /* Disables all the output pins */
358         *AT91C_PIOA_PER = 0xFFFFFFFF;   /* Enables the PIO to control all the pins */
359 #endif
360
361         AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SYS);
362         /* close all peripheral clocks */
363
364 #ifndef DEBUGOUT
365         AT91C_BASE_PMC->PMC_PCDR = 0xFFFFFFFC;
366 #endif
367         /* Disable core interrupts and set supervisor mode */
368         __asm__ ("msr CPSR_c, #0xDF"); //* ARM_MODE_SYS(0x1F) | I_BIT(0x80) | F_BIT(0x40)
369         /* Clear all the interrupts */
370         *AT91C_AIC_ICCR = 0xffffffff;
371
372         /* read the AIC_IVR and AIC_FVR */
373         i = *AT91C_AIC_IVR;
374         i = *AT91C_AIC_FVR;
375
376         /* write the end of interrupt control register */
377         *AT91C_AIC_EOICR        = 0;
378
379         return 1;
380 }
381
382
383 static int AT91F_LoadBoot(void)
384 {
385 //      volatile unsigned int crc1 = 0, crc2 = 0;
386         volatile unsigned int SizeToDownload = 0x21400;
387         volatile unsigned int AddressToDownload = AT91C_BOOT_ADDR;
388
389 #if 0
390         /* Read vector 6 to extract size to load */     
391         if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, 32,
392                            (char *)AddressToDownload) != AT91C_DATAFLASH_OK)
393         {
394                 printf("Bad Code Size\n");
395                 return IMAGE_BAD_SIZE;
396         }
397         /* calculate the size to download */
398         SizeToDownload = *(int *)(AddressToDownload + AT91C_OFFSET_VECT6);
399 #endif
400         
401 //      printf("\nLoad UBOOT from dataflash[%x] to SDRAM[%x]\n",
402 //             AT91C_BOOT_DATAFLASH_ADDR, AT91C_BOOT_ADDR);
403         if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, SizeToDownload + 8,
404                            (char *)AddressToDownload) != AT91C_DATAFLASH_OK)
405         {
406                 printf("F DF RD\n");
407                 return IMAGE_READ_FAILURE;
408         }
409 #if 0
410         pAT91->CRC32((const unsigned char *)AT91C_BOOT_ADDR,
411                      (unsigned int)SizeToDownload , (unsigned int *)&crc2);
412         crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload)) +
413                (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) +
414                (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) +
415                (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24);
416
417         /* Restore the value of Vector 6 */
418         *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) =
419                 *(int *)(AddressToDownload + SizeToDownload + 4);
420         
421         if (crc1 != crc2) {
422                 printf("DF CRC bad %x != %x\n",crc1,crc2);
423                 return  IMAGE_CRC_ERROR;
424         }
425 #endif
426         return SUCCESS;
427 }
428
429 static int AT91F_StartBoot(void)
430 {
431         int     sts;
432         if((sts = AT91F_LoadBoot()) != SUCCESS) return sts;
433 //      printf("\n");
434 //      printf("PLLA[180MHz], MCK[60Mhz] ==> Start UBOOT\n");
435         if (AT91F_ResetRegisters())
436         {
437                 printf("Jump");
438                 Jump(AT91C_BOOT_ADDR);
439 //              LED_blink(0);
440         }
441         return  IMAGE_ERROR;
442 }
443
444 #if 0
445 static void     AT91F_RepeatedStartBoot(void)
446 {
447         int     i;
448         for(i = 0; i < CRC_RETRIES; i++) {
449                 if(AT91F_StartBoot() != IMAGE_CRC_ERROR){
450 //                      LED_blink(1);
451                         return;
452                 }
453         }
454         return;
455 }
456 #endif
457
458 #define TRUE 1
459 #define FALSE 0
460 #define TRX_MAGIC 0x30524448  /* "HDR0" */
461 #define TRX_VERSION 1
462
463 struct trx_header {
464         unsigned int magic;
465         unsigned int len;
466         unsigned int crc32;
467         unsigned int flag_version;
468         unsigned int offsets[3];
469 };
470
471 #define AT91C_MCI_TIMEOUT 1000000
472
473 extern AT91S_MciDevice MCI_Device;
474 extern void AT91F_MCIDeviceWaitReady(unsigned int);
475 extern int AT91F_MCI_ReadBlockSwab(AT91PS_MciDevice, int, unsigned int *, int);
476
477 int Program_From_MCI(void)
478 {
479   int i;
480   unsigned int Max_Read_DataBlock_Length;
481   int block = 0;
482   int buffer = AT91C_DOWNLOAD_BASE_ADDRESS;
483   int bufpos = AT91C_DOWNLOAD_BASE_ADDRESS;
484   int NbPage = 0;
485   struct trx_header *p;
486
487         p = (struct trx_header *)bufpos;
488
489         Max_Read_DataBlock_Length = MCI_Device.pMCI_DeviceFeatures->Max_Read_DataBlock_Length;
490
491         AT91F_MCIDeviceWaitReady(AT91C_MCI_TIMEOUT);
492
493   AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length);
494
495   if (p->magic != TRX_MAGIC) {
496                 printf("Inv IMG 0x%08x\n", p->magic);
497                 return FALSE;
498                 }
499
500         printf("RDSD");
501         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC8 | AT91C_PIO_PC14;
502         for (i=0; i<(p->len/512); i++) {
503                 AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length);
504                 block++;
505                 bufpos += Max_Read_DataBlock_Length;
506                 }
507
508         NbPage = 0;
509         i = dataflash_info[0].Device.pages_number;
510         while(i >>= 1)
511                 NbPage++;
512         i = ((p->offsets[1] - p->offsets[0])/ 512) + 1 + (NbPage << 13) + (dataflash_info[0].Device.pages_size << 17);
513         *(int *)(buffer + p->offsets[0] + AT91C_OFFSET_VECT6) = i;
514
515         printf(" WDFB");
516         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC14;
517         AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8;
518         write_dataflash(0xc0000000, buffer + p->offsets[0], p->offsets[1] - p->offsets[0]);
519         printf(" WUB");
520         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15;
521         AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8 | AT91C_PIO_PC14;
522         write_dataflash(0xc0008000, buffer + p->offsets[1], p->offsets[2] - p->offsets[1]);
523         printf(" WKRFS");
524         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC15;
525         AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC14;
526         write_dataflash(0xc0042000, buffer + p->offsets[2], p->len - p->offsets[2]);
527         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC14;
528         AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC15;
529         return TRUE;
530 }
531
532 //*----------------------------------------------------------------------------
533 //* Function Name       : main
534 //* Object              : Main function
535 //* Input Parameters    : none
536 //* Output Parameters   : True
537 //*----------------------------------------------------------------------------
538 int main(void)
539 {
540 #ifdef XMODEM
541         AT91PS_Buffer           pXmBuffer;
542         AT91PS_SvcComm          pSvcXmodem;
543 #endif
544         AT91S_SvcTempo          svcBootTempo;    // Link to a AT91S_Tempo object
545         unsigned int            ix;
546         volatile unsigned int AddressToDownload, SizeToDownload;        
547         unsigned int DeviceAddress = 0;
548         char command = 0;
549 #ifdef XMODEM
550         volatile int i = 0;     
551         unsigned int crc1 = 0, crc2 = 0;
552         volatile int device;
553         int NbPage;
554 #endif
555         volatile int Nb_Device = 0;
556         int mci_present = 0;
557
558         pAT91 = AT91C_ROM_BOOT_ADDRESS;
559
560         if (!AT91F_SetPLL())
561         {
562                 printf("F SetPLL");
563                 while(1);
564         }
565
566         at91_init_uarts();
567
568         /* Tempo Initialisation */
569         pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC));
570         ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC));
571         
572         // Attach the tempo to a tempo controler
573         ctlTempo.CtlTempoCreate(&ctlTempo, &svcBootTempo);
574 //      LED_init();
575 //      LED_blink(2);
576
577 #ifdef XMODEM
578         /* Xmodem Initialisation */
579         pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer);
580         pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem,
581                      (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo);
582         pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer);
583 #endif
584
585         /* System Timer initialization */
586         AT91F_AIC_ConfigureIt(
587                 AT91C_BASE_AIC,                        // AIC base address
588                 AT91C_ID_SYS,                          // System peripheral ID
589                 AT91C_AIC_PRIOR_HIGHEST,               // Max priority
590                 AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, // Level sensitive
591                 AT91F_ST_ASM_HANDLER
592         );
593         /* Enable ST interrupt */
594         AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);
595
596 #ifndef PRODTEST
597         /* Start tempo to start Boot in a delay of
598          * AT91C_DELAY_TO_BOOT sec if no key pressed */
599         svcBootTempo.Start(&svcBootTempo, AT91C_DELAY_TO_BOOT,
600                            0, AT91F_StartBoot, NULL);
601 #endif
602
603         while(1)
604         {
605                 while(command == 0)
606                 {
607                         AddressToDownload = AT91C_DOWNLOAD_BASE_ADDRESS;
608                         SizeToDownload = AT91C_DOWNLOAD_MAX_SIZE;
609                         DeviceAddress = 0;
610                         
611                         /* try to detect Dataflash */
612                         if (!Nb_Device)
613                                 Nb_Device = AT91F_DataflashInit();                              
614                                                         
615                         mci_present = AT91F_DisplayMenu();
616
617 #ifdef PRODTEST
618                         if (mci_present) {
619                                 if (Program_From_MCI())
620                                         AT91F_StartBoot();
621                         }
622 #endif
623
624                         message[0] = 0;
625                         AT91F_ReadLine ("Enter: ", message);
626
627 #ifndef PRODTEST
628                         /* stop tempo ==> stop autoboot */
629                         svcBootTempo.Stop(&svcBootTempo);
630 #endif
631
632                         command = message[0];
633                         for(ix = 1; (message[ix] == ' ') && (ix < 12); ix++);   // Skip some whitespace
634                                 
635                         if(!AsciiToHex(&message[ix], &DeviceAddress) )
636                                 DeviceAddress = 0;                      // Illegal DeviceAddress
637                                 
638                         switch(command)
639                         {
640 #ifdef XMODEM
641                                 case '1':
642                                 case '2':
643                                 case '5':
644                                         if(command == '1') {
645                                                 DeviceAddress = 0xC0000000;
646 //                                              printf("Download DataflashBoot.bin to [0x%x]\n", DeviceAddress);
647                                         } else if(command == '2') {
648                                                 DeviceAddress = AT91C_BOOT_DATAFLASH_ADDR;
649 //                                              printf("Download u-boot.bin to [0x%x]\n", DeviceAddress);
650                                         } else {
651 //                                              printf("Download Dataflash to [0x%x]\n", DeviceAddress);
652                                         }
653                                         switch(DeviceAddress & 0xFF000000)
654                                         {
655                                                 case CFG_DATAFLASH_LOGIC_ADDR_CS0:
656                                                         if (dataflash_info[0].id == 0){
657                                                                 printf("No DF");
658                                                                 AT91F_WaitKeyPressed();
659                                                                 command = 0;
660                                                         }
661
662                                                         device = 0;
663                                                 break;
664                                         
665                                                 case CFG_DATAFLASH_LOGIC_ADDR_CS3:
666                                                         if (dataflash_info[1].id == 0){
667                                                                 printf("No DF");
668                                                                 AT91F_WaitKeyPressed();
669                                                                 command = 0;
670                                                         }
671                                                         device = 1;
672                                                 break;
673                                         
674                                                 default:
675                                                         command = 0;
676                                                 break;
677                                         }
678                                 break;
679 #endif
680
681                                 case '3':
682                                         if (mci_present)
683                                                 Program_From_MCI();
684                                         command = 0;
685                                         break;
686
687                                 case '4':
688                                         AT91F_StartBoot();
689                                         command = 0;
690                                 break;
691
692 #ifdef MEMDISP
693                                 case '6':
694                                         do 
695                                         {
696                                                 AT91F_MemoryDisplay(DeviceAddress, 256);
697                                                 AT91F_ReadLine (NULL, message);
698                                                 DeviceAddress += 0x100;
699                                         }
700                                         while(message[0] == '\0');
701                                         command = 0;
702                                 break;
703 #endif
704
705                                 case '7':
706                                         switch(DeviceAddress & 0xFF000000)
707                                         {
708                                                 case CFG_DATAFLASH_LOGIC_ADDR_CS0:
709                                                         break;
710                                                 case CFG_DATAFLASH_LOGIC_ADDR_CS3:
711                                                         break;
712                                                 default:
713                                                         command = 0;
714                                                         break;
715                                         }
716
717                                         if (command != 0) {
718                                                 AT91F_ReadLine ("RDY ERA\nSure?",
719                                                                 message);
720                                                 if(message[0] == 'Y' || message[0] == 'y') {
721                                                         erase_dataflash(DeviceAddress & 0xFF000000);
722 //                                                      printf("Erase complete\n\n");
723                                                 }
724 //                                              else
725 //                                                      printf("Erase aborted\n");
726                                         }
727                                         command = 0;
728
729                                 break;
730
731                                 default:
732                                         command = 0;
733                                 break;
734                         }
735                 }
736 #ifdef XMODEM
737                 for(i = 0; i <= AT91C_DOWNLOAD_MAX_SIZE; i++)
738                         *(unsigned char *)(AddressToDownload + i) = 0;
739         
740                 xmodemPipe.Read(&xmodemPipe, (char *)AddressToDownload,
741                                 SizeToDownload, XmodemProtocol, 0);     
742                 while(XmodemComplete !=1);
743                 SizeToDownload = (unsigned int)((svcXmodem.pData) -
744                                  (unsigned int)AddressToDownload);
745
746                 /* Modification of vector 6 */
747                 if ((DeviceAddress == CFG_DATAFLASH_LOGIC_ADDR_CS0)) {
748                         // Vector 6 must be compliant to the BootRom description (ref Datasheet)
749                         NbPage = 0;
750                 i = dataflash_info[device].Device.pages_number;
751                 while(i >>= 1)
752                         NbPage++;
753                         i = (SizeToDownload / 512)+1 + (NbPage << 13) +
754                             (dataflash_info[device].Device.pages_size << 17); //+4 to add crc32
755                     SizeToDownload = 512 * (i &0xFF);
756                 }       
757                 else
758                 {
759                         /* Save the contents of vector 6 ==> will be restored 
760                          * at boot time (AT91F_StartBoot) */
761                         *(int *)(AddressToDownload + SizeToDownload + 4) =
762                                 *(int *)(AddressToDownload + AT91C_OFFSET_VECT6);
763                         /* Modify Vector 6 to contain the size of the
764                          * file to copy (Dataflash -> SDRAM)*/
765                         i = SizeToDownload;     
766                 }               
767
768                 *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) = i;
769 //              printf("\nModification of Arm Vector 6 :%x\n", i);
770                             
771 //              printf("\nWrite %d bytes in DataFlash [0x%x]\n",SizeToDownload, DeviceAddress);
772                 crc1 = 0;
773                 pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc1);
774
775                 /* Add the crc32 at the end of the code */
776                 *(char *)(AddressToDownload + SizeToDownload)     = (char)(crc1 & 0x000000FF);
777                 *(char *)(AddressToDownload + SizeToDownload + 1) = (char)((crc1 & 0x0000FF00) >> 8);
778                 *(char *)(AddressToDownload + SizeToDownload + 2) = (char)((crc1 & 0x00FF0000) >> 16);
779                 *(char *)(AddressToDownload + SizeToDownload + 3) = (char)((crc1 & 0xFF000000) >> 24);
780
781                 /* write dataflash */
782                 write_dataflash (DeviceAddress, AddressToDownload, (SizeToDownload + 8));
783
784                 /* clear the buffer before read */
785                 for(i=0; i <= SizeToDownload; i++)
786                         *(unsigned char *)(AddressToDownload + i) = 0;
787                                         
788                 /* Read dataflash to check the validity of the data */
789                 read_dataflash (DeviceAddress, (SizeToDownload + 4), (char *)(AddressToDownload));
790
791                 printf("VFY: ");        
792                 crc2 = 0;
793                                 
794                 pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc2);
795                 crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload))          +
796                            (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) +
797                            (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) +
798                            (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24);
799
800                 if (crc1 != crc2)
801                         printf("ERR");
802                 else
803                         printf("OK");
804                         
805                 command = 0;
806                 XmodemComplete = 0;
807                 AT91F_WaitKeyPressed();
808 #endif
809         }
810 }
811