From 87f2bb07687054bcc230e38fe4bc9f8198cc3668 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 31 Jul 2010 19:49:24 +0800 Subject: [PATCH] Broke out the ATA IO functions (Read/WriteDMA into their own file to improve code neatness) --- Modules/Storage/ATA/Makefile | 2 +- Modules/Storage/ATA/common.h | 10 +- Modules/Storage/ATA/io.c | 447 +++++++++++++++++++++++++++++++++++ Modules/Storage/ATA/main.c | 445 ++-------------------------------- 4 files changed, 478 insertions(+), 426 deletions(-) create mode 100644 Modules/Storage/ATA/io.c diff --git a/Modules/Storage/ATA/Makefile b/Modules/Storage/ATA/Makefile index 05e66af6..22923422 100644 --- a/Modules/Storage/ATA/Makefile +++ b/Modules/Storage/ATA/Makefile @@ -1,7 +1,7 @@ # # -OBJ = main.o mbr.o +OBJ = main.o io.o mbr.o NAME = ATA -include ../Makefile.tpl diff --git a/Modules/Storage/ATA/common.h b/Modules/Storage/ATA/common.h index 18e62a8d..33be007e 100644 --- a/Modules/Storage/ATA/common.h +++ b/Modules/Storage/ATA/common.h @@ -70,8 +70,16 @@ typedef struct extern tATA_Disk gATA_Disks[]; // === FUNCTIONS === +// --- Common --- extern void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length); + +// --- MBR Parsing --- +extern void ATA_ParseMBR(int Disk, tMBR *MBR); + +// --- IO Functions --- +extern int ATA_SetupIO(void); +extern Uint64 ATA_GetDiskSize(int Disk); extern int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); -extern int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); +extern int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer); #endif diff --git a/Modules/Storage/ATA/io.c b/Modules/Storage/ATA/io.c new file mode 100644 index 00000000..41933770 --- /dev/null +++ b/Modules/Storage/ATA/io.c @@ -0,0 +1,447 @@ +/* + * Acess2 IDE Harddisk Driver + * - io.c + * + * Disk Input/Output control + */ +#define DEBUG 1 +#include +#include // Needed for error codes +#include +#include "common.h" + +// === MACROS === +#define IO_DELAY() do{inb(0x80); inb(0x80); inb(0x80); inb(0x80);}while(0) + +// === TYPES === +/** + * \brief PRDT Entry + */ +typedef struct +{ + Uint32 PBufAddr; // Physical Buffer Address + Uint16 Bytes; // Size of transfer entry + Uint16 Flags; // Flags +} __attribute__ ((packed)) tPRDT_Ent; + +/** + * \brief Structure returned by the ATA IDENTIFY command + */ +typedef struct +{ + Uint16 Flags; // 1 + Uint16 Usused1[9]; // 10 + char SerialNum[20]; // 20 + Uint16 Usused2[3]; // 23 + char FirmwareVer[8]; // 27 + char ModelNumber[40]; // 47 + Uint16 SectPerInt; // 48 - Low byte only + Uint16 Unused3; // 49 + Uint16 Capabilities[2]; // 51 + Uint16 Unused4[2]; // 53 + Uint16 ValidExtData; // 54 + Uint16 Unused5[5]; // 59 + Uint16 SizeOfRWMultiple; // 60 + Uint32 Sectors28; // 62 + Uint16 Unused6[100-62]; + Uint64 Sectors48; + Uint16 Unused7[256-104]; +} __attribute__ ((packed)) tIdentify; + +// === PROTOTYPES === + int ATA_SetupIO(void); +Uint64 ATA_GetDiskSize(int Disk); +Uint16 ATA_GetBasePort(int Disk); +// Read/Write DMA + int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer); + int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer); +// IRQs +void ATA_IRQHandlerPri(int UNUSED(IRQ)); +void ATA_IRQHandlerSec(int UNUSED(IRQ)); +// 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 === +Uint32 gATA_BusMasterBase = 0; +Uint8 *gATA_BusMasterBasePtr = 0; + int gATA_IRQPri = 14; + int gATA_IRQSec = 15; + int giaATA_ControllerLock[2] = {0}; //!< Spinlocks for each controller +Uint8 gATA_Buffers[2][(MAX_DMA_SECTORS+0xFFF)&~0xFFF] __attribute__ ((section(".padata"))); +volatile int gaATA_IRQs[2] = {0}; +tPRDT_Ent gATA_PRDTs[2] = { + {0, 512, IDE_PRDT_LAST}, + {0, 512, IDE_PRDT_LAST} +}; + +// === CODE === +/** + * \brief Sets up the ATA controller's DMA mode + */ +int ATA_SetupIO(void) +{ + int ent; + tPAddr addr; + + ENTER(""); + + // Get IDE Controller's PCI Entry + ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1); + LOG("ent = %i", ent); + gATA_BusMasterBase = PCI_GetBAR4( ent ); + if( gATA_BusMasterBase == 0 ) { + Log_Warning("ATA", "It seems that there is no Bus Master Controller on this machine. Get one"); + // TODO: Use PIO mode instead + LEAVE('i', MODULE_ERR_NOTNEEDED); + return MODULE_ERR_NOTNEEDED; + } + + // Map memory + if( !(gATA_BusMasterBase & 1) ) + { + if( gATA_BusMasterBase < 0x100000 ) + gATA_BusMasterBasePtr = (void*)(KERNEL_BASE | (tVAddr)gATA_BusMasterBase); + else + gATA_BusMasterBasePtr = (void*)( MM_MapHWPages( 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); + } + + // Register IRQs and get Buffers + IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri ); + IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec ); + + gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[0] ); + gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[1] ); + + LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr); + + addr = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[0] ); + LOG("addr = 0x%x", addr); + ATA_int_BusMasterWriteDWord(4, addr); + addr = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[1] ); + LOG("addr = 0x%x", addr); + ATA_int_BusMasterWriteDWord(12, addr); + + // Enable controllers + outb(IDE_PRI_BASE+1, 1); + outb(IDE_SEC_BASE+1, 1); + + // return + LEAVE('i', MODULE_ERR_OK); + return MODULE_ERR_OK; +} + +Uint64 ATA_GetDiskSize(int Disk) +{ + union { + Uint16 buf[256]; + tIdentify identify; + } data; + Uint16 base; + Uint8 val; + int i; + ENTER("iDisk", Disk); + + base = ATA_GetBasePort( Disk ); + + // Send Disk Selector + if(Disk == 1 || Disk == 3) + outb(base+6, 0xB0); + else + outb(base+6, 0xA0); + IO_DELAY(); + + // Check for a floating bus + if( 0xFF == inb(base+7) ) { + LOG("Floating bus"); + LEAVE('i', 0); + return 0; + } + + // Check for the controller + outb(base+0x02, 0x66); + outb(base+0x03, 0xFF); + if(inb(base+0x02) != 0x66 || inb(base+0x03) != 0xFF) { + LOG("No controller"); + LEAVE('i', 0); + return 0; + } + + // Send IDENTIFY + outb(base+7, 0xEC); + IO_DELAY(); + val = inb(base+7); // Read status + LOG("val = 0x%02x", val); + 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); + + // Check for an error + if(val & 1) { + LEAVE('i', 0); + return 0; // Error occured, so return false + } + + // Read Data + for( i = 0; i < 256; i++ ) + data.buf[i] = inw(base); + + // Return the disk size + if(data.identify.Sectors48 != 0) + return data.identify.Sectors48; + else + return data.identify.Sectors28; +} + +/** + * \fn Uint16 ATA_GetPortBase(int Disk) + * \brief Returns the base port for a given disk + */ +Uint16 ATA_GetBasePort(int Disk) +{ + switch(Disk) + { + case 0: case 1: return IDE_PRI_BASE; + case 2: case 3: return IDE_SEC_BASE; + } + return 0; +} + +/** + * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) + */ +int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer) +{ + int cont = (Disk>>1)&1; // Controller ID + int disk = Disk & 1; + Uint16 base; + Uint8 val; + + ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer); + + // Check if the count is small enough + 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 ] ); + + // Set Size + gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE; + + // Get Port Base + base = ATA_GetBasePort(Disk); + + // Reset IRQ Flag + gaATA_IRQs[cont] = 0; + + // Set up transfer + 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+0x4, Address >> 28); // Mid 2 Addr + outb(base+0x5, Address >> 32); // High 2 Addr + } + else + { + outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); // Magic, Disk, High addr + } + + outb(base+0x01, 0x01); //? + 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 + + LOG("Starting Transfer"); + LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes); + if( Address > 0x0FFFFFFF ) + outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48) + else + outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28) + + // Start transfer + ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start + + // Wait for transfer to complete + while( gaATA_IRQs[cont] == 0 ) Threads_Yield(); + + // Complete Transfer + ATA_int_BusMasterWriteByte( cont << 3, 8 ); // Read and stop + + val = inb(base+0x7); + LOG("Status byte = 0x%02x", val); + + LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes); + 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) + * \brief Write up to \a MAX_DMA_SECTORS to a disk + * \param Disk Disk ID to write to + * \param Address LBA of first sector + * \param Count Number of sectors to write (must be >= \a MAX_DMA_SECTORS) + * \param Buffer Source buffer for data + */ +int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const 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; +} + +/** + * \brief Primary ATA Channel IRQ handler + */ +void ATA_IRQHandlerPri(int UNUSED(IRQ)) +{ + Uint8 val; + + // IRQ bit set for Primary Controller + val = ATA_int_BusMasterReadByte( 0x2 ); + LOG("IRQ val = 0x%x", val); + if(val & 4) { + LOG("IRQ hit (val = 0x%x)", val); + ATA_int_BusMasterWriteByte( 0x2, 4 ); + gaATA_IRQs[0] = 1; + return ; + } +} + +/** + * \brief Second ATA Channel IRQ handler + */ +void ATA_IRQHandlerSec(int UNUSED(IRQ)) +{ + Uint8 val; + // IRQ bit set for Secondary Controller + val = ATA_int_BusMasterReadByte( 0xA ); + LOG("IRQ val = 0x%x", val); + if(val & 4) { + LOG("IRQ hit (val = 0x%x)", val); + ATA_int_BusMasterWriteByte( 0xA, 4 ); + gaATA_IRQs[1] = 1; + return ; + } +} + +/** + * \brief Read an 8-bit value from a Bus Master register + * \param Ofs Register offset + */ +Uint8 ATA_int_BusMasterReadByte(int Ofs) +{ + if( gATA_BusMasterBase & 1 ) + return inb( (gATA_BusMasterBase & ~1) + Ofs ); + else + return *(Uint8*)(gATA_BusMasterBasePtr + Ofs); +} + +/** + * \brief Writes a byte to a Bus Master Register + * \param Ofs Register Offset + * \param Value Value to write + */ +void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value) +{ + if( gATA_BusMasterBase & 1 ) + outb( (gATA_BusMasterBase & ~1) + Ofs, Value ); + else + *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value; +} + +/** + * \brief Writes a 32-bit value to a Bus Master Register + * \param Ofs Register offset + * \param Value Value to write + */ +void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value) +{ + if( gATA_BusMasterBase & 1 ) + outd( (gATA_BusMasterBase & ~1) + Ofs, Value ); + else + *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value; +} diff --git a/Modules/Storage/ATA/main.c b/Modules/Storage/ATA/main.c index 69d21215..9760b4dc 100644 --- a/Modules/Storage/ATA/main.c +++ b/Modules/Storage/ATA/main.c @@ -8,49 +8,17 @@ #include #include #include -#include #include #include #include "common.h" +// === MACROS === #define IO_DELAY() do{inb(0x80); inb(0x80); inb(0x80); inb(0x80);}while(0) -// === STRUCTURES === -typedef struct -{ - Uint32 PBufAddr; - Uint16 Bytes; - Uint16 Flags; -} __attribute__ ((packed)) tPRDT_Ent; -typedef struct -{ - Uint16 Flags; // 1 - Uint16 Usused1[9]; // 10 - char SerialNum[20]; // 20 - Uint16 Usused2[3]; // 23 - char FirmwareVer[8]; // 27 - char ModelNumber[40]; // 47 - Uint16 SectPerInt; // 48 - AND with 0xFF to get true value; - Uint16 Unused3; // 49 - Uint16 Capabilities[2]; // 51 - Uint16 Unused4[2]; // 53 - Uint16 ValidExtData; // 54 - Uint16 Unused5[5]; // 59 - Uint16 SizeOfRWMultiple; // 60 - Uint32 Sectors28; // 62 - Uint16 Unused6[100-62]; - Uint64 Sectors48; - Uint16 Unused7[256-104]; -} __attribute__ ((packed)) tIdentify; - -// === IMPORTS === -extern void ATA_ParseMBR(int Disk, tMBR *MBR); - // === PROTOTYPES === - int ATA_Install(); - int ATA_SetupIO(); -void ATA_SetupPartitions(); -void ATA_SetupVFS(); + int ATA_Install(char **Arguments); +void ATA_SetupPartitions(void); +void ATA_SetupVFS(void); int ATA_ScanDisk(int Disk); void ATA_ParseGPT(int Disk); void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length); @@ -64,16 +32,6 @@ Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, 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); - 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, VERSION, i386ATA, ATA_Install, NULL, "PCI", NULL); @@ -91,23 +49,12 @@ tDevFS_Driver gATA_DriverInfo = { tATA_Disk gATA_Disks[MAX_ATA_DISKS]; int giATA_NumNodes; tVFS_Node **gATA_Nodes; -Uint32 gATA_BusMasterBase = 0; -Uint8 *gATA_BusMasterBasePtr = 0; - int gATA_IRQPri = 14; - int gATA_IRQSec = 15; - int giaATA_ControllerLock[2] = {0}; //!< Spinlocks for each controller -Uint8 gATA_Buffers[2][(MAX_DMA_SECTORS+0xFFF)&~0xFFF] __attribute__ ((section(".padata"))); -volatile int gaATA_IRQs[2] = {0}; -tPRDT_Ent gATA_PRDTs[2] = { - {0, 512, IDE_PRDT_LAST}, - {0, 512, IDE_PRDT_LAST} -}; // === CODE === /** - * \fn int ATA_Install() + * \brief Initialise the ATA driver */ -int ATA_Install() +int ATA_Install(char **Arguments) { int ret; @@ -125,70 +72,9 @@ int ATA_Install() } /** - * \fn int ATA_SetupIO() - * \brief Sets up the ATA controller's DMA mode - */ -int ATA_SetupIO() -{ - int ent; - tPAddr addr; - - ENTER(""); - - // Get IDE Controller's PCI Entry - ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1); - LOG("ent = %i", ent); - gATA_BusMasterBase = PCI_GetBAR4( ent ); - if( gATA_BusMasterBase == 0 ) { - Log_Warning("ATA", "It seems that there is no Bus Master Controller on this machine. Get one"); - // TODO: Use PIO mode instead - LEAVE('i', MODULE_ERR_NOTNEEDED); - return MODULE_ERR_NOTNEEDED; - } - - // Map memory - if( !(gATA_BusMasterBase & 1) ) - { - if( gATA_BusMasterBase < 0x100000 ) - gATA_BusMasterBasePtr = (void*)(KERNEL_BASE | (tVAddr)gATA_BusMasterBase); - else - gATA_BusMasterBasePtr = (void*)( MM_MapHWPages( 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); - } - - // Register IRQs and get Buffers - IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri ); - IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec ); - - gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[0] ); - gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[1] ); - - LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr); - - addr = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[0] ); - LOG("addr = 0x%x", addr); - ATA_int_BusMasterWriteDWord(4, addr); - addr = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[1] ); - LOG("addr = 0x%x", addr); - ATA_int_BusMasterWriteDWord(12, addr); - - // Enable controllers - outb(IDE_PRI_BASE+1, 1); - outb(IDE_SEC_BASE+1, 1); - - // return - LEAVE('i', MODULE_ERR_OK); - return MODULE_ERR_OK; -} - -/** - * \fn void ATA_SetupPartitions() + * \brief Scan all disks, looking for partitions */ -void ATA_SetupPartitions() +void ATA_SetupPartitions(void) { int i; for( i = 0; i < MAX_ATA_DISKS; i ++ ) @@ -201,10 +87,9 @@ void ATA_SetupPartitions() } /** - * \fn void ATA_SetupVFS() * \brief Sets up the ATA drivers VFS information and registers with DevFS */ -void ATA_SetupVFS() +void ATA_SetupVFS(void) { int i, j, k; @@ -234,77 +119,24 @@ void ATA_SetupVFS() } /** - * \fn int ATA_ScanDisk(int Disk) + * \brief Scan a disk, getting the size and any paritions + * \param Disk Disk ID to scan */ int ATA_ScanDisk(int Disk) { - union { - Uint16 buf[256]; - tIdentify identify; - tMBR mbr; - } data; - Uint16 base; - Uint8 val; - int i; tVFS_Node *node; + tMBR mbr; ENTER("iDisk", Disk); - - base = ATA_GetBasePort( Disk ); - - LOG("base = 0x%x", base); - - // Send Disk Selector - if(Disk == 1 || Disk == 3) - outb(base+6, 0xB0); - else - outb(base+6, 0xA0); - IO_DELAY(); - // Check for a floating bus - if( 0xFF == inb(base+7) ) { - LOG("Floating bus"); - LEAVE('i', 0); - return 0; - } - - // Check for the controller - outb(base+0x02, 0x66); - outb(base+0x03, 0xFF); - if(inb(base+0x02) != 0x66 || inb(base+0x03) != 0xFF) { - LOG("No controller"); + // Get the disk size + gATA_Disks[ Disk ].Sectors = ATA_GetDiskSize(Disk); + if(gATA_Disks[ Disk ].Sectors == 0) + { LEAVE('i', 0); return 0; } - // Send IDENTIFY - outb(base+7, 0xEC); - IO_DELAY(); - val = inb(base+7); // Read status - LOG("val = 0x%02x", val); - 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) { - LEAVE('i', 0); - return 0; // Error occured, so return false - } - - // Read Data - for(i=0;i<256;i++) data.buf[i] = inw(base); - - // Populate Disk Structure - if(data.identify.Sectors48 != 0) - gATA_Disks[ Disk ].Sectors = data.identify.Sectors48; - else - gATA_Disks[ Disk ].Sectors = data.identify.Sectors28; - - LOG("gATA_Disks[ %i ].Sectors = 0x%x", Disk, gATA_Disks[ Disk ].Sectors); { @@ -347,17 +179,17 @@ int ATA_ScanDisk(int Disk) // --- Scan Partitions --- LOG("Reading MBR"); // Read Boot Sector - ATA_ReadDMA( Disk, 0, 1, &data.mbr ); + ATA_ReadDMA( Disk, 0, 1, &mbr ); // Check for a GPT table - if(data.mbr.Parts[0].SystemID == 0xEE) + if(mbr.Parts[0].SystemID == 0xEE) ATA_ParseGPT(Disk); else // No? Just parse the MBR - ATA_ParseMBR(Disk, &data.mbr); + ATA_ParseMBR(Disk, &mbr); #if DEBUG >= 2 - ATA_ReadDMA( Disk, 1, 1, &data ); - Debug_HexDump("ATA_ScanDisk", &data, 512); + ATA_ReadDMA( Disk, 1, 1, &mbr ); + Debug_HexDump("ATA_ScanDisk", &mbr, 512); #endif LEAVE('i', 0); @@ -404,20 +236,6 @@ void ATA_ParseGPT(int Disk) Warning("GPT Disks are currently unsupported (Disk %i)", Disk); } -/** - * \fn Uint16 ATA_GetPortBase(int Disk) - * \brief Returns the base port for a given disk - */ -Uint16 ATA_GetBasePort(int Disk) -{ - switch(Disk) - { - case 0: case 1: return IDE_PRI_BASE; - case 2: case 3: return IDE_SEC_BASE; - } - return 0; -} - /** * \fn char *ATA_ReadDir(tVFS_Node *Node, int Pos) */ @@ -626,224 +444,3 @@ Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk) 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) -{ - int cont = (Disk>>1)&1; // Controller ID - int disk = Disk & 1; - Uint16 base; - Uint8 val; - - ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer); - - // Check if the count is small enough - 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 ] ); - - // Set Size - gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE; - - // Get Port Base - base = ATA_GetBasePort(Disk); - - // Reset IRQ Flag - gaATA_IRQs[cont] = 0; - - // Set up transfer - 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+0x4, Address >> 28); // Mid 2 Addr - outb(base+0x5, Address >> 32); // High 2 Addr - } - else - { - outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); // Magic, Disk, High addr - } - - outb(base+0x01, 0x01); //? - 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 - - LOG("Starting Transfer"); - LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes); - if( Address > 0x0FFFFFFF ) - outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48) - else - outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28) - - // Start transfer - ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start - - // Wait for transfer to complete - while( gaATA_IRQs[cont] == 0 ) Threads_Yield(); - - // Complete Transfer - ATA_int_BusMasterWriteByte( cont << 3, 8 ); // Read and stop - - val = inb(base+0x7); - LOG("Status byte = 0x%02x", val); - - LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes); - 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(int unused) - */ -void ATA_IRQHandlerPri(int UNUSED(IRQ)) -{ - Uint8 val; - - // IRQ bit set for Primary Controller - val = ATA_int_BusMasterReadByte( 0x2 ); - LOG("IRQ val = 0x%x", val); - if(val & 4) { - LOG("IRQ hit (val = 0x%x)", val); - ATA_int_BusMasterWriteByte( 0x2, 4 ); - gaATA_IRQs[0] = 1; - return ; - } -} - -/** - * \fn void ATA_IRQHandlerSec(int unused) - */ -void ATA_IRQHandlerSec(int UNUSED(IRQ)) -{ - Uint8 val; - // IRQ bit set for Secondary Controller - val = ATA_int_BusMasterReadByte( 0xA ); - LOG("IRQ val = 0x%x", val); - if(val & 4) { - LOG("IRQ hit (val = 0x%x)", val); - ATA_int_BusMasterWriteByte( 0xA, 4 ); - gaATA_IRQs[1] = 1; - return ; - } -} - -/** - * \fn Uint8 ATA_int_BusMasterReadByte(int Ofs) - */ -Uint8 ATA_int_BusMasterReadByte(int Ofs) -{ - if( gATA_BusMasterBase & 1 ) - return inb( (gATA_BusMasterBase & ~1) + Ofs ); - else - return *(Uint8*)(gATA_BusMasterBasePtr + Ofs); -} - -/** - * \fn void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value) - * \brief Writes a byte to a Bus Master Register - */ -void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value) -{ - if( gATA_BusMasterBase & 1 ) - outb( (gATA_BusMasterBase & ~1) + Ofs, Value ); - else - *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value; -} - -/** - * \fn void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value) - * \brief Writes a dword to a Bus Master Register - */ -void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value) -{ - - if( gATA_BusMasterBase & 1 ) - outd( (gATA_BusMasterBase & ~1) + Ofs, Value ); - else - *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value; -} -- 2.20.1