#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
+#define FDD_MAX_READWRITE_ATTEMPTS 16\r
\r
// === TYPEDEFS ===\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
static const char *cFDD_TYPES[] = {"None", "360kB 5.25\"", "1.2MB 5.25\"", "720kB 3.5\"", "1.44MB 3.5\"", "2.88MB 3.5\"" };\r
static const int cFDD_SIZES[] = { 0, 360*1024, 1200*1024, 720*1024, 1440*1024, 2880*1024 };\r
static const short cPORTBASE[] = { 0x3F0, 0x370 };\r
+#if DEBUG\r
+static const char *cFDD_STATUSES[] = {NULL, "Error", "Invalid command", "Drive not ready"};\r
+#endif\r
\r
enum FloppyPorts {\r
PORT_STATUSA = 0x0,\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
gFDD_Devices[0].track[0] = -1;\r
gFDD_Devices[1].track[1] = -1;\r
\r
- Log("[FDD ] Detected Disk 0: %s and Disk 1: %s", cFDD_TYPES[data>>4], cFDD_TYPES[data&0xF]);\r
+ Log_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
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
return ret;\r
}\r
\r
-/**\r
- * \fn int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
- * \fn Read a sector from disk\r
-*/\r
-int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
+int FDD_int_ReadWriteSector(Uint32 Disk, Uint64 SectorAddr, int Write, void *Buffer)\r
{\r
int cyl, head, sec;\r
int spt, base;\r
int i;\r
int lba = SectorAddr;\r
+ Uint8 st0, st1, st2, rcy, rhe, rse, bps; // Status Values\r
\r
- ENTER("idisk Xlba pbuf", disk, lba, buf);\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
+ ENTER("iDisk XSectorAddr pBuffer", Disk, SectorAddr, Buffer);\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
+ RELEASE(&glFDD);\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
+ DMA_SetChannel(2, 512, !Write); // Read 512 Bytes from channel 2\r
\r
- //Read Data from DMA\r
- DMA_SetChannel(2, 512, 1); // Read 512 Bytes\r
- \r
- LOG("Sending read command");\r
+ LOG("Sending command");\r
\r
//Threads_Wait(100); // Wait for Head to settle\r
Time_Delay(100);\r
- FDD_int_SendByte(base, READ_SECTOR); // Was 0xE6\r
- FDD_int_SendByte(base, (head << 2) | (Disk&1));\r
- FDD_int_SendByte(base, (Uint8)cyl);\r
- FDD_int_SendByte(base, (Uint8)head);\r
- FDD_int_SendByte(base, (Uint8)sec);\r
- FDD_int_SendByte(base, 0x02); // Bytes Per Sector (Real BPS=128*2^{val})\r
- FDD_int_SendByte(base, spt); // SPT\r
- FDD_int_SendByte(base, 0x1B); // Gap Length (27 is default)\r
- FDD_int_SendByte(base, 0xFF); // Data Length\r
\r
- // Wait for IRQ\r
- LOG("Waiting for Data to be read");\r
- FDD_WaitIRQ();\r
+ for( i = 0; i < FDD_MAX_READWRITE_ATTEMPTS; i ++ )\r
+ {\r
+ if( Write )\r
+ FDD_int_SendByte(base, READ_SECTOR); // Was 0xE6\r
+ else\r
+ FDD_int_SendByte(base, READ_SECTOR); // Was 0xE6\r
+ FDD_int_SendByte(base, (head << 2) | (Disk&1));\r
+ FDD_int_SendByte(base, (Uint8)cyl);\r
+ FDD_int_SendByte(base, (Uint8)head);\r
+ FDD_int_SendByte(base, (Uint8)sec);\r
+ FDD_int_SendByte(base, 0x02); // Bytes Per Sector (Real BPS=128*2^{val})\r
+ FDD_int_SendByte(base, spt); // SPT\r
+ FDD_int_SendByte(base, 0x1B); // Gap Length (27 is default)\r
+ FDD_int_SendByte(base, 0xFF); // Data Length\r
+ \r
+ // Wait for IRQ\r
+ if( Write ) {\r
+ LOG("Writing Data");\r
+ DMA_WriteData(2, 512, Buffer);\r
+ LOG("Waiting for Data to be written");\r
+ FDD_WaitIRQ();\r
+ }\r
+ else {\r
+ LOG("Waiting for data to be read");\r
+ FDD_WaitIRQ();\r
+ LOG("Reading Data");\r
+ DMA_ReadData(2, 512, Buffer);\r
+ }\r
+ \r
+ // Clear Input Buffer\r
+ LOG("Clearing Input Buffer");\r
+ // Status Values\r
+ st0 = FDD_int_GetByte(base);\r
+ st1 = FDD_int_GetByte(base);\r
+ st2 = FDD_int_GetByte(base);\r
+ \r
+ // Cylinder, Head and Sector (mutilated in some way\r
+ rcy = FDD_int_GetByte(base);\r
+ rhe = FDD_int_GetByte(base);\r
+ rse = FDD_int_GetByte(base);\r
+ // Should be the BPS set above (0x02)\r
+ bps = FDD_int_GetByte(base);\r
+ \r
+ // Check Status\r
+ // - Error Code\r
+ if(st0 & 0xC0) {\r
+ LOG("Error (st0 & 0xC0) \"%s\"", cFDD_STATUSES[st0 >> 6]);\r
+ continue;\r
+ }\r
+ // - Status Flags\r
+ if(st0 & 0x08) { LOG("Drive not ready"); continue; }\r
+ if(st1 & 0x80) { LOG("End of Cylinder"); continue; }\r
+ if(st1 & 0x20) { LOG("CRC Error"); continue; }\r
+ if(st1 & 0x10) { LOG("Controller Timeout"); continue; }\r
+ if(st1 & 0x04) { LOG("No Data Found"); continue; }\r
+ if(st1 & 0x01 || st2 & 0x01) {\r
+ LOG("No Address mark found");\r
+ continue;\r
+ }\r
+ if(st2 & 0x40) { LOG("Deleted address mark"); continue; }\r
+ if(st2 & 0x20) { LOG("CRC error in data"); continue; }\r
+ if(st2 & 0x10) { LOG("Wrong Cylinder"); continue; }\r
+ if(st2 & 0x04) { LOG("uPD765 sector not found"); continue; }\r
+ if(st2 & 0x02) { LOG("Bad Cylinder"); continue; }\r
+ \r
+ if(bps != 0x2) {\r
+ LOG("Returned BPS = 0x%02x, not 0x02", bps);\r
+ continue;\r
+ }\r
+ \r
+ if(st1 & 0x02) {\r
+ LOG("Floppy not writable");\r
+ i = FDD_MAX_READWRITE_ATTEMPTS+1;\r
+ break;\r
+ }\r
+ \r
+ // Success!\r
+ break;\r
+ }\r
\r
- // Read Data from DMA\r
- LOG(" FDD_ReadSector: Reading Data");\r
- DMA_ReadData(2, 512, Buffer);\r
+ // Release Spinlock\r
+ LOG("Realeasing Spinlock and setting motor to stop");\r
+ RELEASE(&glFDD);\r
+ \r
+ if(i == FDD_MAX_READWRITE_ATTEMPTS) {\r
+ Log_Warning("FDD", "Exceeded %i attempts in %s the disk",\r
+ FDD_MAX_READWRITE_ATTEMPTS,\r
+ (Write ? "writing to" : "reading from")\r
+ );\r
+ }\r
\r
- // Clear Input Buffer\r
- LOG("Clearing Input Buffer");\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
+ // 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
+\r
+ if( i < FDD_MAX_READWRITE_ATTEMPTS ) {\r
+ LEAVE('i', 0);\r
+ return 0;\r
+ }\r
+ else {\r
+ LEAVE('i', 1);\r
+ return 1;\r
+ }\r
+}\r
+\r
+/**\r
+ * \fn int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
+ * \brief Read a sector from disk\r
+ * \todo Make real-hardware safe (account for read errors)\r
+*/\r
+int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)\r
+{\r
+ int ret;\r
\r
- LOG("Realeasing Spinlock and Setting motor to stop");\r
- // Release Spinlock\r
- FDD_FreeSpinlock();\r
+ ENTER("iDisk XSectorAddr pBuffer", Disk, SectorAddr, Buffer);\r
+ \r
+ if( IOCache_Read( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer ) == 1 ) {\r
+ LEAVE('i', 1);\r
+ return 1;\r
+ }\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
+ // Pass to general function\r
+ ret = FDD_int_ReadWriteSector(Disk, SectorAddr, 0, Buffer);
\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
+ if( ret == 0 ) {\r
+ IOCache_Add( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer );
+ LEAVE('i', 1);\r
+ return 1;\r
+ }\r
+ else {\r
+ LOG("Reading failed");\r
+ LEAVE('i', 0);\r
+ return 0;\r
}\r
- #else\r
- IOCache_Add( gFDD_Devices[Disk].CacheHandle, SectorAddr, Buffer );\r
- #endif\r
-
- LEAVE('i', 1);\r
- return 1;\r
}\r
\r
/**\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