From a47783ed9c06f7c2c0c3bdbcf2ed449736427f70 Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Tue, 5 Oct 2021 21:59:36 +0200 Subject: [PATCH] fix ATA disk and controller detection --- core/io.h | 7 + drivers/ata.c | 505 +++++++++++++++++++++++++++++++++++++++++++++----- drivers/ata.h | 60 +++--- 3 files changed, 507 insertions(+), 65 deletions(-) diff --git a/core/io.h b/core/io.h index 5db61c7..2f766f2 100644 --- a/core/io.h +++ b/core/io.h @@ -18,3 +18,10 @@ static inline uint8_t inb(uint16_t port) asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port)); return ret; } + +static inline uint16_t inw(uint16_t port) +{ + uint16_t ret; + asm volatile("inw %w1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} diff --git a/drivers/ata.c b/drivers/ata.c index a2e7e01..9d2264e 100644 --- a/drivers/ata.c +++ b/drivers/ata.c @@ -2,70 +2,487 @@ #include "io.h" #include "kernel.h" #include "klibc.h" +#include "kthread.h" -static struct ata_drive drives[4]; +// from +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data +struct _IDENTIFY_DEVICE_DATA { + struct { + uint16_t Reserved1 : 1; + uint16_t Retired3 : 1; + uint16_t ResponseIncomplete : 1; + uint16_t Retired2 : 3; + uint16_t FixedDevice : 1; + uint16_t RemovableMedia : 1; + uint16_t Retired1 : 7; + uint16_t DeviceType : 1; + } GeneralConfiguration; + uint16_t NumCylinders; + uint16_t SpecificConfiguration; + uint16_t NumHeads; + uint16_t Retired1[2]; + uint16_t NumSectorsPerTrack; + uint16_t VendorUnique1[3]; + uint8_t SerialNumber[20]; + uint16_t Retired2[2]; + uint16_t Obsolete1; + uint8_t FirmwareRevision[8]; + uint8_t ModelNumber[40]; + uint8_t MaximumBlockTransfer; + uint8_t VendorUnique2; + struct { + uint16_t FeatureSupported : 1; + uint16_t Reserved : 15; + } TrustedComputing; + struct { + uint8_t CurrentLongPhysicalSectorAlignment : 2; + uint8_t ReservedByte49 : 6; + uint8_t DmaSupported : 1; + uint8_t LbaSupported : 1; + uint8_t IordyDisable : 1; + uint8_t IordySupported : 1; + uint8_t Reserved1 : 1; + uint8_t StandybyTimerSupport : 1; + uint8_t Reserved2 : 2; + uint16_t ReservedWord50; + } Capabilities; + uint16_t ObsoleteWords51[2]; + uint16_t TranslationFieldsValid : 3; + uint16_t Reserved3 : 5; + uint16_t FreeFallControlSensitivity : 8; + uint16_t NumberOfCurrentCylinders; + uint16_t NumberOfCurrentHeads; + uint16_t CurrentSectorsPerTrack; + uint32_t CurrentSectorCapacity; + uint8_t CurrentMultiSectorSetting; + uint8_t MultiSectorSettingValid : 1; + uint8_t ReservedByte59 : 3; + uint8_t SanitizeFeatureSupported : 1; + uint8_t CryptoScrambleExtCommandSupported : 1; + uint8_t OverwriteExtCommandSupported : 1; + uint8_t BlockEraseExtCommandSupported : 1; + uint32_t UserAddressableSectors; + uint16_t ObsoleteWord62; + uint16_t MultiWordDMASupport : 8; + uint16_t MultiWordDMAActive : 8; + uint16_t AdvancedPIOModes : 8; + uint16_t ReservedByte64 : 8; + uint16_t MinimumMWXferCycleTime; + uint16_t RecommendedMWXferCycleTime; + uint16_t MinimumPIOCycleTime; + uint16_t MinimumPIOCycleTimeIORDY; + struct { + uint16_t ZonedCapabilities : 2; + uint16_t NonVolatileWriteCache : 1; + uint16_t ExtendedUserAddressableSectorsSupported : 1; + uint16_t DeviceEncryptsAllUserData : 1; + uint16_t ReadZeroAfterTrimSupported : 1; + uint16_t Optional28BitCommandsSupported : 1; + uint16_t IEEE1667 : 1; + uint16_t DownloadMicrocodeDmaSupported : 1; + uint16_t SetMaxSetPasswordUnlockDmaSupported : 1; + uint16_t WriteBufferDmaSupported : 1; + uint16_t ReadBufferDmaSupported : 1; + uint16_t DeviceConfigIdentifySetDmaSupported : 1; + uint16_t LPSAERCSupported : 1; + uint16_t DeterministicReadAfterTrimSupported : 1; + uint16_t CFastSpecSupported : 1; + } AdditionalSupported; + uint16_t ReservedWords70[5]; + uint16_t QueueDepth : 5; + uint16_t ReservedWord75 : 11; + struct { + uint16_t Reserved0 : 1; + uint16_t SataGen1 : 1; + uint16_t SataGen2 : 1; + uint16_t SataGen3 : 1; + uint16_t Reserved1 : 4; + uint16_t NCQ : 1; + uint16_t HIPM : 1; + uint16_t PhyEvents : 1; + uint16_t NcqUnload : 1; + uint16_t NcqPriority : 1; + uint16_t HostAutoPS : 1; + uint16_t DeviceAutoPS : 1; + uint16_t ReadLogDMA : 1; + uint16_t Reserved2 : 1; + uint16_t CurrentSpeed : 3; + uint16_t NcqStreaming : 1; + uint16_t NcqQueueMgmt : 1; + uint16_t NcqReceiveSend : 1; + uint16_t DEVSLPtoReducedPwrState : 1; + uint16_t Reserved3 : 8; + } SerialAtaCapabilities; + struct { + uint16_t Reserved0 : 1; + uint16_t NonZeroOffsets : 1; + uint16_t DmaSetupAutoActivate : 1; + uint16_t DIPM : 1; + uint16_t InOrderData : 1; + uint16_t HardwareFeatureControl : 1; + uint16_t SoftwareSettingsPreservation : 1; + uint16_t NCQAutosense : 1; + uint16_t DEVSLP : 1; + uint16_t HybridInformation : 1; + uint16_t Reserved1 : 6; + } SerialAtaFeaturesSupported; + struct { + uint16_t Reserved0 : 1; + uint16_t NonZeroOffsets : 1; + uint16_t DmaSetupAutoActivate : 1; + uint16_t DIPM : 1; + uint16_t InOrderData : 1; + uint16_t HardwareFeatureControl : 1; + uint16_t SoftwareSettingsPreservation : 1; + uint16_t DeviceAutoPS : 1; + uint16_t DEVSLP : 1; + uint16_t HybridInformation : 1; + uint16_t Reserved1 : 6; + } SerialAtaFeaturesEnabled; + uint16_t MajorRevision; + uint16_t MinorRevision; + struct { + uint16_t SmartCommands : 1; + uint16_t SecurityMode : 1; + uint16_t RemovableMediaFeature : 1; + uint16_t PowerManagement : 1; + uint16_t Reserved1 : 1; + uint16_t WriteCache : 1; + uint16_t LookAhead : 1; + uint16_t ReleaseInterrupt : 1; + uint16_t ServiceInterrupt : 1; + uint16_t DeviceReset : 1; + uint16_t HostProtectedArea : 1; + uint16_t Obsolete1 : 1; + uint16_t WriteBuffer : 1; + uint16_t ReadBuffer : 1; + uint16_t Nop : 1; + uint16_t Obsolete2 : 1; + uint16_t DownloadMicrocode : 1; + uint16_t DmaQueued : 1; + uint16_t Cfa : 1; + uint16_t AdvancedPm : 1; + uint16_t Msn : 1; + uint16_t PowerUpInStandby : 1; + uint16_t ManualPowerUp : 1; + uint16_t Reserved2 : 1; + uint16_t SetMax : 1; + uint16_t Acoustics : 1; + uint16_t BigLba : 1; + uint16_t DeviceConfigOverlay : 1; + uint16_t FlushCache : 1; + uint16_t FlushCacheExt : 1; + uint16_t WordValid83 : 2; + uint16_t SmartErrorLog : 1; + uint16_t SmartSelfTest : 1; + uint16_t MediaSerialNumber : 1; + uint16_t MediaCardPassThrough : 1; + uint16_t StreamingFeature : 1; + uint16_t GpLogging : 1; + uint16_t WriteFua : 1; + uint16_t WriteQueuedFua : 1; + uint16_t WWN64Bit : 1; + uint16_t URGReadStream : 1; + uint16_t URGWriteStream : 1; + uint16_t ReservedForTechReport : 2; + uint16_t IdleWithUnloadFeature : 1; + uint16_t WordValid : 2; + } CommandSetSupport; + struct { + uint16_t SmartCommands : 1; + uint16_t SecurityMode : 1; + uint16_t RemovableMediaFeature : 1; + uint16_t PowerManagement : 1; + uint16_t Reserved1 : 1; + uint16_t WriteCache : 1; + uint16_t LookAhead : 1; + uint16_t ReleaseInterrupt : 1; + uint16_t ServiceInterrupt : 1; + uint16_t DeviceReset : 1; + uint16_t HostProtectedArea : 1; + uint16_t Obsolete1 : 1; + uint16_t WriteBuffer : 1; + uint16_t ReadBuffer : 1; + uint16_t Nop : 1; + uint16_t Obsolete2 : 1; + uint16_t DownloadMicrocode : 1; + uint16_t DmaQueued : 1; + uint16_t Cfa : 1; + uint16_t AdvancedPm : 1; + uint16_t Msn : 1; + uint16_t PowerUpInStandby : 1; + uint16_t ManualPowerUp : 1; + uint16_t Reserved2 : 1; + uint16_t SetMax : 1; + uint16_t Acoustics : 1; + uint16_t BigLba : 1; + uint16_t DeviceConfigOverlay : 1; + uint16_t FlushCache : 1; + uint16_t FlushCacheExt : 1; + uint16_t Resrved3 : 1; + uint16_t Words119_120Valid : 1; + uint16_t SmartErrorLog : 1; + uint16_t SmartSelfTest : 1; + uint16_t MediaSerialNumber : 1; + uint16_t MediaCardPassThrough : 1; + uint16_t StreamingFeature : 1; + uint16_t GpLogging : 1; + uint16_t WriteFua : 1; + uint16_t WriteQueuedFua : 1; + uint16_t WWN64Bit : 1; + uint16_t URGReadStream : 1; + uint16_t URGWriteStream : 1; + uint16_t ReservedForTechReport : 2; + uint16_t IdleWithUnloadFeature : 1; + uint16_t Reserved4 : 2; + } CommandSetActive; + uint16_t UltraDMASupport : 8; + uint16_t UltraDMAActive : 8; + struct { + uint16_t TimeRequired : 15; + uint16_t ExtendedTimeReported : 1; + } NormalSecurityEraseUnit; + struct { + uint16_t TimeRequired : 15; + uint16_t ExtendedTimeReported : 1; + } EnhancedSecurityEraseUnit; + uint16_t CurrentAPMLevel : 8; + uint16_t ReservedWord91 : 8; + uint16_t MasterPasswordID; + uint16_t HardwareResetResult; + uint16_t CurrentAcousticValue : 8; + uint16_t RecommendedAcousticValue : 8; + uint16_t StreamMinRequestSize; + uint16_t StreamingTransferTimeDMA; + uint16_t StreamingAccessLatencyDMAPIO; + uint32_t StreamingPerfGranularity; + uint32_t Max48BitLBA[2]; + uint16_t StreamingTransferTime; + uint16_t DsmCap; + struct { + uint16_t LogicalSectorsPerPhysicalSector : 4; + uint16_t Reserved0 : 8; + uint16_t LogicalSectorLongerThan256Words : 1; + uint16_t MultipleLogicalSectorsPerPhysicalSector : 1; + uint16_t Reserved1 : 2; + } PhysicalLogicalSectorSize; + uint16_t InterSeekDelay; + uint16_t WorldWideName[4]; + uint16_t ReservedForWorldWideName128[4]; + uint16_t ReservedForTlcTechnicalReport; + uint16_t WordsPerLogicalSector[2]; + struct { + uint16_t ReservedForDrqTechnicalReport : 1; + uint16_t WriteReadVerify : 1; + uint16_t WriteUncorrectableExt : 1; + uint16_t ReadWriteLogDmaExt : 1; + uint16_t DownloadMicrocodeMode3 : 1; + uint16_t FreefallControl : 1; + uint16_t SenseDataReporting : 1; + uint16_t ExtendedPowerConditions : 1; + uint16_t Reserved0 : 6; + uint16_t WordValid : 2; + } CommandSetSupportExt; + struct { + uint16_t ReservedForDrqTechnicalReport : 1; + uint16_t WriteReadVerify : 1; + uint16_t WriteUncorrectableExt : 1; + uint16_t ReadWriteLogDmaExt : 1; + uint16_t DownloadMicrocodeMode3 : 1; + uint16_t FreefallControl : 1; + uint16_t SenseDataReporting : 1; + uint16_t ExtendedPowerConditions : 1; + uint16_t Reserved0 : 6; + uint16_t Reserved1 : 2; + } CommandSetActiveExt; + uint16_t ReservedForExpandedSupportandActive[6]; + uint16_t MsnSupport : 2; + uint16_t ReservedWord127 : 14; + struct { + uint16_t SecuritySupported : 1; + uint16_t SecurityEnabled : 1; + uint16_t SecurityLocked : 1; + uint16_t SecurityFrozen : 1; + uint16_t SecurityCountExpired : 1; + uint16_t EnhancedSecurityEraseSupported : 1; + uint16_t Reserved0 : 2; + uint16_t SecurityLevel : 1; + uint16_t Reserved1 : 7; + } SecurityStatus; + uint16_t ReservedWord129[31]; + struct { + uint16_t MaximumCurrentInMA : 12; + uint16_t CfaPowerMode1Disabled : 1; + uint16_t CfaPowerMode1Required : 1; + uint16_t Reserved0 : 1; + uint16_t Word160Supported : 1; + } CfaPowerMode1; + uint16_t ReservedForCfaWord161[7]; + uint16_t NominalFormFactor : 4; + uint16_t ReservedWord168 : 12; + struct { + uint16_t SupportsTrim : 1; + uint16_t Reserved0 : 15; + } DataSetManagementFeature; + uint16_t AdditionalProductID[4]; + uint16_t ReservedForCfaWord174[2]; + uint16_t CurrentMediaSerialNumber[30]; + struct { + uint16_t Supported : 1; + uint16_t Reserved0 : 1; + uint16_t WriteSameSuported : 1; + uint16_t ErrorRecoveryControlSupported : 1; + uint16_t FeatureControlSuported : 1; + uint16_t DataTablesSuported : 1; + uint16_t Reserved1 : 6; + uint16_t VendorSpecific : 4; + } SCTCommandTransport; + uint16_t ReservedWord207[2]; + struct { + uint16_t AlignmentOfLogicalWithinPhysical : 14; + uint16_t Word209Supported : 1; + uint16_t Reserved0 : 1; + } BlockAlignment; + uint16_t WriteReadVerifySectorCountMode3Only[2]; + uint16_t WriteReadVerifySectorCountMode2Only[2]; + struct { + uint16_t NVCachePowerModeEnabled : 1; + uint16_t Reserved0 : 3; + uint16_t NVCacheFeatureSetEnabled : 1; + uint16_t Reserved1 : 3; + uint16_t NVCachePowerModeVersion : 4; + uint16_t NVCacheFeatureSetVersion : 4; + } NVCacheCapabilities; + uint16_t NVCacheSizeLSW; + uint16_t NVCacheSizeMSW; + uint16_t NominalMediaRotationRate; + uint16_t ReservedWord218; + struct { + uint8_t NVCacheEstimatedTimeToSpinUpInSeconds; + uint8_t Reserved; + } NVCacheOptions; + uint16_t WriteReadVerifySectorCountMode : 8; + uint16_t ReservedWord220 : 8; + uint16_t ReservedWord221; + struct { + uint16_t MajorVersion : 12; + uint16_t TransportType : 4; + } TransportMajorVersion; + uint16_t TransportMinorVersion; + uint16_t ReservedWord224[6]; + uint32_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} __attribute__((packed)); -int ATADectectType(struct ata_drive *drive) +static struct ata_controller controllers[MAX_ATA_CONTROLLER] = {{ + .id = 0, + .base = 0x1F0, + .dev_ctl = 0x3F6, + .present = 0, + }, + { + .id = 1, + .base = 0x170, + .dev_ctl = 0x376, + .present = 0, + }}; +int ATADetectDevice(struct ata_device *dev) { - outb(drive->base + ATA_PIO_DRIVE, 0xA0 | drive->isSlave << 4); - outb(drive->base + ATA_PIO_SEC_COUNT, 0x0); - outb(drive->base + ATA_PIO_LBALO, 0x0); - outb(drive->base + ATA_PIO_LBAMID, 0x0); - outb(drive->base + ATA_PIO_LBAHI, 0x0); - outb(drive->base + ATA_PIO_CMD, ATA_PIO_CMD_IDENTIFY); - unsigned st = inb(drive->base + ATA_PIO_STATUS); - if(st & ATA_PIO_STATUS_DRIVE_BUSY) + struct ata_controller *ctl = dev->ctl; + outb(ctl->base + ATA_PIO_DRIVE, 0xA0 | dev->isSlave << 4); + unsigned st = inb(ctl->base + ATA_PIO_STATUS); + if (st & ATA_PIO_STATUS_DRIVE_BUSY) goto no_disk; - inb(drive->dev_ctl); /* Drop the next 4 read to wait */ - inb(drive->dev_ctl); - inb(drive->dev_ctl); - inb(drive->dev_ctl); - unsigned cl = inb(drive->base + ATA_PIO_LBAMID); /* get the "signature bytes" */ - unsigned ch = inb(drive->base + ATA_PIO_LBAHI); + unsigned cl = inb(ctl->base + ATA_PIO_LBAMID); /* get the "signature bytes" */ + unsigned ch = inb(ctl->base + ATA_PIO_LBAHI); /* differentiate ATA, ATAPI, SATA and SATAPI */ if (cl == 0x14 && ch == 0xEB) { - drive->status = ATA_DEV_PATAPI; - return 0; + return ATA_DEV_PATAPI; } if (cl == 0x69 && ch == 0x96) { - drive->status = ATA_DEV_SATAPI; - return 0; + return ATA_DEV_SATAPI; } if (cl == 0 && ch == 0) { - drive->status = ATA_DEV_PATA; - return 0; + return ATA_DEV_PATA; } if (cl == 0x3c && ch == 0xc3) { - drive->status = ATA_DEV_SATA; - return 0; + return ATA_DEV_SATA; } no_disk: - drive->status = ATA_DEV_UNKNOWN; - return -1; + return ATA_DEV_UNKNOWN; +} + +int ATAGetDeviceInfo(struct ata_device *dev) +{ + int status; + int16_t buffer[256]; + struct ata_controller *ctl = dev->ctl; + struct _IDENTIFY_DEVICE_DATA *deviceInfo; + + outb(ctl->base + ATA_PIO_DRIVE, 0xA0 | dev->isSlave << 4); + outb(ctl->base + ATA_PIO_CMD, ATA_PIO_CMD_IDENTIFY); + + /* Wait for command completion (wait while busy bit is set) */ + for (int timeout = 0; timeout < 30000; timeout++) { + status = inb(ctl->base + ATA_PIO_STATUS); + if (!(status & ATA_PIO_STATUS_DRIVE_BUSY)) + break; + } + + /* DRQ bit indicates that data is ready to be read. If it is not set + after an IDENTIFY command, there is a problem */ + if (!(status & ATA_PIO_STATUS_DRQ)) { + return -1; + } + /* Read data from the controller buffer to a temporary buffer */ + for (int i = 0; i < 256; i++) + buffer[i] = inw(ctl->base + ATA_PIO_DATA); + + deviceInfo = (struct _IDENTIFY_DEVICE_DATA *)buffer; + + dev->heads = deviceInfo->NumHeads; + dev->cyls = deviceInfo->NumCylinders; + dev->sectors = deviceInfo->NumSectorsPerTrack; + printf("Disk Detected[%d][%d]: %d Ko\n", ctl->id, dev->id, + (dev->heads * dev->cyls * dev->sectors * DISK_SECTOR_SIZE) / 1024); + return 0; +} + +int ATADetectController(struct ata_controller *controller) +{ + controller->devices[0].id = 0; + controller->devices[0].isSlave = 0; + controller->devices[0].ctl = controller; + controller->devices[0].type = ATADetectDevice(&controllers->devices[0]); + + if (controller->devices[0].type == ATA_DEV_PATA || + controller->devices[0].type == ATA_DEV_SATA) { + ATAGetDeviceInfo(&controller->devices[0]); + } + + controller->devices[1].id = 1; + controller->devices[1].isSlave = 1; + controller->devices[1].ctl = controller; + controller->devices[1].type = ATADetectDevice(&controllers->devices[1]); + + if (controller->devices[1].type == ATA_DEV_PATA || + controller->devices[1].type == ATA_DEV_SATA) { + ATAGetDeviceInfo(&controller->devices[1]); + } + + return 0; } int ATAInit() { - memset(drives, 0, sizeof(drives)); - drives[0].base = 0x1F0; - drives[0].dev_ctl = 0x3F6; - drives[0].isSlave = 0; - drives[1].base = 0x1F0; - drives[1].dev_ctl = 0x3F6; - drives[1].isSlave = 1; - drives[1].base = 0x170; - drives[1].dev_ctl = 0x376; - drives[1].isSlave = 0; - drives[2].base = 0x170; - drives[2].dev_ctl = 0x376; - drives[2].isSlave = 1; - - for(uint i = 0; i < ARRAY_SIZE(drives); i++){ - if(!ATADectectType(&drives[i])){ - printf("Driver %d detected %d\n", i, drives[i].status); - } + for (uint i = 0; i < MAX_ATA_CONTROLLER; i++) { + ATADetectController(&controllers[i]); } return 0; } diff --git a/drivers/ata.h b/drivers/ata.h index 761b121..2988ad2 100644 --- a/drivers/ata.h +++ b/drivers/ata.h @@ -1,9 +1,9 @@ #pragma once #include "stdarg.h" -#define ATA_PIO_REG_DATA 0 -#define ATA_PIO_REG_ERR 1 -#define ATA_PIO_REG_FEAT 1 +#define ATA_PIO_DATA 0 +#define ATA_PIO_ERR 1 +#define ATA_PIO_FEAT 1 #define ATA_PIO_SEC_COUNT 2 #define ATA_PIO_LBALO 3 #define ATA_PIO_LBAMID 4 @@ -14,6 +14,8 @@ #define ATA_PIO_STATUS 7 #define ATA_PIO_CMD 7 +// cmd details +// https://people.freebsd.org/~imp/asiabsdcon2015/works/d2161r5-ATAATAPI_Command_Set_-_3.pdf #define ATA_PIO_CMD_IDENTIFY 0xEC #define ATA_PIO_ERROR_ADDR_MARK_NOT_FOUND 0 @@ -25,28 +27,44 @@ #define ATA_PIO_ERROR_UNCORRECTABLE_DATA 6 #define ATA_PIO_ERROR_BAD_BLOCK 7 -#define ATA_PIO_STATUS_REG_ERR (1<<0) -#define ATA_PIO_STATUS_IDX (1<<1) -#define ATA_PIO_STATUS_CORP (1<<2) -#define ATA_PIO_STATUS_DRQ (1<<3) -#define ATA_PIO_STATUS_SRV (1<<4) -#define ATA_PIO_STATUS_DRIVE_FAULT (1<<5) -#define ATA_PIO_STATUS_DRIVE_RDY (1<<6) -#define ATA_PIO_STATUS_DRIVE_BUSY (1<<7) +#define ATA_PIO_STATUS_REG_ERR (1 << 0) +#define ATA_PIO_STATUS_IDX (1 << 1) +#define ATA_PIO_STATUS_CORP (1 << 2) +#define ATA_PIO_STATUS_DRQ (1 << 3) +#define ATA_PIO_STATUS_SRV (1 << 4) +#define ATA_PIO_STATUS_DRIVE_FAULT (1 << 5) +#define ATA_PIO_STATUS_DRIVE_RDY (1 << 6) +#define ATA_PIO_STATUS_DRIVE_BUSY (1 << 7) -#define ATA_DEV_PATA 1 -#define ATA_DEV_SATA 2 -#define ATA_DEV_PATAPI 3 -#define ATA_DEV_SATAPI 4 -#define ATA_DEV_UNKNOWN 0 +#define MAX_ATA_CONTROLLER 2 +#define MAX_ATA_DEVICES 2 -struct ata_drive { - int16_t base; - int16_t dev_ctl; - int status; +#define DISK_SECTOR_SIZE 512 + +typedef enum { + ATA_DEV_UNKNOWN, + ATA_DEV_PATA, + ATA_DEV_SATA, + ATA_DEV_PATAPI, + ATA_DEV_SATAPI +} ata_type; + +struct ata_device { + int id; + ata_type type; int isSlave; + struct ata_controller *ctl; + int heads; + int cyls; + int sectors; }; +struct ata_controller { + int id; + int16_t base; + int16_t dev_ctl; + int present; + struct ata_device devices[MAX_ATA_DEVICES]; +}; -int ATADectectType(struct ata_drive* drive); int ATAInit();