Updated the build files to use $(xCP), allows use of mcopy to a mtools disk
[tpg/acess2.git] / Kernel / drv / ata_x86.c
index a4c5306..8d9e2e8 100644 (file)
@@ -2,12 +2,17 @@
  * Acess2 IDE Harddisk Driver
  * drv/ide.c
  */
+#define DEBUG  1
 #include <common.h>
 #include <modules.h>
 #include <vfs.h>
 #include <fs_devfs.h>
 #include <drv_pci.h>
 #include <tpl_drv_common.h>
+#include <tpl_drv_disk.h>
+
+// --- Flags ---
+#define START_BEFORE_CMD       0
 
 // === CONSTANTS ===
 #define        MAX_ATA_DISKS   4
@@ -90,31 +95,40 @@ typedef struct {
 // === PROTOTYPES ===
  int   ATA_Install();
  int   ATA_SetupIO();
-static void    ATA_SetupPartitions();
- void  ATA_SetupVFS();
+void   ATA_SetupPartitions();
+void   ATA_SetupVFS();
  int   ATA_ScanDisk(int Disk);
 void   ATA_ParseGPT(int Disk);
 void   ATA_ParseMBR(int Disk);
 void   ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length);
 Uint16 ATA_GetBasePort(int Disk);
+// Filesystem Interface
 char   *ATA_ReadDir(tVFS_Node *Node, int Pos);
 tVFS_Node      *ATA_FindDir(tVFS_Node *Node, char *Name);
 Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
  int   ATA_IOCtl(tVFS_Node *Node, int Id, void *Data);
- int   ATA_Read(Uint8 Disk, Uint64 Address, Uint64 Count, void *Buffer);
+// Read/Write Interface/Quantiser
+Uint   ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
+Uint   ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
+// Read/Write DMA
  int   ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
-void   ATA_IRQHandlerPri(void);
-void   ATA_IRQHandlerSec(void);
+ int   ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
+// IRQs
+void   ATA_IRQHandlerPri(int unused);
+void   ATA_IRQHandlerSec(int unused);
+// Controller IO
 Uint8  ATA_int_BusMasterReadByte(int Ofs);
 void   ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value);
 void   ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value);
 
 // === GLOBALS ===
-MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL);
+MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL, NULL);
 tDevFS_Driver  gATA_DriverInfo = {
        NULL, "ata",
        {
                .NumACLs = 1,
+               .Size = -1,
                .Flags = VFS_FFLAG_DIRECTORY,
                .ACLs = &gVFS_ACL_EveryoneRX,
                .ReadDir = ATA_ReadDir,
@@ -164,15 +178,14 @@ int ATA_Install()
 int ATA_SetupIO()
 {
         int    ent;
-       Uint    addr;
+       tPAddr  addr;
        
        ENTER("");
        
        // Get IDE Controller's PCI Entry
        ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1);
-       LOG("ent = %i\n", ent);
+       LOG("ent = %i", ent);
        gATA_BusMasterBase = PCI_GetBAR4( ent );
-       LOG("gATA_BusMasterBase = 0x%x\n", gATA_BusMasterBase);
        if( gATA_BusMasterBase == 0 ) {
                Warning("It seems that there is no Bus Master Controller on this machine, get one");
                LEAVE('i', 0);
@@ -184,6 +197,11 @@ int ATA_SetupIO()
                        gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase);
                else
                        gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
+               LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr);
+       }
+       else {
+               // Bit 0 is left set as a flag to other functions
+               LOG("gATA_BusMasterBase = 0x%x", gATA_BusMasterBase & ~1);
        }
        
        IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri );
@@ -192,21 +210,26 @@ int ATA_SetupIO()
        gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[0] );
        gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[1] );
        
-       LOG("gATA_PRDTs = {0x%x, 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
+       LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
        
        addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[0] );
+       LOG("addr = 0x%x", addr);
        ATA_int_BusMasterWriteDWord(4, addr);
        addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[1] );
