#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
// === PROTOTYPES ===\r
// --- Filesystem\r
int FDD_Install(char **Arguments);\r
+void FDD_UnloadModule();\r
+// --- VFS Methods\r
char *FDD_ReadDir(tVFS_Node *Node, int pos);\r
tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, char *Name);\r
int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
-// --- 1st Level Disk Access\r
+// --- Functions for IOCache/DrvUtil\r
Uint FDD_ReadSectors(Uint64 SectorAddr, Uint Count, void *Buffer, Uint Disk);\r
// --- Raw Disk Access\r
int FDD_ReadSector(Uint32 disk, Uint64 lba, void *Buffer);\r
int FDD_WriteSector(Uint32 Disk, Uint64 LBA, void *Buffer);\r
// --- Helpers\r
void FDD_IRQHandler(int Num);\r
-void FDD_WaitIRQ();\r
+inline void FDD_WaitIRQ();\r
void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl);\r
-inline void FDD_AquireSpinlock();\r
-inline void FDD_FreeSpinlock();\r
-#if USE_CACHE\r
-inline void FDD_AquireCacheSpinlock();\r
-inline void FDD_FreeCacheSpinlock();\r
-#endif\r
void FDD_int_SendByte(int base, char byte);\r
int FDD_int_GetByte(int base);\r
void FDD_Reset(int id);\r
int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt);\r
\r
// === GLOBALS ===\r
-MODULE_DEFINE(0, FDD_VERSION, FDD, FDD_Install, NULL, NULL);\r
+MODULE_DEFINE(0, FDD_VERSION, FDD, FDD_Install, NULL, "ISADMA", 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
\r
Log("[FDD ] Detected Disk 0: %s and Disk 1: %s", cFDD_TYPES[data>>4], cFDD_TYPES[data&0xF]);\r
\r
+ if( data == 0 ) {\r
+ return MODULE_ERR_NOTNEEDED;\r
+ }\r
+ \r
// Clear FDD IRQ Flag\r
FDD_SensInt(0x3F0, NULL, NULL);\r
// Install IRQ6 Handler\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
\r
- return 1;\r
+ return MODULE_ERR_OK;\r
+}\r
+\r
+/**\r
+ * \brief Prepare the module for removal\r
+ */\r
+void FDD_UnloadModule()\r
+{\r
+ int i;\r
+ //DevFS_DelDevice( &gFDD_DriverInfo );\r
+ LOCK(&glFDD);\r
+ for(i=0;i<4;i++) {\r
+ Time_RemoveTimer(gFDD_Devices[i].timer);\r
+ FDD_int_StopMotor(i);\r
+ }\r
+ RELEASE(&glFDD);\r
+ //IRQ_Clear(6);\r
}\r
\r
/**\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
- LOG("Found %i in cache %i", lba, i);\r
- memcpy(Buffer, sFDD_SectorCache[i].data, 512);\r
- sFDD_SectorCache[i].timestamp = now();\r
- FDD_FreeCacheSpinlock();\r
- LEAVE('i', 1);\r
- return 1;\r
- }\r
- }\r
- LOG("Read %i from Disk", lba);\r
- FDD_FreeCacheSpinlock();\r
- #else\r
if( IOCache_Read( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ) == 1 ) {\r
LEAVE('i', 1);\r
return 1;\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
+ LOG("Cyl=%i, Head=%i, Sector=%i", cyl, head, sec);\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
+ LOCK(&glFDD); // Lock to stop the motor stopping on us\r
+ Time_RemoveTimer(gFDD_Devices[Disk].timer); // Remove Old Timer\r
+ // Start motor if needed\r
+ if(gFDD_Devices[Disk].motorState != 2) FDD_int_StartMotor(Disk);\r
+ RELEASE(&glFDD);\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("Acquire Spinlock");\r
- \r
- FDD_AquireSpinlock();\r
+ LOCK(&glFDD);\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
- FDD_FreeSpinlock();\r
+ LOG("Realeasing Spinlock and setting motor to stop");\r
+ RELEASE(&glFDD);\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
* \fn FDD_WaitIRQ()\r
* \brief Wait for an IRQ6\r
*/\r
-void FDD_WaitIRQ()\r
+inline 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
-{\r
- while(fdd_inUse)\r
- Threads_Yield();\r
- fdd_inUse = 1;\r
-}\r
-\r
-inline void FDD_FreeSpinlock()\r
-{\r
- fdd_inUse = 0;\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
}\r
inb(0x80); //Delay\r
}\r
+ \r
#if WARN\r
- Warning("FDD_int_SendByte - Timeout sending byte 0x%x to base 0x%x\n", byte, base);\r
+ Warning("FDD_int_SendByte - Timeout sending byte 0x%x to base 0x%x\n", byte, base);\r
#endif\r
}\r
\r
void FDD_int_StopMotor(int disk)\r
{\r
Uint8 state;\r
+ if( IS_LOCKED(&glFDD) ) return ;\r
+ ENTER("iDisk", disk);\r
+ \r
state = inb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT );\r
state &= ~( 1 << (4+disk) );\r
outb( cPORTBASE[ disk>>1 ] + PORT_DIGOUTPUT, state );\r
gFDD_Devices[disk].motorState = 0;\r
-}\r
-\r
-/**\r
- * \fn void ModuleUnload()\r
- * \brief Prepare the module for removal\r
- */\r
-void ModuleUnload()\r
-{\r
- int i;\r
- FDD_AquireSpinlock();\r
- for(i=0;i<4;i++) {\r
- Time_RemoveTimer(gFDD_Devices[i].timer);\r
- FDD_int_StopMotor(i);\r
- }\r
- //IRQ_Clear(6);\r
+ LEAVE('-');\r
}\r