Diff: FAT_FS/diskio.c
- Revision:
- 0:76427232f435
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FAT_FS/diskio.c Thu Feb 16 00:41:26 2012 +0000
@@ -0,0 +1,934 @@
+#include "mbed.h"
+#include "LPC17xx.h"
+#include "integer.h"
+#include "diskio.h"
+#include "stdarg.h"
+#include "USBHost.h"
+#include "Terminal.h"
+
+/*--------------------------------------------------------------------------
+
+ Module Private Functions
+
+---------------------------------------------------------------------------*/
+
+static volatile DSTATUS Stat[3] = {STA_NOINIT | STA_NODISK}; /* Disk status */
+static volatile BYTE DiskProcTimer[3]={0}; /* 100Hz decrement timer */
+
+
+
+
+
+BYTE RAM_DISK[512];
+
+DWORD BlockSize;
+DWORD BlockCount;
+
+//#define _CF_DEBUG_MESSAGES
+//#define _CF_DEBUG_READ_ATA
+
+#ifdef _CF_DEBUG_MESSAGES
+ #define CF_DEBUG(...) printf(__VA_ARGS__)
+#else
+ #define CF_DEBUG do{}while(0);
+#endif
+
+void disk_timerproc (void);
+
+#define LED1_MASK (uint32_t )(1<<18)
+#define LED2_MASK (uint32_t )(1<<20)
+#define LED3_MASK (uint32_t )(1<<21)
+#define LED4_MASK (uint32_t )(1<<23)
+
+
+#define LED1_ON LPC_GPIO1->FIOSET=LED1_MASK
+#define LED1_OFF LPC_GPIO1->FIOCLR=LED1_MASK
+#define LED1_TOGGLE LPC_GPIO1->FIOPIN^=LED1_MASK
+
+#define LED2_ON LPC_GPIO1->FIOSET=LED2_MASK
+#define LED2_OFF LPC_GPIO1->FIOCLR=LED2_MASK
+#define LED2_TOGGLE LPC_GPIO1->FIOPIN^=LED2_MASK
+
+#define LED3_ON LPC_GPIO1->FIOSET=LED3_MASK
+#define LED3_OFF LPC_GPIO1->FIOCLR=LED3_MASK
+#define LED3_TOGGLE LPC_GPIO1->FIOPIN^=LED3_MASK
+
+#define LED4_ON LPC_GPIO1->FIOSET=LED4_MASK
+#define LED4_OFF LPC_GPIO1->FIOCLR=LED4_MASK
+#define LED4_TOGGLE LPC_GPIO1->FIOPIN^=LED4_MASK
+
+
+
+//8-bit Data Bus is on Pins P0.4 - P0.11
+#define DATA_BUS_MASK (uint32_t )((0xFF)<<4)
+
+//3 bit address is on Port 2.0 - 2.2
+#define ADDRESS_BUS_MASK (uint32_t )(0x7)
+
+//ChipSelects are on port 2
+#define CS0_MASK (uint32_t )(1<<3)
+#define CS1_MASK (uint32_t )(1<<4)
+
+//IORD and IOWR are on port 0
+#define IORD_MASK (uint32_t )(1<<24)
+#define IOWR_MASK (uint32_t )(1<<23)
+
+
+//Reset and power enable are on port 1
+#define COMPACT_FLASH_RESET_MASK (uint32_t )(1<<30)
+#define COMPACT_FLASH_POWER_ENABLE_MASK (uint32_t )(0x80000000)
+//Card Detect is on Port 2
+#define COMPACT_FLASH_CARD_DETECT_MASK (uint32_t )(1<<5)
+
+//Low Level Bus Operation Macros
+//Note: LPC 176x have dedicate set and clear registers
+
+#define SET_DATA_BUS_TO_INPUTS LPC_GPIO0->FIODIR &= ~(DATA_BUS_MASK);
+#define SET_DATA_BUS_TO_OUTPUT LPC_GPIO0->FIODIR |= (DATA_BUS_MASK);
+
+#define CS0_ACTIVE LPC_GPIO2->FIOCLR = CS0_MASK
+#define CS0_INACTIVE LPC_GPIO2->FIOSET = CS0_MASK
+#define CS1_ACTIVE LPC_GPIO2->FIOCLR = CS1_MASK
+#define CS1_INACTIVE LPC_GPIO2->FIOSET = CS1_MASK
+
+#define IORD_ACTIVE LPC_GPIO0->FIOCLR = IORD_MASK
+#define IORD_INACTIVE LPC_GPIO0->FIOSET = IORD_MASK
+
+#define IOWR_ACTIVE LPC_GPIO0->FIOCLR = IOWR_MASK
+#define IOWR_INACTIVE LPC_GPIO0->FIOSET = IOWR_MASK
+
+#define COMPACT_FLASH_RESET_ACTIVE LPC_GPIO1->FIOCLR = COMPACT_FLASH_RESET_MASK
+#define COMPACT_FLASH_RESET_INACTIVE LPC_GPIO1->FIOSET = COMPACT_FLASH_RESET_MASK
+
+#define COMPACT_FLASH_POWER_ENABLE LPC_GPIO1->FIOCLR = COMPACT_FLASH_POWER_ENABLE_MASK
+#define COMPACT_FLASH_POWER_DISABLE LPC_GPIO1->FIOSET = COMPACT_FLASH_POWER_ENABLE_MASK
+
+#define COMPACT_FLASH_CARD_DETECTED (!((LPC_GPIO2->FIOPIN)&COMPACT_FLASH_CARD_DETECT_MASK))
+
+//To set the Address and Data Bus Lines we will use the convient Mask register in the Port I/O modules
+//The Hardware will mask out pins that are set to 1 in the MASK register
+
+#define SET_CF_ADDRESS(ADDRESS) LPC_GPIO2->FIOMASK=~(ADDRESS_BUS_MASK); \
+ LPC_GPIO2->FIOPIN=ADDRESS; \
+ LPC_GPIO2->FIOMASK=0 //Always remember to reset the mask for other operations to complete correctly
+
+
+#define SET_CF_DATA(DATA) LPC_GPIO0->FIOMASK=~(DATA_BUS_MASK); \
+ LPC_GPIO0->FIOPIN=(((uint32_t)DATA)<<4); \
+ LPC_GPIO0->FIOMASK=0 //Always remember to reset the mask for other operations to complete correctly
+
+#define GET_CF_DATA(DATA) LPC_GPIO0->FIOMASK=~(DATA_BUS_MASK); \
+ (DATA) = (LPC_GPIO0->FIOPIN)>>4; \
+ LPC_GPIO0->FIOMASK=0 //Always remember to reset the mask for other operations to complete correctly
+
+#define SET_DATA_BUS_AS_OUTPUTS LPC_GPIO0->FIODIR|=DATA_BUS_MASK
+#define SET_DATA_BUS_AS_INPUTS LPC_GPIO0->FIODIR&=~DATA_BUS_MASK
+
+/* ATA command */
+#define CMD_RESET 0x08 /* DEVICE RESET */
+#define CMD_READ 0x20 /* READ SECTOR(S) */
+#define CMD_WRITE 0x30 /* WRITE SECTOR(S) */
+#define CMD_IDENTIFY 0xEC /* DEVICE IDENTIFY */
+#define CMD_SETFEATURES 0xEF /* SET FEATURES */
+
+/* ATA register bit definitions */
+#define LBA 0xE0
+#define BUSY 0x80
+#define DRDY 0x40
+#define DF 0x20
+#define DRQ 0x08
+#define ERR 0x01
+#define SRST 0x40
+#define nIEN 0x20
+
+/* Bit definitions for Control Port */
+#define CTL_READ 0x20
+#define CTL_WRITE 0x40
+#define CTL_RESET 0x80
+#define REG_DATA 0x0
+#define REG_ERROR 0x1
+#define REG_FEATURES 0x1
+#define REG_COUNT 0x2
+#define REG_SECTOR 0x3
+#define REG_CYLL 0x4
+#define REG_CYLH 0x5
+#define REG_DEV 0x6
+#define REG_COMMAND 0x7
+#define REG_STATUS 0x7
+#define REG_DEVCTRL 0xE
+#define REG_ALTSTAT 0xE
+
+void InitCompactFlashInterface()
+{
+ SET_DATA_BUS_AS_INPUTS;
+
+ LPC_GPIO2->FIODIR |= ADDRESS_BUS_MASK | CS0_MASK | CS1_MASK;
+ LPC_GPIO2->FIODIR &=~(COMPACT_FLASH_CARD_DETECT_MASK);
+ LPC_GPIO1->FIODIR |= COMPACT_FLASH_RESET_MASK | COMPACT_FLASH_POWER_ENABLE_MASK | LED1_MASK | LED2_MASK | LED3_MASK | LED4_MASK;
+ LPC_GPIO0->FIODIR |= IORD_MASK | IOWR_MASK ;
+
+ COMPACT_FLASH_RESET_ACTIVE;
+ COMPACT_FLASH_POWER_DISABLE;
+ CS0_INACTIVE;
+ CS1_INACTIVE;
+
+ SysTick_Config(SystemCoreClock/100);
+ NVIC_SetVector(SysTick_IRQn, (uint32_t)(&disk_timerproc));
+}
+
+/*-----------------------------------------------------------------------*/
+/* Read an ATA register */
+/*-----------------------------------------------------------------------*/
+
+static
+BYTE read_ata (
+ BYTE reg /* Register to be read */
+)
+{
+ BYTE rd;
+
+ CS0_ACTIVE;
+ SET_DATA_BUS_AS_INPUTS;
+ SET_CF_ADDRESS(reg);
+ IORD_ACTIVE;
+ __nop();
+ __nop();
+ __nop();
+ __nop();
+
+ GET_CF_DATA(rd);
+ __nop();
+ __nop();
+ __nop();
+ __nop();
+ IORD_INACTIVE;
+ CS0_INACTIVE;
+ #ifdef _CF_DEBUG_READ_ATA
+ CF_DEBUG("rd 0x%2x\r\n",rd);
+ #endif
+ return rd;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Write a byte to an ATA register */
+/*-----------------------------------------------------------------------*/
+
+static
+void write_ata (
+ BYTE reg, /* Register to be written */
+ BYTE dat /* Data to be written */
+)
+{
+
+ __nop();
+ CS0_ACTIVE;
+ SET_DATA_BUS_AS_OUTPUTS;
+ SET_CF_ADDRESS(reg);
+ SET_CF_DATA(dat);
+ IOWR_ACTIVE;
+ __nop();
+ __nop();
+ __nop();
+ __nop();
+ IOWR_INACTIVE;
+ __nop();
+ __nop();
+ __nop();
+ __nop();
+ CS0_INACTIVE;
+ SET_DATA_BUS_AS_INPUTS;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read a part of data block */
+/*-----------------------------------------------------------------------*/
+
+static
+void read_part (
+ BYTE *buff, /* Data buffer to store read data */
+ BYTE ofs, /* Offset of the part of data in unit of word */
+ BYTE count /* Number of word to pick up */
+)
+{
+ BYTE c = 0, dl, dh;
+
+ SET_CF_ADDRESS(REG_DATA); /* Select Data register */
+ __nop();
+ __nop();
+
+ SET_DATA_BUS_AS_INPUTS;
+ CS0_ACTIVE;
+ __nop();
+ __nop();
+ do {
+ IORD_ACTIVE; /* IORD = L */
+ __nop();
+ __nop();
+ __nop();
+ __nop();
+ GET_CF_DATA(dl); /* Read Even data */
+ IORD_INACTIVE; /* IORD = H */
+ __nop();
+ __nop();
+ __nop();
+ __nop();
+ IORD_ACTIVE; /* IORD = L */
+ __nop();
+ __nop();
+ __nop();
+ __nop();
+ GET_CF_DATA(dh); /* Read Odd data */
+ IORD_INACTIVE; /* IORD = H */
+ __nop();
+ __nop();
+ __nop();
+ __nop();
+ if (count && (c >= ofs)) { /* Pick up a part of block */
+ *buff++ = dl;
+ *buff++ = dh;
+ count--;
+ }
+ } while (++c);
+ CS0_INACTIVE;
+
+ read_ata(REG_ALTSTAT);
+ read_ata(REG_STATUS);
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* Wait for Data Ready */
+/*-----------------------------------------------------------------------*/
+
+static
+int wait_data (void)
+{
+ BYTE s;
+
+ DiskProcTimer[CF] = 100; /* Time out = 1 sec */
+ do {
+ if (!DiskProcTimer[CF]) return 0; /* Abort when timeout occured */
+ s = read_ata(REG_STATUS); /* Get status */
+ } while ((s & (BUSY|DRQ)) != DRQ); /* Wait for BUSY goes low and DRQ goes high */
+
+ read_ata(REG_ALTSTAT);
+ return 1;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Initialize Disk Drive */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS disk_initialize (
+ BYTE drv /* Physical drive number (0) */
+)
+{
+ DSTATUS RetVal;
+
+ switch(drv)
+ {
+ case COMPACT_FLASH:
+
+ Stat[CF] |= STA_NOINIT;
+ for (DiskProcTimer[CF] = 10; DiskProcTimer[CF]; ); /* 100ms */
+ if (Stat[CF] & STA_NODISK) return Stat[CF]; /* Exit when socket is empty */
+ COMPACT_FLASH_POWER_ENABLE; /* Initialize CFC control port */
+ for (DiskProcTimer[CF] = 1;DiskProcTimer[CF]; ); /* 10ms */
+
+ SET_DATA_BUS_AS_INPUTS;
+ for (DiskProcTimer[CF] = 5; DiskProcTimer[CF]; ); /* 50ms */
+ COMPACT_FLASH_RESET_INACTIVE;
+ for (DiskProcTimer[CF] = 5; DiskProcTimer[CF]; ); /* 50ms */
+ write_ata(REG_DEV, LBA); /* Select Device 0 */
+ DiskProcTimer[CF] = 200;
+
+ do { /* Wait for card goes ready */
+ if (!DiskProcTimer[CF])
+ {
+ CF_DEBUG("Timeout waiting for card BUSY to go inactive\r\n");
+ return Stat[CF];
+ }
+ } while (read_ata(REG_STATUS) & BUSY);
+
+
+ write_ata(REG_DEVCTRL, SRST | nIEN); /* Software reset */
+ for (DiskProcTimer[CF] = 2; DiskProcTimer[CF]; ); /* 20ms */
+
+ write_ata(REG_DEVCTRL, nIEN); /* Release software reset */
+
+ for (DiskProcTimer[CF] = 2; DiskProcTimer[CF]; ); /* 20ms */
+
+ DiskProcTimer[CF] = 200;
+ do { /* Wait for card goes ready */
+ if (!DiskProcTimer[CF])
+ {
+ CF_DEBUG("Timeout waiting for card DRDY\r\n");
+ return Stat[CF];
+ }
+ } while ((read_ata(REG_STATUS) & (DRDY|BUSY)) != DRDY);
+
+ CF_DEBUG("Setting to 8-bit PIO MOD\r\n");
+ write_ata(REG_FEATURES, 0x01); /* Select 8-bit PIO transfer mode */
+ write_ata(REG_COMMAND, CMD_SETFEATURES);
+ DiskProcTimer[CF] = 200;
+ do {
+ if (!DiskProcTimer[CF])
+ {
+ CF_DEBUG("Timeout waiting after trying to call the SETFEATURES command\r\n");
+ return Stat[CF];
+ }
+
+ } while (read_ata(REG_STATUS) & (BUSY | ERR));
+
+ Stat[CF] &= ~STA_NOINIT; /* When device goes ready, clear STA_NOINIT */
+
+ RetVal = Stat[CF];
+
+ break;
+
+ case USB:
+
+ if(USB_Disk_Detected)
+ {
+ TERMINAL_PRINTF("USB Disk Detected.\r\n");
+ Stat[USB] &= ~(STA_NOINIT | STA_NODISK);
+ }
+ else
+ {
+ TERMINAL_PRINTF("USB Disk not attached.\r\n");
+ Stat[USB] |= STA_NOINIT | STA_NODISK;
+ }
+
+ RetVal = Stat[USB];
+ break;
+
+
+ case RAM:
+ Stat[RAM] &= ~STA_NOINIT;
+ RetVal = Stat[RAM];
+ break;
+
+ default:
+ RetVal = STA_NOINIT;
+ break;
+ }
+
+ return RetVal;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Return Disk Status */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS disk_status (
+ BYTE drv
+)
+{
+ DSTATUS RetVal;
+
+ switch(drv)
+ {
+ case CF:
+ RetVal = Stat[CF];
+ break;
+
+
+ case USB:
+ RetVal = Stat[USB];
+ break;
+
+ case RAM:
+ RetVal = Stat[RAM];
+ break;
+
+ default:
+ RetVal = STA_NOINIT;
+ break;
+ }
+
+ return RetVal;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Sector(s) */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_read (
+ BYTE drv, /* Physical drive nmuber (0) */
+ BYTE *buff, /* Data buffer to store read data */
+ DWORD sector, /* Sector number (LBA) */
+ BYTE count /* Sector count (1..255) */
+)
+{
+ BYTE c;
+ DWORD i;
+
+ switch(drv)
+ {
+ case CF:
+ if (Stat[CF] & STA_NOINIT) return RES_NOTRDY;
+
+ /* Issue Read Setor(s) command */
+ write_ata(REG_COUNT, count);
+ write_ata(REG_SECTOR, (BYTE)sector);
+ write_ata(REG_CYLL, (BYTE)(sector >> 8));
+ write_ata(REG_CYLH, (BYTE)(sector >> 16));
+ write_ata(REG_DEV, ((BYTE)(sector >> 24) & 0x0F) | LBA);
+ write_ata(REG_COMMAND, CMD_READ);
+
+ do {
+ if (!wait_data()) return RES_ERROR; /* Wait data ready */
+
+ SET_CF_ADDRESS(REG_DATA);
+ __nop();
+ __nop();
+ __nop();
+ __nop();
+ CS0_ACTIVE;
+ c = 0;
+
+ __nop();
+ __nop();
+ __nop();
+
+ SET_DATA_BUS_AS_INPUTS;
+ do {
+ IORD_ACTIVE; /* IORD = L */
+ __nop();
+ __nop();
+ __nop();
+ GET_CF_DATA(*buff++); /* Get even data */
+ __nop();
+ __nop();
+ __nop();
+
+ __nop();
+ __nop();
+ __nop();
+
+ IORD_INACTIVE; /* IORD = H */
+ __nop();
+ __nop();
+ __nop();
+
+ IORD_ACTIVE; /* IORD = L */
+ __nop();
+ __nop();
+ __nop();
+
+ GET_CF_DATA(*buff++); /* Get Odd data */
+ __nop();
+ __nop();
+ __nop();
+
+ __nop();
+ IORD_INACTIVE; /* IORD = H */
+ __nop();
+ __nop();
+ __nop();
+
+
+ } while (--c);
+ } while (--count);
+
+ CS0_INACTIVE;
+ read_ata(REG_ALTSTAT);
+ read_ata(REG_STATUS);
+
+ return RES_OK;
+ break;
+
+
+ case USB:
+
+ if(MassStorage_Read(sector, 1,(u8 *) buff, 512) == 0)
+ return RES_OK;
+ else
+ return RES_NOTRDY;
+
+ break;
+
+ case RAM:
+ for(i=0;i<512;i++)
+ {
+ buff[i] = RAM_DISK[i];
+ }
+ return RES_OK;
+ break;
+
+ default:
+ return RES_PARERR;
+ break;
+ }
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* Write Sector(s) */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_write (
+ BYTE drv, /* Physical drive number (0) */
+ const BYTE *buff, /* Data to be written */
+ DWORD sector, /* Sector number (LBA) */
+ BYTE count /* Sector count (1..255) */
+)
+{
+ BYTE s, c;
+ DWORD i;
+ DRESULT RetVal;
+
+ switch(drv)
+ {
+ case CF:
+ /* Issue Write Setor(s) command */
+ write_ata(REG_COUNT, count);
+ write_ata(REG_SECTOR, (BYTE)sector);
+ write_ata(REG_CYLL, (BYTE)(sector >> 8));
+ write_ata(REG_CYLH, (BYTE)(sector >> 16));
+ write_ata(REG_DEV, ((BYTE)(sector >> 24) & 0x0F) | LBA);
+ write_ata(REG_COMMAND, CMD_WRITE);
+
+ do {
+ if (!wait_data()) return RES_ERROR;
+
+ SET_CF_ADDRESS(REG_DATA);
+ __nop();
+ __nop();
+ __nop();
+ CS0_ACTIVE;
+ __nop();
+ __nop();
+ __nop();
+
+ SET_DATA_BUS_AS_OUTPUTS;
+ c = 0;
+ do {
+ SET_CF_DATA(*buff++); /* Set even data */
+ __nop();
+ __nop();
+ __nop();
+
+ IOWR_ACTIVE; /* IOWR = L */
+ __nop();
+ __nop();
+ __nop();
+
+ IOWR_INACTIVE; /* IOWR = H */
+ __nop();
+ __nop();
+ __nop();
+
+ SET_CF_DATA(*buff++); /* Set odd data */
+ __nop();
+ __nop();
+ __nop();
+
+ IOWR_ACTIVE; /* IOWR = L */
+ __nop();
+ __nop();
+ __nop();
+
+ IOWR_INACTIVE; /* IOWR = H */
+ __nop();
+ __nop();
+ __nop();
+ } while (--c);
+
+ } while (--count);
+
+ SET_DATA_BUS_AS_INPUTS;
+ CS0_INACTIVE;
+
+ DiskProcTimer[CF] = 100;
+ do {
+ if (!DiskProcTimer[CF]) return RES_ERROR;
+ s = read_ata(REG_STATUS);
+ } while (s & BUSY);
+ if (s & ERR) return RES_ERROR;
+
+ read_ata(REG_ALTSTAT);
+ read_ata(REG_STATUS);
+
+ RetVal = RES_OK;
+ break;
+
+
+ case USB:
+
+ if( MassStorage_Write(sector, 1, (u8 *)buff, 512) == 0)
+ RetVal = RES_OK;
+ else
+ RetVal = RES_NOTRDY;
+
+ break;
+
+ case RAM:
+
+ for(i=0;i<512;i++)
+ {
+ RAM_DISK[i] = buff[i];
+ }
+ RetVal = RES_OK;
+
+ break;
+
+ default:
+ RetVal = RES_PARERR;
+ break;
+
+ }
+ return RetVal;
+ }
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Miscellaneous Functions */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_ioctl (
+ BYTE drv, /* Physical drive nmuber (0) */
+ BYTE ctrl, /* Control code */
+ void *buff /* Buffer to send/receive data block */
+)
+{
+ BYTE n, w, ofs, dl, dh, *ptr = (BYTE *)buff;
+
+ switch(drv)
+ {
+ case CF:
+ switch (ctrl)
+ {
+ case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
+ ofs = 60; w = 2; n = 0;
+ break;
+
+ case GET_BLOCK_SIZE : /* Get erase block size in sectors (DWORD) */
+ *(DWORD*)buff = 32;
+ return RES_OK;
+ break;
+ case CTRL_SYNC : /* Nothing to do */
+ return RES_OK;
+ break;
+ case ATA_GET_REV : /* Get firmware revision (8 chars) */
+ ofs = 23; w = 4; n = 4;
+ break;
+
+ case ATA_GET_MODEL : /* Get model name (40 chars) */
+ ofs = 27; w = 20; n = 20;
+ break;
+
+ case ATA_GET_SN : /* Get serial number (20 chars) */
+ ofs = 10; w = 10; n = 10;
+ break;
+
+ default:
+ return RES_PARERR;
+ }
+
+ write_ata(REG_COMMAND, CMD_IDENTIFY);
+
+ if (!wait_data()) return RES_ERROR;
+
+ read_part(ptr, ofs, w);
+
+ while (n--)
+ {
+ dl = *ptr; dh = *(ptr+1);
+ *ptr++ = dh; *ptr++ = dl;
+ }
+
+ return RES_OK;
+ break;
+
+
+ case USB:
+ if (USB_Disk_Detected == 0)
+ {
+ // TERMINAL_PRINTF("USB Disk not attached\r\n");
+ return RES_ERROR;
+ }
+ else
+ {
+ Stat[USB] &= ~STA_NOINIT;
+ switch (ctrl)
+ {
+
+ case GET_SECTOR_COUNT:
+ /* if(MassStorage_ReadCapacity(USB_Disk_Device, &BlockCount, &BlockSize) == 0)
+ {
+
+ *(DWORD *)(buff) = BlockCount;
+
+
+ }
+ else
+ {
+ return RES_ERROR;
+ }*/
+ return RES_OK;
+ break;
+
+ case GET_BLOCK_SIZE :
+
+ /* if(MassStorage_ReadCapacity(USB_Disk_Device, &BlockCount, &BlockSize) == 0)
+ {
+ *(DWORD *)(buff) = BlockSize;
+ return RES_OK;
+ }
+ else
+ {
+ return RES_ERROR;
+ }*/
+ return RES_OK;
+
+ break;
+
+ case CTRL_SYNC :
+ return RES_OK;
+ break;
+
+ case ATA_GET_REV :
+ strcpy ((CHAR *)buff,"00000");
+ return RES_OK;
+ break;
+
+ case ATA_GET_MODEL :
+ strcpy ((CHAR *)buff, "000000");
+ return RES_OK;
+ break;
+
+ case ATA_GET_SN :
+ strcpy ((CHAR *)buff,"00000000");
+ return RES_OK;
+ break;
+
+ default:
+ return RES_PARERR;
+ }
+ }
+
+ break;
+
+ case RAM:
+ switch (ctrl)
+
+ {
+ case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
+ *(DWORD *)(buff) = 1;
+ break;
+
+ case GET_BLOCK_SIZE : /* Get erase block size in sectors (DWORD) */
+ *(DWORD *)(buff) = 1;
+ return RES_OK;
+ break;
+ case CTRL_SYNC : /* Nothing to do */
+ return RES_OK;
+ break;
+
+ case ATA_GET_REV : /* Get firmware revision (8 chars) */
+ strcpy ((CHAR *)buff,"Rev 0.01");
+ break;
+
+ case ATA_GET_MODEL : /* Get model name (40 chars) */
+ strcpy ((CHAR *)buff,"Wavenumber RAM Drive");
+ break;
+
+ case ATA_GET_SN : /* Get serial number (20 chars) */
+ strcpy ((CHAR *)buff,"12345");
+ break;
+ default:
+ return RES_PARERR;
+ }
+ return RES_OK;
+ break;
+
+ default:
+ return RES_PARERR;
+ break;
+ }
+
+ return RES_OK;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* Device timer interrupt procedure */
+/*-----------------------------------------------------------------------*/
+/* This function must be called in period of 10ms */
+
+void disk_timerproc (void)
+{
+ static BYTE pv;
+ BYTE n;
+
+ n = DiskProcTimer[CF]; /* 100Hz decrement timer */
+ if (n) DiskProcTimer[CF] = --n;
+
+ n = DiskProcTimer[USB]; /* 100Hz decrement timer */
+ if (n) DiskProcTimer[USB] = --n;
+
+ n = DiskProcTimer[RAM]; /* 100Hz decrement timer */
+ if (n) DiskProcTimer[RAM] = --n;
+
+ n = pv;
+ pv = COMPACT_FLASH_CARD_DETECTED ; /* Sapmle socket switch */
+
+
+ //Check Compact Flash Card Detect
+ if (n == pv) { /* Have contacts stabled? */
+ if (!COMPACT_FLASH_CARD_DETECTED )
+ { /* CD1 or CD2 is high (Socket empty) */
+ Stat[CF] |= (STA_NODISK | STA_NOINIT);
+ SET_DATA_BUS_TO_INPUTS; /* Float D0-D7 */
+ COMPACT_FLASH_RESET_ACTIVE; /* Assert RESET# */
+ COMPACT_FLASH_POWER_DISABLE; /* Power OFF */
+ LED1_OFF;
+ }
+ else
+ { /* CD1 and CD2 are low (Card inserted) */
+ Stat[CF] &= ~STA_NODISK;
+ LED1_ON;
+ }
+ }
+
+ //Check to see if a USB drive is connected
+ if(USB_Disk_Detected>0)
+ LED2_ON;
+ else
+ LED2_OFF;
+
+}
+
+
+DWORD get_fattime(void)
+{
+ time_t CurrentTimeStamp;
+ tm *CurrentLocalTime;
+ DWORD FATFSTimeCode;
+
+ CurrentTimeStamp = time(NULL);
+ CurrentLocalTime = localtime(&CurrentTimeStamp);
+
+ //Map the tm struct time into the FatFs time code
+ FATFSTimeCode = ((CurrentLocalTime->tm_year-80)<<25) |
+ ((CurrentLocalTime->tm_mon+1)<<21) |
+ ((CurrentLocalTime->tm_mday)<<16) |
+ ((CurrentLocalTime->tm_hour)<<11) |
+ ((CurrentLocalTime->tm_min)<<5) |
+ ((CurrentLocalTime->tm_sec));
+
+ return FATFSTimeCode;
+}
\ No newline at end of file