+       LOG("addr = 0x%x", addr);
        ATA_int_BusMasterWriteDWord(12, addr);
        
+       outb(IDE_PRI_BASE+1, 1);
+       outb(IDE_SEC_BASE+1, 1);
+       
        LEAVE('i', 1);
        return 1;
 }
 
 /**
- * \fn static void     ATA_SetupPartitions()
+ * \fn void ATA_SetupPartitions()
  */
-static void    ATA_SetupPartitions()
+void ATA_SetupPartitions()
 {
         int    i;
        for( i = 0; i < MAX_ATA_DISKS; i ++ )
@@ -247,6 +270,8 @@ void ATA_SetupVFS()
                for( j = 0; j < gATA_Disks[i].NumPartitions; j ++ )
                        gATA_Nodes[ k++ ] = &gATA_Disks[i].Partitions[j].Node;
        }
+       
+       gATA_DriverInfo.RootNode.Size = giATA_NumNodes;
 }
 
 /**
@@ -262,8 +287,12 @@ int ATA_ScanDisk(int Disk)
         int    i;
        tVFS_Node       *node;
        
+       ENTER("iDisk", Disk);
+       
        base = ATA_GetBasePort( Disk );
        
+       LOG("base = 0x%x", base);
+       
        // Send Disk Selector
        if(Disk == 1 || Disk == 3)
                outb(base+6, 0xB0);
@@ -273,12 +302,18 @@ int ATA_ScanDisk(int Disk)
        // Send IDENTIFY
        outb(base+7, 0xEC);
        val = inb(base+7);      // Read status
-       if(val == 0)    return 0;       // Disk does not exist
+       if(val == 0) {
+               LEAVE('i', 0);
+               return 0;       // Disk does not exist
+       }
        
        // Poll until BSY clears and DRQ sets or ERR is set
        while( ((val & 0x80) || !(val & 0x08)) && !(val & 1))   val = inb(base+7);
        
-       if(val & 1)     return 0;       // Error occured, so return false
+       if(val & 1) {
+               LEAVE('i', 0);
+               return 0;       // Error occured, so return false
+       }
        
        // Read Data
        for(i=0;i<256;i++)      buf[i] = inw(base);
@@ -290,6 +325,8 @@ int ATA_ScanDisk(int Disk)
                gATA_Disks[ Disk ].Sectors = identify->Sectors28;
        
        
+       LOG("gATA_Disks[ Disk ].Sectors = 0x%x", gATA_Disks[ Disk ].Sectors);
+       
        if( gATA_Disks[ Disk ].Sectors / (2048*1024) )
                Log("Disk %i: 0x%llx Sectors (%i GiB)", Disk,
                        gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / (2048*1024));
@@ -315,11 +352,12 @@ int ATA_ScanDisk(int Disk)
                = node->CTime = now();
        
        node->Read = ATA_ReadFS;
-       //node->Write = ATA_WriteFS;
+       node->Write = ATA_WriteFS;
        node->IOCtl = ATA_IOCtl;
 
 
        // --- Scan Partitions ---
+       LOG("Reading MBR");
        // Read Boot Sector
        ATA_ReadDMA( Disk, 0, 1, mbr );
        
@@ -329,6 +367,7 @@ int ATA_ScanDisk(int Disk)
        else    // No? Just parse the MBR
                ATA_ParseMBR(Disk);
        
+       LEAVE('i', 0);
        return 1;
 }
 
@@ -351,6 +390,8 @@ void ATA_ParseMBR(int Disk)
        tMBR    mbr;
        Uint64  extendedLBA;
        
+       ENTER("iDisk", Disk);
+       
        // Read Boot Sector
        ATA_ReadDMA( Disk, 0, 1, &mbr );
        
@@ -366,6 +407,7 @@ void ATA_ParseMBR(int Disk)
                        )
                {
                        if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) {
+                               LOG("Extended Partition");
                                if(extendedLBA != 0) {
                                        Warning("Disk %i has multiple extended partitions, ignoring rest", Disk);
                                        continue;
@@ -373,6 +415,7 @@ void ATA_ParseMBR(int Disk)
                                extendedLBA = mbr.Parts[i].LBAStart;
                                continue;
                        }
+                       LOG("Primary Partition");
                        
                        gATA_Disks[Disk].NumPartitions ++;
                        continue;
@@ -420,6 +463,7 @@ void ATA_ParseMBR(int Disk)
                        }
                }
        }
+       LOG("gATA_Disks[Disk].NumPartitions = %i", gATA_Disks[Disk].NumPartitions);
        
        // Create patition array
        gATA_Disks[Disk].Partitions = malloc( gATA_Disks[Disk].NumPartitions * sizeof(tATA_Partition) );
@@ -428,6 +472,7 @@ void ATA_ParseMBR(int Disk)
        extendedLBA = 0;
        for( i = 0; i < 4; i ++ )
        {
+               Log("mbr.Parts[%i].SystemID = 0x%02x", i, mbr.Parts[i].SystemID);
                if( mbr.Parts[i].SystemID == 0 )        continue;
                if(     mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) // LBA 28
                {
@@ -554,6 +599,8 @@ void ATA_ParseMBR(int Disk)
                        }
                }
        }
+       
+       LEAVE('-');
 }
 
 /**
@@ -579,6 +626,7 @@ void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start
        Part->Node.ImplPtr = Part->Name;
        
        Part->Node.Read = ATA_ReadFS;
+       Part->Node.Write = ATA_WriteFS;
        Part->Node.IOCtl = ATA_IOCtl;
        LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node);
        LEAVE('-');
@@ -604,7 +652,7 @@ Uint16 ATA_GetBasePort(int Disk)
 char *ATA_ReadDir(tVFS_Node *Node, int Pos)
 {
        if(Pos >= giATA_NumNodes || Pos < 0)    return NULL;
-       return gATA_Nodes[Pos]->ImplPtr;
+       return strdup( gATA_Nodes[Pos]->ImplPtr );
 }
 
 /**
@@ -617,7 +665,11 @@ tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
        if(Name[0] < 'A' || Name[0] > 'A'+MAX_ATA_DISKS)
                return NULL;
        // Raw Disk
-       if(Name[1] == '\0')     return &gATA_Disks[Name[0]-'A'].Node;
+       if(Name[1] == '\0') {
+               if( gATA_Disks[Name[0]-'A'].Sectors == 0 )
+                       return NULL;
+               return &gATA_Disks[Name[0]-'A'].Node;
+       }
        
        // Partitions
        if(Name[1] < '0' || '9' < Name[1])      return NULL;
@@ -642,54 +694,29 @@ tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
  */
 Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
 {
-        int    ret;
-        int    disk, part;
-       Uint64  sector, count;
+        int    disk = Node->Inode >> 8;
+        int    part = Node->Inode & 0xFF;
        
-       disk = Node->Inode >> 8;
-       part = Node->Inode & 0xFF;
-       
-       // Aligned Read
-       if(Offset % SECTOR_SIZE == 0 && Length % SECTOR_SIZE == 0)
+       // Raw Disk Access
+       if(part == 0xFF)
        {
-               sector = Offset / SECTOR_SIZE;
-               count = Length / SECTOR_SIZE;
-               // Raw Disk?
-               if(part == 0xFF)
-               {
-                       // Bounds Check
-                       if( sector >= gATA_Disks[disk].Sectors )        return 0;
-                       if( sector + count > gATA_Disks[disk].Sectors )
-                               count = gATA_Disks[disk].Sectors - sector;
-                       // Read Data
-                       ret = ATA_Read(disk, sector, count, Buffer);
-               }
-               else    // Or a partition
-               {
-                       //Log(" ATA_ReadFS: %i:%i 0x%llx + 0x%llx\n", disk, part,
-                       //      gATA_Disks[disk].Partitions[part].Start,
-                       //      gATA_Disks[disk].Partitions[part].Length );
-                       
-                       // Bounds Check
-                       if( sector >= gATA_Disks[disk].Partitions[part].Length )        return 0;
-                       if( sector + count > gATA_Disks[disk].Partitions[part].Length )
-                               count = gATA_Disks[disk].Partitions[part].Length - sector;
-                       // Read Disk
-                       ret = ATA_Read(disk,
-                               gATA_Disks[disk].Partitions[part].Start + sector,
-                               count,
-                               Buffer);
-               }
-               // Check return value
-               if(ret == 1)
-                       return count * SECTOR_SIZE;
-               else {
-                       Warning("ATA_ReadFS: RETURN 0 (Read failed with ret = %i)", ret);
+               if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE )
                        return 0;
-               }
+               if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE )
+                       Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset;
        }
