From 9c1f32a49cd51a991aff277ebb83574fff9e5de4 Mon Sep 17 00:00:00 2001 From: notsomeidiot123 Date: Sat, 20 Sep 2025 10:27:15 -0400 Subject: [PATCH] IDE IDENTIFY --- src/kernel/system/modules.c | 4 +- src/kmodules/disk_driver.c | 138 ++++++++++++++++++++++++++++++------ 2 files changed, 118 insertions(+), 24 deletions(-) diff --git a/src/kernel/system/modules.c b/src/kernel/system/modules.c index 7499240..a504566 100644 --- a/src/kernel/system/modules.c +++ b/src/kernel/system/modules.c @@ -100,9 +100,9 @@ uint32_t module_api(uint32_t func, ...){ return_value = pm_alloc_64kaligned(); break; 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); - return_value = kmalloc_page_paddr((uint32_t)paddr, size); + return_value = (uint32_t)kmalloc_page_paddr((uint32_t)paddr, size); break; } diff --git a/src/kmodules/disk_driver.c b/src/kmodules/disk_driver.c index 01defad..26a4ad6 100644 --- a/src/kmodules/disk_driver.c +++ b/src/kmodules/disk_driver.c @@ -74,7 +74,8 @@ make fini function to destroy global object, and free any remaining resources. #define ATA_TK0NF(a) a & 0x2 //data address mark not found #define ATA_AMNF(a) a & 0x1; - +#define ATA_MASTER 0xa0 +#define ATA_SLAVE 0xb0 //commands #define ATA_CMD_READ_PIO 0x20 #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_CLASS_IS_IDE(a) a == 0x0101; + typedef struct PRD{ uint32_t address; uint16_t byte_count; uint16_t reserved;//set msb when last; }__attribute__((packed)) PRD_T; - +uint8_t native_ide_present = 0; void fini(); @@ -143,15 +145,25 @@ uint16_t get_bus_from_drive(uint32_t drive){ //return 1 if ready, 0 if not int ata_ready(uint32_t BAR, uint32_t BAR2, uint8_t drive){ - if(drive){ - outb(BAR ATA_DRIVE_HEAD, drive ? 0xB0 : 0xA0); + static uint16_t last_disk = 0; + 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++){ - uint8_t _ = inb(BAR2 ATA_ALT_STATUS); + uint8_t _ = inb(BAR2 ATA_STATUS); } uint8_t status = inb(BAR2 ATA_ALT_STATUS); - if(!ATA_BSY(status) || ATA_DRQ(status)) return 1; - return 0; + return ~(status >> 7); +} +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 uint32_t find_free_drive(){ @@ -162,15 +174,96 @@ uint32_t find_free_drive(){ } } -void ide_init(uint32_t BARS[5]){ - uint32_t index = find_free_drive(); - drives[index].type = TYPE_IDE; - for(int i = 0; i < 5; i++){ - drives[index].BARs[i] = BARS[i]; +//return 255 if err/ does not exist +//return 0 if is ATA drive +//return 1 if is ATAPI +//return 2 if is SATA +//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){ @@ -197,16 +290,17 @@ void init(KOS_MAPI_FP module_api, uint32_t api_version){ uint32_t progif = class >> 8 & 0xff; class >>= 16; 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}; fread(api, current_file, BARs, 0x10, 5); - if(PCI_IDE_NATIVE(progif)){ - BARs[0] = ATA_PRIMARY_BUS; - BARs[1] = ATA_PRIMARY_BUS + 0x206; + if(PCI_IDE_NATIVE(~progif)){ + native_ide_present = 1; + BARs[0] = (ATA_PRIMARY_BUS) << 2 | 1; + BARs[1] = (ATA_PRIMARY_BUS + 0x206) << 2 | 1; } - if(PCI_IDE_SECONDARY_NATIVE(progif)){ - BARs[2] = ATA_SECONDARY_BUS; - BARs[3] = ATA_SECONDARY_BUS + 0x206; + if(PCI_IDE_SECONDARY_NATIVE(~progif)){ + BARs[2] = (ATA_SECONDARY_BUS << 2) | 1; + BARs[3] = (ATA_SECONDARY_BUS + 0x206) << 2 | 1; } ide_init(BARs); }