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