#define FDD_VERSION ((0<<8)|(75))\r
\r
// --- Options\r
-#define USE_CACHE 0 // Use Sector Cache\r
-#define CACHE_SIZE 32 // Number of cachable sectors\r
#define FDD_SEEK_TIMEOUT 10 // Timeout for a seek operation\r
#define MOTOR_ON_DELAY 500 // Miliseconds\r
#define MOTOR_OFF_DELAY 2000 // Miliseconds\r
/**\r
* \brief Representation of a floppy drive\r
*/\r
-typedef struct {\r
+typedef struct sFloppyDrive\r
+{\r
int type;\r
volatile int motorState; //2 - On, 1 - Spinup, 0 - Off\r
int track[2];\r
// === GLOBALS ===\r
MODULE_DEFINE(0, FDD_VERSION, FDD, FDD_Install, NULL, NULL);\r
t_floppyDevice gFDD_Devices[2];\r
-volatile int fdd_inUse = 0;\r
-volatile int fdd_irq6 = 0;\r
+tSpinlock glFDD;\r
+volatile int gbFDD_IrqFired = 0;\r
tDevFS_Driver gFDD_DriverInfo = {\r
NULL, "fdd",\r
{\r
.IOCtl = FDD_IOCtl\r
}\r
};\r
-#if USE_CACHE\r
-int siFDD_CacheInUse = 0;\r
-int siFDD_SectorCacheSize = CACHE_SIZE;\r
-t_floppySector sFDD_SectorCache[CACHE_SIZE];\r
-#endif\r
\r
// === CODE ===\r
/**\r
gFDD_Devices[0].Node.Flags = 0;\r
gFDD_Devices[0].Node.NumACLs = 0;\r
gFDD_Devices[0].Node.Read = FDD_ReadFS;\r
- gFDD_Devices[0].Node.Write = NULL;//fdd_writeFS;\r
+ gFDD_Devices[0].Node.Write = NULL;//FDD_WriteFS;\r
memcpy(&gFDD_Devices[1].Node, &gFDD_Devices[0].Node, sizeof(tVFS_Node));\r
\r
gFDD_Devices[1].Node.Inode = 1;\r
gFDD_Devices[1].Node.Size = cFDD_SIZES[data & 0xF];\r
\r
// Create Sector Cache\r
- #if USE_CACHE\r
- //sFDD_SectorCache = malloc(sizeof(*sFDD_SectorCache)*CACHE_SIZE);\r
- //siFDD_SectorCacheSize = CACHE_SIZE;\r
- #else\r
- if( cFDD_SIZES[data >> 4] ) {\r
+ if( cFDD_SIZES[data >> 4] )\r
+ {\r
gFDD_Devices[0].CacheHandle = IOCache_Create(\r
FDD_WriteSector, 0, 512,\r
gFDD_Devices[0].Node.Size / (512*4)\r
); // Cache is 1/4 the size of the disk\r
}\r
- if( cFDD_SIZES[data & 15] ) {\r
+ if( cFDD_SIZES[data & 15] )\r
+ {\r
gFDD_Devices[1].CacheHandle = IOCache_Create(\r
FDD_WriteSector, 0, 512,\r
gFDD_Devices[1].Node.Size / (512*4)\r
); // Cache is 1/4 the size of the disk\r
}\r
- #endif\r
\r
// Register with devfs\r
DevFS_AddDevice(&gFDD_DriverInfo);\r
* \fn char *FDD_ReadDir(tVFS_Node *Node, int pos)\r
* \brief Read Directory\r
*/\r
-char *FDD_ReadDir(tVFS_Node *Node, int pos)\r
+char *FDD_ReadDir(tVFS_Node *Node, int Pos)\r
{\r
char name[2] = "0\0";\r
- //Update Accessed Time\r
- //gFDD_DrvInfo.rootNode.atime = now();\r
- \r
- //Check for bounds\r
- if(pos >= 2 || pos < 0)\r
- return NULL;\r
+\r
+ if(Pos >= 2 || Pos < 0) return NULL;\r
\r
- if(gFDD_Devices[pos].type == 0)\r
- return VFS_SKIP;\r
+ if(gFDD_Devices[Pos].type == 0) return VFS_SKIP;\r
\r
- name[0] += pos;\r
+ name[0] += Pos;\r
\r
- //Return\r
return strdup(name);\r
}\r
\r
*/\r
Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
{\r
- int i = 0;\r
- int disk;\r
- //Uint32 buf[128];\r
+ int ret;\r
\r
ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
\r
return -1;\r
}\r
\r
- disk = Node->Inode;\r
- \r
- // Update Accessed Time\r
- Node->ATime = now();\r
- \r
- #if 0\r
- if((Offset & 0x1FF) || (Length & 0x1FF))\r
- {\r
- // Un-Aligned Offset/Length\r
- int startOff = Offset >> 9;\r
- int sectOff = Offset & 0x1FF;\r
- int sectors = (Length + 0x1FF) >> 9;\r
- \r
- LOG("Non-aligned Read");\r
- \r
- //Read Starting Sector\r
- if(!FDD_ReadSector(disk, startOff, buf))\r
- return 0;\r
- memcpy(Buffer, (char*)(buf+sectOff), Length > 512-sectOff ? 512-sectOff : Length);\r
- \r
- // If the data size is one sector or less\r
- if(Length <= 512-sectOff)\r
- {\r
- LEAVE('X', Length);\r
- return Length; //Return\r
- }\r
- Buffer += 512-sectOff;\r
- \r
- //Read Middle Sectors\r
- for( i = 1; i < sectors - 1; i++ )\r
- {\r
- if(!FDD_ReadSector(disk, startOff+i, buf)) {\r
- LEAVE('i', -1);\r
- return -1;\r
- }\r
- memcpy(Buffer, buf, 512);\r
- Buffer += 512;\r
- }\r
- \r
- //Read End Sectors\r
- if(!FDD_ReadSector(disk, startOff+i, buf))\r
- return 0;\r
- memcpy(Buffer, buf, (len&0x1FF)-sectOff);\r
-
- LEAVE('X', Length);\r
- return Length;\r
- }\r
- else\r
- {\r
- int count = Length >> 9;\r
- int sector = Offset >> 9;\r
- LOG("Aligned Read");\r
- //Aligned Offset and Length - Simple Code\r
- for( i = 0; i < count; i ++ )\r
- {\r
- FDD_ReadSector(disk, sector, buf);\r
- memcpy(buffer, buf, 512);\r
- buffer += 512;\r
- sector++;\r
- }
- LEAVE('i', Length);\r
- return Length;\r
- }\r
- #endif\r
- \r
- i = DrvUtil_ReadBlock(Offset, Length, Buffer, FDD_ReadSectors, 512, disk);\r
- LEAVE('i', i);\r
- return i;\r
+ ret = DrvUtil_ReadBlock(Offset, Length, Buffer, FDD_ReadSectors, 512, Node->Inode);\r
+ LEAVE('i', ret);\r
+ return ret;\r
}\r
\r
/**\r
- * \fn Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint32 Disk)\r
* \brief Reads \a Count contiguous sectors from a disk\r
* \param SectorAddr Address of the first sector\r
* \param Count Number of sectors to read\r
int i;\r
int lba = SectorAddr;\r
\r
- ENTER("idisk Xlba pbuf", disk, lba, buf);\r
+ ENTER("iDisk XSectorAddr pBuffer", disk, SectorAddr, Buffer);\r
\r
#if USE_CACHE\r
FDD_AquireCacheSpinlock();\r
for( i = 0; i < siFDD_SectorCacheSize; i++ )\r
{\r
if(sFDD_SectorCache[i].timestamp == 0) continue;\r
- if(sFDD_SectorCache[i].disk == Disk\r
- && sFDD_SectorCache[i].sector == lba) {\r
+ if( sFDD_SectorCache[i].disk == Disk\r
+ && sFDD_SectorCache[i].sector == lba)\r
+ {\r
LOG("Found %i in cache %i", lba, i);\r
memcpy(Buffer, sFDD_SectorCache[i].data, 512);\r
sFDD_SectorCache[i].timestamp = now();\r
}\r
#endif\r
\r
- base = cPORTBASE[Disk>>1];\r
+ base = cPORTBASE[Disk >> 1];\r
\r
LOG("Calculating Disk Dimensions");\r
// Get CHS position\r
- if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1) {\r
+ if(FDD_int_GetDims(gFDD_Devices[Disk].type, lba, &cyl, &head, &sec, &spt) != 1)\r
+ {\r
LEAVE('i', -1);\r
return -1;\r
}\r
// Remove Old Timer\r
Time_RemoveTimer(gFDD_Devices[Disk].timer);\r
// Check if Motor is on\r
- if(gFDD_Devices[Disk].motorState == 0) {\r
- FDD_int_StartMotor(Disk);\r
- }\r
+ if(gFDD_Devices[Disk].motorState == 0) FDD_int_StartMotor(Disk);\r
\r
- LOG("Wait for Motor Spinup");\r
+ LOG("Wait for the motor to spin up");\r
\r
// Wait for spinup\r
while(gFDD_Devices[Disk].motorState == 1) Threads_Yield();\r
\r
- LOG("C:%i,H:%i,S:%i", cyl, head, sec);\r
+ LOG("Cyl=%i, Head=%i, Sector=%i", cyl, head, sec);\r
LOG("Acquire Spinlock");\r
\r
FDD_AquireSpinlock();\r
\r
// Seek to track\r
- outb(base+CALIBRATE_DRIVE, 0);\r
+ outb(base + CALIBRATE_DRIVE, 0);\r
i = 0;\r
- while(FDD_int_SeekTrack(Disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT ) Threads_Yield();\r
+ while(FDD_int_SeekTrack(Disk, head, (Uint8)cyl) == 0 && i++ < FDD_SEEK_TIMEOUT )\r
+ Threads_Yield();\r
+ if( i > FDD_SEEK_TIMEOUT ) {\r
+ LEAVE('i', 0);\r
+ return 0;\r
+ }\r
//FDD_SensInt(base, NULL, NULL); // Wait for IRQ\r
- \r
+ \r
+ // Read Data from DMA\r
LOG("Setting DMA for read");\r
- \r
- //Read Data from DMA\r
- DMA_SetChannel(2, 512, 1); // Read 512 Bytes\r
+ DMA_SetChannel(2, 512, 1); // Read 512 Bytes from channel 2\r
\r
LOG("Sending read command");\r
\r
FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base);\r
FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base); FDD_int_GetByte(base);\r
\r
- LOG("Realeasing Spinlock and Setting motor to stop");\r
// Release Spinlock\r
+ LOG("Realeasing Spinlock and setting motor to stop");\r
FDD_FreeSpinlock();\r
\r
- //Set timer to turn off motor affter a gap\r
- gFDD_Devices[Disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)Disk); //One Shot Timer
+ // Don't turn the motor off now, wait for a while\r
+ gFDD_Devices[Disk].timer = Time_CreateTimer(MOTOR_OFF_DELAY, FDD_int_StopMotor, (void*)Disk);
\r
- #if USE_CACHE\r
- {\r
- FDD_AquireCacheSpinlock();\r
- int oldest = 0;\r
- for(i=0;i<siFDD_SectorCacheSize;i++)\r
- {\r
- if(sFDD_SectorCache[i].timestamp == 0) {\r
- oldest = i;\r
- break;\r
- }\r
- if(sFDD_SectorCache[i].timestamp < sFDD_SectorCache[oldest].timestamp)\r
- oldest = i;\r
- }\r
- sFDD_SectorCache[oldest].timestamp = now();\r
- sFDD_SectorCache[oldest].disk = Disk;\r
- sFDD_SectorCache[oldest].sector = lba;\r
- memcpy(sFDD_SectorCache[oldest].data, Buffer, 512);\r
- FDD_FreeCacheSpinlock();\r
- }\r
- #else\r
IOCache_Add( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer );\r
- #endif\r
LEAVE('i', 1);\r
return 1;\r
*/\r
void FDD_IRQHandler(int Num)\r
{\r
- fdd_irq6 = 1;\r
+ gbFDD_IrqFired = 1;\r
}\r
\r
/**\r
void FDD_WaitIRQ()\r
{\r
// Wait for IRQ\r
- while(!fdd_irq6) Threads_Yield();\r
- fdd_irq6 = 0;\r
+ while(!gbFDD_IrqFired) Threads_Yield();\r
+ gbFDD_IrqFired = 0;\r
}\r
\r
void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl)\r
else FDD_int_GetByte(base);\r
}\r
\r
-void FDD_AquireSpinlock()\r
+inline void FDD_AquireSpinlock()\r
{\r
- while(fdd_inUse)\r
- Threads_Yield();\r
- fdd_inUse = 1;\r
+ LOCK(&glFDD);\r
}\r
\r
inline void FDD_FreeSpinlock()\r
{\r
- fdd_inUse = 0;\r
+ RELEASE(&glFDD)\r
}\r
\r
-#if USE_CACHE\r
-inline void FDD_AquireCacheSpinlock()\r
-{\r
- while(siFDD_CacheInUse) Threads_Yield();\r
- siFDD_CacheInUse = 1;\r
-}\r
-inline void FDD_FreeCacheSpinlock()\r
-{\r
- siFDD_CacheInUse = 0;\r
-}\r
-#endif\r
-\r
/**\r
* void FDD_int_SendByte(int base, char byte)\r
* \brief Sends a command to the controller\r