-       Warning("ATA_ReadFS: RETURN 0 (Non-Aligned Read 0x%llx 0x%llx)", Offset, Length);
-       return 0;
+       // Partition
+       else
+       {
+               if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
+                       return 0;
+               if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
+                       Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset;
+               Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE;
+       }
+       
+       //Log("ATA_ReadFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer);
+       return DrvUtil_ReadBlock(Offset, Length, Buffer, ATA_ReadRaw, SECTOR_SIZE, disk);
 }
 
 /**
@@ -697,7 +724,30 @@ Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
  */
 Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
 {
-       return 0;
+        int    disk = Node->Inode >> 8;
+        int    part = Node->Inode & 0xFF;
+       
+       // Raw Disk Access
+       if(part == 0xFF)
+       {
+               if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE )
+                       return 0;
+               if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE )
+                       Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset;
+       }
+       // Partition
+       else
+       {
+               if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
+                       return 0;
+               if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
+                       Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset;
+               Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE;
+       }
+       
+       Log("ATA_WriteFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer);
+       Debug_HexDump("ATA_WriteFS", Buffer, Length);
+       return DrvUtil_WriteBlock(Offset, Length, Buffer, ATA_ReadRaw, ATA_WriteRaw, SECTOR_SIZE, disk);
 }
 
 /**
@@ -715,16 +765,21 @@ int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data)
 
 // --- Disk Access ---
 /**
- * \fn int ATA_Read(Uint8 Disk, Uint64 Address, Uint64 Count, void *Buffer)
+ * \fn Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
  */
