IDE IDENTIFY

This commit is contained in:
notsomeidiot123 2025-09-20 10:27:15 -04:00
parent c880843b6c
commit 9c1f32a49c
2 changed files with 118 additions and 24 deletions

View File

@ -100,9 +100,9 @@ uint32_t module_api(uint32_t func, ...){
return_value = pm_alloc_64kaligned(); return_value = pm_alloc_64kaligned();
break; break;
case MODULE_API_KMALLOC_PADDR: case MODULE_API_KMALLOC_PADDR:
paddr = va_arg(vars, uint32_t); paddr = (void *)va_arg(vars, uint32_t);
uint32_t size = va_arg(vars, uint32_t); uint32_t size = va_arg(vars, uint32_t);
return_value = kmalloc_page_paddr((uint32_t)paddr, size); return_value = (uint32_t)kmalloc_page_paddr((uint32_t)paddr, size);
break; break;
} }

View File

@ -74,7 +74,8 @@ make fini function to destroy global object, and free any remaining resources.
#define ATA_TK0NF(a) a & 0x2 #define ATA_TK0NF(a) a & 0x2
//data address mark not found //data address mark not found
#define ATA_AMNF(a) a & 0x1; #define ATA_AMNF(a) a & 0x1;
#define ATA_MASTER 0xa0
#define ATA_SLAVE 0xb0
//commands //commands
#define ATA_CMD_READ_PIO 0x20 #define ATA_CMD_READ_PIO 0x20
#define ATA_CMD_READ_PIO_EXT 0x24 #define ATA_CMD_READ_PIO_EXT 0x24
@ -102,13 +103,14 @@ make fini function to destroy global object, and free any remaining resources.
#define PCI_IDE_SUPPORT_DMA(a) (a & 0x80) #define PCI_IDE_SUPPORT_DMA(a) (a & 0x80)
#define PCI_CLASS_IS_IDE(a) a == 0x0101; #define PCI_CLASS_IS_IDE(a) a == 0x0101;
typedef struct PRD{ typedef struct PRD{
uint32_t address; uint32_t address;
uint16_t byte_count; uint16_t byte_count;
uint16_t reserved;//set msb when last; uint16_t reserved;//set msb when last;
}__attribute__((packed)) PRD_T; }__attribute__((packed)) PRD_T;
uint8_t native_ide_present = 0;
void fini(); void fini();
@ -143,15 +145,25 @@ uint16_t get_bus_from_drive(uint32_t drive){
//return 1 if ready, 0 if not //return 1 if ready, 0 if not
int ata_ready(uint32_t BAR, uint32_t BAR2, uint8_t drive){ int ata_ready(uint32_t BAR, uint32_t BAR2, uint8_t drive){
if(drive){ static uint16_t last_disk = 0;
outb(BAR ATA_DRIVE_HEAD, drive ? 0xB0 : 0xA0); static uint16_t last_bar = 0;
if(last_disk != drive && last_bar != BAR){
last_disk = drive;
last_bar == BAR;
outb(BAR ATA_DRIVE_HEAD, drive);
} }
for(uint32_t i = 0; i < 15; i++){ for(uint32_t i = 0; i < 15; i++){
uint8_t _ = inb(BAR2 ATA_ALT_STATUS); uint8_t _ = inb(BAR2 ATA_STATUS);
} }
uint8_t status = inb(BAR2 ATA_ALT_STATUS); uint8_t status = inb(BAR2 ATA_ALT_STATUS);
if(!ATA_BSY(status) || ATA_DRQ(status)) return 1; return ~(status >> 7);
return 0; }
void ata_reset(uint16_t bar1){
outw(bar1 ATA_DEVICE_CONTROL, 0x4);
for(uint32_t i = 0; i < 4096; i++){
asm volatile("" ::: "memory");
}
outw(bar1 ATA_DEVICE_CONTROL, 0x0);
} }
//return index of first free drive descriptor //return index of first free drive descriptor
uint32_t find_free_drive(){ uint32_t find_free_drive(){
@ -162,15 +174,96 @@ uint32_t find_free_drive(){
} }
} }
void ide_init(uint32_t BARS[5]){ //return 255 if err/ does not exist
uint32_t index = find_free_drive(); //return 0 if is ATA drive
drives[index].type = TYPE_IDE; //return 1 if is ATAPI
for(int i = 0; i < 5; i++){ //return 2 if is SATA
drives[index].BARs[i] = BARS[i]; //return 3 if is SATAPI
uint8_t ata_identify(uint32_t index, uint16_t disk){
uint16_t bar0 = drives[index].BARs[0] >> 2;
uint16_t bar1 = drives[index].BARs[1] >> 2;
while(!ata_ready(bar0, bar1, disk)){
asm volatile ("" ::: "memory");
}
outb(bar0 ATA_DRIVE_HEAD, disk);
outw(bar0 ATA_SECTOR_COUNT, 0);
outw(bar0 ATA_LBA_HIH, 0);
outw(bar0 ATA_LBA_MID, 0);
outw(bar0 ATA_LBA_LOW, 0);
outw(bar0 ATA_COMMAND, ATA_CMD_IDENTIFY);
uint16_t identify[256] = {0};
uint8_t status = inb(bar0 ATA_STATUS);
if(!status){
return -1;
}
while(ATA_BSY(status)){
asm volatile ("":::"memory"); //prevent gcc from optimizing out this loop
if(inw(bar0 ATA_LBA_MID)){
return -1;//we don't support ATAPI and SATAPI yet
}
status = inw(bar0 ATA_STATUS);
if(ATA_ERR(status)){
return -1;
}
}
for(uint16_t i = 0; i < 256; i++){
identify[i] = inw(bar0 ATA_DATA);
}
// drives[index].size_sectors
uint32_t lba48 = (identify[83] & (1 << 10));
drives[index].flags.huge = lba48 ? 1 : 0;
drives[index].size_sectors = lba48 ? (identify[60] | (identify[61] << 16)) : ((uint64_t)(identify[100]) | (uint64_t)(identify[101] << 16) | ((uint64_t)identify[102] << 32));
api(MODULE_API_PRINT, MODULE_NAME, "Sector Count: %x\n", drives[index].size_sectors);
return 1;
}
void ide_init(uint32_t BARS[5]){
uint32_t primary_index = find_free_drive();
drives[primary_index].type = TYPE_IDE;
uint32_t secondary_index = find_free_drive();
drives[secondary_index].type = TYPE_IDE;
for(int i = 0; i < 2; i++){
drives[primary_index].BARs[i] = BARS[i];
drives[secondary_index].BARs[i] = BARS[i+2];
}
drives[primary_index].BARs[4] = BARS[4];
drives[secondary_index].BARs[4] = BARS[4];
uint32_t prdt_primary_paddr = api(MODULE_API_PMALLOC64K);
uint32_t prdt_secondary_paddr = api(MODULE_API_PMALLOC64K);
drives[primary_index].PRDT = (void *)api(MODULE_API_KMALLOC_PADDR, prdt_primary_paddr, 16);
drives[secondary_index].PRDT = (void *)api(MODULE_API_KMALLOC_PADDR, prdt_secondary_paddr, 16);
//now call ATA IDENTIFY
uint8_t master_status = ata_identify(primary_index, ATA_MASTER);
drive_t master_copy = drives[primary_index];
if(ata_identify(primary_index, ATA_SLAVE) == 0){
if(master_status == -1){
drives[primary_index].flags.slave = 1;
}
else{
uint32_t slave_index = find_free_drive();
drives[slave_index] = drives[primary_index];
drives[slave_index].flags.slave = 1;
drives[primary_index] = master_copy;
drives[slave_index].type = TYPE_IDE;
}
}
master_status = ata_identify(secondary_index, ATA_MASTER);
master_copy = drives[secondary_index];
if(ata_identify(secondary_index, ATA_SLAVE) == 0){
if(master_status == -1){
drives[secondary_index].flags.slave = 1;
}
else{
uint32_t slave_index = find_free_drive();
drives[slave_index] = drives[secondary_index];
drives[slave_index].flags.slave = 1;
drives[secondary_index] = master_copy;
drives[slave_index].type = TYPE_IDE;
}
} }
uint32_t paddr = api(MODULE_API_PMALLOC64K);
drives[index].PRDT = api(MODULE_API_KMALLOC_PADDR, paddr, 16);
api(MODULE_API_PRINT, MODULE_NAME, "Vaddr: %x, Paddr: %x", drives[index].PRDT, paddr);
} }
void init(KOS_MAPI_FP module_api, uint32_t api_version){ void init(KOS_MAPI_FP module_api, uint32_t api_version){
@ -197,16 +290,17 @@ void init(KOS_MAPI_FP module_api, uint32_t api_version){
uint32_t progif = class >> 8 & 0xff; uint32_t progif = class >> 8 & 0xff;
class >>= 16; class >>= 16;
api(MODULE_API_PRINT, MODULE_NAME, "Class: %x, %x\n", class, progif); api(MODULE_API_PRINT, MODULE_NAME, "Class: %x, %x\n", class, progif);
if(class == 0x101 && PCI_IDE_SUPPORT_DMA(progif)){ //in this house, we only support DMA. if(class == 0x101 && PCI_IDE_SUPPORT_DMA(progif) && !native_ide_present){ //in this house, we only support DMA.
uint32_t BARs[5] = {0}; uint32_t BARs[5] = {0};
fread(api, current_file, BARs, 0x10, 5); fread(api, current_file, BARs, 0x10, 5);
if(PCI_IDE_NATIVE(progif)){ if(PCI_IDE_NATIVE(~progif)){
BARs[0] = ATA_PRIMARY_BUS; native_ide_present = 1;
BARs[1] = ATA_PRIMARY_BUS + 0x206; BARs[0] = (ATA_PRIMARY_BUS) << 2 | 1;
BARs[1] = (ATA_PRIMARY_BUS + 0x206) << 2 | 1;
} }
if(PCI_IDE_SECONDARY_NATIVE(progif)){ if(PCI_IDE_SECONDARY_NATIVE(~progif)){
BARs[2] = ATA_SECONDARY_BUS; BARs[2] = (ATA_SECONDARY_BUS << 2) | 1;
BARs[3] = ATA_SECONDARY_BUS + 0x206; BARs[3] = (ATA_SECONDARY_BUS + 0x206) << 2 | 1;
} }
ide_init(BARs); ide_init(BARs);
} }