Eli Hughes / Mbed 2 deprecated COMPACT_FLASH

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers diskio.c Source File

diskio.c

00001 #include "mbed.h"
00002 #include "LPC17xx.h"
00003 #include "integer.h"
00004 #include "diskio.h"
00005 #include "stdarg.h"
00006 #include "usbhost_inc.h"
00007 
00008 
00009 /*--------------------------------------------------------------------------
00010 
00011    Module Private Functions
00012 
00013 ---------------------------------------------------------------------------*/
00014 
00015 static volatile DSTATUS Stat[3] = {STA_NOINIT | STA_NODISK};    /* Disk status */
00016 static volatile BYTE DiskProcTimer[3]={0};            /* 100Hz decrement timer */
00017 
00018 
00019 BYTE RAM_DISK[512];
00020 
00021 
00022 //Usb Stuff
00023 uint32_t _numBlks;
00024 uint32_t _blkSize;
00025 USB_INT08U  inquiryResult[INQUIRY_LENGTH];  
00026 
00027 
00028 //#define _CF_DEBUG_MESSAGES
00029 //#define _CF_DEBUG_READ_ATA
00030 
00031 #ifdef _CF_DEBUG_MESSAGES 
00032    #define  CF_DEBUG(...) printf(__VA_ARGS__)    
00033 #else
00034    #define  CF_DEBUG     
00035 #endif
00036 
00037 void disk_timerproc (void);
00038 
00039 #define LED1_MASK  (uint32_t )(1<<18)
00040 #define LED2_MASK  (uint32_t )(1<<20)
00041 #define LED3_MASK  (uint32_t )(1<<21)
00042 #define LED4_MASK  (uint32_t )(1<<23)
00043 
00044 
00045 #define LED1_ON             LPC_GPIO1->FIOSET=LED1_MASK
00046 #define LED1_OFF            LPC_GPIO1->FIOCLR=LED1_MASK
00047 #define LED1_TOGGLE         LPC_GPIO1->FIOPIN^=LED1_MASK
00048 
00049 #define LED2_ON             LPC_GPIO1->FIOSET=LED2_MASK
00050 #define LED2_OFF            LPC_GPIO1->FIOCLR=LED2_MASK
00051 #define LED2_TOGGLE         LPC_GPIO1->FIOPIN^=LED2_MASK
00052 
00053 #define LED3_ON             LPC_GPIO1->FIOSET=LED3_MASK
00054 #define LED3_OFF            LPC_GPIO1->FIOCLR=LED3_MASK
00055 #define LED3_TOGGLE         LPC_GPIO1->FIOPIN^=LED3_MASK
00056 
00057 #define LED4_ON             LPC_GPIO1->FIOSET=LED4_MASK
00058 #define LED4_OFF            LPC_GPIO1->FIOCLR=LED4_MASK
00059 #define LED4_TOGGLE         LPC_GPIO1->FIOPIN^=LED4_MASK
00060 
00061 
00062 
00063 //8-bit Data Bus is on Pins P0.4 - P0.11
00064 #define DATA_BUS_MASK      (uint32_t )((0xFF)<<4)
00065 
00066 //3 bit address is on Port 2.0 - 2.2
00067 #define ADDRESS_BUS_MASK   (uint32_t )(0x7)
00068 
00069 //ChipSelects are on port 2
00070 #define CS0_MASK    (uint32_t )(1<<3)
00071 #define CS1_MASK    (uint32_t )(1<<4)
00072 
00073 //IORD and IOWR are on port 0
00074 #define IORD_MASK   (uint32_t )(1<<24)
00075 #define IOWR_MASK   (uint32_t )(1<<23)
00076 
00077 
00078 //Reset and power enable are on port 1
00079 #define COMPACT_FLASH_RESET_MASK           (uint32_t )(1<<30)
00080 #define COMPACT_FLASH_POWER_ENABLE_MASK    (uint32_t )(0x80000000)
00081 //Card Detect is on Port 2
00082 #define COMPACT_FLASH_CARD_DETECT_MASK     (uint32_t )(1<<5)
00083 
00084 //Low Level Bus Operation Macros
00085 //Note: LPC 176x have dedicate set and clear registers
00086 
00087 #define SET_DATA_BUS_TO_INPUTS                LPC_GPIO0->FIODIR &= ~(DATA_BUS_MASK);
00088 #define SET_DATA_BUS_TO_OUTPUT                LPC_GPIO0->FIODIR |=  (DATA_BUS_MASK);
00089 
00090 #define CS0_ACTIVE                            LPC_GPIO2->FIOCLR = CS0_MASK
00091 #define CS0_INACTIVE                          LPC_GPIO2->FIOSET   = CS0_MASK
00092 #define CS1_ACTIVE                            LPC_GPIO2->FIOCLR = CS1_MASK
00093 #define CS1_INACTIVE                          LPC_GPIO2->FIOSET   = CS1_MASK
00094 
00095 #define IORD_ACTIVE                           LPC_GPIO0->FIOCLR = IORD_MASK
00096 #define IORD_INACTIVE                         LPC_GPIO0->FIOSET   = IORD_MASK
00097 
00098 #define IOWR_ACTIVE                           LPC_GPIO0->FIOCLR   = IOWR_MASK
00099 #define IOWR_INACTIVE                         LPC_GPIO0->FIOSET   = IOWR_MASK
00100 
00101 #define COMPACT_FLASH_RESET_ACTIVE            LPC_GPIO1->FIOCLR = COMPACT_FLASH_RESET_MASK
00102 #define COMPACT_FLASH_RESET_INACTIVE          LPC_GPIO1->FIOSET = COMPACT_FLASH_RESET_MASK
00103 
00104 #define  COMPACT_FLASH_POWER_ENABLE           LPC_GPIO1->FIOCLR = COMPACT_FLASH_POWER_ENABLE_MASK
00105 #define  COMPACT_FLASH_POWER_DISABLE          LPC_GPIO1->FIOSET = COMPACT_FLASH_POWER_ENABLE_MASK
00106 
00107 #define COMPACT_FLASH_CARD_DETECTED            (!((LPC_GPIO2->FIOPIN)&COMPACT_FLASH_CARD_DETECT_MASK))
00108 
00109 //To set the Address and Data Bus Lines we will use the convient Mask register in the Port I/O modules
00110 //The Hardware will mask out pins that are set to 1 in the MASK register
00111 
00112 #define SET_CF_ADDRESS(ADDRESS)       LPC_GPIO2->FIOMASK=~(ADDRESS_BUS_MASK);   \
00113                                       LPC_GPIO2->FIOPIN=ADDRESS;                \
00114                                       LPC_GPIO2->FIOMASK=0                      //Always remember to reset the mask for other operations to complete correctly
00115 
00116 
00117 #define SET_CF_DATA(DATA)             LPC_GPIO0->FIOMASK=~(DATA_BUS_MASK);      \
00118                                       LPC_GPIO0->FIOPIN=(((uint32_t)DATA)<<4);           \
00119                                       LPC_GPIO0->FIOMASK=0                  //Always remember to reset the mask for other operations to complete correctly
00120 
00121 #define GET_CF_DATA(DATA)             LPC_GPIO0->FIOMASK=~(DATA_BUS_MASK);        \
00122                                       (DATA) = (LPC_GPIO0->FIOPIN)>>4;           \
00123                                       LPC_GPIO0->FIOMASK=0                  //Always remember to reset the mask for other operations to complete correctly
00124 
00125 #define SET_DATA_BUS_AS_OUTPUTS       LPC_GPIO0->FIODIR|=DATA_BUS_MASK
00126 #define SET_DATA_BUS_AS_INPUTS        LPC_GPIO0->FIODIR&=~DATA_BUS_MASK
00127 
00128 /* ATA command */
00129 #define CMD_RESET        0x08    /* DEVICE RESET */
00130 #define CMD_READ         0x20    /* READ SECTOR(S) */
00131 #define CMD_WRITE        0x30    /* WRITE SECTOR(S) */
00132 #define CMD_IDENTIFY     0xEC    /* DEVICE IDENTIFY */
00133 #define CMD_SETFEATURES  0xEF    /* SET FEATURES */
00134 
00135 /* ATA register bit definitions */
00136 #define    LBA             0xE0
00137 #define    BUSY            0x80
00138 #define    DRDY            0x40
00139 #define    DF              0x20
00140 #define    DRQ             0x08
00141 #define    ERR             0x01
00142 #define    SRST            0x40
00143 #define    nIEN            0x20
00144 
00145 /* Bit definitions for Control Port */
00146 #define    CTL_READ        0x20
00147 #define    CTL_WRITE       0x40
00148 #define    CTL_RESET       0x80
00149 #define    REG_DATA        0x0
00150 #define    REG_ERROR       0x1
00151 #define    REG_FEATURES    0x1
00152 #define    REG_COUNT       0x2
00153 #define    REG_SECTOR      0x3
00154 #define    REG_CYLL        0x4
00155 #define    REG_CYLH        0x5
00156 #define    REG_DEV         0x6
00157 #define    REG_COMMAND     0x7
00158 #define    REG_STATUS      0x7
00159 #define    REG_DEVCTRL     0xE
00160 #define    REG_ALTSTAT     0xE
00161 
00162 void InitCompactFlashInterface()
00163 {
00164     SET_DATA_BUS_AS_INPUTS;
00165 
00166     LPC_GPIO2->FIODIR  |= ADDRESS_BUS_MASK | CS0_MASK | CS1_MASK;
00167     LPC_GPIO2->FIODIR  &=~(COMPACT_FLASH_CARD_DETECT_MASK);
00168     LPC_GPIO1->FIODIR  |= COMPACT_FLASH_RESET_MASK | COMPACT_FLASH_POWER_ENABLE_MASK | LED1_MASK | LED2_MASK | LED3_MASK | LED4_MASK;
00169     LPC_GPIO0->FIODIR  |= IORD_MASK  | IOWR_MASK ;
00170 
00171     COMPACT_FLASH_RESET_ACTIVE;
00172     COMPACT_FLASH_POWER_DISABLE;
00173     CS0_INACTIVE;
00174     CS1_INACTIVE;
00175 
00176     SysTick_Config(SystemCoreClock/100);
00177     NVIC_SetVector(SysTick_IRQn, (uint32_t)(&disk_timerproc));
00178 }
00179 
00180 /*-----------------------------------------------------------------------*/
00181 /* Read an ATA register                                                  */
00182 /*-----------------------------------------------------------------------*/
00183 
00184 static
00185 BYTE read_ata (
00186     BYTE reg            /* Register to be read */
00187 )
00188 {
00189     BYTE rd;
00190  
00191     CS0_ACTIVE; 
00192     SET_DATA_BUS_AS_INPUTS;
00193     SET_CF_ADDRESS(reg); 
00194     IORD_ACTIVE;  
00195     __nop();
00196     __nop();
00197     __nop();
00198     __nop();
00199   
00200     GET_CF_DATA(rd); 
00201     __nop();
00202     __nop();
00203     __nop();
00204     __nop();
00205     IORD_INACTIVE;  
00206     CS0_INACTIVE; 
00207     #ifdef _CF_DEBUG_READ_ATA
00208       CF_DEBUG("rd 0x%2x\r\n",rd);
00209     #endif
00210     return rd;
00211 }
00212 
00213 
00214 
00215 /*-----------------------------------------------------------------------*/
00216 /* Write a byte to an ATA register                                       */
00217 /*-----------------------------------------------------------------------*/
00218 
00219 static
00220 void write_ata (
00221     BYTE reg,        /* Register to be written */
00222     BYTE dat        /* Data to be written */
00223 )
00224 {
00225    
00226     __nop();
00227     CS0_ACTIVE; 
00228     SET_DATA_BUS_AS_OUTPUTS;
00229     SET_CF_ADDRESS(reg);
00230     SET_CF_DATA(dat); 
00231     IOWR_ACTIVE;  
00232     __nop();
00233     __nop();
00234     __nop();
00235     __nop();
00236       IOWR_INACTIVE; 
00237       __nop();
00238       __nop();
00239       __nop();
00240       __nop();
00241     CS0_INACTIVE; 
00242     SET_DATA_BUS_AS_INPUTS;
00243 }
00244 
00245 
00246 
00247 /*-----------------------------------------------------------------------*/
00248 /* Read a part of data block                                             */
00249 /*-----------------------------------------------------------------------*/
00250 
00251 static
00252 void read_part (
00253     BYTE *buff,     /* Data buffer to store read data */
00254     BYTE ofs,        /* Offset of the part of data in unit of word */
00255     BYTE count        /* Number of word to pick up */
00256 )
00257 {
00258     BYTE c = 0, dl, dh;
00259     
00260     SET_CF_ADDRESS(REG_DATA);        /* Select Data register */
00261     __nop();
00262     __nop();
00263   
00264      SET_DATA_BUS_AS_INPUTS;   
00265     CS0_ACTIVE; 
00266     __nop();
00267     __nop();
00268   do {
00269         IORD_ACTIVE;        /* IORD = L */
00270         __nop();
00271         __nop();
00272         __nop();
00273         __nop();
00274          GET_CF_DATA(dl);                /* Read Even data */
00275         IORD_INACTIVE;        /* IORD = H */
00276         __nop();
00277         __nop();
00278         __nop();
00279         __nop();
00280          IORD_ACTIVE;        /* IORD = L */
00281         __nop();
00282         __nop();
00283         __nop();
00284         __nop();
00285         GET_CF_DATA(dh);                /* Read Odd data */
00286         IORD_INACTIVE;    /* IORD = H */
00287         __nop();
00288         __nop();
00289         __nop();
00290         __nop();
00291         if (count && (c >= ofs)) {    /* Pick up a part of block */
00292             *buff++ = dl;
00293             *buff++ = dh;
00294             count--;
00295         }
00296     } while (++c);
00297     CS0_INACTIVE; 
00298     
00299     read_ata(REG_ALTSTAT);
00300     read_ata(REG_STATUS);
00301 }
00302 
00303 
00304 /*-----------------------------------------------------------------------*/
00305 /* Wait for Data Ready                                                   */
00306 /*-----------------------------------------------------------------------*/
00307 
00308 static
00309 int wait_data (void)
00310 {
00311     BYTE s;
00312 
00313     DiskProcTimer[CF] = 100;    /* Time out = 1 sec */
00314     do {
00315         if (!DiskProcTimer[CF]) return 0;            /* Abort when timeout occured */
00316         s = read_ata(REG_STATUS);        /* Get status */
00317     } while ((s & (BUSY|DRQ)) != DRQ);    /* Wait for BUSY goes low and DRQ goes high */
00318 
00319     read_ata(REG_ALTSTAT);
00320     return 1;
00321 }
00322 
00323 
00324 
00325 
00326 /*-----------------------------------------------------------------------*/
00327 /* Initialize Disk Drive                                                 */
00328 /*-----------------------------------------------------------------------*/
00329 
00330 DSTATUS disk_initialize (
00331     BYTE drv        /* Physical drive number (0) */
00332 )
00333 {
00334     DSTATUS RetVal;
00335     USB_INT32S  rc;
00336   
00337     switch(drv)
00338     {
00339         case COMPACT_FLASH:
00340                  
00341               Stat[CF] |= STA_NOINIT;
00342               for (DiskProcTimer[CF] = 10; DiskProcTimer[CF]; );                /* 100ms */
00343               if (Stat[CF] & STA_NODISK) return Stat[CF];        /* Exit when socket is empty */
00344               COMPACT_FLASH_POWER_ENABLE;     /* Initialize CFC control port */
00345               for (DiskProcTimer[CF] = 1;DiskProcTimer[CF]; );                /* 10ms */
00346          
00347               SET_DATA_BUS_AS_INPUTS;
00348               for (DiskProcTimer[CF] = 5; DiskProcTimer[CF]; );                /* 50ms */
00349               COMPACT_FLASH_RESET_INACTIVE;
00350               for (DiskProcTimer[CF] = 5; DiskProcTimer[CF]; );                /* 50ms */
00351               write_ata(REG_DEV, LBA);                /* Select Device 0 */
00352               DiskProcTimer[CF] = 200;
00353                              
00354                 do {                                    /* Wait for card goes ready */
00355                     if (!DiskProcTimer[CF]) 
00356                     {
00357                         CF_DEBUG("Timeout waiting for card BUSY to go inactive\r\n");
00358                         return Stat[CF];
00359                     }
00360                 } while (read_ata(REG_STATUS) & BUSY);
00361       
00362       
00363                 write_ata(REG_DEVCTRL, SRST | nIEN);    /* Software reset */
00364                 for (DiskProcTimer[CF] = 2; DiskProcTimer[CF]; );                /* 20ms */
00365                 
00366                 write_ata(REG_DEVCTRL, nIEN);            /* Release software reset */
00367                 
00368                 for (DiskProcTimer[CF] = 2; DiskProcTimer[CF]; );                /* 20ms */
00369                 
00370                 DiskProcTimer[CF] = 200;
00371                 do {                                    /* Wait for card goes ready */
00372                     if (!DiskProcTimer[CF])
00373                     {
00374                         CF_DEBUG("Timeout waiting for card DRDY\r\n");
00375                         return Stat[CF];
00376                      }
00377                 } while ((read_ata(REG_STATUS) & (DRDY|BUSY)) != DRDY);
00378                 
00379                 CF_DEBUG("Setting to 8-bit PIO MOD\r\n");
00380                 write_ata(REG_FEATURES, 0x01);            /* Select 8-bit PIO transfer mode */
00381                 write_ata(REG_COMMAND, CMD_SETFEATURES);
00382                 DiskProcTimer[CF] = 200;
00383                 do {
00384                     if (!DiskProcTimer[CF])
00385                     {
00386                         CF_DEBUG("Timeout waiting after trying to call the SETFEATURES command\r\n");
00387                         return Stat[CF];
00388                     }
00389                      
00390                 } while (read_ata(REG_STATUS) & (BUSY | ERR));
00391             
00392                 Stat[CF] &= ~STA_NOINIT;                    /* When device goes ready, clear STA_NOINIT */
00393             
00394                 RetVal = Stat[CF];
00395       
00396         break;
00397         
00398         case USB:
00399         
00400                 Host_Init();
00401                 if(!Host_EnumDev())
00402                 {
00403               
00404                     rc = MS_Init( &_blkSize, &_numBlks, inquiryResult );
00405                     if (rc != OK)
00406                     {
00407                         TERMINAL_PRINTF("Could not initialize mass storage interface: %d\r\n", rc);
00408                         Stat[USB] |= STA_NOINIT;
00409                     }
00410                     else
00411                     {
00412                          Stat[USB] &= ~STA_NOINIT;
00413                     }
00414                 }
00415                 else
00416                 {
00417                      Stat[USB] |= STA_NOINIT;
00418                 }
00419                  
00420                   RetVal = Stat[USB];
00421         break;
00422         
00423         
00424         case RAM:
00425              Stat[RAM] &= ~STA_NOINIT;
00426               RetVal = Stat[RAM];
00427         break; 
00428         
00429         default:
00430              RetVal = STA_NOINIT;
00431         break;
00432     }
00433 
00434     return RetVal;
00435 }
00436 
00437 
00438 
00439 /*-----------------------------------------------------------------------*/
00440 /* Return Disk Status                                                    */
00441 /*-----------------------------------------------------------------------*/
00442 
00443 DSTATUS disk_status (
00444     BYTE drv     
00445 )
00446 {
00447     DSTATUS RetVal;
00448     
00449     switch(drv)
00450     {
00451         case CF:
00452              RetVal = Stat[CF];
00453         break;
00454         
00455         
00456         case USB:
00457            RetVal = Stat[USB];
00458         break;
00459         
00460         case RAM:
00461            RetVal = Stat[RAM];
00462         break;
00463         
00464         default:
00465              RetVal = STA_NOINIT; 
00466         break;
00467     }
00468     
00469     return  RetVal;
00470 }
00471 
00472 
00473 
00474 /*-----------------------------------------------------------------------*/
00475 /* Read Sector(s)                                                        */
00476 /*-----------------------------------------------------------------------*/
00477 
00478 DRESULT disk_read (
00479     BYTE drv,        /* Physical drive nmuber (0) */
00480     BYTE *buff,        /* Data buffer to store read data */
00481     DWORD sector,    /* Sector number (LBA) */
00482     BYTE count        /* Sector count (1..255) */
00483 )
00484 {
00485     BYTE c;
00486     DWORD i,j;
00487     
00488     switch(drv)
00489     {
00490         case CF:
00491               if (Stat[CF] & STA_NOINIT) return RES_NOTRDY;
00492 
00493                 /* Issue Read Setor(s) command */
00494                 write_ata(REG_COUNT, count);
00495                 write_ata(REG_SECTOR, (BYTE)sector);
00496                 write_ata(REG_CYLL, (BYTE)(sector >> 8));
00497                 write_ata(REG_CYLH, (BYTE)(sector >> 16));
00498                 write_ata(REG_DEV, ((BYTE)(sector >> 24) & 0x0F) | LBA);
00499                 write_ata(REG_COMMAND, CMD_READ);
00500                 
00501                  do {
00502                          if (!wait_data()) return RES_ERROR;    /* Wait data ready */
00503                    
00504                                 SET_CF_ADDRESS(REG_DATA);
00505                                 __nop();
00506                                 __nop();
00507                                 __nop();
00508                                 __nop();
00509                                CS0_ACTIVE;
00510                                c = 0;
00511                                
00512                                 __nop();
00513                                 __nop();
00514                                __nop();
00515                             
00516                                 SET_DATA_BUS_AS_INPUTS;
00517                                 do {
00518                                         IORD_ACTIVE;        /* IORD = L */
00519                                         __nop();
00520                                         __nop();
00521                                         __nop();
00522                                         GET_CF_DATA(*buff++);        /* Get even data */
00523                                         __nop();
00524                                         __nop();
00525                                         __nop();
00526                                     
00527                                         __nop();
00528                                         __nop();
00529                                         __nop();
00530                                 
00531                                         IORD_INACTIVE;        /* IORD = H */
00532                                         __nop();
00533                                         __nop();
00534                                         __nop();
00535                                  
00536                                         IORD_ACTIVE;        /* IORD = L */
00537                                         __nop();
00538                                         __nop();
00539                                         __nop();
00540                                 
00541                                         GET_CF_DATA(*buff++);    /* Get Odd data */
00542                                         __nop();
00543                                         __nop();
00544                                         __nop();
00545                                 
00546                                         __nop();
00547                                         IORD_INACTIVE;            /* IORD = H */
00548                                         __nop();
00549                                         __nop();
00550                                         __nop();
00551                                  
00552                                            
00553                                         } while (--c);
00554                         } while (--count);
00555             
00556                 CS0_INACTIVE;
00557                 read_ata(REG_ALTSTAT);
00558                 read_ata(REG_STATUS);
00559                 
00560                 return RES_OK;
00561         break;
00562         
00563         
00564         case USB:
00565         
00566          if ( OK == MS_BulkRecv(sector, 1, (USB_INT08U *)buff) )
00567              return RES_OK;
00568          else
00569              return  RES_NOTRDY;
00570         break;
00571         
00572         case RAM:
00573                 for(i=0;i<512;i++)
00574                 {
00575                     buff[i] = RAM_DISK[i];
00576                 }
00577              return RES_OK;
00578         break;
00579         
00580         default:
00581              return RES_PARERR;
00582         break;
00583     }
00584 }
00585 
00586 
00587 /*-----------------------------------------------------------------------*/
00588 /* Write Sector(s)                                                       */
00589 /*-----------------------------------------------------------------------*/
00590 
00591 DRESULT disk_write (
00592     BYTE drv,            /* Physical drive number (0) */
00593     const BYTE *buff,    /* Data to be written */
00594     DWORD sector,        /* Sector number (LBA) */
00595     BYTE count            /* Sector count (1..255) */
00596 )
00597 {
00598     BYTE s, c;
00599     DWORD i;
00600     DRESULT RetVal;
00601       
00602     switch(drv)
00603     {
00604         case CF:
00605                  /* Issue Write Setor(s) command */
00606                 write_ata(REG_COUNT, count);
00607                 write_ata(REG_SECTOR, (BYTE)sector);
00608                 write_ata(REG_CYLL, (BYTE)(sector >> 8));
00609                 write_ata(REG_CYLH, (BYTE)(sector >> 16));
00610                 write_ata(REG_DEV, ((BYTE)(sector >> 24) & 0x0F) | LBA);
00611                 write_ata(REG_COMMAND, CMD_WRITE);
00612                 
00613                  do {
00614                         if (!wait_data()) return RES_ERROR;
00615                       
00616                         SET_CF_ADDRESS(REG_DATA);
00617                         __nop();
00618                          __nop();
00619                          __nop();
00620                         CS0_ACTIVE;
00621                         __nop();
00622                          __nop();
00623                          __nop();
00624                     
00625                         SET_DATA_BUS_AS_OUTPUTS;
00626                         c = 0;
00627                         do {
00628                             SET_CF_DATA(*buff++);    /* Set even data */
00629                             __nop();
00630                             __nop();
00631                             __nop();
00632                 
00633                             IOWR_ACTIVE;        /* IOWR = L */
00634                             __nop();
00635                             __nop();
00636                             __nop();
00637                 
00638                             IOWR_INACTIVE;        /* IOWR = H */
00639                             __nop();
00640                             __nop();
00641                             __nop();
00642                     
00643                             SET_CF_DATA(*buff++);    /* Set odd data */
00644                             __nop();
00645                             __nop();
00646                             __nop();
00647                  
00648                             IOWR_ACTIVE;        /* IOWR = L */
00649                             __nop();
00650                             __nop();
00651                             __nop();
00652                 
00653                             IOWR_INACTIVE;        /* IOWR = H */
00654                             __nop();
00655                             __nop();
00656                             __nop();
00657                             } while (--c);
00658                  
00659                     } while (--count);
00660                       
00661                        SET_DATA_BUS_AS_INPUTS;
00662                        CS0_INACTIVE;
00663                 
00664                     DiskProcTimer[CF] = 100;
00665                     do {
00666                         if (!DiskProcTimer[CF]) return RES_ERROR;
00667                         s = read_ata(REG_STATUS);
00668                     } while (s & BUSY);
00669                     if (s & ERR) return RES_ERROR;
00670                 
00671                     read_ata(REG_ALTSTAT);
00672                     read_ata(REG_STATUS);
00673 
00674                 RetVal = RES_OK;
00675         break;
00676         
00677         
00678         case USB:
00679             if ( OK == MS_BulkSend(sector, 1, (USB_INT08U *)buff) )
00680                RetVal = RES_OK;
00681             else;
00682                RetVal =  RES_NOTRDY;
00683         break;
00684         
00685         case RAM:
00686           
00687                 for(i=0;i<512;i++)
00688                 {
00689                      RAM_DISK[i] = buff[i];
00690                 }
00691               RetVal =  RES_OK;
00692          
00693         break;
00694         
00695         default:
00696               RetVal = RES_PARERR;
00697         break;
00698         
00699         return RetVal;
00700     }
00701 
00702  }   
00703  
00704   
00705    
00706 
00707 /*-----------------------------------------------------------------------*/
00708 /* Miscellaneous Functions                                               */
00709 /*-----------------------------------------------------------------------*/
00710 
00711 DRESULT disk_ioctl (
00712     BYTE drv,        /* Physical drive nmuber (0) */
00713     BYTE ctrl,        /* Control code */
00714     void *buff        /* Buffer to send/receive data block */
00715 )
00716 {
00717     BYTE n, w, ofs, dl, dh, *ptr = (BYTE *)buff;
00718     USB_INT32S  rc;
00719     
00720     switch(drv)
00721     {
00722         case CF:
00723             switch (ctrl)
00724               {
00725                         case GET_SECTOR_COUNT :    /* Get number of sectors on the disk (DWORD) */
00726                             ofs = 60; w = 2; n = 0;
00727                             break;
00728                 
00729                         case GET_BLOCK_SIZE :    /* Get erase block size in sectors (DWORD) */
00730                             *(DWORD*)buff = 32;
00731                             return RES_OK;
00732                         break;
00733                         case CTRL_SYNC :        /* Nothing to do */
00734                             return RES_OK;
00735                         break;
00736                         case ATA_GET_REV :        /* Get firmware revision (8 chars) */
00737                             ofs = 23; w = 4; n = 4;
00738                             break;
00739                 
00740                         case ATA_GET_MODEL :    /* Get model name (40 chars) */
00741                             ofs = 27; w = 20; n = 20;
00742                             break;
00743                 
00744                         case ATA_GET_SN :        /* Get serial number (20 chars) */
00745                             ofs = 10; w = 10; n = 10;
00746                             break;
00747                 
00748                         default:
00749                             return RES_PARERR;
00750              }
00751                     
00752             write_ata(REG_COMMAND, CMD_IDENTIFY);
00753             
00754             if (!wait_data()) return RES_ERROR;
00755             
00756             read_part(ptr, ofs, w);
00757             
00758             while (n--)
00759              {
00760                 dl = *ptr; dh = *(ptr+1);
00761                 *ptr++ = dh; *ptr++ = dl; 
00762              }
00763                         
00764              return RES_OK;
00765         break;
00766         
00767         
00768         case USB:
00769                     rc = MS_Init( &_blkSize, &_numBlks, inquiryResult );
00770                    
00771                     if (rc != OK)
00772                     {
00773                         TERMINAL_PRINTF("Could not get data from USB Inquiry: %d\r\n", rc);
00774                         return RES_ERROR;
00775                     }
00776                     else
00777                     {
00778                         Stat[USB] &= ~STA_NOINIT;
00779                          switch (ctrl)
00780                               {
00781                                     case GET_SECTOR_COUNT :    
00782                                        *(DWORD *)(buff) =_numBlks;
00783                                         break;
00784                             
00785                                     case GET_BLOCK_SIZE :   
00786                                        *(DWORD *)(buff) = _blkSize;
00787                                         return RES_OK;
00788                                     break;
00789                                     case CTRL_SYNC :      
00790                                         return RES_OK;
00791                                     break;
00792                                     case ATA_GET_REV :        
00793                                        memcpy ((CHAR *)buff,(const char *)&inquiryResult[32],8);
00794                                         return RES_OK;
00795                                         break;
00796                             
00797                                     case ATA_GET_MODEL :  
00798                                         memcpy ((CHAR *)buff, (const char *)&inquiryResult[8],8);
00799                                          return RES_OK;
00800                                         break;
00801                             
00802                                     case ATA_GET_SN :      
00803                                          memcpy ((CHAR *)buff,(const char *)&inquiryResult[16],8);
00804                                           return RES_OK;
00805                                         break;
00806                                         
00807                                     default:
00808                                         return RES_PARERR;
00809                                }
00810                     }
00811              
00812         break;
00813         
00814         case RAM:
00815               switch (ctrl)
00816               {
00817                         case GET_SECTOR_COUNT :    /* Get number of sectors on the disk (DWORD) */
00818                            *(DWORD *)(buff) = 1;
00819                             break;
00820                 
00821                         case GET_BLOCK_SIZE :    /* Get erase block size in sectors (DWORD) */
00822                            *(DWORD *)(buff) = 1;
00823                             return RES_OK;
00824                         break;
00825                         case CTRL_SYNC :        /* Nothing to do */
00826                             return RES_OK;
00827                         break;
00828                         case ATA_GET_REV :        /* Get firmware revision (8 chars) */
00829                            strcpy ((CHAR *)buff,"Rev 0.01");
00830                             break;
00831                 
00832                         case ATA_GET_MODEL :    /* Get model name (40 chars) */
00833                             strcpy ((CHAR *)buff,"Wavenumber RAM Drive");
00834                             break;
00835                 
00836                         case ATA_GET_SN :        /* Get serial number (20 chars) */
00837                              strcpy ((CHAR *)buff,"12345");
00838                             break;
00839                         default:
00840                             return RES_PARERR;
00841              }
00842              return RES_OK;
00843         break;
00844         
00845         default:
00846              return RES_PARERR;
00847         break;
00848     }
00849 
00850     return RES_OK;
00851 }
00852 
00853 
00854 /*-----------------------------------------------------------------------*/
00855 /* Device timer interrupt procedure                                      */
00856 /*-----------------------------------------------------------------------*/
00857 /* This function must be called in period of 10ms */
00858 
00859 void disk_timerproc (void)
00860 {
00861     static BYTE pv;
00862     BYTE n;
00863    
00864     n = DiskProcTimer[CF];                    /* 100Hz decrement timer */
00865     if (n) DiskProcTimer[CF] = --n;
00866 
00867     n = DiskProcTimer[USB];                    /* 100Hz decrement timer */
00868     if (n) DiskProcTimer[USB] = --n;
00869 
00870     n = DiskProcTimer[RAM];                    /* 100Hz decrement timer */
00871     if (n) DiskProcTimer[RAM] = --n;
00872 
00873     n = pv;
00874     pv = COMPACT_FLASH_CARD_DETECTED ;    /* Sapmle socket switch */
00875 
00876 
00877     //Check Compact Flash Card Detect
00878     if (n == pv) {                    /* Have contacts stabled? */
00879         if (!COMPACT_FLASH_CARD_DETECTED )
00880         {            /* CD1 or CD2 is high (Socket empty) */
00881             Stat[CF] |= (STA_NODISK | STA_NOINIT);
00882             SET_DATA_BUS_TO_INPUTS;        /* Float D0-D7 */
00883             COMPACT_FLASH_RESET_ACTIVE;    /* Assert RESET# */
00884             COMPACT_FLASH_POWER_DISABLE;   /* Power OFF */
00885             LED1_OFF; 
00886         }
00887         else 
00888         {                    /* CD1 and CD2 are low (Card inserted) */
00889             Stat[CF] &= ~STA_NODISK;
00890             LED1_ON;
00891         }
00892     }
00893     
00894     //Check to see if a USB drive is connected
00895     if(HOST_RhscIntr>0)
00896         LED2_ON;
00897     else
00898         LED2_OFF;
00899     
00900 }
00901 
00902 
00903 DWORD get_fattime(void)
00904 {
00905     time_t CurrentTimeStamp;
00906     tm *CurrentLocalTime;
00907     DWORD FATFSTimeCode;
00908         
00909     CurrentTimeStamp = time(NULL);
00910     CurrentLocalTime = localtime(&CurrentTimeStamp);
00911         
00912         //Map the tm struct time into the FatFs time code    
00913     FATFSTimeCode =  ((CurrentLocalTime->tm_year-80)<<25) | 
00914                      ((CurrentLocalTime->tm_mon+1)<<21)   | 
00915                      ((CurrentLocalTime->tm_mday)<<16)    | 
00916                      ((CurrentLocalTime->tm_hour)<<11)    |
00917                      ((CurrentLocalTime->tm_min)<<5)     | 
00918                      ((CurrentLocalTime->tm_sec));
00919 
00920    return FATFSTimeCode;
00921 }