-int ATA_Read(Uint8 Disk, Uint64 Address, Uint64 Count, void *Buffer)
+Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
 {
         int    ret;
        Uint    offset;
+       Uint    done = 0;
         
        // Pass straight on to ATA_ReadDMAPage if we can
        if(Count <= MAX_DMA_SECTORS)
-               return ATA_ReadDMA(Disk, Address, Count, Buffer);
+       {
+               ret = ATA_ReadDMA(Disk, Address, Count, Buffer);
+               if(ret == 0)    return 0;
+               return Count;
+       }
        
        // Else we will have to break up the transfer
        offset = 0;
@@ -732,17 +787,55 @@ int ATA_Read(Uint8 Disk, Uint64 Address, Uint64 Count, void *Buffer)
        {
                ret = ATA_ReadDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
                // Check for errors
-               if(ret != 1)    return ret;
+               if(ret != 1)    return done;
                // Change Position
+               done += MAX_DMA_SECTORS;
                Count -= MAX_DMA_SECTORS;
                offset += MAX_DMA_SECTORS*SECTOR_SIZE;
        }
        
-       return ATA_ReadDMA(Disk, Address+offset, Count, Buffer+offset);
+       ret = ATA_ReadDMA(Disk, Address+offset, Count, Buffer+offset);
+       if(ret != 1)    return 0;
+       return done+Count;
 }
 
 /**
- * \fn int ATA_ReadDMAPage(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
+ * \fn Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
+ */
+Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
+{
+        int    ret;
+       Uint    offset;
+       Uint    done = 0;
+        
+       // Pass straight on to ATA_WriteDMA if we can
+       if(Count <= MAX_DMA_SECTORS)
+       {
+               ret = ATA_WriteDMA(Disk, Address, Count, Buffer);
+               if(ret == 0)    return 0;
+               return Count;
+       }
+       
+       // Else we will have to break up the transfer
+       offset = 0;
+       while(Count > MAX_DMA_SECTORS)
+       {
+               ret = ATA_WriteDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
+               // Check for errors
+               if(ret != 1)    return done;
+               // Change Position
+               done += MAX_DMA_SECTORS;
+               Count -= MAX_DMA_SECTORS;
+               offset += MAX_DMA_SECTORS*SECTOR_SIZE;
+       }
+       
+       ret = ATA_WriteDMA(Disk, Address+offset, Count, Buffer+offset);
+       if(ret != 1)    return 0;
+       return done+Count;
+}
+
+/**
+ * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
  */
 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
 {
@@ -750,8 +843,15 @@ int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
         int    disk = Disk & 1;
        Uint16  base;
        
+       ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer);
+       
        // Check if the count is small enough
