#include <tpl_drv_disk.h>
#include "common.h"
-// --- Flags ---
-#define START_BEFORE_CMD 0
-
// === STRUCTURES ===
typedef struct
{
} __attribute__ ((packed)) tIdentify;
// === IMPORTS ===
-extern void ATA_ParseMBR(int Disk);
+extern void ATA_ParseMBR(int Disk, tMBR *MBR);
// === PROTOTYPES ===
int ATA_Install();
int gATA_IRQPri = 14;
int gATA_IRQSec = 15;
int giaATA_ControllerLock[2] = {0}; //!< Spinlocks for each controller
-Uint8 gATA_Buffers[2][4096] __attribute__ ((section(".padata")));
- int gaATA_IRQs[2] = {0};
+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}
LOG("ent = %i", ent);
gATA_BusMasterBase = PCI_GetBAR4( ent );
if( gATA_BusMasterBase == 0 ) {
- Warning("It seems that there is no Bus Master Controller on this machine. Get one");
+ 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;
}
if( !(gATA_BusMasterBase & 1) )
{
if( gATA_BusMasterBase < 0x100000 )
- gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase);
+ gATA_BusMasterBasePtr = (void*)(KERNEL_BASE | (tVAddr)gATA_BusMasterBase);
else
- gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
+ gATA_BusMasterBasePtr = (void*)( MM_MapHWPages( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr);
}
else {
IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri );
IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec );
- gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[0] );
- gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[1] );
+ 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( (Uint)&gATA_PRDTs[0] );
+ addr = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[0] );
LOG("addr = 0x%x", addr);
ATA_int_BusMasterWriteDWord(4, addr);
- addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[1] );
+ addr = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[1] );
LOG("addr = 0x%x", addr);
ATA_int_BusMasterWriteDWord(12, addr);
*/
int ATA_ScanDisk(int Disk)
{
- Uint16 buf[256];
- tIdentify *identify = (void*)buf;
- tMBR *mbr = (void*)buf;
+ union {
+ Uint16 buf[256];
+ tIdentify identify;
+ tMBR mbr;
+ } data;
Uint16 base;
Uint8 val;
int i;
}
// Read Data
- for(i=0;i<256;i++) buf[i] = inw(base);
+ for(i=0;i<256;i++) data.buf[i] = inw(base);
// Populate Disk Structure
- if(identify->Sectors48 != 0)
- gATA_Disks[ Disk ].Sectors = identify->Sectors48;
+ if(data.identify.Sectors48 != 0)
+ gATA_Disks[ Disk ].Sectors = data.identify.Sectors48;
else
- gATA_Disks[ Disk ].Sectors = identify->Sectors28;
+ gATA_Disks[ Disk ].Sectors = data.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));
- else if( gATA_Disks[ Disk ].Sectors / 2048 )
- Log("Disk %i: 0x%llx Sectors (%i MiB)", Disk,
- gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2048);
- else
- Log("Disk %i: 0x%llx Sectors (%i KiB)", Disk,
- gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2);
+ {
+ Uint64 val = gATA_Disks[ Disk ].Sectors / 2;
+ char *units = "KiB";
+ if( val > 4*1024 ) {
+ val /= 1024;
+ units = "MiB";
+ }
+ else if( val > 4*1024 ) {
+ val /= 1024;
+ units = "GiB";
+ }
+ else if( val > 4*1024 ) {
+ val /= 1024;
+ units = "TiB";
+ }
+ Log_Log("ATA", "Disk %i: 0x%llx Sectors (%i %s)", Disk,
+ gATA_Disks[ Disk ].Sectors, val, units);
+ }
// Create Name
gATA_Disks[ Disk ].Name[0] = 'A'+Disk;
node->Write = ATA_WriteFS;
node->IOCtl = ATA_IOCtl;
-
// --- Scan Partitions ---
LOG("Reading MBR");
// Read Boot Sector
- ATA_ReadDMA( Disk, 0, 1, mbr );
+ ATA_ReadDMA( Disk, 0, 1, &data.mbr );
// Check for a GPT table
- if(mbr->Parts[0].SystemID == 0xEE)
+ if(data.mbr.Parts[0].SystemID == 0xEE)
ATA_ParseGPT(Disk);
else // No? Just parse the MBR
- ATA_ParseMBR(Disk);
+ ATA_ParseMBR(Disk, &data.mbr);
+
+ ATA_ReadDMA( Disk, 1, 1, &data );
+ Debug_HexDump("ATA_ScanDisk", &data, 512);
LEAVE('i', 0);
return 1;
Part->Node.Read = ATA_ReadFS;
Part->Node.Write = ATA_WriteFS;
Part->Node.IOCtl = ATA_IOCtl;
+ Log_Notice("ATA", "Note '%s' at 0x%llx, 0x%llx long", Part->Name, Part->Start, Part->Length);
LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node);
LEAVE('-');
}
tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
{
int part;
+ tATA_Disk *disk;
+
// Check first character
if(Name[0] < 'A' || Name[0] > 'A'+MAX_ATA_DISKS)
return NULL;
+ disk = &gATA_Disks[Name[0]-'A'];
// Raw Disk
if(Name[1] == '\0') {
- if( gATA_Disks[Name[0]-'A'].Sectors == 0 )
+ if( disk->Sectors == 0 && disk->Name[0] == '\0')
return NULL;
- return &gATA_Disks[Name[0]-'A'].Node;
+ return &disk->Node;
}
// Partitions
if(Name[2] == '\0') { // <= 9
part = Name[1] - '0';
part --;
- return &gATA_Disks[Name[0]-'A'].Partitions[part].Node;
+ return &disk->Partitions[part].Node;
}
// > 9
if('0' > Name[2] || '9' < Name[2]) return NULL;
part = (Name[1] - '0') * 10;
part += Name[2] - '0';
part --;
- return &gATA_Disks[Name[0]-'A'].Partitions[part].Node;
+ return &disk->Partitions[part].Node;
}
int disk = Node->Inode >> 8;
int part = Node->Inode & 0xFF;
+ ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+
// Raw Disk Access
if(part == 0xFF)
{
- if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE )
+ if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE ) {
+ LEAVE('i', 0);
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 )
+ if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) {
+ LEAVE('i', 0);
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);
+ {
+ int ret = DrvUtil_ReadBlock(Offset, Length, Buffer, ATA_ReadRaw, SECTOR_SIZE, disk);
+ Debug_HexDump("ATA_ReadFS", Buffer, Length);
+ LEAVE('i', ret);
+ return ret;
+ }
}
/**
Uint offset;
Uint done = 0;
- // Pass straight on to ATA_WriteDMA if we can
+ // Pass straight on to ATA_WriteDMA, if we can
if(Count <= MAX_DMA_SECTORS)
{
ret = ATA_WriteDMA(Disk, Address, Count, 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);
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
+ 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)); //Disk,Magic,High addr
+ outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); // Magic, Disk, High addr
}
outb(base+0x02, (Uint8) Count); // Sector Count
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)
// Start transfer
ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start
- #endif
// Wait for transfer to complete
- //ATA_int_BusMasterWriteByte( (cont << 3) + 2, 0x4 );
- while( gaATA_IRQs[cont] == 0 ) {
- //Uint8 val = ATA_int_BusMasterReadByte( (cont << 3) + 2, 0x4 );
+ 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, 0 ); // Write and stop
+ ATA_int_BusMasterWriteByte( cont << 3, 8 ); // Read and stop
+
+ val = inb(base+0x7);
+ LOG("Status byte = 0x%02x", val);
LOG("Transfer Completed & Acknowledged");