add new dfboot loader - a complete revison of romboot code.
[openwrt/svn-archive/archive.git] / target / linux / at91-2.6 / image / dfboot / src / main.c
diff --git a/target/linux/at91-2.6/image/dfboot/src/main.c b/target/linux/at91-2.6/image/dfboot/src/main.c
new file mode 100644 (file)
index 0000000..f2747e3
--- /dev/null
@@ -0,0 +1,810 @@
+/*----------------------------------------------------------------------------
+ *         ATMEL Microcontroller Software Support  -  ROUSSET  -
+ *----------------------------------------------------------------------------
+ * The software is delivered "AS IS" without warranty or condition of any
+ * kind, either express, implied or statutory. This includes without
+ * limitation any warranty or condition with respect to merchantability or
+ * fitness for any particular purpose, or against the infringements of
+ * intellectual property rights of others.
+ *----------------------------------------------------------------------------
+ * File Name           : main.c
+ * Object              : 
+ * Creation            : HIi   10/10/2003
+ * Modif               : HIi   15/06/2004 :    add crc32 to verify the download
+ *                                             from dataflash
+ *                     : HIi   21/09/2004 :    Set first PLLA to 180Mhz and MCK to
+ *                                             60Mhz to speed up dataflash boot (15Mhz)
+ *                     : MLC   12/04/2005 :    Modify SetPLL() to avoid errata
+ *                     : USA   30/12/2005 :    Change to page Size 1056
+ *                                             Change startaddress to C0008400
+ *                                             Change SPI Speed to ~4 Mhz
+ *                                             Add retry on CRC Error
+ *----------------------------------------------------------------------------
+ */
+#include "config.h"
+#include "stdio.h"
+#include "AT91RM9200.h"
+#include "lib_AT91RM9200.h"
+#include "com.h"
+#include "main.h"
+#include "dataflash.h"
+#include "AT91C_MCI_Device.h"
+
+#define        DEBUGOUT
+#define XMODEM
+#define MEMDISP
+
+#ifdef PAGESZ_1056
+#define        PAGESIZE        1056
+#else
+#define        PAGESIZE        1024
+#endif
+
+#define AT91C_SDRAM_START 0x20000000
+#define AT91C_BOOT_ADDR 0x21F00000
+#define AT91C_BOOT_SIZE 128*PAGESIZE
+#ifdef PAGESZ_1056
+#define AT91C_BOOT_DATAFLASH_ADDR 0xC0008400
+#else
+#define AT91C_BOOT_DATAFLASH_ADDR 0xC0008000
+#endif
+#define AT91C_PLLA_VALUE 0x2026BE04    // crystal= 18.432MHz
+//#define AT91C_PLLA_VALUE 0x202CBE01  // crystal= 4MHz
+
+
+
+#define DISP_LINE_LEN 16
+
+// Reason for boot failure
+#define        IMAGE_BAD_SIZE                  0
+#define        IMAGE_READ_FAILURE      1
+#define        IMAGE_CRC_ERROR         2
+#define        IMAGE_ERROR                     3
+#define        SUCCESS                         -1
+
+/* prototypes*/
+extern void AT91F_ST_ASM_HANDLER(void);
+extern void Jump(unsigned int addr);
+
+const char *menu_dataflash[] = {
+#ifdef XMODEM
+       "1: P DFboot\n",
+       "2: P U-Boot\n",
+#endif
+       "3: P SDCard\n",
+#ifdef PAGESZ_1056
+       "4: R UBOOT\n",
+#else
+       "4: R UBOOT\n",
+#endif
+#ifdef XMODEM
+       "5: P DF [addr]\n",
+#endif
+       "6: RD DF [addr]\n",
+       "7: E DF\n"
+};
+#ifdef XMODEM
+#define        MAXMENU 7
+#else
+#define MAXMENU 4
+#endif
+
+char message[20];
+#ifdef XMODEM
+volatile char XmodemComplete = 0;
+#endif
+unsigned int StTick = 0;
+
+AT91S_RomBoot const *pAT91;
+#ifdef XMODEM
+AT91S_SBuffer sXmBuffer;
+AT91S_SvcXmodem svcXmodem;
+AT91S_Pipe xmodemPipe;
+#endif
+AT91S_CtlTempo ctlTempo;
+
+
+//*--------------------------------------------------------------------------------------
+//* Function Name       : GetTickCount()
+//* Object              : Return the number of systimer tick 
+//* Input Parameters    :
+//* Output Parameters   :
+//*--------------------------------------------------------------------------------------
+unsigned int GetTickCount(void)
+{
+       return StTick;
+}
+
+#ifdef XMODEM
+//*--------------------------------------------------------------------------------------
+//* Function Name       : AT91_XmodemComplete()
+//* Object              : Perform the remap and jump to appli in RAM
+//* Input Parameters    :
+//* Output Parameters   :
+//*--------------------------------------------------------------------------------------
+static void AT91_XmodemComplete(AT91S_PipeStatus status, void *pVoid)
+{
+       /* stop the Xmodem tempo */
+       svcXmodem.tempo.Stop(&(svcXmodem.tempo));
+       XmodemComplete = 1;
+}
+
+
+//*--------------------------------------------------------------------------------------
+//* Function Name       : AT91F_XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
+//* Object              : Xmodem dispatcher
+//* Input Parameters    :
+//* Output Parameters   :
+//*--------------------------------------------------------------------------------------
+static void XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
+{
+       AT91PS_SBuffer pSBuffer = (AT91PS_SBuffer) xmodemPipe.pBuffer->pChild;
+       AT91PS_USART   pUsart     = svcXmodem.pUsart;
+                       
+       if (pSBuffer->szRdBuffer == 0) {
+               /* Start a tempo to wait the Xmodem protocol complete */
+               svcXmodem.tempo.Start(&(svcXmodem.tempo), 10, 0, AT91_XmodemComplete, pUsart);                                                          
+       }
+}
+#endif
+
+//*--------------------------------------------------------------------------------------
+//* Function Name       : irq1_c_handler()
+//* Object              : C Interrupt handler for Interrutp source 1
+//* Input Parameters    : none
+//* Output Parameters   : none
+//*--------------------------------------------------------------------------------------
+void AT91F_ST_HANDLER(void)
+{
+       volatile unsigned int csr = *AT91C_DBGU_CSR;
+#ifdef XMODEM
+       unsigned int error;
+#endif
+       
+       if (AT91C_BASE_ST->ST_SR & 0x01) {
+               StTick++;
+               ctlTempo.CtlTempoTick(&ctlTempo);
+               return;
+       }
+
+#ifdef XMODEM
+       error = AT91F_US_Error((AT91PS_USART)AT91C_BASE_DBGU);
+       if (csr & error) {
+               /* Stop previous Xmodem transmition*/
+               *(AT91C_DBGU_CR) = AT91C_US_RSTSTA;
+               AT91F_US_DisableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_ENDRX);
+               AT91F_US_EnableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_RXRDY);
+
+       }
+       
+       else if (csr & (AT91C_US_TXRDY | AT91C_US_ENDTX | AT91C_US_TXEMPTY | 
+                       AT91C_US_RXRDY | AT91C_US_ENDRX | AT91C_US_TIMEOUT | 
+                       AT91C_US_RXBUFF)) {
+               if ( !(svcXmodem.eot) )
+                       svcXmodem.Handler(&svcXmodem, csr);
+       }
+#endif
+}
+
+
+//*-----------------------------------------------------------------------------
+//* Function Name       : AT91F_DisplayMenu()
+//* Object              : 
+//* Input Parameters    : 
+//* Return value               : 
+//*-----------------------------------------------------------------------------
+static int AT91F_DisplayMenu(void)
+{
+       int i, mci_present = 0;
+       printf("\nDF LOADER %s %s %s\n",AT91C_VERSION,__DATE__,__TIME__);
+       AT91F_DataflashPrintInfo();
+       mci_present = AT91F_MCI_Init();
+       for(i = 0; i < MAXMENU; i++) {
+               puts(menu_dataflash[i]);
+       }
+       return mci_present;
+}      
+
+
+//*-----------------------------------------------------------------------------
+//* Function Name       : AsciiToHex()
+//* Object              : ascii to hexa conversion
+//* Input Parameters    : 
+//* Return value               : 
+//*-----------------------------------------------------------------------------
+static unsigned int AsciiToHex(char *s, unsigned int *val)
+{
+       int n;
+
+       *val=0;
+       
+       if(s[0] == '0' && ((s[1] == 'x') || (s[1] == 'X')))
+               s+=2;
+       n = 0;  
+       while((n < 8) && (s[n] !=0))
+       {
+               *val <<= 4;
+               if ( (s[n] >= '0') && (s[n] <='9'))
+                       *val += (s[n] - '0');
+               else    
+                       if ((s[n] >= 'a') && (s[n] <='f'))
+                               *val += (s[n] - 0x57);
+                       else
+                               if ((s[n] >= 'A') && (s[n] <='F'))
+                                       *val += (s[n] - 0x37);
+                       else
+                               return 0;
+               n++;
+       }
+
+       return 1;                               
+}
+
+
+#ifdef MEMDISP
+//*-----------------------------------------------------------------------------
+//* Function Name       : AT91F_MemoryDisplay()
+//* Object              : Display the content of the dataflash
+//* Input Parameters    : 
+//* Return value               : 
+//*-----------------------------------------------------------------------------
+static int AT91F_MemoryDisplay(unsigned int addr, unsigned int length)
+{
+       unsigned long   i, nbytes, linebytes;
+       char    *cp;
+//     unsigned int    *uip;
+//     unsigned short  *usp;
+       unsigned char   *ucp;
+       char linebuf[DISP_LINE_LEN];
+
+//     nbytes = length * size;
+       nbytes = length;
+       do
+       {
+//             uip = (unsigned int *)linebuf;
+//             usp = (unsigned short *)linebuf;
+               ucp = (unsigned char *)linebuf;
+               
+               printf("%08x:", addr);
+               linebytes = (nbytes > DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
+                if((addr & 0xF0000000) == 0x20000000) {
+                       for(i = 0; i < linebytes; i ++) {
+                               linebuf[i] =  *(char *)(addr+i);
+                       }
+               } else {
+                       read_dataflash(addr, linebytes, linebuf);
+               }
+               for (i=0; i<linebytes; i++)
+               {
+/*                     if (size == 4) 
+                               printf(" %08x", *uip++);
+                       else if (size == 2)
+                               printf(" %04x", *usp++);
+                       else
+*/
+                               printf(" %02x", *ucp++);
+//                     addr += size;
+                       addr++;
+               }
+               printf("    ");
+               cp = linebuf;
+               for (i=0; i<linebytes; i++) {
+                       if ((*cp < 0x20) || (*cp > 0x7e))
+                               printf(".");
+                       else
+                               printf("%c", *cp);
+                       cp++;
+               }
+               printf("\n");
+               nbytes -= linebytes;
+       } while (nbytes > 0);
+       return 0;
+}
+#endif
+
+//*--------------------------------------------------------------------------------------
+//* Function Name       : AT91F_SetPLL
+//* Object              : Set the PLLA to 180Mhz and Master clock to 60 Mhz
+//* Input Parameters    :
+//* Output Parameters   :
+//*--------------------------------------------------------------------------------------
+static unsigned int AT91F_SetPLL(void)
+{
+       AT91_REG tmp;
+       AT91PS_PMC pPmc = AT91C_BASE_PMC;
+       AT91PS_CKGR pCkgr = AT91C_BASE_CKGR;
+
+       pPmc->PMC_IDR = 0xFFFFFFFF;
+
+       /* -Setup the PLL A */
+       pCkgr->CKGR_PLLAR = AT91C_PLLA_VALUE;
+
+       while (!(*AT91C_PMC_SR & AT91C_PMC_LOCKA));
+       
+       /* - Switch Master Clock from PLLB to PLLA/3 */
+       tmp = pPmc->PMC_MCKR;
+       /* See Atmel Errata #27 and #28 */
+       if (tmp & 0x0000001C) {
+               tmp = (tmp & ~0x0000001C);
+               pPmc->PMC_MCKR = tmp;
+               while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
+       }
+       if (tmp != 0x00000202) {
+               pPmc->PMC_MCKR = 0x00000202;
+               if ((tmp & 0x00000003) != 0x00000002)
+                       while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
+       }
+
+       return 1;       
+}
+
+
+//*--------------------------------------------------------------------------------------
+//* Function Name       : AT91F_ResetRegisters
+//* Object              : Restore the initial state to registers
+//* Input Parameters    :
+//* Output Parameters   :
+//*--------------------------------------------------------------------------------------
+static unsigned int AT91F_ResetRegisters(void)
+{
+       volatile int i = 0;
+
+       /* set the PIOs in input*/
+       /* This disables the UART output, so dont execute for now*/
+
+#ifndef        DEBUGOUT
+       *AT91C_PIOA_ODR = 0xFFFFFFFF;   /* Disables all the output pins */
+       *AT91C_PIOA_PER = 0xFFFFFFFF;   /* Enables the PIO to control all the pins */
+#endif
+
+       AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SYS);
+       /* close all peripheral clocks */
+
+#ifndef        DEBUGOUT
+       AT91C_BASE_PMC->PMC_PCDR = 0xFFFFFFFC;
+#endif
+       /* Disable core interrupts and set supervisor mode */
+       __asm__ ("msr CPSR_c, #0xDF"); //* ARM_MODE_SYS(0x1F) | I_BIT(0x80) | F_BIT(0x40)
+       /* Clear all the interrupts */
+       *AT91C_AIC_ICCR = 0xffffffff;
+
+       /* read the AIC_IVR and AIC_FVR */
+       i = *AT91C_AIC_IVR;
+       i = *AT91C_AIC_FVR;
+
+       /* write the end of interrupt control register */
+       *AT91C_AIC_EOICR        = 0;
+
+       return 1;
+}
+
+
+static int AT91F_LoadBoot(void)
+{
+//     volatile unsigned int crc1 = 0, crc2 = 0;
+       volatile unsigned int SizeToDownload = 0x21400;
+       volatile unsigned int AddressToDownload = AT91C_BOOT_ADDR;
+
+#if 0
+       /* Read vector 6 to extract size to load */     
+       if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, 32,
+                          (char *)AddressToDownload) != AT91C_DATAFLASH_OK)
+       {
+               printf("Bad Code Size\n");
+               return IMAGE_BAD_SIZE;
+       }
+       /* calculate the size to download */
+       SizeToDownload = *(int *)(AddressToDownload + AT91C_OFFSET_VECT6);
+#endif
+       
+//     printf("\nLoad UBOOT from dataflash[%x] to SDRAM[%x]\n",
+//            AT91C_BOOT_DATAFLASH_ADDR, AT91C_BOOT_ADDR);
+       if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, SizeToDownload + 8,
+                          (char *)AddressToDownload) != AT91C_DATAFLASH_OK)
+       {
+               printf("F DF RD\n");
+               return IMAGE_READ_FAILURE;
+       }
+#if 0
+       pAT91->CRC32((const unsigned char *)AT91C_BOOT_ADDR,
+                    (unsigned int)SizeToDownload , (unsigned int *)&crc2);
+       crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload)) +
+              (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) +
+              (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) +
+              (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24);
+
+       /* Restore the value of Vector 6 */
+       *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) =
+               *(int *)(AddressToDownload + SizeToDownload + 4);
+       
+       if (crc1 != crc2) {
+               printf("DF CRC bad %x != %x\n",crc1,crc2);
+               return  IMAGE_CRC_ERROR;
+       }
+#endif
+       return SUCCESS;
+}
+
+static int AT91F_StartBoot(void)
+{
+       int     sts;
+       if((sts = AT91F_LoadBoot()) != SUCCESS) return sts;
+//     printf("\n");
+//     printf("PLLA[180MHz], MCK[60Mhz] ==> Start UBOOT\n");
+       if (AT91F_ResetRegisters())
+       {
+               printf("Jump");
+               Jump(AT91C_BOOT_ADDR);
+//             LED_blink(0);
+       }
+       return  IMAGE_ERROR;
+}
+
+#if 0
+static void    AT91F_RepeatedStartBoot(void)
+{
+       int     i;
+       for(i = 0; i < CRC_RETRIES; i++) {
+               if(AT91F_StartBoot() != IMAGE_CRC_ERROR){
+//                     LED_blink(1);
+                       return;
+               }
+       }
+       return;
+}
+#endif
+
+#define TRUE 1
+#define FALSE 0
+#define TRX_MAGIC 0x30524448  /* "HDR0" */
+#define TRX_VERSION 1
+
+struct trx_header {
+       unsigned int magic;
+       unsigned int len;
+       unsigned int crc32;
+       unsigned int flag_version;
+       unsigned int offsets[3];
+};
+
+#define AT91C_MCI_TIMEOUT 1000000
+
+extern AT91S_MciDevice MCI_Device;
+extern void AT91F_MCIDeviceWaitReady(unsigned int);
+extern int AT91F_MCI_ReadBlockSwab(AT91PS_MciDevice, int, unsigned int *, int);
+
+int Program_From_MCI(void)
+{
+  int i;
+  unsigned int Max_Read_DataBlock_Length;
+  int block = 0;
+  int buffer = AT91C_DOWNLOAD_BASE_ADDRESS;
+  int bufpos = AT91C_DOWNLOAD_BASE_ADDRESS;
+  int NbPage = 0;
+  struct trx_header *p;
+
+       p = (struct trx_header *)bufpos;
+
+       Max_Read_DataBlock_Length = MCI_Device.pMCI_DeviceFeatures->Max_Read_DataBlock_Length;
+
+       AT91F_MCIDeviceWaitReady(AT91C_MCI_TIMEOUT);
+
+  AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length);
+
+  if (p->magic != TRX_MAGIC) {
+               printf("Inv IMG 0x%08x\n", p->magic);
+               return FALSE;
+               }
+
+       printf("RDSD");
+       AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC8 | AT91C_PIO_PC14;
+       for (i=0; i<(p->len/512); i++) {
+               AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length);
+               block++;
+               bufpos += Max_Read_DataBlock_Length;
+               }
+
+       NbPage = 0;
+       i = dataflash_info[0].Device.pages_number;
+       while(i >>= 1)
+               NbPage++;
+       i = ((p->offsets[1] - p->offsets[0])/ 512) + 1 + (NbPage << 13) + (dataflash_info[0].Device.pages_size << 17);
+       *(int *)(buffer + p->offsets[0] + AT91C_OFFSET_VECT6) = i;
+
+       printf(" WDFB");
+       AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC14;
+       AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8;
+       write_dataflash(0xc0000000, buffer + p->offsets[0], p->offsets[1] - p->offsets[0]);
+       printf(" WUB");
+       AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15;
+       AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8 | AT91C_PIO_PC14;
+       write_dataflash(0xc0008000, buffer + p->offsets[1], p->offsets[2] - p->offsets[1]);
+       printf(" WKRFS");
+       AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC15;
+       AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC14;
+       write_dataflash(0xc0042000, buffer + p->offsets[2], p->len - p->offsets[2]);
+       AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC14;
+       AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC15;
+       return TRUE;
+}
+
+//*----------------------------------------------------------------------------
+//* Function Name       : main
+//* Object              : Main function
+//* Input Parameters    : none
+//* Output Parameters   : True
+//*----------------------------------------------------------------------------
+int main(void)
+{
+#ifdef XMODEM
+       AT91PS_Buffer           pXmBuffer;
+       AT91PS_SvcComm          pSvcXmodem;
+#endif
+       AT91S_SvcTempo          svcBootTempo;    // Link to a AT91S_Tempo object
+       unsigned int            ix;
+       volatile unsigned int AddressToDownload, SizeToDownload;        
+       unsigned int DeviceAddress = 0;
+       char command = 0;
+#ifdef XMODEM
+       volatile int i = 0;     
+       unsigned int crc1 = 0, crc2 = 0;
+       volatile int device;
+       int NbPage;
+#endif
+       volatile int Nb_Device = 0;
+       int mci_present = 0;
+
+       pAT91 = AT91C_ROM_BOOT_ADDRESS;
+
+       if (!AT91F_SetPLL())
+       {
+               printf("F SetPLL");
+               while(1);
+       }
+
+       at91_init_uarts();
+
+       /* Tempo Initialisation */
+       pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC));
+       ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC));
+       
+       // Attach the tempo to a tempo controler
+       ctlTempo.CtlTempoCreate(&ctlTempo, &svcBootTempo);
+//     LED_init();
+//     LED_blink(2);
+
+#ifdef XMODEM
+       /* Xmodem Initialisation */
+       pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer);
+       pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem,
+                    (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo);
+       pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer);
+#endif
+
+       /* System Timer initialization */
+       AT91F_AIC_ConfigureIt(
+               AT91C_BASE_AIC,                        // AIC base address
+               AT91C_ID_SYS,                          // System peripheral ID
+               AT91C_AIC_PRIOR_HIGHEST,               // Max priority
+               AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, // Level sensitive
+               AT91F_ST_ASM_HANDLER
+       );
+       /* Enable ST interrupt */
+       AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);
+
+#ifndef PRODTEST
+       /* Start tempo to start Boot in a delay of
+        * AT91C_DELAY_TO_BOOT sec if no key pressed */
+       svcBootTempo.Start(&svcBootTempo, AT91C_DELAY_TO_BOOT,
+                          0, AT91F_StartBoot, NULL);
+#endif
+
+       while(1)
+       {
+               while(command == 0)
+               {
+                       AddressToDownload = AT91C_DOWNLOAD_BASE_ADDRESS;
+                       SizeToDownload = AT91C_DOWNLOAD_MAX_SIZE;
+                       DeviceAddress = 0;
+                       
+                       /* try to detect Dataflash */
+                       if (!Nb_Device)
+                               Nb_Device = AT91F_DataflashInit();                              
+                                                       
+                       mci_present = AT91F_DisplayMenu();
+
+#ifdef PRODTEST
+                       if (mci_present) {
+                               if (Program_From_MCI())
+                                       AT91F_StartBoot();
+                       }
+#endif
+
+                       message[0] = 0;
+                       AT91F_ReadLine ("Enter: ", message);
+
+#ifndef PRODTEST
+                       /* stop tempo ==> stop autoboot */
+                       svcBootTempo.Stop(&svcBootTempo);
+#endif
+
+                       command = message[0];
+                       for(ix = 1; (message[ix] == ' ') && (ix < 12); ix++);   // Skip some whitespace
+                               
+                       if(!AsciiToHex(&message[ix], &DeviceAddress) )
+                               DeviceAddress = 0;                      // Illegal DeviceAddress
+                               
+                       switch(command)
+                       {
+#ifdef XMODEM
+                               case '1':
+                               case '2':
+                               case '5':
+                                       if(command == '1') {
+                                               DeviceAddress = 0xC0000000;
+//                                             printf("Download DataflashBoot.bin to [0x%x]\n", DeviceAddress);
+                                       } else if(command == '2') {
+                                               DeviceAddress = AT91C_BOOT_DATAFLASH_ADDR;
+//                                             printf("Download u-boot.bin to [0x%x]\n", DeviceAddress);
+                                       } else {
+//                                             printf("Download Dataflash to [0x%x]\n", DeviceAddress);
+                                       }
+                                       switch(DeviceAddress & 0xFF000000)
+                                       {
+                                               case CFG_DATAFLASH_LOGIC_ADDR_CS0:
+                                                       if (dataflash_info[0].id == 0){
+                                                               printf("No DF");
+                                                               AT91F_WaitKeyPressed();
+                                                               command = 0;
+                                                       }
+
+                                                       device = 0;
+                                               break;
+                                       
+                                               case CFG_DATAFLASH_LOGIC_ADDR_CS3:
+                                                       if (dataflash_info[1].id == 0){
+                                                               printf("No DF");
+                                                               AT91F_WaitKeyPressed();
+                                                               command = 0;
+                                                       }
+                                                       device = 1;
+                                               break;
+                                       
+                                               default:
+                                                       command = 0;
+                                               break;
+                                       }
+                               break;
+#endif
+
+                               case '3':
+                                       if (mci_present)
+                                               Program_From_MCI();
+                                       command = 0;
+                                       break;
+
+                               case '4':
+                                       AT91F_StartBoot();
+                                       command = 0;
+                               break;
+
+#ifdef MEMDISP
+                               case '6':
+                                       do 
+                                       {
+                                               AT91F_MemoryDisplay(DeviceAddress, 256);
+                                               AT91F_ReadLine (NULL, message);
+                                               DeviceAddress += 0x100;
+                                       }
+                                       while(message[0] == '\0');
+                                       command = 0;
+                               break;
+#endif
+
+                               case '7':
+                                       switch(DeviceAddress & 0xFF000000)
+                                       {
+                                               case CFG_DATAFLASH_LOGIC_ADDR_CS0:
+                                                       break;
+                                               case CFG_DATAFLASH_LOGIC_ADDR_CS3:
+                                                       break;
+                                               default:
+                                                       command = 0;
+                                                       break;
+                                       }
+
+                                       if (command != 0) {
+                                               AT91F_ReadLine ("RDY ERA\nSure?",
+                                                               message);
+                                               if(message[0] == 'Y' || message[0] == 'y') {
+                                                       erase_dataflash(DeviceAddress & 0xFF000000);
+//                                                     printf("Erase complete\n\n");
+                                               }
+//                                             else
+//                                                     printf("Erase aborted\n");
+                                       }
+                                       command = 0;
+
+                               break;
+
+                               default:
+                                       command = 0;
+                               break;
+                       }
+               }
+#ifdef XMODEM
+               for(i = 0; i <= AT91C_DOWNLOAD_MAX_SIZE; i++)
+                       *(unsigned char *)(AddressToDownload + i) = 0;
+       
+               xmodemPipe.Read(&xmodemPipe, (char *)AddressToDownload,
+                               SizeToDownload, XmodemProtocol, 0);     
+               while(XmodemComplete !=1);
+               SizeToDownload = (unsigned int)((svcXmodem.pData) -
+                                (unsigned int)AddressToDownload);
+
+               /* Modification of vector 6 */
+               if ((DeviceAddress == CFG_DATAFLASH_LOGIC_ADDR_CS0)) {
+                       // Vector 6 must be compliant to the BootRom description (ref Datasheet)
+                       NbPage = 0;
+               i = dataflash_info[device].Device.pages_number;
+               while(i >>= 1)
+                       NbPage++;
+                       i = (SizeToDownload / 512)+1 + (NbPage << 13) +
+                           (dataflash_info[device].Device.pages_size << 17); //+4 to add crc32
+                   SizeToDownload = 512 * (i &0xFF);
+               }       
+               else
+               {
+                       /* Save the contents of vector 6 ==> will be restored 
+                        * at boot time (AT91F_StartBoot) */
+                       *(int *)(AddressToDownload + SizeToDownload + 4) =
+                               *(int *)(AddressToDownload + AT91C_OFFSET_VECT6);
+                       /* Modify Vector 6 to contain the size of the
+                        * file to copy (Dataflash -> SDRAM)*/
+                       i = SizeToDownload;     
+               }               
+
+               *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) = i;
+//             printf("\nModification of Arm Vector 6 :%x\n", i);
+                           
+//             printf("\nWrite %d bytes in DataFlash [0x%x]\n",SizeToDownload, DeviceAddress);
+               crc1 = 0;
+               pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc1);
+
+               /* Add the crc32 at the end of the code */
+               *(char *)(AddressToDownload + SizeToDownload)     = (char)(crc1 & 0x000000FF);
+               *(char *)(AddressToDownload + SizeToDownload + 1) = (char)((crc1 & 0x0000FF00) >> 8);
+               *(char *)(AddressToDownload + SizeToDownload + 2) = (char)((crc1 & 0x00FF0000) >> 16);
+               *(char *)(AddressToDownload + SizeToDownload + 3) = (char)((crc1 & 0xFF000000) >> 24);
+
+               /* write dataflash */
+               write_dataflash (DeviceAddress, AddressToDownload, (SizeToDownload + 8));
+
+               /* clear the buffer before read */
+               for(i=0; i <= SizeToDownload; i++)
+                       *(unsigned char *)(AddressToDownload + i) = 0;
+                                       
+               /* Read dataflash to check the validity of the data */
+               read_dataflash (DeviceAddress, (SizeToDownload + 4), (char *)(AddressToDownload));
+
+               printf("VFY: ");        
+               crc2 = 0;
+                               
+               pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc2);
+               crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload))          +
+                          (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) +
+                          (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) +
+                          (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24);
+
+               if (crc1 != crc2)
+                       printf("ERR");
+               else
+                       printf("OK");
+                       
+               command = 0;
+               XmodemComplete = 0;
+               AT91F_WaitKeyPressed();
+#endif
+       }
+}
+