X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FStorage%2FATA%2Fmain.c;h=11498da96a7321572e1935253e37e51b5290be93;hb=e6795eb552a6be88b7870dae14a958ab391bfae8;hp=5e9eaac0f5ad8988dc8e6365acbe45fbc5f51ec0;hpb=30e30d7bc325852a8677819d11a47373b08d6271;p=tpg%2Facess2.git diff --git a/Modules/Storage/ATA/main.c b/Modules/Storage/ATA/main.c index 5e9eaac0..11498da9 100644 --- a/Modules/Storage/ATA/main.c +++ b/Modules/Storage/ATA/main.c @@ -2,80 +2,39 @@ * Acess2 IDE Harddisk Driver * - main.c */ -#define DEBUG 1 +#define DEBUG 0 +#define VERSION 0x0032 #include #include #include #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); Uint16 ATA_GetBasePort(int Disk); // Filesystem Interface char *ATA_ReadDir(tVFS_Node *Node, int Pos); -tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name); +tVFS_Node *ATA_FindDir(tVFS_Node *Node, const 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); // 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, 0x0032, i386ATA, ATA_Install, NULL, "PCI", NULL); +MODULE_DEFINE(0, VERSION, i386ATA, ATA_Install, NULL, "PCI", NULL); tDevFS_Driver gATA_DriverInfo = { NULL, "ata", { @@ -90,23 +49,12 @@ tDevFS_Driver gATA_DriverInfo = { tATA_Disk gATA_Disks[MAX_ATA_DISKS]; int giATA_NumNodes; tVFS_Node **gATA_Nodes; -Uint16 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; @@ -124,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 ++ ) @@ -200,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; @@ -233,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); { @@ -321,7 +154,7 @@ int ATA_ScanDisk(int Disk) val /= 1024; units = "TiB"; } - Log_Log("ATA", "Disk %i: 0x%llx Sectors (%i %s)", Disk, + Log_Log("ATA", "Disk %i: 0x%llx Sectors (%lli %s)", Disk, gATA_Disks[ Disk ].Sectors, val, units); } @@ -346,18 +179,24 @@ int ATA_ScanDisk(int Disk) // --- Scan Partitions --- LOG("Reading MBR"); // Read Boot Sector - ATA_ReadDMA( Disk, 0, 1, &data.mbr ); + if( ATA_ReadDMA( Disk, 0, 1, &mbr ) != 0 ) { + Log_Warning("ATA", "Error in reading MBR on %i", Disk); + LEAVE('i', 0); + return 0; + } // 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); - ATA_ReadDMA( Disk, 1, 1, &data ); - Debug_HexDump("ATA_ScanDisk", &data, 512); + #if DEBUG >= 2 + ATA_ReadDMA( Disk, 1, 1, &mbr ); + Debug_HexDump("ATA_ScanDisk", &mbr, 512); + #endif - LEAVE('i', 0); + LEAVE('i', 1); return 1; } @@ -398,36 +237,22 @@ void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start void ATA_ParseGPT(int Disk) { ///\todo Support GPT Disks - Warning("GPT Disks are currently unsupported"); -} - -/** - * \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; + Warning("GPT Disks are currently unsupported (Disk %i)", Disk); } /** * \fn char *ATA_ReadDir(tVFS_Node *Node, int Pos) */ -char *ATA_ReadDir(tVFS_Node *Node, int Pos) +char *ATA_ReadDir(tVFS_Node *UNUSED(Node), int Pos) { if(Pos >= giATA_NumNodes || Pos < 0) return NULL; return strdup( gATA_Nodes[Pos]->ImplPtr ); } /** - * \fn tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name) + * \fn tVFS_Node *ATA_FindDir(tVFS_Node *Node, const char *Name) */ -tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name) +tVFS_Node *ATA_FindDir(tVFS_Node *UNUSED(Node), const char *Name) { int part; tATA_Disk *disk; @@ -495,7 +320,8 @@ Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) { int ret = DrvUtil_ReadBlock(Offset, Length, Buffer, ATA_ReadRaw, SECTOR_SIZE, disk); - Debug_HexDump("ATA_ReadFS", Buffer, Length); + //Log("ATA_ReadFS: disk=%i, Offset=%lli, Length=%lli", disk, Offset, Length); + //Debug_HexDump("ATA_ReadFS", Buffer, Length); LEAVE('i', ret); return ret; } @@ -532,15 +358,22 @@ Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) return DrvUtil_WriteBlock(Offset, Length, Buffer, ATA_ReadRaw, ATA_WriteRaw, SECTOR_SIZE, disk); } +const char *csaATA_IOCtls[] = {DRV_IOCTLNAMES, DRV_DISK_IOCTLNAMES, NULL}; /** * \fn int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data) * \brief IO Control Funtion */ -int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data) +int ATA_IOCtl(tVFS_Node *UNUSED(Node), int Id, void *Data) { switch(Id) { - case DRV_IOCTL_TYPE: return DRV_TYPE_DISK; + BASE_IOCTLS(DRV_TYPE_DISK, "i386ATA", VERSION, csaATA_IOCtls); + + case DISK_IOCTL_GETBLOCKSIZE: + return 512; + + default: + return 0; } return 0; } @@ -615,226 +448,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 - 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+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+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"); - 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 - val = 0; - while( gaATA_IRQs[cont] == 0 && !(val & 0x4) ) { - val = ATA_int_BusMasterReadByte( (cont << 3) + 2 ); - //LOG("val = 0x%02x", val); - Threads_Yield(); - } - - // Complete Transfer - ATA_int_BusMasterWriteByte( cont << 3, 8 ); // Read and stop - - val = inb(base+0x7); - LOG("Status byte = 0x%02x", val); - - 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) -{ - 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) -{ - 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; -}