-       if(Count > MAX_DMA_SECTORS)     return -1;
+       if(Count > MAX_DMA_SECTORS) {
+               Warning("Passed too many sectors for a bulk DMA read (%i > %i)",
+                       Count, MAX_DMA_SECTORS);
+               LEAVE('i');
+               return 0;
+       }
        
        // Get exclusive access to the disk controller
        LOCK( &giaATA_ControllerLock[ cont ] );
@@ -762,6 +862,9 @@ int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
        // Get Port Base
        base = ATA_GetBasePort(Disk);
        
+       // Reset IRQ Flag
+       gaATA_IRQs[cont] = 0;
+       
        // Set up transfer
        outb(base+0x01, 0x00);
        if( Address > 0x0FFFFFFF )      // Use LBA48
@@ -781,43 +884,125 @@ int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
        outb(base+0x03, (Uint8) Address);               // Low Addr
        outb(base+0x04, (Uint8) (Address >> 8));        // Middle Addr
        outb(base+0x05, (Uint8) (Address >> 16));       // High Addr
+       
+       LOG("Starting Transfer");
+       #if START_BEFORE_CMD
+       // Start transfer
+       ATA_int_BusMasterWriteByte( cont << 3, 9 );     // Read and start
+       if( Address > 0x0FFFFFFF )
+               outb(base+0x07, HDD_DMA_R48);   // Read Command (LBA48)
+       else
+               outb(base+0x07, HDD_DMA_R28);   // Read Command (LBA28)
+       #else
        if( Address > 0x0FFFFFFF )
                outb(base+0x07, HDD_DMA_R48);   // Read Command (LBA48)
        else
                outb(base+0x07, HDD_DMA_R28);   // Read Command (LBA28)
-       
-       // Reset IRQ Flag
-       gaATA_IRQs[cont] = 0;
-       
        // Start transfer
        ATA_int_BusMasterWriteByte( cont << 3, 9 );     // Read and start
+       #endif
        
        // Wait for transfer to complete
-       while( gaATA_IRQs[cont] == 0 )  Proc_Yield();
+       //ATA_int_BusMasterWriteByte( (cont << 3) + 2, 0x4 );
+       while( gaATA_IRQs[cont] == 0 ) {
+               //Uint8 val = ATA_int_BusMasterReadByte( (cont << 3) + 2, 0x4 );
+               //LOG("val = 0x%02x", val);
+               Threads_Yield();
+       }
        
        // Complete Transfer
        ATA_int_BusMasterWriteByte( cont << 3, 0 );     // Write and stop
        
+       LOG("Transfer Completed & Acknowledged");
+       
        // Copy to destination buffer
        memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
        
        // Release controller lock
        RELEASE( &giaATA_ControllerLock[ cont ] );
        
