Multiple fixes
[tpg/acess2.git] / Modules / Storage / FDD / fdd.c
index 58fb824..793e76c 100644 (file)
@@ -17,8 +17,6 @@
 #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
@@ -27,7 +25,8 @@
 /**\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
@@ -82,25 +81,21 @@ enum FloppyCommands {
 // === 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
@@ -112,10 +107,10 @@ void      FDD_int_StartMotor(int disk);
  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
@@ -128,11 +123,6 @@ tDevFS_Driver      gFDD_DriverInfo = {
        .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
@@ -153,6 +143,10 @@ int FDD_Install(char **Arguments)
        \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
@@ -169,7 +163,7 @@ int FDD_Install(char **Arguments)
        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
@@ -179,50 +173,57 @@ int FDD_Install(char **Arguments)
        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
@@ -295,9 +296,7 @@ int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data)
 */\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
@@ -311,78 +310,12 @@ Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                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
@@ -418,68 +351,52 @@ int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)
         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
@@ -508,35 +425,14 @@ int FDD_ReadSector(Uint32 Disk, Uint64 SectorAddr, void *Buffer)
        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
@@ -648,18 +544,18 @@ int FDD_int_GetDims(int type, int lba, int *c, int *h, int *s, int *spt)
  */\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
@@ -671,30 +567,6 @@ void FDD_SensInt(int base, Uint8 *sr0, Uint8 *cyl)
        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
@@ -713,8 +585,9 @@ void FDD_int_SendByte(int base, char byte)
         }\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
@@ -828,23 +701,12 @@ void FDD_int_StartMotor(int disk)
 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

UCC git Repository :: git.ucc.asn.au