+       LEAVE('i', 1);
+       return 1;
+}
+
+/**
+ * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
+ */
+int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
+{
+        int    cont = (Disk>>1)&1;     // Controller ID
+        int    disk = Disk & 1;
+       Uint16  base;
+       
+       // Check if the count is small enough
+       if(Count > MAX_DMA_SECTORS)     return 0;
+       
+       // Get exclusive access to the disk controller
+       LOCK( &giaATA_ControllerLock[ cont ] );
+       
+       // Set Size
+       gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
+       
+       // Get Port Base
+       base = ATA_GetBasePort(Disk);
+       
+       // Set up transfer
+       outb(base+0x01, 0x00);
+       if( Address > 0x0FFFFFFF )      // Use LBA48
+       {
+               outb(base+0x6, 0x40 | (disk << 4));
+               outb(base+0x2, 0 >> 8); // Upper Sector Count
+               outb(base+0x3, Address >> 24);  // Low 2 Addr
+               outb(base+0x3, Address >> 28);  // Mid 2 Addr
+               outb(base+0x3, Address >> 32);  // High 2 Addr
+       }
+       else
+       {
+               outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr
+       }
+       
+       outb(base+0x02, (Uint8) Count);         // Sector Count
+       outb(base+0x03, (Uint8) Address);               // Low Addr
+       outb(base+0x04, (Uint8) (Address >> 8));        // Middle Addr
+       outb(base+0x05, (Uint8) (Address >> 16));       // High Addr
+       if( Address > 0x0FFFFFFF )
+               outb(base+0x07, HDD_DMA_W48);   // Write Command (LBA48)
+       else
+               outb(base+0x07, HDD_DMA_W28);   // Write Command (LBA28)
+       
+       // Reset IRQ Flag
+       gaATA_IRQs[cont] = 0;
+       
+       // Copy to output buffer
+       memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE );
+       
+       // Start transfer
+       ATA_int_BusMasterWriteByte( cont << 3, 1 );     // Write and start
+       
+       // Wait for transfer to complete
+       while( gaATA_IRQs[cont] == 0 )  Threads_Yield();
+       
+       // Complete Transfer
+       ATA_int_BusMasterWriteByte( cont << 3, 0 );     // Write and stop
+       
+       // Release controller lock
+       RELEASE( &giaATA_ControllerLock[ cont ] );
+       
        return 1;
 }
 
 /**
- * \fn void ATA_IRQHandlerPri(void)
+ * \fn void ATA_IRQHandlerPri(int unused)
  */
-void ATA_IRQHandlerPri(void)
+void ATA_IRQHandlerPri(int unused)
 {
        Uint8   val;
        
        // IRQ bit set for Primary Controller
        val = ATA_int_BusMasterReadByte( 0x2 );
+       LOG("IRQ val = 0x%x", val);
        if(val & 4) {
-               //Log(" ATA_IRQHandlerPri: IRQ hit (val = 0x%x)", val);
+               LOG("IRQ hit (val = 0x%x)", val);
                ATA_int_BusMasterWriteByte( 0x2, 4 );
                gaATA_IRQs[0] = 1;
                return ;
@@ -825,15 +1010,15 @@ void ATA_IRQHandlerPri(void)
 }
 
 /**
- * \fn void ATA_IRQHandlerSec(void)
+ * \fn void ATA_IRQHandlerSec(int unused)
  */
-void ATA_IRQHandlerSec(void)
+void ATA_IRQHandlerSec(int unused)
 {
        Uint8   val;
        // IRQ bit set for Secondary Controller
        val = ATA_int_BusMasterReadByte( 0xA );
        if(val & 4) {
-               //Log(" ATA_IRQHandlerSec: IRQ hit (val = 0x%x)", val);
+               LOG("IRQ hit (val = 0x%x)", val);
                ATA_int_BusMasterWriteByte( 0xA, 4 );
                gaATA_IRQs[1] = 1;
                return ;

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