diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index ef60189..d420c60 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -28,9 +28,12 @@ #define CMD_COUNTER2 0x80 void sleep(uint16_t millis) { - uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + int32_t ticksLeft = getCurrentTask()->ticksLeft - millis; getCurrentTask()->ticksLeft = millis; yield(); + if (ticksLeft > 0) { + getCurrentTask()->ticksLeft = ticksLeft; + } } void setTimerFrequency(uint32_t hz) { diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index ef60189..d420c60 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -28,9 +28,12 @@ #define CMD_COUNTER2 0x80 void sleep(uint16_t millis) { - uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + int32_t ticksLeft = getCurrentTask()->ticksLeft - millis; getCurrentTask()->ticksLeft = millis; yield(); + if (ticksLeft > 0) { + getCurrentTask()->ticksLeft = ticksLeft; + } } void setTimerFrequency(uint32_t hz) { diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c new file mode 100644 index 0000000..8f3e441 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +#define LOWER(ptr) (uint32_t)(uintptr_t) ptr +#define UPPER(ptr) (uint32_t)((uint64_t)(uintptr_t)ptr >> 32) + +uint8_t CheckPortType(HBAPort *Port) { + uint32_t SataStatus = Port->SataStatus; + + uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111; + uint8_t DeviceDetection = SataStatus & 0b111; + + if (DeviceDetection != HBA_PORT_DEV_PRESENT) { + return None; + } + if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE) { + return None; + } + + switch (Port->Signature) { + case SATA_SIG_ATAPI: + return SATAPI; + case SATA_SIG_ATA: + return SATA; + case SATA_SIG_PM: + return PM; + case SATA_SIG_SEMB: + return SEMB; + default: + return None; + } +} + +void configurePort(Port *); +bool ahciCommand(HBAPort *HBAPortPtr, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command); +void StartCMD(HBAPort *HBAPortPtr); +void StopCMD(HBAPort *HBAPortPtr); + +AtaIdentifyData ident; + +void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction) { + Port *port = (void *)drive->interface; + printf("start "); + yields(); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + printf("end %x\n", *(uint64_t *)buffer); + yields(); +} + +void preparePorts(HBAMemory *hba, ListElement **drives) { + for (uint8_t i = 0; i < 32; i++) { + if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { + continue; + } + uint8_t portType = CheckPortType(&hba->Ports[i]); + if (!portType) { + continue; + } + if (portType == SATAPI) { + printf("satapi devices not implemented yet!\n"); + yields(); + continue; + } + if (portType != SATA) { + continue; + } + Port *port = malloc(sizeof(Port)); + port->AHCIPortType = portType; + port->HBAPortPtr = &hba->Ports[i]; + configurePort(port); + printf("reconfigured the port\n"); + yields(); + ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->interface = port; + hardDrive->access = accessAHCIDrive; + addIdentifyData(hardDrive, &ident); + listAdd(drives, hardDrive); + } +} + +void configurePort(Port *port) { + HBAPort *HBAPortPtr = port->HBAPortPtr; + StopCMD(HBAPortPtr); + + HBACommandHeader *CommandHeader = mallocAligned(1024, 10); + HBAPortPtr->CommandListBase = LOWER(CommandHeader); + HBAPortPtr->CommandListBaseUpper = UPPER(CommandHeader); + memset(CommandHeader, 0, 1024); + + void *fis = mallocAligned(1024, 10); + HBAPortPtr->FISBaseAddress = LOWER(fis); + HBAPortPtr->FISBaseAddressUpper = UPPER(fis); + memset(fis, 0, 256); + for (int i = 0; i < 32; i++) { + CommandHeader[i].PRDTLength = 8; + void *CommandTable = mallocAligned(sizeof(HBACommandTable), 8); + CommandHeader[i].CommandTableBaseAddress = LOWER(CommandTable); + CommandHeader[i].CommandTableBaseAddressUpper = UPPER(CommandTable); + memset(CommandTable, 0, 256); + } + StartCMD(HBAPortPtr); +} + +void StopCMD(HBAPort *HBAPortPtr) { + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST; + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE; + + while (true) { + if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR) { + continue; + } + if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + continue; + } + break; + } +} + +void StartCMD(HBAPort *HBAPortPtr) { + while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + } + HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE; + HBAPortPtr->CommandStatus |= HBA_PxCMD_ST; +} + +#define HBA_PxIS_TFES (1 << 30) + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + hbaPort->InterruptEnable = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->PRDTLength = 1; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + memset(CommandTable, 0, sizeof(HBACommandTable)); + + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); + CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); + CommandTable->PRDTEntry[0].ByteCount = + SectorCount ? 512 * SectorCount - 1 : 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->command = command; + CommandFIS->LBA0 = (uint8_t)(Sector); + CommandFIS->LBA1 = (uint8_t)(Sector >> 8); + CommandFIS->LBA2 = (uint8_t)(Sector >> 16); + CommandFIS->LBA3 = (uint8_t)(Sector >> 24); + CommandFIS->LBA4 = (uint8_t)(Sector >> 32); + CommandFIS->LBA5 = (uint8_t)(Sector >> 40); + CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->countLow = SectorCount & 0xFF; + CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; + CommandFIS->Control = 0; // 1 << 3; + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return false; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return false; + } + } + printf("count: %i ", commandHeader->PRDBCount); + return true; +} + +#define OsOwnership (1 << 1) +#define BiosOwnership (1 << 0) + +void initializeSataController(PciDevice *pciDevice, ListElement **drives) { + if (pciDevice->programmingInterface != 1) { + return; + } + HBAMemory *hba = (void *)(uintptr_t)(pciDevice->bar5 & 0xFFFFFFF0); + if (!(hba->GlobalHostControl & (1 << 31))) { + printf("controller not in ahci mode!\n"); + return; + } + // hba->GlobalHostControl |= 1 << 31; + if (hba->HostCapabilitiesExtended & 1) { + printf("the os does not own the hba, getting it now...\n"); + yields(); + hba->BIOSHandoffControlStatus |= OsOwnership; + while (hba->BIOSHandoffControlStatus & BiosOwnership || + !(hba->BIOSHandoffControlStatus & OsOwnership)) { + } + } + // hba->GlobalHostControl |= 1; + // while (hba->GlobalHostControl & 1) { + //} + // hba->GlobalHostControl |= 1 << 31; + // sleep(1000); + // enabling bus mastering and memory access + // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, + // pciDevice->function, 4); + // command |= (1 << 1) | (1 << 2); + // pciConfigWriteByte(pciDevice->bus, pciDevice->device, + // pciDevice->function, + // 4, (uint8_t)command); + preparePorts(hba, drives); +} diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index ef60189..d420c60 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -28,9 +28,12 @@ #define CMD_COUNTER2 0x80 void sleep(uint16_t millis) { - uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + int32_t ticksLeft = getCurrentTask()->ticksLeft - millis; getCurrentTask()->ticksLeft = millis; yield(); + if (ticksLeft > 0) { + getCurrentTask()->ticksLeft = ticksLeft; + } } void setTimerFrequency(uint32_t hz) { diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c new file mode 100644 index 0000000..8f3e441 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +#define LOWER(ptr) (uint32_t)(uintptr_t) ptr +#define UPPER(ptr) (uint32_t)((uint64_t)(uintptr_t)ptr >> 32) + +uint8_t CheckPortType(HBAPort *Port) { + uint32_t SataStatus = Port->SataStatus; + + uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111; + uint8_t DeviceDetection = SataStatus & 0b111; + + if (DeviceDetection != HBA_PORT_DEV_PRESENT) { + return None; + } + if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE) { + return None; + } + + switch (Port->Signature) { + case SATA_SIG_ATAPI: + return SATAPI; + case SATA_SIG_ATA: + return SATA; + case SATA_SIG_PM: + return PM; + case SATA_SIG_SEMB: + return SEMB; + default: + return None; + } +} + +void configurePort(Port *); +bool ahciCommand(HBAPort *HBAPortPtr, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command); +void StartCMD(HBAPort *HBAPortPtr); +void StopCMD(HBAPort *HBAPortPtr); + +AtaIdentifyData ident; + +void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction) { + Port *port = (void *)drive->interface; + printf("start "); + yields(); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + printf("end %x\n", *(uint64_t *)buffer); + yields(); +} + +void preparePorts(HBAMemory *hba, ListElement **drives) { + for (uint8_t i = 0; i < 32; i++) { + if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { + continue; + } + uint8_t portType = CheckPortType(&hba->Ports[i]); + if (!portType) { + continue; + } + if (portType == SATAPI) { + printf("satapi devices not implemented yet!\n"); + yields(); + continue; + } + if (portType != SATA) { + continue; + } + Port *port = malloc(sizeof(Port)); + port->AHCIPortType = portType; + port->HBAPortPtr = &hba->Ports[i]; + configurePort(port); + printf("reconfigured the port\n"); + yields(); + ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->interface = port; + hardDrive->access = accessAHCIDrive; + addIdentifyData(hardDrive, &ident); + listAdd(drives, hardDrive); + } +} + +void configurePort(Port *port) { + HBAPort *HBAPortPtr = port->HBAPortPtr; + StopCMD(HBAPortPtr); + + HBACommandHeader *CommandHeader = mallocAligned(1024, 10); + HBAPortPtr->CommandListBase = LOWER(CommandHeader); + HBAPortPtr->CommandListBaseUpper = UPPER(CommandHeader); + memset(CommandHeader, 0, 1024); + + void *fis = mallocAligned(1024, 10); + HBAPortPtr->FISBaseAddress = LOWER(fis); + HBAPortPtr->FISBaseAddressUpper = UPPER(fis); + memset(fis, 0, 256); + for (int i = 0; i < 32; i++) { + CommandHeader[i].PRDTLength = 8; + void *CommandTable = mallocAligned(sizeof(HBACommandTable), 8); + CommandHeader[i].CommandTableBaseAddress = LOWER(CommandTable); + CommandHeader[i].CommandTableBaseAddressUpper = UPPER(CommandTable); + memset(CommandTable, 0, 256); + } + StartCMD(HBAPortPtr); +} + +void StopCMD(HBAPort *HBAPortPtr) { + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST; + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE; + + while (true) { + if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR) { + continue; + } + if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + continue; + } + break; + } +} + +void StartCMD(HBAPort *HBAPortPtr) { + while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + } + HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE; + HBAPortPtr->CommandStatus |= HBA_PxCMD_ST; +} + +#define HBA_PxIS_TFES (1 << 30) + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + hbaPort->InterruptEnable = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->PRDTLength = 1; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + memset(CommandTable, 0, sizeof(HBACommandTable)); + + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); + CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); + CommandTable->PRDTEntry[0].ByteCount = + SectorCount ? 512 * SectorCount - 1 : 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->command = command; + CommandFIS->LBA0 = (uint8_t)(Sector); + CommandFIS->LBA1 = (uint8_t)(Sector >> 8); + CommandFIS->LBA2 = (uint8_t)(Sector >> 16); + CommandFIS->LBA3 = (uint8_t)(Sector >> 24); + CommandFIS->LBA4 = (uint8_t)(Sector >> 32); + CommandFIS->LBA5 = (uint8_t)(Sector >> 40); + CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->countLow = SectorCount & 0xFF; + CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; + CommandFIS->Control = 0; // 1 << 3; + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return false; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return false; + } + } + printf("count: %i ", commandHeader->PRDBCount); + return true; +} + +#define OsOwnership (1 << 1) +#define BiosOwnership (1 << 0) + +void initializeSataController(PciDevice *pciDevice, ListElement **drives) { + if (pciDevice->programmingInterface != 1) { + return; + } + HBAMemory *hba = (void *)(uintptr_t)(pciDevice->bar5 & 0xFFFFFFF0); + if (!(hba->GlobalHostControl & (1 << 31))) { + printf("controller not in ahci mode!\n"); + return; + } + // hba->GlobalHostControl |= 1 << 31; + if (hba->HostCapabilitiesExtended & 1) { + printf("the os does not own the hba, getting it now...\n"); + yields(); + hba->BIOSHandoffControlStatus |= OsOwnership; + while (hba->BIOSHandoffControlStatus & BiosOwnership || + !(hba->BIOSHandoffControlStatus & OsOwnership)) { + } + } + // hba->GlobalHostControl |= 1; + // while (hba->GlobalHostControl & 1) { + //} + // hba->GlobalHostControl |= 1 << 31; + // sleep(1000); + // enabling bus mastering and memory access + // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, + // pciDevice->function, 4); + // command |= (1 << 1) | (1 << 2); + // pciConfigWriteByte(pciDevice->bus, pciDevice->device, + // pciDevice->function, + // 4, (uint8_t)command); + preparePorts(hba, drives); +} diff --git a/src/kernel/drivers/pci/hardDrive/ata.c b/src/kernel/drivers/pci/hardDrive/ata.c new file mode 100644 index 0000000..f339f11 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ata.c @@ -0,0 +1,25 @@ +#include +#include +#include + +void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data) { + hardDrive->model = malloc(41); + for (int i = 0; i < 40; i += 2) { + hardDrive->model[i] = data->model[i + 1]; + hardDrive->model[i + 1] = data->model[i]; + } + hardDrive->model[40] = 0; + if (data->CommandSetActive.BigLba) { + hardDrive->sectorCount = *((uint32_t *)data->Max48BitLBA); + } else { + hardDrive->sectorCount = data->ObsoleteWord62; + } + hardDrive->sectorSize = 512; + if (data->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words) { + hardDrive->sectorSize = ((uint32_t)data->WordsPerLogicalSector[0] | + (uint32_t)data->WordsPerLogicalSector[1] << 16) + << 1; + } + printf("sector count: %i, sector size: %i\nmodel: %s\n", + hardDrive->sectorCount, hardDrive->sectorSize, hardDrive->model); +} diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index ef60189..d420c60 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -28,9 +28,12 @@ #define CMD_COUNTER2 0x80 void sleep(uint16_t millis) { - uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + int32_t ticksLeft = getCurrentTask()->ticksLeft - millis; getCurrentTask()->ticksLeft = millis; yield(); + if (ticksLeft > 0) { + getCurrentTask()->ticksLeft = ticksLeft; + } } void setTimerFrequency(uint32_t hz) { diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c new file mode 100644 index 0000000..8f3e441 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +#define LOWER(ptr) (uint32_t)(uintptr_t) ptr +#define UPPER(ptr) (uint32_t)((uint64_t)(uintptr_t)ptr >> 32) + +uint8_t CheckPortType(HBAPort *Port) { + uint32_t SataStatus = Port->SataStatus; + + uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111; + uint8_t DeviceDetection = SataStatus & 0b111; + + if (DeviceDetection != HBA_PORT_DEV_PRESENT) { + return None; + } + if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE) { + return None; + } + + switch (Port->Signature) { + case SATA_SIG_ATAPI: + return SATAPI; + case SATA_SIG_ATA: + return SATA; + case SATA_SIG_PM: + return PM; + case SATA_SIG_SEMB: + return SEMB; + default: + return None; + } +} + +void configurePort(Port *); +bool ahciCommand(HBAPort *HBAPortPtr, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command); +void StartCMD(HBAPort *HBAPortPtr); +void StopCMD(HBAPort *HBAPortPtr); + +AtaIdentifyData ident; + +void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction) { + Port *port = (void *)drive->interface; + printf("start "); + yields(); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + printf("end %x\n", *(uint64_t *)buffer); + yields(); +} + +void preparePorts(HBAMemory *hba, ListElement **drives) { + for (uint8_t i = 0; i < 32; i++) { + if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { + continue; + } + uint8_t portType = CheckPortType(&hba->Ports[i]); + if (!portType) { + continue; + } + if (portType == SATAPI) { + printf("satapi devices not implemented yet!\n"); + yields(); + continue; + } + if (portType != SATA) { + continue; + } + Port *port = malloc(sizeof(Port)); + port->AHCIPortType = portType; + port->HBAPortPtr = &hba->Ports[i]; + configurePort(port); + printf("reconfigured the port\n"); + yields(); + ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->interface = port; + hardDrive->access = accessAHCIDrive; + addIdentifyData(hardDrive, &ident); + listAdd(drives, hardDrive); + } +} + +void configurePort(Port *port) { + HBAPort *HBAPortPtr = port->HBAPortPtr; + StopCMD(HBAPortPtr); + + HBACommandHeader *CommandHeader = mallocAligned(1024, 10); + HBAPortPtr->CommandListBase = LOWER(CommandHeader); + HBAPortPtr->CommandListBaseUpper = UPPER(CommandHeader); + memset(CommandHeader, 0, 1024); + + void *fis = mallocAligned(1024, 10); + HBAPortPtr->FISBaseAddress = LOWER(fis); + HBAPortPtr->FISBaseAddressUpper = UPPER(fis); + memset(fis, 0, 256); + for (int i = 0; i < 32; i++) { + CommandHeader[i].PRDTLength = 8; + void *CommandTable = mallocAligned(sizeof(HBACommandTable), 8); + CommandHeader[i].CommandTableBaseAddress = LOWER(CommandTable); + CommandHeader[i].CommandTableBaseAddressUpper = UPPER(CommandTable); + memset(CommandTable, 0, 256); + } + StartCMD(HBAPortPtr); +} + +void StopCMD(HBAPort *HBAPortPtr) { + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST; + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE; + + while (true) { + if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR) { + continue; + } + if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + continue; + } + break; + } +} + +void StartCMD(HBAPort *HBAPortPtr) { + while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + } + HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE; + HBAPortPtr->CommandStatus |= HBA_PxCMD_ST; +} + +#define HBA_PxIS_TFES (1 << 30) + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + hbaPort->InterruptEnable = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->PRDTLength = 1; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + memset(CommandTable, 0, sizeof(HBACommandTable)); + + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); + CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); + CommandTable->PRDTEntry[0].ByteCount = + SectorCount ? 512 * SectorCount - 1 : 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->command = command; + CommandFIS->LBA0 = (uint8_t)(Sector); + CommandFIS->LBA1 = (uint8_t)(Sector >> 8); + CommandFIS->LBA2 = (uint8_t)(Sector >> 16); + CommandFIS->LBA3 = (uint8_t)(Sector >> 24); + CommandFIS->LBA4 = (uint8_t)(Sector >> 32); + CommandFIS->LBA5 = (uint8_t)(Sector >> 40); + CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->countLow = SectorCount & 0xFF; + CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; + CommandFIS->Control = 0; // 1 << 3; + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return false; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return false; + } + } + printf("count: %i ", commandHeader->PRDBCount); + return true; +} + +#define OsOwnership (1 << 1) +#define BiosOwnership (1 << 0) + +void initializeSataController(PciDevice *pciDevice, ListElement **drives) { + if (pciDevice->programmingInterface != 1) { + return; + } + HBAMemory *hba = (void *)(uintptr_t)(pciDevice->bar5 & 0xFFFFFFF0); + if (!(hba->GlobalHostControl & (1 << 31))) { + printf("controller not in ahci mode!\n"); + return; + } + // hba->GlobalHostControl |= 1 << 31; + if (hba->HostCapabilitiesExtended & 1) { + printf("the os does not own the hba, getting it now...\n"); + yields(); + hba->BIOSHandoffControlStatus |= OsOwnership; + while (hba->BIOSHandoffControlStatus & BiosOwnership || + !(hba->BIOSHandoffControlStatus & OsOwnership)) { + } + } + // hba->GlobalHostControl |= 1; + // while (hba->GlobalHostControl & 1) { + //} + // hba->GlobalHostControl |= 1 << 31; + // sleep(1000); + // enabling bus mastering and memory access + // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, + // pciDevice->function, 4); + // command |= (1 << 1) | (1 << 2); + // pciConfigWriteByte(pciDevice->bus, pciDevice->device, + // pciDevice->function, + // 4, (uint8_t)command); + preparePorts(hba, drives); +} diff --git a/src/kernel/drivers/pci/hardDrive/ata.c b/src/kernel/drivers/pci/hardDrive/ata.c new file mode 100644 index 0000000..f339f11 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ata.c @@ -0,0 +1,25 @@ +#include +#include +#include + +void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data) { + hardDrive->model = malloc(41); + for (int i = 0; i < 40; i += 2) { + hardDrive->model[i] = data->model[i + 1]; + hardDrive->model[i + 1] = data->model[i]; + } + hardDrive->model[40] = 0; + if (data->CommandSetActive.BigLba) { + hardDrive->sectorCount = *((uint32_t *)data->Max48BitLBA); + } else { + hardDrive->sectorCount = data->ObsoleteWord62; + } + hardDrive->sectorSize = 512; + if (data->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words) { + hardDrive->sectorSize = ((uint32_t)data->WordsPerLogicalSector[0] | + (uint32_t)data->WordsPerLogicalSector[1] << 16) + << 1; + } + printf("sector count: %i, sector size: %i\nmodel: %s\n", + hardDrive->sectorCount, hardDrive->sectorSize, hardDrive->model); +} diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index a9c7a4e..0e8c536 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -5,6 +5,8 @@ #include #include +extern void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction); void scanHardDrives() { ListElement *drives = NULL; for (ListElement *current = *getPciDevices(); current; diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index ef60189..d420c60 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -28,9 +28,12 @@ #define CMD_COUNTER2 0x80 void sleep(uint16_t millis) { - uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + int32_t ticksLeft = getCurrentTask()->ticksLeft - millis; getCurrentTask()->ticksLeft = millis; yield(); + if (ticksLeft > 0) { + getCurrentTask()->ticksLeft = ticksLeft; + } } void setTimerFrequency(uint32_t hz) { diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c new file mode 100644 index 0000000..8f3e441 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +#define LOWER(ptr) (uint32_t)(uintptr_t) ptr +#define UPPER(ptr) (uint32_t)((uint64_t)(uintptr_t)ptr >> 32) + +uint8_t CheckPortType(HBAPort *Port) { + uint32_t SataStatus = Port->SataStatus; + + uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111; + uint8_t DeviceDetection = SataStatus & 0b111; + + if (DeviceDetection != HBA_PORT_DEV_PRESENT) { + return None; + } + if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE) { + return None; + } + + switch (Port->Signature) { + case SATA_SIG_ATAPI: + return SATAPI; + case SATA_SIG_ATA: + return SATA; + case SATA_SIG_PM: + return PM; + case SATA_SIG_SEMB: + return SEMB; + default: + return None; + } +} + +void configurePort(Port *); +bool ahciCommand(HBAPort *HBAPortPtr, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command); +void StartCMD(HBAPort *HBAPortPtr); +void StopCMD(HBAPort *HBAPortPtr); + +AtaIdentifyData ident; + +void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction) { + Port *port = (void *)drive->interface; + printf("start "); + yields(); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + printf("end %x\n", *(uint64_t *)buffer); + yields(); +} + +void preparePorts(HBAMemory *hba, ListElement **drives) { + for (uint8_t i = 0; i < 32; i++) { + if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { + continue; + } + uint8_t portType = CheckPortType(&hba->Ports[i]); + if (!portType) { + continue; + } + if (portType == SATAPI) { + printf("satapi devices not implemented yet!\n"); + yields(); + continue; + } + if (portType != SATA) { + continue; + } + Port *port = malloc(sizeof(Port)); + port->AHCIPortType = portType; + port->HBAPortPtr = &hba->Ports[i]; + configurePort(port); + printf("reconfigured the port\n"); + yields(); + ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->interface = port; + hardDrive->access = accessAHCIDrive; + addIdentifyData(hardDrive, &ident); + listAdd(drives, hardDrive); + } +} + +void configurePort(Port *port) { + HBAPort *HBAPortPtr = port->HBAPortPtr; + StopCMD(HBAPortPtr); + + HBACommandHeader *CommandHeader = mallocAligned(1024, 10); + HBAPortPtr->CommandListBase = LOWER(CommandHeader); + HBAPortPtr->CommandListBaseUpper = UPPER(CommandHeader); + memset(CommandHeader, 0, 1024); + + void *fis = mallocAligned(1024, 10); + HBAPortPtr->FISBaseAddress = LOWER(fis); + HBAPortPtr->FISBaseAddressUpper = UPPER(fis); + memset(fis, 0, 256); + for (int i = 0; i < 32; i++) { + CommandHeader[i].PRDTLength = 8; + void *CommandTable = mallocAligned(sizeof(HBACommandTable), 8); + CommandHeader[i].CommandTableBaseAddress = LOWER(CommandTable); + CommandHeader[i].CommandTableBaseAddressUpper = UPPER(CommandTable); + memset(CommandTable, 0, 256); + } + StartCMD(HBAPortPtr); +} + +void StopCMD(HBAPort *HBAPortPtr) { + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST; + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE; + + while (true) { + if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR) { + continue; + } + if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + continue; + } + break; + } +} + +void StartCMD(HBAPort *HBAPortPtr) { + while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + } + HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE; + HBAPortPtr->CommandStatus |= HBA_PxCMD_ST; +} + +#define HBA_PxIS_TFES (1 << 30) + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + hbaPort->InterruptEnable = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->PRDTLength = 1; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + memset(CommandTable, 0, sizeof(HBACommandTable)); + + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); + CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); + CommandTable->PRDTEntry[0].ByteCount = + SectorCount ? 512 * SectorCount - 1 : 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->command = command; + CommandFIS->LBA0 = (uint8_t)(Sector); + CommandFIS->LBA1 = (uint8_t)(Sector >> 8); + CommandFIS->LBA2 = (uint8_t)(Sector >> 16); + CommandFIS->LBA3 = (uint8_t)(Sector >> 24); + CommandFIS->LBA4 = (uint8_t)(Sector >> 32); + CommandFIS->LBA5 = (uint8_t)(Sector >> 40); + CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->countLow = SectorCount & 0xFF; + CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; + CommandFIS->Control = 0; // 1 << 3; + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return false; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return false; + } + } + printf("count: %i ", commandHeader->PRDBCount); + return true; +} + +#define OsOwnership (1 << 1) +#define BiosOwnership (1 << 0) + +void initializeSataController(PciDevice *pciDevice, ListElement **drives) { + if (pciDevice->programmingInterface != 1) { + return; + } + HBAMemory *hba = (void *)(uintptr_t)(pciDevice->bar5 & 0xFFFFFFF0); + if (!(hba->GlobalHostControl & (1 << 31))) { + printf("controller not in ahci mode!\n"); + return; + } + // hba->GlobalHostControl |= 1 << 31; + if (hba->HostCapabilitiesExtended & 1) { + printf("the os does not own the hba, getting it now...\n"); + yields(); + hba->BIOSHandoffControlStatus |= OsOwnership; + while (hba->BIOSHandoffControlStatus & BiosOwnership || + !(hba->BIOSHandoffControlStatus & OsOwnership)) { + } + } + // hba->GlobalHostControl |= 1; + // while (hba->GlobalHostControl & 1) { + //} + // hba->GlobalHostControl |= 1 << 31; + // sleep(1000); + // enabling bus mastering and memory access + // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, + // pciDevice->function, 4); + // command |= (1 << 1) | (1 << 2); + // pciConfigWriteByte(pciDevice->bus, pciDevice->device, + // pciDevice->function, + // 4, (uint8_t)command); + preparePorts(hba, drives); +} diff --git a/src/kernel/drivers/pci/hardDrive/ata.c b/src/kernel/drivers/pci/hardDrive/ata.c new file mode 100644 index 0000000..f339f11 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ata.c @@ -0,0 +1,25 @@ +#include +#include +#include + +void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data) { + hardDrive->model = malloc(41); + for (int i = 0; i < 40; i += 2) { + hardDrive->model[i] = data->model[i + 1]; + hardDrive->model[i + 1] = data->model[i]; + } + hardDrive->model[40] = 0; + if (data->CommandSetActive.BigLba) { + hardDrive->sectorCount = *((uint32_t *)data->Max48BitLBA); + } else { + hardDrive->sectorCount = data->ObsoleteWord62; + } + hardDrive->sectorSize = 512; + if (data->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words) { + hardDrive->sectorSize = ((uint32_t)data->WordsPerLogicalSector[0] | + (uint32_t)data->WordsPerLogicalSector[1] << 16) + << 1; + } + printf("sector count: %i, sector size: %i\nmodel: %s\n", + hardDrive->sectorCount, hardDrive->sectorSize, hardDrive->model); +} diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index a9c7a4e..0e8c536 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -5,6 +5,8 @@ #include #include +extern void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction); void scanHardDrives() { ListElement *drives = NULL; for (ListElement *current = *getPciDevices(); current; diff --git a/src/kernel/drivers/pci/hardDrive/ideController.c b/src/kernel/drivers/pci/hardDrive/ideController.c index e5ac6df..5d7a010 100644 --- a/src/kernel/drivers/pci/hardDrive/ideController.c +++ b/src/kernel/drivers/pci/hardDrive/ideController.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -224,17 +225,11 @@ // any bit has to be set if it is a real device continue; } - char *model = malloc(41); - for (int i = 0; i < 40; i += 2) { - *((uint16_t *)&model[i]) = buffer[54 + i + 1]; - *((uint16_t *)&model[i + 1]) = buffer[54 + i]; - } - model[40] = 0; usedChannels |= 1 << channel; HardDrive *hardDrive = malloc(sizeof(HardDrive)); IdeInterface *interface = malloc(sizeof(IdeInterface)); hardDrive->interface = interface; - hardDrive->model = model; + addIdentifyData(hardDrive, (void *)buffer); hardDrive->access = ideDriveAccess; interface->channels = CHANNEL; interface->channel = channel; @@ -245,14 +240,7 @@ interface->sectors = *(uint16_t *)buffer + 12; interface->capabilities = *(uint16_t *)buffer + 98; interface->commandSets = *(uint32_t *)(buffer + 164); - if (interface->commandSets + (1 << 26)) { - hardDrive->size = *(uint32_t *)buffer + 200; - } else { - hardDrive->size = *(uint32_t *)buffer + 120; - } listAdd(drives, hardDrive); - printf("found a hard drive %i sectors big, model: %s\n", - hardDrive->size, model); } } if (!(usedChannels & 1)) { diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index ef60189..d420c60 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -28,9 +28,12 @@ #define CMD_COUNTER2 0x80 void sleep(uint16_t millis) { - uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + int32_t ticksLeft = getCurrentTask()->ticksLeft - millis; getCurrentTask()->ticksLeft = millis; yield(); + if (ticksLeft > 0) { + getCurrentTask()->ticksLeft = ticksLeft; + } } void setTimerFrequency(uint32_t hz) { diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c new file mode 100644 index 0000000..8f3e441 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +#define LOWER(ptr) (uint32_t)(uintptr_t) ptr +#define UPPER(ptr) (uint32_t)((uint64_t)(uintptr_t)ptr >> 32) + +uint8_t CheckPortType(HBAPort *Port) { + uint32_t SataStatus = Port->SataStatus; + + uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111; + uint8_t DeviceDetection = SataStatus & 0b111; + + if (DeviceDetection != HBA_PORT_DEV_PRESENT) { + return None; + } + if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE) { + return None; + } + + switch (Port->Signature) { + case SATA_SIG_ATAPI: + return SATAPI; + case SATA_SIG_ATA: + return SATA; + case SATA_SIG_PM: + return PM; + case SATA_SIG_SEMB: + return SEMB; + default: + return None; + } +} + +void configurePort(Port *); +bool ahciCommand(HBAPort *HBAPortPtr, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command); +void StartCMD(HBAPort *HBAPortPtr); +void StopCMD(HBAPort *HBAPortPtr); + +AtaIdentifyData ident; + +void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction) { + Port *port = (void *)drive->interface; + printf("start "); + yields(); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + printf("end %x\n", *(uint64_t *)buffer); + yields(); +} + +void preparePorts(HBAMemory *hba, ListElement **drives) { + for (uint8_t i = 0; i < 32; i++) { + if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { + continue; + } + uint8_t portType = CheckPortType(&hba->Ports[i]); + if (!portType) { + continue; + } + if (portType == SATAPI) { + printf("satapi devices not implemented yet!\n"); + yields(); + continue; + } + if (portType != SATA) { + continue; + } + Port *port = malloc(sizeof(Port)); + port->AHCIPortType = portType; + port->HBAPortPtr = &hba->Ports[i]; + configurePort(port); + printf("reconfigured the port\n"); + yields(); + ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->interface = port; + hardDrive->access = accessAHCIDrive; + addIdentifyData(hardDrive, &ident); + listAdd(drives, hardDrive); + } +} + +void configurePort(Port *port) { + HBAPort *HBAPortPtr = port->HBAPortPtr; + StopCMD(HBAPortPtr); + + HBACommandHeader *CommandHeader = mallocAligned(1024, 10); + HBAPortPtr->CommandListBase = LOWER(CommandHeader); + HBAPortPtr->CommandListBaseUpper = UPPER(CommandHeader); + memset(CommandHeader, 0, 1024); + + void *fis = mallocAligned(1024, 10); + HBAPortPtr->FISBaseAddress = LOWER(fis); + HBAPortPtr->FISBaseAddressUpper = UPPER(fis); + memset(fis, 0, 256); + for (int i = 0; i < 32; i++) { + CommandHeader[i].PRDTLength = 8; + void *CommandTable = mallocAligned(sizeof(HBACommandTable), 8); + CommandHeader[i].CommandTableBaseAddress = LOWER(CommandTable); + CommandHeader[i].CommandTableBaseAddressUpper = UPPER(CommandTable); + memset(CommandTable, 0, 256); + } + StartCMD(HBAPortPtr); +} + +void StopCMD(HBAPort *HBAPortPtr) { + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST; + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE; + + while (true) { + if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR) { + continue; + } + if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + continue; + } + break; + } +} + +void StartCMD(HBAPort *HBAPortPtr) { + while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + } + HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE; + HBAPortPtr->CommandStatus |= HBA_PxCMD_ST; +} + +#define HBA_PxIS_TFES (1 << 30) + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + hbaPort->InterruptEnable = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->PRDTLength = 1; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + memset(CommandTable, 0, sizeof(HBACommandTable)); + + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); + CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); + CommandTable->PRDTEntry[0].ByteCount = + SectorCount ? 512 * SectorCount - 1 : 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->command = command; + CommandFIS->LBA0 = (uint8_t)(Sector); + CommandFIS->LBA1 = (uint8_t)(Sector >> 8); + CommandFIS->LBA2 = (uint8_t)(Sector >> 16); + CommandFIS->LBA3 = (uint8_t)(Sector >> 24); + CommandFIS->LBA4 = (uint8_t)(Sector >> 32); + CommandFIS->LBA5 = (uint8_t)(Sector >> 40); + CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->countLow = SectorCount & 0xFF; + CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; + CommandFIS->Control = 0; // 1 << 3; + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return false; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return false; + } + } + printf("count: %i ", commandHeader->PRDBCount); + return true; +} + +#define OsOwnership (1 << 1) +#define BiosOwnership (1 << 0) + +void initializeSataController(PciDevice *pciDevice, ListElement **drives) { + if (pciDevice->programmingInterface != 1) { + return; + } + HBAMemory *hba = (void *)(uintptr_t)(pciDevice->bar5 & 0xFFFFFFF0); + if (!(hba->GlobalHostControl & (1 << 31))) { + printf("controller not in ahci mode!\n"); + return; + } + // hba->GlobalHostControl |= 1 << 31; + if (hba->HostCapabilitiesExtended & 1) { + printf("the os does not own the hba, getting it now...\n"); + yields(); + hba->BIOSHandoffControlStatus |= OsOwnership; + while (hba->BIOSHandoffControlStatus & BiosOwnership || + !(hba->BIOSHandoffControlStatus & OsOwnership)) { + } + } + // hba->GlobalHostControl |= 1; + // while (hba->GlobalHostControl & 1) { + //} + // hba->GlobalHostControl |= 1 << 31; + // sleep(1000); + // enabling bus mastering and memory access + // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, + // pciDevice->function, 4); + // command |= (1 << 1) | (1 << 2); + // pciConfigWriteByte(pciDevice->bus, pciDevice->device, + // pciDevice->function, + // 4, (uint8_t)command); + preparePorts(hba, drives); +} diff --git a/src/kernel/drivers/pci/hardDrive/ata.c b/src/kernel/drivers/pci/hardDrive/ata.c new file mode 100644 index 0000000..f339f11 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ata.c @@ -0,0 +1,25 @@ +#include +#include +#include + +void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data) { + hardDrive->model = malloc(41); + for (int i = 0; i < 40; i += 2) { + hardDrive->model[i] = data->model[i + 1]; + hardDrive->model[i + 1] = data->model[i]; + } + hardDrive->model[40] = 0; + if (data->CommandSetActive.BigLba) { + hardDrive->sectorCount = *((uint32_t *)data->Max48BitLBA); + } else { + hardDrive->sectorCount = data->ObsoleteWord62; + } + hardDrive->sectorSize = 512; + if (data->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words) { + hardDrive->sectorSize = ((uint32_t)data->WordsPerLogicalSector[0] | + (uint32_t)data->WordsPerLogicalSector[1] << 16) + << 1; + } + printf("sector count: %i, sector size: %i\nmodel: %s\n", + hardDrive->sectorCount, hardDrive->sectorSize, hardDrive->model); +} diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index a9c7a4e..0e8c536 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -5,6 +5,8 @@ #include #include +extern void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction); void scanHardDrives() { ListElement *drives = NULL; for (ListElement *current = *getPciDevices(); current; diff --git a/src/kernel/drivers/pci/hardDrive/ideController.c b/src/kernel/drivers/pci/hardDrive/ideController.c index e5ac6df..5d7a010 100644 --- a/src/kernel/drivers/pci/hardDrive/ideController.c +++ b/src/kernel/drivers/pci/hardDrive/ideController.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -224,17 +225,11 @@ // any bit has to be set if it is a real device continue; } - char *model = malloc(41); - for (int i = 0; i < 40; i += 2) { - *((uint16_t *)&model[i]) = buffer[54 + i + 1]; - *((uint16_t *)&model[i + 1]) = buffer[54 + i]; - } - model[40] = 0; usedChannels |= 1 << channel; HardDrive *hardDrive = malloc(sizeof(HardDrive)); IdeInterface *interface = malloc(sizeof(IdeInterface)); hardDrive->interface = interface; - hardDrive->model = model; + addIdentifyData(hardDrive, (void *)buffer); hardDrive->access = ideDriveAccess; interface->channels = CHANNEL; interface->channel = channel; @@ -245,14 +240,7 @@ interface->sectors = *(uint16_t *)buffer + 12; interface->capabilities = *(uint16_t *)buffer + 98; interface->commandSets = *(uint32_t *)(buffer + 164); - if (interface->commandSets + (1 << 26)) { - hardDrive->size = *(uint32_t *)buffer + 200; - } else { - hardDrive->size = *(uint32_t *)buffer + 120; - } listAdd(drives, hardDrive); - printf("found a hard drive %i sectors big, model: %s\n", - hardDrive->size, model); } } if (!(usedChannels & 1)) { diff --git a/src/kernel/drivers/pci/hardDrive/sataController.c b/src/kernel/drivers/pci/hardDrive/sataController.c deleted file mode 100644 index 13008e3..0000000 --- a/src/kernel/drivers/pci/hardDrive/sataController.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include -#include - -// information source: -// https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/serial-ata-ahci-spec-rev1_3.pdf - -#define SATA_ATA 0x00000101 -#define SATA_ATAPI 0xEB140101 -#define SATA_ENCLOSURE_MANAGEMENT_BRIDGE 0xC33C0101 -#define SATA_SIG_PM 0x96690101 - -#define AHCI_DEV_NULL 0 -#define AHCI_SATA_DEVICE 1 -#define AHCI_SEMB_DEVICE 2 -#define AHCI_DEV_PM 3 -#define AHCI_DEV_SATAPI 4 - -#define POWER_ACTIVE 1 -#define DEVICE_PRESENT 3 - -#define ATA_DEV_BUSY 0x80 -#define ATA_DEV_DRQ 0x08 - -typedef struct { - uint32_t commandListLower, commandListUpper; - uint32_t fisLower, fisUpper; - uint32_t interruptStatus, interruptEnable; - uint32_t command; - uint32_t reserved; - uint32_t taskFileData; - uint32_t signature; - uint32_t sataStatus, sataControl, sataError, sataActive; - uint32_t commandIssue; - uint32_t sataNotification; - uint32_t fisSwitchingControl; - uint32_t deviceSleep; - uint8_t reserved_[50]; - uint32_t vendorSpecific; -} PortControlRegisters; - -typedef struct { - uint32_t hostCapabilities, globalHostControl, interruptStatus, - implementedPorts, version, cccCtl, cccPts, enclosureManagementLocation, - enclosureManagementControl, hostCapabilitiesExtended, handoffStatus; - uint8_t reserved[116]; - uint8_t vendor[96]; - PortControlRegisters ports[32]; -} HbaMemoryRegisters; - -typedef struct { - uint8_t fisLength : 5, ATAPI : 1, write : 1, prefetchable : 1; - - uint8_t reset : 1, bist : 1, clearBusy : 1, reserved : 1, - portMultiplierPort : 4; - - uint16_t regionDescriptorCount; - - volatile uint32_t transferedBytes; - - uint32_t commandTableLower, commandTableUpper; - - uint32_t reserved_[4]; -} CommandHeader; - -typedef struct { - CommandHeader commandHeaders[32]; -} CommandListStructure; - -typedef struct { - uint32_t dataBaseLower, dataBaseUpper; - uint32_t reserved; - uint32_t byteCount : 22, reserved_ : 9, interrupt : 1; -} PhysicalRegionDescriptor; - -typedef struct { - uint8_t fis[64]; - uint8_t atapi[16]; - uint8_t reserved[48]; - PhysicalRegionDescriptor regionDescriptor[8]; -} CommandTable; - -typedef struct { - HbaMemoryRegisters *registers; - PortControlRegisters *port; -} SataInterface; - -#define FIS_TO_DEVICE_TYPE 0x27 - -typedef struct { - uint8_t type; - uint8_t portMultiplierPort : 4, reserved : 3, commandControl : 1; - - uint8_t command, featureLow; - - uint8_t lba0, lba1, lba2, device; - - uint8_t lba3, lba4, lba5, featureHigh; - - uint8_t countLow, countHigh, isochronousCommandCompletion, control; - - uint8_t reserved_[4]; -} FisToDevice; - -void *getPointer(uint32_t lower, uint32_t upper) { - return (void *)(uintptr_t)(lower | (uintptr_t)upper << 32); -} - -uint32_t getType(PortControlRegisters *registers) { - uint32_t status = registers->sataStatus; - uint8_t detectionStatus = status & 0xF; - uint8_t interfacePowerManagement = (status >> 8) & 0xF; - if (detectionStatus != DEVICE_PRESENT || - interfacePowerManagement != POWER_ACTIVE) { - return AHCI_DEV_NULL; - } - switch (registers->signature) { - case SATA_ATAPI: - return AHCI_DEV_SATAPI; - case SATA_ENCLOSURE_MANAGEMENT_BRIDGE: - return AHCI_SEMB_DEVICE; - case SATA_SIG_PM: - return AHCI_DEV_PM; - default: - return AHCI_SATA_DEVICE; - } -} - -int8_t findFreeCommandHeader(PortControlRegisters *port) { - uint32_t filledSlots = port->sataControl | port->commandIssue; - for (uint8_t i = 0; i < 32; i++) { - if (!(filledSlots & 1 >> i)) { - return i; - } - } - return -1; -} - -void insertLba(FisToDevice *fis, uint64_t lba) { - fis->lba0 = (uint8_t)lba; - fis->lba1 = (uint8_t)(lba >> 8); - fis->lba2 = (uint8_t)(lba >> 16); - fis->lba3 = (uint8_t)(lba >> 24); - fis->lba4 = (uint8_t)(lba >> 32); - fis->lba5 = (uint8_t)(lba >> 40); -} - -void setupFisToRead(FisToDevice *fis, uint16_t sectorCount, uint64_t lba, - uint8_t command) { - fis->type = FIS_TO_DEVICE_TYPE; - fis->commandControl = 1; - fis->command = command; - fis->device = 1 << 6; - fis->countLow = (uint8_t)sectorCount; - fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, lba); -} - -void sataIssueCommand(PortControlRegisters *port) { - while (port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - port->commandIssue = 1; - while (port->commandIssue == 1) { - yields(); - } -} - -void sataCommand(PortControlRegisters *port, uint8_t command, void *buffer, - uint64_t lba, uint16_t sectorCount) { - port->interruptStatus = -1; - CommandListStructure *commandList = - getPointer(port->commandListLower, port->commandListUpper); - int8_t slot = findFreeCommandHeader(port); - if (slot == -1) { - printf("sata command failed: no free command header slot found!\n"); - return; - } - CommandHeader *commandHeader = &(commandList->commandHeaders[slot]); - commandHeader->fisLength = sizeof(FisToDevice) / sizeof(uint32_t); - commandHeader->write = 0; - commandHeader->regionDescriptorCount = 1; - CommandTable *commandTable = getPointer(commandHeader->commandTableLower, - commandHeader->commandTableUpper); - memset(commandTable, 0, - sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * - sizeof(PhysicalRegionDescriptor)); - commandTable->regionDescriptor[0].dataBaseLower = (uintptr_t)buffer; - commandTable->regionDescriptor[0].dataBaseUpper = (uintptr_t)buffer >> 32; - commandTable->regionDescriptor[0].byteCount = 511; - commandTable->regionDescriptor[0].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, sectorCount, lba, command); - sataIssueCommand(port); -} - -void sataDriveAccess(HardDrive *hardDrive, uint64_t lba, void *buffer, - uint16_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - sataCommand(interface->port, ATA_CMD_READ_DMA_EXT, buffer, lba, - sectorCount); -} - -#define HBA_PxCMD_ST 0x0001 -#define HBA_PxCMD_FRE 0x0010 -#define HBA_PxCMD_FR 0x4000 -#define HBA_PxCMD_CR 0x8000 - -void disableCommands(PortControlRegisters *port) { - port->command &= ~(HBA_PxCMD_ST | HBA_PxCMD_FRE); - while (port->command & HBA_PxCMD_FR && port->command + HBA_PxCMD_CR) { - } -} - -void enableCommands(PortControlRegisters *port) { - while (port->command & HBA_PxCMD_CR) { - } - port->command |= HBA_PxCMD_ST | HBA_PxCMD_FRE; -} - -void relocatePort(PortControlRegisters *port) { - // call only once for each port, nothing is being freed here - disableCommands(port); - CommandListStructure *commandList = - mallocAligned(sizeof(CommandListStructure), 10); - port->commandListLower = (uintptr_t)commandList; - port->commandListUpper = (uintptr_t)commandList >> 32; - uintptr_t fis = (uintptr_t)mallocAligned(sizeof(CommandListStructure), 10); - port->fisLower = fis; - port->fisUpper = (uintptr_t)commandList >> 32; - memset(commandList, 0, sizeof(CommandListStructure)); - for (uint8_t i = 0; i < 32; i++) { - uint16_t size = 256; // sizeof(CommandTable) - commandList->commandHeaders[i].regionDescriptorCount = 8; - uintptr_t commandTable = (uintptr_t)mallocAligned(size, 8); - commandList->commandHeaders[i].commandTableLower = commandTable; - commandList->commandHeaders[i].commandTableUpper = commandTable >> 32; - memset((void *)commandTable, 0, size); - } - enableCommands(port); -} - -void sataDeviceInitialize(PortControlRegisters *port, ListElement **drives, - HbaMemoryRegisters *registers) { - HardDrive *hardDrive = malloc(sizeof(HardDrive)); - SataInterface *interface = malloc(sizeof(SataInterface)); - hardDrive->access = sataDriveAccess; - hardDrive->interface = interface; - interface->registers = registers; - interface->port = port; - relocatePort(interface->port); - uint8_t *buffer = malloc(512); - sataCommand(port, ATA_CMD_IDENTIFY, buffer, 0, 1); - char *model = malloc(41); - for (int i = 0; i < 40; i += 2) { - *((uint16_t *)&model[i]) = buffer[54 + i + 1]; - *((uint16_t *)&model[i + 1]) = buffer[54 + i]; - } - model[41] = 0; - printf("model: %s\n", model); - hardDrive->model = model; - free(buffer); - listAdd(drives, hardDrive); -} - -void initializeSataController(PciDevice *pciDevice, ListElement **drives) { - if (pciDevice->programmingInterface != 1) { - // todo - return; - } - HbaMemoryRegisters *registers = (void *)(uintptr_t)pciDevice->bar5; - for (uint8_t i = 0; i < 32; i++) { - if (!(registers->implementedPorts & (1 << i))) { - continue; - } - uint32_t type = getType(®isters->ports[i]); - if (type == AHCI_DEV_NULL) { - continue; - } - if (type != AHCI_SATA_DEVICE) { - printf("type %i not implemented yet...\n", type); - // todo - continue; - } - sataDeviceInitialize(®isters->ports[i], drives, registers); - } -} diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index ef60189..d420c60 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -28,9 +28,12 @@ #define CMD_COUNTER2 0x80 void sleep(uint16_t millis) { - uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + int32_t ticksLeft = getCurrentTask()->ticksLeft - millis; getCurrentTask()->ticksLeft = millis; yield(); + if (ticksLeft > 0) { + getCurrentTask()->ticksLeft = ticksLeft; + } } void setTimerFrequency(uint32_t hz) { diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c new file mode 100644 index 0000000..8f3e441 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +#define LOWER(ptr) (uint32_t)(uintptr_t) ptr +#define UPPER(ptr) (uint32_t)((uint64_t)(uintptr_t)ptr >> 32) + +uint8_t CheckPortType(HBAPort *Port) { + uint32_t SataStatus = Port->SataStatus; + + uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111; + uint8_t DeviceDetection = SataStatus & 0b111; + + if (DeviceDetection != HBA_PORT_DEV_PRESENT) { + return None; + } + if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE) { + return None; + } + + switch (Port->Signature) { + case SATA_SIG_ATAPI: + return SATAPI; + case SATA_SIG_ATA: + return SATA; + case SATA_SIG_PM: + return PM; + case SATA_SIG_SEMB: + return SEMB; + default: + return None; + } +} + +void configurePort(Port *); +bool ahciCommand(HBAPort *HBAPortPtr, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command); +void StartCMD(HBAPort *HBAPortPtr); +void StopCMD(HBAPort *HBAPortPtr); + +AtaIdentifyData ident; + +void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction) { + Port *port = (void *)drive->interface; + printf("start "); + yields(); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + printf("end %x\n", *(uint64_t *)buffer); + yields(); +} + +void preparePorts(HBAMemory *hba, ListElement **drives) { + for (uint8_t i = 0; i < 32; i++) { + if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { + continue; + } + uint8_t portType = CheckPortType(&hba->Ports[i]); + if (!portType) { + continue; + } + if (portType == SATAPI) { + printf("satapi devices not implemented yet!\n"); + yields(); + continue; + } + if (portType != SATA) { + continue; + } + Port *port = malloc(sizeof(Port)); + port->AHCIPortType = portType; + port->HBAPortPtr = &hba->Ports[i]; + configurePort(port); + printf("reconfigured the port\n"); + yields(); + ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->interface = port; + hardDrive->access = accessAHCIDrive; + addIdentifyData(hardDrive, &ident); + listAdd(drives, hardDrive); + } +} + +void configurePort(Port *port) { + HBAPort *HBAPortPtr = port->HBAPortPtr; + StopCMD(HBAPortPtr); + + HBACommandHeader *CommandHeader = mallocAligned(1024, 10); + HBAPortPtr->CommandListBase = LOWER(CommandHeader); + HBAPortPtr->CommandListBaseUpper = UPPER(CommandHeader); + memset(CommandHeader, 0, 1024); + + void *fis = mallocAligned(1024, 10); + HBAPortPtr->FISBaseAddress = LOWER(fis); + HBAPortPtr->FISBaseAddressUpper = UPPER(fis); + memset(fis, 0, 256); + for (int i = 0; i < 32; i++) { + CommandHeader[i].PRDTLength = 8; + void *CommandTable = mallocAligned(sizeof(HBACommandTable), 8); + CommandHeader[i].CommandTableBaseAddress = LOWER(CommandTable); + CommandHeader[i].CommandTableBaseAddressUpper = UPPER(CommandTable); + memset(CommandTable, 0, 256); + } + StartCMD(HBAPortPtr); +} + +void StopCMD(HBAPort *HBAPortPtr) { + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST; + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE; + + while (true) { + if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR) { + continue; + } + if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + continue; + } + break; + } +} + +void StartCMD(HBAPort *HBAPortPtr) { + while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + } + HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE; + HBAPortPtr->CommandStatus |= HBA_PxCMD_ST; +} + +#define HBA_PxIS_TFES (1 << 30) + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + hbaPort->InterruptEnable = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->PRDTLength = 1; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + memset(CommandTable, 0, sizeof(HBACommandTable)); + + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); + CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); + CommandTable->PRDTEntry[0].ByteCount = + SectorCount ? 512 * SectorCount - 1 : 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->command = command; + CommandFIS->LBA0 = (uint8_t)(Sector); + CommandFIS->LBA1 = (uint8_t)(Sector >> 8); + CommandFIS->LBA2 = (uint8_t)(Sector >> 16); + CommandFIS->LBA3 = (uint8_t)(Sector >> 24); + CommandFIS->LBA4 = (uint8_t)(Sector >> 32); + CommandFIS->LBA5 = (uint8_t)(Sector >> 40); + CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->countLow = SectorCount & 0xFF; + CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; + CommandFIS->Control = 0; // 1 << 3; + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return false; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return false; + } + } + printf("count: %i ", commandHeader->PRDBCount); + return true; +} + +#define OsOwnership (1 << 1) +#define BiosOwnership (1 << 0) + +void initializeSataController(PciDevice *pciDevice, ListElement **drives) { + if (pciDevice->programmingInterface != 1) { + return; + } + HBAMemory *hba = (void *)(uintptr_t)(pciDevice->bar5 & 0xFFFFFFF0); + if (!(hba->GlobalHostControl & (1 << 31))) { + printf("controller not in ahci mode!\n"); + return; + } + // hba->GlobalHostControl |= 1 << 31; + if (hba->HostCapabilitiesExtended & 1) { + printf("the os does not own the hba, getting it now...\n"); + yields(); + hba->BIOSHandoffControlStatus |= OsOwnership; + while (hba->BIOSHandoffControlStatus & BiosOwnership || + !(hba->BIOSHandoffControlStatus & OsOwnership)) { + } + } + // hba->GlobalHostControl |= 1; + // while (hba->GlobalHostControl & 1) { + //} + // hba->GlobalHostControl |= 1 << 31; + // sleep(1000); + // enabling bus mastering and memory access + // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, + // pciDevice->function, 4); + // command |= (1 << 1) | (1 << 2); + // pciConfigWriteByte(pciDevice->bus, pciDevice->device, + // pciDevice->function, + // 4, (uint8_t)command); + preparePorts(hba, drives); +} diff --git a/src/kernel/drivers/pci/hardDrive/ata.c b/src/kernel/drivers/pci/hardDrive/ata.c new file mode 100644 index 0000000..f339f11 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ata.c @@ -0,0 +1,25 @@ +#include +#include +#include + +void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data) { + hardDrive->model = malloc(41); + for (int i = 0; i < 40; i += 2) { + hardDrive->model[i] = data->model[i + 1]; + hardDrive->model[i + 1] = data->model[i]; + } + hardDrive->model[40] = 0; + if (data->CommandSetActive.BigLba) { + hardDrive->sectorCount = *((uint32_t *)data->Max48BitLBA); + } else { + hardDrive->sectorCount = data->ObsoleteWord62; + } + hardDrive->sectorSize = 512; + if (data->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words) { + hardDrive->sectorSize = ((uint32_t)data->WordsPerLogicalSector[0] | + (uint32_t)data->WordsPerLogicalSector[1] << 16) + << 1; + } + printf("sector count: %i, sector size: %i\nmodel: %s\n", + hardDrive->sectorCount, hardDrive->sectorSize, hardDrive->model); +} diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index a9c7a4e..0e8c536 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -5,6 +5,8 @@ #include #include +extern void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction); void scanHardDrives() { ListElement *drives = NULL; for (ListElement *current = *getPciDevices(); current; diff --git a/src/kernel/drivers/pci/hardDrive/ideController.c b/src/kernel/drivers/pci/hardDrive/ideController.c index e5ac6df..5d7a010 100644 --- a/src/kernel/drivers/pci/hardDrive/ideController.c +++ b/src/kernel/drivers/pci/hardDrive/ideController.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -224,17 +225,11 @@ // any bit has to be set if it is a real device continue; } - char *model = malloc(41); - for (int i = 0; i < 40; i += 2) { - *((uint16_t *)&model[i]) = buffer[54 + i + 1]; - *((uint16_t *)&model[i + 1]) = buffer[54 + i]; - } - model[40] = 0; usedChannels |= 1 << channel; HardDrive *hardDrive = malloc(sizeof(HardDrive)); IdeInterface *interface = malloc(sizeof(IdeInterface)); hardDrive->interface = interface; - hardDrive->model = model; + addIdentifyData(hardDrive, (void *)buffer); hardDrive->access = ideDriveAccess; interface->channels = CHANNEL; interface->channel = channel; @@ -245,14 +240,7 @@ interface->sectors = *(uint16_t *)buffer + 12; interface->capabilities = *(uint16_t *)buffer + 98; interface->commandSets = *(uint32_t *)(buffer + 164); - if (interface->commandSets + (1 << 26)) { - hardDrive->size = *(uint32_t *)buffer + 200; - } else { - hardDrive->size = *(uint32_t *)buffer + 120; - } listAdd(drives, hardDrive); - printf("found a hard drive %i sectors big, model: %s\n", - hardDrive->size, model); } } if (!(usedChannels & 1)) { diff --git a/src/kernel/drivers/pci/hardDrive/sataController.c b/src/kernel/drivers/pci/hardDrive/sataController.c deleted file mode 100644 index 13008e3..0000000 --- a/src/kernel/drivers/pci/hardDrive/sataController.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include -#include - -// information source: -// https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/serial-ata-ahci-spec-rev1_3.pdf - -#define SATA_ATA 0x00000101 -#define SATA_ATAPI 0xEB140101 -#define SATA_ENCLOSURE_MANAGEMENT_BRIDGE 0xC33C0101 -#define SATA_SIG_PM 0x96690101 - -#define AHCI_DEV_NULL 0 -#define AHCI_SATA_DEVICE 1 -#define AHCI_SEMB_DEVICE 2 -#define AHCI_DEV_PM 3 -#define AHCI_DEV_SATAPI 4 - -#define POWER_ACTIVE 1 -#define DEVICE_PRESENT 3 - -#define ATA_DEV_BUSY 0x80 -#define ATA_DEV_DRQ 0x08 - -typedef struct { - uint32_t commandListLower, commandListUpper; - uint32_t fisLower, fisUpper; - uint32_t interruptStatus, interruptEnable; - uint32_t command; - uint32_t reserved; - uint32_t taskFileData; - uint32_t signature; - uint32_t sataStatus, sataControl, sataError, sataActive; - uint32_t commandIssue; - uint32_t sataNotification; - uint32_t fisSwitchingControl; - uint32_t deviceSleep; - uint8_t reserved_[50]; - uint32_t vendorSpecific; -} PortControlRegisters; - -typedef struct { - uint32_t hostCapabilities, globalHostControl, interruptStatus, - implementedPorts, version, cccCtl, cccPts, enclosureManagementLocation, - enclosureManagementControl, hostCapabilitiesExtended, handoffStatus; - uint8_t reserved[116]; - uint8_t vendor[96]; - PortControlRegisters ports[32]; -} HbaMemoryRegisters; - -typedef struct { - uint8_t fisLength : 5, ATAPI : 1, write : 1, prefetchable : 1; - - uint8_t reset : 1, bist : 1, clearBusy : 1, reserved : 1, - portMultiplierPort : 4; - - uint16_t regionDescriptorCount; - - volatile uint32_t transferedBytes; - - uint32_t commandTableLower, commandTableUpper; - - uint32_t reserved_[4]; -} CommandHeader; - -typedef struct { - CommandHeader commandHeaders[32]; -} CommandListStructure; - -typedef struct { - uint32_t dataBaseLower, dataBaseUpper; - uint32_t reserved; - uint32_t byteCount : 22, reserved_ : 9, interrupt : 1; -} PhysicalRegionDescriptor; - -typedef struct { - uint8_t fis[64]; - uint8_t atapi[16]; - uint8_t reserved[48]; - PhysicalRegionDescriptor regionDescriptor[8]; -} CommandTable; - -typedef struct { - HbaMemoryRegisters *registers; - PortControlRegisters *port; -} SataInterface; - -#define FIS_TO_DEVICE_TYPE 0x27 - -typedef struct { - uint8_t type; - uint8_t portMultiplierPort : 4, reserved : 3, commandControl : 1; - - uint8_t command, featureLow; - - uint8_t lba0, lba1, lba2, device; - - uint8_t lba3, lba4, lba5, featureHigh; - - uint8_t countLow, countHigh, isochronousCommandCompletion, control; - - uint8_t reserved_[4]; -} FisToDevice; - -void *getPointer(uint32_t lower, uint32_t upper) { - return (void *)(uintptr_t)(lower | (uintptr_t)upper << 32); -} - -uint32_t getType(PortControlRegisters *registers) { - uint32_t status = registers->sataStatus; - uint8_t detectionStatus = status & 0xF; - uint8_t interfacePowerManagement = (status >> 8) & 0xF; - if (detectionStatus != DEVICE_PRESENT || - interfacePowerManagement != POWER_ACTIVE) { - return AHCI_DEV_NULL; - } - switch (registers->signature) { - case SATA_ATAPI: - return AHCI_DEV_SATAPI; - case SATA_ENCLOSURE_MANAGEMENT_BRIDGE: - return AHCI_SEMB_DEVICE; - case SATA_SIG_PM: - return AHCI_DEV_PM; - default: - return AHCI_SATA_DEVICE; - } -} - -int8_t findFreeCommandHeader(PortControlRegisters *port) { - uint32_t filledSlots = port->sataControl | port->commandIssue; - for (uint8_t i = 0; i < 32; i++) { - if (!(filledSlots & 1 >> i)) { - return i; - } - } - return -1; -} - -void insertLba(FisToDevice *fis, uint64_t lba) { - fis->lba0 = (uint8_t)lba; - fis->lba1 = (uint8_t)(lba >> 8); - fis->lba2 = (uint8_t)(lba >> 16); - fis->lba3 = (uint8_t)(lba >> 24); - fis->lba4 = (uint8_t)(lba >> 32); - fis->lba5 = (uint8_t)(lba >> 40); -} - -void setupFisToRead(FisToDevice *fis, uint16_t sectorCount, uint64_t lba, - uint8_t command) { - fis->type = FIS_TO_DEVICE_TYPE; - fis->commandControl = 1; - fis->command = command; - fis->device = 1 << 6; - fis->countLow = (uint8_t)sectorCount; - fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, lba); -} - -void sataIssueCommand(PortControlRegisters *port) { - while (port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - port->commandIssue = 1; - while (port->commandIssue == 1) { - yields(); - } -} - -void sataCommand(PortControlRegisters *port, uint8_t command, void *buffer, - uint64_t lba, uint16_t sectorCount) { - port->interruptStatus = -1; - CommandListStructure *commandList = - getPointer(port->commandListLower, port->commandListUpper); - int8_t slot = findFreeCommandHeader(port); - if (slot == -1) { - printf("sata command failed: no free command header slot found!\n"); - return; - } - CommandHeader *commandHeader = &(commandList->commandHeaders[slot]); - commandHeader->fisLength = sizeof(FisToDevice) / sizeof(uint32_t); - commandHeader->write = 0; - commandHeader->regionDescriptorCount = 1; - CommandTable *commandTable = getPointer(commandHeader->commandTableLower, - commandHeader->commandTableUpper); - memset(commandTable, 0, - sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * - sizeof(PhysicalRegionDescriptor)); - commandTable->regionDescriptor[0].dataBaseLower = (uintptr_t)buffer; - commandTable->regionDescriptor[0].dataBaseUpper = (uintptr_t)buffer >> 32; - commandTable->regionDescriptor[0].byteCount = 511; - commandTable->regionDescriptor[0].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, sectorCount, lba, command); - sataIssueCommand(port); -} - -void sataDriveAccess(HardDrive *hardDrive, uint64_t lba, void *buffer, - uint16_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - sataCommand(interface->port, ATA_CMD_READ_DMA_EXT, buffer, lba, - sectorCount); -} - -#define HBA_PxCMD_ST 0x0001 -#define HBA_PxCMD_FRE 0x0010 -#define HBA_PxCMD_FR 0x4000 -#define HBA_PxCMD_CR 0x8000 - -void disableCommands(PortControlRegisters *port) { - port->command &= ~(HBA_PxCMD_ST | HBA_PxCMD_FRE); - while (port->command & HBA_PxCMD_FR && port->command + HBA_PxCMD_CR) { - } -} - -void enableCommands(PortControlRegisters *port) { - while (port->command & HBA_PxCMD_CR) { - } - port->command |= HBA_PxCMD_ST | HBA_PxCMD_FRE; -} - -void relocatePort(PortControlRegisters *port) { - // call only once for each port, nothing is being freed here - disableCommands(port); - CommandListStructure *commandList = - mallocAligned(sizeof(CommandListStructure), 10); - port->commandListLower = (uintptr_t)commandList; - port->commandListUpper = (uintptr_t)commandList >> 32; - uintptr_t fis = (uintptr_t)mallocAligned(sizeof(CommandListStructure), 10); - port->fisLower = fis; - port->fisUpper = (uintptr_t)commandList >> 32; - memset(commandList, 0, sizeof(CommandListStructure)); - for (uint8_t i = 0; i < 32; i++) { - uint16_t size = 256; // sizeof(CommandTable) - commandList->commandHeaders[i].regionDescriptorCount = 8; - uintptr_t commandTable = (uintptr_t)mallocAligned(size, 8); - commandList->commandHeaders[i].commandTableLower = commandTable; - commandList->commandHeaders[i].commandTableUpper = commandTable >> 32; - memset((void *)commandTable, 0, size); - } - enableCommands(port); -} - -void sataDeviceInitialize(PortControlRegisters *port, ListElement **drives, - HbaMemoryRegisters *registers) { - HardDrive *hardDrive = malloc(sizeof(HardDrive)); - SataInterface *interface = malloc(sizeof(SataInterface)); - hardDrive->access = sataDriveAccess; - hardDrive->interface = interface; - interface->registers = registers; - interface->port = port; - relocatePort(interface->port); - uint8_t *buffer = malloc(512); - sataCommand(port, ATA_CMD_IDENTIFY, buffer, 0, 1); - char *model = malloc(41); - for (int i = 0; i < 40; i += 2) { - *((uint16_t *)&model[i]) = buffer[54 + i + 1]; - *((uint16_t *)&model[i + 1]) = buffer[54 + i]; - } - model[41] = 0; - printf("model: %s\n", model); - hardDrive->model = model; - free(buffer); - listAdd(drives, hardDrive); -} - -void initializeSataController(PciDevice *pciDevice, ListElement **drives) { - if (pciDevice->programmingInterface != 1) { - // todo - return; - } - HbaMemoryRegisters *registers = (void *)(uintptr_t)pciDevice->bar5; - for (uint8_t i = 0; i < 32; i++) { - if (!(registers->implementedPorts & (1 << i))) { - continue; - } - uint32_t type = getType(®isters->ports[i]); - if (type == AHCI_DEV_NULL) { - continue; - } - if (type != AHCI_SATA_DEVICE) { - printf("type %i not implemented yet...\n", type); - // todo - continue; - } - sataDeviceInitialize(®isters->ports[i], drives, registers); - } -} diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index 275d1fa..7f407e1 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -13,7 +13,8 @@ } #define getOffset() \ - (alignment ? alignmentBit - ((uintptr_t)(current + 1) & (alignmentMask)) \ + (alignment ? alignmentMask & (alignmentBit - ((uintptr_t)(current + 1) & \ + (alignmentMask))) \ : 0) void memmove(uint8_t *to, uint8_t *from, uintptr_t count) { diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index ef60189..d420c60 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -28,9 +28,12 @@ #define CMD_COUNTER2 0x80 void sleep(uint16_t millis) { - uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + int32_t ticksLeft = getCurrentTask()->ticksLeft - millis; getCurrentTask()->ticksLeft = millis; yield(); + if (ticksLeft > 0) { + getCurrentTask()->ticksLeft = ticksLeft; + } } void setTimerFrequency(uint32_t hz) { diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c new file mode 100644 index 0000000..8f3e441 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +#define LOWER(ptr) (uint32_t)(uintptr_t) ptr +#define UPPER(ptr) (uint32_t)((uint64_t)(uintptr_t)ptr >> 32) + +uint8_t CheckPortType(HBAPort *Port) { + uint32_t SataStatus = Port->SataStatus; + + uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111; + uint8_t DeviceDetection = SataStatus & 0b111; + + if (DeviceDetection != HBA_PORT_DEV_PRESENT) { + return None; + } + if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE) { + return None; + } + + switch (Port->Signature) { + case SATA_SIG_ATAPI: + return SATAPI; + case SATA_SIG_ATA: + return SATA; + case SATA_SIG_PM: + return PM; + case SATA_SIG_SEMB: + return SEMB; + default: + return None; + } +} + +void configurePort(Port *); +bool ahciCommand(HBAPort *HBAPortPtr, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command); +void StartCMD(HBAPort *HBAPortPtr); +void StopCMD(HBAPort *HBAPortPtr); + +AtaIdentifyData ident; + +void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction) { + Port *port = (void *)drive->interface; + printf("start "); + yields(); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + printf("end %x\n", *(uint64_t *)buffer); + yields(); +} + +void preparePorts(HBAMemory *hba, ListElement **drives) { + for (uint8_t i = 0; i < 32; i++) { + if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { + continue; + } + uint8_t portType = CheckPortType(&hba->Ports[i]); + if (!portType) { + continue; + } + if (portType == SATAPI) { + printf("satapi devices not implemented yet!\n"); + yields(); + continue; + } + if (portType != SATA) { + continue; + } + Port *port = malloc(sizeof(Port)); + port->AHCIPortType = portType; + port->HBAPortPtr = &hba->Ports[i]; + configurePort(port); + printf("reconfigured the port\n"); + yields(); + ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->interface = port; + hardDrive->access = accessAHCIDrive; + addIdentifyData(hardDrive, &ident); + listAdd(drives, hardDrive); + } +} + +void configurePort(Port *port) { + HBAPort *HBAPortPtr = port->HBAPortPtr; + StopCMD(HBAPortPtr); + + HBACommandHeader *CommandHeader = mallocAligned(1024, 10); + HBAPortPtr->CommandListBase = LOWER(CommandHeader); + HBAPortPtr->CommandListBaseUpper = UPPER(CommandHeader); + memset(CommandHeader, 0, 1024); + + void *fis = mallocAligned(1024, 10); + HBAPortPtr->FISBaseAddress = LOWER(fis); + HBAPortPtr->FISBaseAddressUpper = UPPER(fis); + memset(fis, 0, 256); + for (int i = 0; i < 32; i++) { + CommandHeader[i].PRDTLength = 8; + void *CommandTable = mallocAligned(sizeof(HBACommandTable), 8); + CommandHeader[i].CommandTableBaseAddress = LOWER(CommandTable); + CommandHeader[i].CommandTableBaseAddressUpper = UPPER(CommandTable); + memset(CommandTable, 0, 256); + } + StartCMD(HBAPortPtr); +} + +void StopCMD(HBAPort *HBAPortPtr) { + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST; + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE; + + while (true) { + if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR) { + continue; + } + if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + continue; + } + break; + } +} + +void StartCMD(HBAPort *HBAPortPtr) { + while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + } + HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE; + HBAPortPtr->CommandStatus |= HBA_PxCMD_ST; +} + +#define HBA_PxIS_TFES (1 << 30) + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + hbaPort->InterruptEnable = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->PRDTLength = 1; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + memset(CommandTable, 0, sizeof(HBACommandTable)); + + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); + CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); + CommandTable->PRDTEntry[0].ByteCount = + SectorCount ? 512 * SectorCount - 1 : 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->command = command; + CommandFIS->LBA0 = (uint8_t)(Sector); + CommandFIS->LBA1 = (uint8_t)(Sector >> 8); + CommandFIS->LBA2 = (uint8_t)(Sector >> 16); + CommandFIS->LBA3 = (uint8_t)(Sector >> 24); + CommandFIS->LBA4 = (uint8_t)(Sector >> 32); + CommandFIS->LBA5 = (uint8_t)(Sector >> 40); + CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->countLow = SectorCount & 0xFF; + CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; + CommandFIS->Control = 0; // 1 << 3; + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return false; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return false; + } + } + printf("count: %i ", commandHeader->PRDBCount); + return true; +} + +#define OsOwnership (1 << 1) +#define BiosOwnership (1 << 0) + +void initializeSataController(PciDevice *pciDevice, ListElement **drives) { + if (pciDevice->programmingInterface != 1) { + return; + } + HBAMemory *hba = (void *)(uintptr_t)(pciDevice->bar5 & 0xFFFFFFF0); + if (!(hba->GlobalHostControl & (1 << 31))) { + printf("controller not in ahci mode!\n"); + return; + } + // hba->GlobalHostControl |= 1 << 31; + if (hba->HostCapabilitiesExtended & 1) { + printf("the os does not own the hba, getting it now...\n"); + yields(); + hba->BIOSHandoffControlStatus |= OsOwnership; + while (hba->BIOSHandoffControlStatus & BiosOwnership || + !(hba->BIOSHandoffControlStatus & OsOwnership)) { + } + } + // hba->GlobalHostControl |= 1; + // while (hba->GlobalHostControl & 1) { + //} + // hba->GlobalHostControl |= 1 << 31; + // sleep(1000); + // enabling bus mastering and memory access + // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, + // pciDevice->function, 4); + // command |= (1 << 1) | (1 << 2); + // pciConfigWriteByte(pciDevice->bus, pciDevice->device, + // pciDevice->function, + // 4, (uint8_t)command); + preparePorts(hba, drives); +} diff --git a/src/kernel/drivers/pci/hardDrive/ata.c b/src/kernel/drivers/pci/hardDrive/ata.c new file mode 100644 index 0000000..f339f11 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ata.c @@ -0,0 +1,25 @@ +#include +#include +#include + +void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data) { + hardDrive->model = malloc(41); + for (int i = 0; i < 40; i += 2) { + hardDrive->model[i] = data->model[i + 1]; + hardDrive->model[i + 1] = data->model[i]; + } + hardDrive->model[40] = 0; + if (data->CommandSetActive.BigLba) { + hardDrive->sectorCount = *((uint32_t *)data->Max48BitLBA); + } else { + hardDrive->sectorCount = data->ObsoleteWord62; + } + hardDrive->sectorSize = 512; + if (data->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words) { + hardDrive->sectorSize = ((uint32_t)data->WordsPerLogicalSector[0] | + (uint32_t)data->WordsPerLogicalSector[1] << 16) + << 1; + } + printf("sector count: %i, sector size: %i\nmodel: %s\n", + hardDrive->sectorCount, hardDrive->sectorSize, hardDrive->model); +} diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index a9c7a4e..0e8c536 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -5,6 +5,8 @@ #include #include +extern void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction); void scanHardDrives() { ListElement *drives = NULL; for (ListElement *current = *getPciDevices(); current; diff --git a/src/kernel/drivers/pci/hardDrive/ideController.c b/src/kernel/drivers/pci/hardDrive/ideController.c index e5ac6df..5d7a010 100644 --- a/src/kernel/drivers/pci/hardDrive/ideController.c +++ b/src/kernel/drivers/pci/hardDrive/ideController.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -224,17 +225,11 @@ // any bit has to be set if it is a real device continue; } - char *model = malloc(41); - for (int i = 0; i < 40; i += 2) { - *((uint16_t *)&model[i]) = buffer[54 + i + 1]; - *((uint16_t *)&model[i + 1]) = buffer[54 + i]; - } - model[40] = 0; usedChannels |= 1 << channel; HardDrive *hardDrive = malloc(sizeof(HardDrive)); IdeInterface *interface = malloc(sizeof(IdeInterface)); hardDrive->interface = interface; - hardDrive->model = model; + addIdentifyData(hardDrive, (void *)buffer); hardDrive->access = ideDriveAccess; interface->channels = CHANNEL; interface->channel = channel; @@ -245,14 +240,7 @@ interface->sectors = *(uint16_t *)buffer + 12; interface->capabilities = *(uint16_t *)buffer + 98; interface->commandSets = *(uint32_t *)(buffer + 164); - if (interface->commandSets + (1 << 26)) { - hardDrive->size = *(uint32_t *)buffer + 200; - } else { - hardDrive->size = *(uint32_t *)buffer + 120; - } listAdd(drives, hardDrive); - printf("found a hard drive %i sectors big, model: %s\n", - hardDrive->size, model); } } if (!(usedChannels & 1)) { diff --git a/src/kernel/drivers/pci/hardDrive/sataController.c b/src/kernel/drivers/pci/hardDrive/sataController.c deleted file mode 100644 index 13008e3..0000000 --- a/src/kernel/drivers/pci/hardDrive/sataController.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include -#include - -// information source: -// https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/serial-ata-ahci-spec-rev1_3.pdf - -#define SATA_ATA 0x00000101 -#define SATA_ATAPI 0xEB140101 -#define SATA_ENCLOSURE_MANAGEMENT_BRIDGE 0xC33C0101 -#define SATA_SIG_PM 0x96690101 - -#define AHCI_DEV_NULL 0 -#define AHCI_SATA_DEVICE 1 -#define AHCI_SEMB_DEVICE 2 -#define AHCI_DEV_PM 3 -#define AHCI_DEV_SATAPI 4 - -#define POWER_ACTIVE 1 -#define DEVICE_PRESENT 3 - -#define ATA_DEV_BUSY 0x80 -#define ATA_DEV_DRQ 0x08 - -typedef struct { - uint32_t commandListLower, commandListUpper; - uint32_t fisLower, fisUpper; - uint32_t interruptStatus, interruptEnable; - uint32_t command; - uint32_t reserved; - uint32_t taskFileData; - uint32_t signature; - uint32_t sataStatus, sataControl, sataError, sataActive; - uint32_t commandIssue; - uint32_t sataNotification; - uint32_t fisSwitchingControl; - uint32_t deviceSleep; - uint8_t reserved_[50]; - uint32_t vendorSpecific; -} PortControlRegisters; - -typedef struct { - uint32_t hostCapabilities, globalHostControl, interruptStatus, - implementedPorts, version, cccCtl, cccPts, enclosureManagementLocation, - enclosureManagementControl, hostCapabilitiesExtended, handoffStatus; - uint8_t reserved[116]; - uint8_t vendor[96]; - PortControlRegisters ports[32]; -} HbaMemoryRegisters; - -typedef struct { - uint8_t fisLength : 5, ATAPI : 1, write : 1, prefetchable : 1; - - uint8_t reset : 1, bist : 1, clearBusy : 1, reserved : 1, - portMultiplierPort : 4; - - uint16_t regionDescriptorCount; - - volatile uint32_t transferedBytes; - - uint32_t commandTableLower, commandTableUpper; - - uint32_t reserved_[4]; -} CommandHeader; - -typedef struct { - CommandHeader commandHeaders[32]; -} CommandListStructure; - -typedef struct { - uint32_t dataBaseLower, dataBaseUpper; - uint32_t reserved; - uint32_t byteCount : 22, reserved_ : 9, interrupt : 1; -} PhysicalRegionDescriptor; - -typedef struct { - uint8_t fis[64]; - uint8_t atapi[16]; - uint8_t reserved[48]; - PhysicalRegionDescriptor regionDescriptor[8]; -} CommandTable; - -typedef struct { - HbaMemoryRegisters *registers; - PortControlRegisters *port; -} SataInterface; - -#define FIS_TO_DEVICE_TYPE 0x27 - -typedef struct { - uint8_t type; - uint8_t portMultiplierPort : 4, reserved : 3, commandControl : 1; - - uint8_t command, featureLow; - - uint8_t lba0, lba1, lba2, device; - - uint8_t lba3, lba4, lba5, featureHigh; - - uint8_t countLow, countHigh, isochronousCommandCompletion, control; - - uint8_t reserved_[4]; -} FisToDevice; - -void *getPointer(uint32_t lower, uint32_t upper) { - return (void *)(uintptr_t)(lower | (uintptr_t)upper << 32); -} - -uint32_t getType(PortControlRegisters *registers) { - uint32_t status = registers->sataStatus; - uint8_t detectionStatus = status & 0xF; - uint8_t interfacePowerManagement = (status >> 8) & 0xF; - if (detectionStatus != DEVICE_PRESENT || - interfacePowerManagement != POWER_ACTIVE) { - return AHCI_DEV_NULL; - } - switch (registers->signature) { - case SATA_ATAPI: - return AHCI_DEV_SATAPI; - case SATA_ENCLOSURE_MANAGEMENT_BRIDGE: - return AHCI_SEMB_DEVICE; - case SATA_SIG_PM: - return AHCI_DEV_PM; - default: - return AHCI_SATA_DEVICE; - } -} - -int8_t findFreeCommandHeader(PortControlRegisters *port) { - uint32_t filledSlots = port->sataControl | port->commandIssue; - for (uint8_t i = 0; i < 32; i++) { - if (!(filledSlots & 1 >> i)) { - return i; - } - } - return -1; -} - -void insertLba(FisToDevice *fis, uint64_t lba) { - fis->lba0 = (uint8_t)lba; - fis->lba1 = (uint8_t)(lba >> 8); - fis->lba2 = (uint8_t)(lba >> 16); - fis->lba3 = (uint8_t)(lba >> 24); - fis->lba4 = (uint8_t)(lba >> 32); - fis->lba5 = (uint8_t)(lba >> 40); -} - -void setupFisToRead(FisToDevice *fis, uint16_t sectorCount, uint64_t lba, - uint8_t command) { - fis->type = FIS_TO_DEVICE_TYPE; - fis->commandControl = 1; - fis->command = command; - fis->device = 1 << 6; - fis->countLow = (uint8_t)sectorCount; - fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, lba); -} - -void sataIssueCommand(PortControlRegisters *port) { - while (port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - port->commandIssue = 1; - while (port->commandIssue == 1) { - yields(); - } -} - -void sataCommand(PortControlRegisters *port, uint8_t command, void *buffer, - uint64_t lba, uint16_t sectorCount) { - port->interruptStatus = -1; - CommandListStructure *commandList = - getPointer(port->commandListLower, port->commandListUpper); - int8_t slot = findFreeCommandHeader(port); - if (slot == -1) { - printf("sata command failed: no free command header slot found!\n"); - return; - } - CommandHeader *commandHeader = &(commandList->commandHeaders[slot]); - commandHeader->fisLength = sizeof(FisToDevice) / sizeof(uint32_t); - commandHeader->write = 0; - commandHeader->regionDescriptorCount = 1; - CommandTable *commandTable = getPointer(commandHeader->commandTableLower, - commandHeader->commandTableUpper); - memset(commandTable, 0, - sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * - sizeof(PhysicalRegionDescriptor)); - commandTable->regionDescriptor[0].dataBaseLower = (uintptr_t)buffer; - commandTable->regionDescriptor[0].dataBaseUpper = (uintptr_t)buffer >> 32; - commandTable->regionDescriptor[0].byteCount = 511; - commandTable->regionDescriptor[0].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, sectorCount, lba, command); - sataIssueCommand(port); -} - -void sataDriveAccess(HardDrive *hardDrive, uint64_t lba, void *buffer, - uint16_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - sataCommand(interface->port, ATA_CMD_READ_DMA_EXT, buffer, lba, - sectorCount); -} - -#define HBA_PxCMD_ST 0x0001 -#define HBA_PxCMD_FRE 0x0010 -#define HBA_PxCMD_FR 0x4000 -#define HBA_PxCMD_CR 0x8000 - -void disableCommands(PortControlRegisters *port) { - port->command &= ~(HBA_PxCMD_ST | HBA_PxCMD_FRE); - while (port->command & HBA_PxCMD_FR && port->command + HBA_PxCMD_CR) { - } -} - -void enableCommands(PortControlRegisters *port) { - while (port->command & HBA_PxCMD_CR) { - } - port->command |= HBA_PxCMD_ST | HBA_PxCMD_FRE; -} - -void relocatePort(PortControlRegisters *port) { - // call only once for each port, nothing is being freed here - disableCommands(port); - CommandListStructure *commandList = - mallocAligned(sizeof(CommandListStructure), 10); - port->commandListLower = (uintptr_t)commandList; - port->commandListUpper = (uintptr_t)commandList >> 32; - uintptr_t fis = (uintptr_t)mallocAligned(sizeof(CommandListStructure), 10); - port->fisLower = fis; - port->fisUpper = (uintptr_t)commandList >> 32; - memset(commandList, 0, sizeof(CommandListStructure)); - for (uint8_t i = 0; i < 32; i++) { - uint16_t size = 256; // sizeof(CommandTable) - commandList->commandHeaders[i].regionDescriptorCount = 8; - uintptr_t commandTable = (uintptr_t)mallocAligned(size, 8); - commandList->commandHeaders[i].commandTableLower = commandTable; - commandList->commandHeaders[i].commandTableUpper = commandTable >> 32; - memset((void *)commandTable, 0, size); - } - enableCommands(port); -} - -void sataDeviceInitialize(PortControlRegisters *port, ListElement **drives, - HbaMemoryRegisters *registers) { - HardDrive *hardDrive = malloc(sizeof(HardDrive)); - SataInterface *interface = malloc(sizeof(SataInterface)); - hardDrive->access = sataDriveAccess; - hardDrive->interface = interface; - interface->registers = registers; - interface->port = port; - relocatePort(interface->port); - uint8_t *buffer = malloc(512); - sataCommand(port, ATA_CMD_IDENTIFY, buffer, 0, 1); - char *model = malloc(41); - for (int i = 0; i < 40; i += 2) { - *((uint16_t *)&model[i]) = buffer[54 + i + 1]; - *((uint16_t *)&model[i + 1]) = buffer[54 + i]; - } - model[41] = 0; - printf("model: %s\n", model); - hardDrive->model = model; - free(buffer); - listAdd(drives, hardDrive); -} - -void initializeSataController(PciDevice *pciDevice, ListElement **drives) { - if (pciDevice->programmingInterface != 1) { - // todo - return; - } - HbaMemoryRegisters *registers = (void *)(uintptr_t)pciDevice->bar5; - for (uint8_t i = 0; i < 32; i++) { - if (!(registers->implementedPorts & (1 << i))) { - continue; - } - uint32_t type = getType(®isters->ports[i]); - if (type == AHCI_DEV_NULL) { - continue; - } - if (type != AHCI_SATA_DEVICE) { - printf("type %i not implemented yet...\n", type); - // todo - continue; - } - sataDeviceInitialize(®isters->ports[i], drives, registers); - } -} diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index 275d1fa..7f407e1 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -13,7 +13,8 @@ } #define getOffset() \ - (alignment ? alignmentBit - ((uintptr_t)(current + 1) & (alignmentMask)) \ + (alignment ? alignmentMask & (alignmentBit - ((uintptr_t)(current + 1) & \ + (alignmentMask))) \ : 0) void memmove(uint8_t *to, uint8_t *from, uintptr_t count) { diff --git a/src/kernel/memory/fileSystem.c b/src/kernel/memory/fileSystem.c index b88b4ff..9d4b9f7 100644 --- a/src/kernel/memory/fileSystem.c +++ b/src/kernel/memory/fileSystem.c @@ -8,7 +8,7 @@ void printFolderTree(FileSystemFolder *folder, char *prefix) { char *nextPrefix = stringCombine(prefix, " "); - for (ListElement *current = *folder->children; current; + for (ListElement *current = folder->children; current; current = current->next) { FileSystemTreeNode *child = current->data; printf("%s%s\n", prefix, child->name); @@ -153,9 +153,9 @@ uint32_t cluster = directory->firstDataClusterLower | directory->fistDataClusterUpper << 16; folder->cluster = cluster; - listAdd(parent->children, folder); + listAdd(&parent->children, folder); if (info->knownFolders[cluster]) { - folder->children = info->knownFolders[cluster]; + folder->children = *info->knownFolders[cluster]; return; } if (cluster == 0) { @@ -163,8 +163,8 @@ return; } folder->children = malloc(sizeof(ListElement **)); - info->knownFolders[cluster] = folder->children; - *folder->children = NULL; + info->knownFolders[cluster] = &folder->children; + folder->children = NULL; void *data = readClusterChain(info, cluster); scanFolder(info, data, folder); free(data); @@ -180,7 +180,7 @@ file->type = FS_FILE; file->subType = 0; file->size = directory->size; - listAdd(parent->children, file); + listAdd(&parent->children, file); } void setupChild(char *name, FatDirectoryEntry *directoryEntry, FatInfo *info, @@ -224,12 +224,17 @@ FatInfo *info; void mountDisk(HardDrive *drive) { + if (!drive) { + printf("no drive available to mount\n"); + yields(); + return; + } void *bootSector = malloc(512); drive->access(drive, 0, bootSector, 1, 0); FatBootSector *boot = bootSector; info = malloc(sizeof(FatInfo)); setupFatInfo(info, boot, drive); - rootFolder.children = malloc(sizeof(ListElement *)); + rootFolder.children = 0; void *data = malloc(info->clusterSize * info->rootDirectorySize); info->hardDrive->access(info->hardDrive, info->firstRootSector, data, info->rootDirectorySize, 0); @@ -242,10 +247,13 @@ printf("relative file paths not implemented yet!\n"); return NULL; } + if (rootFolder.children == NULL) { + return NULL; + } char *currentName = path + 1; FileSystemFolder *currentFolder = &rootFolder; while (strlen(currentName)) { - foreach (*currentFolder->children) { + foreach (currentFolder->children) { FileSystemTreeNode *node = current->data; uint16_t i; for (i = 0; currentName[i] != '/' && currentName[i] != 0; i++) { diff --git a/Makefile b/Makefile index 2b35f61..e9c02be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC = i686-elf-gcc -CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 LD = i686-elf-ld LD_FLAGS = -z max-page-size=0x1000 -T linker.ld AS = nasm @@ -7,7 +7,7 @@ GENISO = genisoimage GENISOFLAGS = -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -input-charset utf8 -quiet -boot-info-table -A tree-os EMU = qemu-system-x86_64 -EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img +EMUFLAGS = -m 256M -drive format=raw,file=tree-os.iso -drive format=raw,file=disk.img,id=disk,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 BUILD_FOLDER = build diff --git a/src/include/ahci.h b/src/include/ahci.h new file mode 100644 index 0000000..8c63ca2 --- /dev/null +++ b/src/include/ahci.h @@ -0,0 +1,141 @@ +#ifndef AHCI_H +#define AHCI_H + +#include + +typedef enum PortType { + None = 0, + SATA = 1, + SEMB = 2, + PM = 3, + SATAPI = 4, +} PortType; + +typedef enum FIS_TYPE { + FIS_TYPE_REG_H2D = 0x27, + FIS_TYPE_REG_D2H = 0x34, + FIS_TYPE_DMA_ACT = 0x39, + FIS_TYPE_DMA_SETUP = 0x41, + FIS_TYPE_DATA = 0x46, + FIS_TYPE_BIST = 0x58, + FIS_TYPE_PIO_SETUP = 0x5F, + FIS_TYPE_DEV_BITS = 0xA1, +} FIS_TYPE; + +typedef struct HBAPort { + uint32_t CommandListBase; + uint32_t CommandListBaseUpper; + uint32_t FISBaseAddress; + uint32_t FISBaseAddressUpper; + uint32_t InterruptStatus; + uint32_t InterruptEnable; + uint32_t CommandStatus; + uint32_t Reserved0; + uint32_t TaskFileData; + uint32_t Signature; + uint32_t SataStatus; + uint32_t SataControl; + uint32_t SataError; + uint32_t SataActive; + uint32_t CommandIssue; + uint32_t SataNotification; + uint32_t FISSwitchControl; + uint32_t Reserved1[11]; + uint32_t Vendor[4]; +} HBAPort; + +typedef struct HBAMemory { + uint32_t HostCapability; + uint32_t GlobalHostControl; + uint32_t InterruptStatus; + uint32_t PortsImplemented; + uint32_t Version; + uint32_t CCCControl; + uint32_t CCCPorts; + uint32_t EnclosureManagementLocation; + uint32_t EnclosureManagementControl; + uint32_t HostCapabilitiesExtended; + uint32_t BIOSHandoffControlStatus; + uint8_t Reserved0[0x74]; + uint8_t Vendor[0x60]; + HBAPort Ports[1]; +} HBAMemory; + +typedef struct HBACommandHeader { + uint8_t CommandFISLength : 5; + uint8_t ATAPI : 1; + uint8_t Write : 1; + uint8_t Prefetchable : 1; + + uint8_t Reset : 1; + uint8_t BIST : 1; + uint8_t ClearBusy : 1; + uint8_t Reserved0 : 1; + uint8_t PortMultiplier : 4; + + uint16_t PRDTLength; + uint32_t PRDBCount; + uint32_t CommandTableBaseAddress; + uint32_t CommandTableBaseAddressUpper; + uint32_t Reserved1[4]; +} HBACommandHeader; + +typedef struct HBAPRDTEntry { + uint32_t DataBaseAddress; + uint32_t DataBaseAddressUpper; + uint32_t Reserved0; + + uint32_t ByteCount : 22; + uint32_t Reserved1 : 9; + uint32_t InterruptOnCompletion : 1; +} HBAPRDTEntry; + +typedef struct HBACommandTable { + uint8_t CommandFIS[64]; + uint8_t ATAPICommand[16]; + uint8_t Reserved[48]; + HBAPRDTEntry PRDTEntry[]; +} HBACommandTable; + +typedef struct { + uint8_t FISType; + uint8_t PortMultiplier; + uint8_t command; + uint8_t FeatureLow; + + uint8_t LBA0; + uint8_t LBA1; + uint8_t LBA2; + uint8_t DeviceRegister; + + uint8_t LBA3; + uint8_t LBA4; + uint8_t LBA5; + uint8_t FeatureHigh; + + uint8_t countLow; + uint8_t countHigh; + uint8_t ISOCommandCompletion; + uint8_t Control; + + uint8_t Reserved1[4]; +} FisToDevice; + +typedef struct Port { + PortType AHCIPortType; + HBAPort *HBAPortPtr; +} Port; + +#define HBA_PORT_DEV_PRESENT 0x3 +#define HBA_PORT_IPM_ACTIVE 0x1 +#define SATA_SIG_ATAPI 0xEB140101 +#define SATA_SIG_ATA 0x00000101 +#define SATA_SIG_SEMB 0xC33C0101 +#define SATA_SIG_PM 0x96690101 + +#define HBA_PxCMD_CR 0x8000 +#define HBA_PxCMD_FRE 0x0010 +#define HBA_PxCMD_ST 0x0001 +#define HBA_PxCMD_FR 0x4000 + +#endif diff --git a/src/include/ata.h b/src/include/ata.h new file mode 100644 index 0000000..7a40dd6 --- /dev/null +++ b/src/include/ata.h @@ -0,0 +1,402 @@ +#ifndef ATA_H +#define ATA_H + +#include +#include + +// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data + +#define ATA_DEV_BUSY 0x80 +#define ATA_DEV_DRQ 0x08 +#define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 + +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + 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]; + char model[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; + uint64_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; + uint64_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; + uint64_t StreamingPerfGranularity; + uint64_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]; + uint64_t ExtendedNumberOfUserAddressableSectors[2]; + uint16_t MinBlocksPerDownloadMicrocodeMode03; + uint16_t MaxBlocksPerDownloadMicrocodeMode03; + uint16_t ReservedWord236[19]; + uint16_t Signature : 8; + uint16_t CheckSum : 8; +} AtaIdentifyData; + +extern void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data); + +#endif diff --git a/src/include/fileSystem.h b/src/include/fileSystem.h index 1063b2a..ef5d9ee 100644 --- a/src/include/fileSystem.h +++ b/src/include/fileSystem.h @@ -20,7 +20,7 @@ typedef struct { FileSystemTreeNode; - ListElement **children; + ListElement *children; } FileSystemFolder; typedef struct { diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 28eae99..00e0096 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -5,23 +5,10 @@ #include #include -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC - typedef struct HardDrive { char *model; - uint32_t size; + uint32_t sectorCount; + uint32_t sectorSize; void *interface; void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point diff --git a/src/include/pci.h b/src/include/pci.h index 9a16b66..1bf83ee 100644 --- a/src/include/pci.h +++ b/src/include/pci.h @@ -16,4 +16,12 @@ extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, uint8_t offset, uint8_t data); +extern uint8_t pciConfigReadByte(uint32_t bus, uint32_t device, + uint32_t function, uint8_t offset); +extern void pciConfigWriteByte(uint32_t bus, uint32_t device, uint32_t function, + uint8_t offset, uint8_t data); +extern uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +extern uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); #endif diff --git a/src/kernel/drivers/interrupts/exceptions.c b/src/kernel/drivers/interrupts/exceptions.c index f443dfa..c24dda6 100644 --- a/src/kernel/drivers/interrupts/exceptions.c +++ b/src/kernel/drivers/interrupts/exceptions.c @@ -73,5 +73,5 @@ void handleException(regs *registers) { printf("exception %s was raised with error code 0x%x!\n", EXCEPTION_MESSAGES[registers->int_no], registers->err_code); - yields(); + yield(); } diff --git a/src/kernel/drivers/interrupts/timer/timer.c b/src/kernel/drivers/interrupts/timer/timer.c index ef60189..d420c60 100644 --- a/src/kernel/drivers/interrupts/timer/timer.c +++ b/src/kernel/drivers/interrupts/timer/timer.c @@ -28,9 +28,12 @@ #define CMD_COUNTER2 0x80 void sleep(uint16_t millis) { - uint32_t ticksLeft = getCurrentTask()->ticksLeft - millis; + int32_t ticksLeft = getCurrentTask()->ticksLeft - millis; getCurrentTask()->ticksLeft = millis; yield(); + if (ticksLeft > 0) { + getCurrentTask()->ticksLeft = ticksLeft; + } } void setTimerFrequency(uint32_t hz) { diff --git a/src/kernel/drivers/pci/hardDrive/ahciController.c b/src/kernel/drivers/pci/hardDrive/ahciController.c new file mode 100644 index 0000000..8f3e441 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ahciController.c @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include + +#define LOWER(ptr) (uint32_t)(uintptr_t) ptr +#define UPPER(ptr) (uint32_t)((uint64_t)(uintptr_t)ptr >> 32) + +uint8_t CheckPortType(HBAPort *Port) { + uint32_t SataStatus = Port->SataStatus; + + uint8_t InterfacePowerManagement = (SataStatus >> 8) & 0b111; + uint8_t DeviceDetection = SataStatus & 0b111; + + if (DeviceDetection != HBA_PORT_DEV_PRESENT) { + return None; + } + if (InterfacePowerManagement != HBA_PORT_IPM_ACTIVE) { + return None; + } + + switch (Port->Signature) { + case SATA_SIG_ATAPI: + return SATAPI; + case SATA_SIG_ATA: + return SATA; + case SATA_SIG_PM: + return PM; + case SATA_SIG_SEMB: + return SEMB; + default: + return None; + } +} + +void configurePort(Port *); +bool ahciCommand(HBAPort *HBAPortPtr, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command); +void StartCMD(HBAPort *HBAPortPtr); +void StopCMD(HBAPort *HBAPortPtr); + +AtaIdentifyData ident; + +void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction) { + Port *port = (void *)drive->interface; + printf("start "); + yields(); + ahciCommand(port->HBAPortPtr, lba, buffer, count, ATA_CMD_READ_DMA_EXT); + printf("end %x\n", *(uint64_t *)buffer); + yields(); +} + +void preparePorts(HBAMemory *hba, ListElement **drives) { + for (uint8_t i = 0; i < 32; i++) { + if (!(hba->PortsImplemented & (uint32_t)(1 << i))) { + continue; + } + uint8_t portType = CheckPortType(&hba->Ports[i]); + if (!portType) { + continue; + } + if (portType == SATAPI) { + printf("satapi devices not implemented yet!\n"); + yields(); + continue; + } + if (portType != SATA) { + continue; + } + Port *port = malloc(sizeof(Port)); + port->AHCIPortType = portType; + port->HBAPortPtr = &hba->Ports[i]; + configurePort(port); + printf("reconfigured the port\n"); + yields(); + ahciCommand(port->HBAPortPtr, 0, &ident, 0, ATA_CMD_IDENTIFY); + HardDrive *hardDrive = malloc(sizeof(HardDrive)); + hardDrive->interface = port; + hardDrive->access = accessAHCIDrive; + addIdentifyData(hardDrive, &ident); + listAdd(drives, hardDrive); + } +} + +void configurePort(Port *port) { + HBAPort *HBAPortPtr = port->HBAPortPtr; + StopCMD(HBAPortPtr); + + HBACommandHeader *CommandHeader = mallocAligned(1024, 10); + HBAPortPtr->CommandListBase = LOWER(CommandHeader); + HBAPortPtr->CommandListBaseUpper = UPPER(CommandHeader); + memset(CommandHeader, 0, 1024); + + void *fis = mallocAligned(1024, 10); + HBAPortPtr->FISBaseAddress = LOWER(fis); + HBAPortPtr->FISBaseAddressUpper = UPPER(fis); + memset(fis, 0, 256); + for (int i = 0; i < 32; i++) { + CommandHeader[i].PRDTLength = 8; + void *CommandTable = mallocAligned(sizeof(HBACommandTable), 8); + CommandHeader[i].CommandTableBaseAddress = LOWER(CommandTable); + CommandHeader[i].CommandTableBaseAddressUpper = UPPER(CommandTable); + memset(CommandTable, 0, 256); + } + StartCMD(HBAPortPtr); +} + +void StopCMD(HBAPort *HBAPortPtr) { + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_ST; + HBAPortPtr->CommandStatus &= ~HBA_PxCMD_FRE; + + while (true) { + if (HBAPortPtr->CommandStatus & HBA_PxCMD_FR) { + continue; + } + if (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + continue; + } + break; + } +} + +void StartCMD(HBAPort *HBAPortPtr) { + while (HBAPortPtr->CommandStatus & HBA_PxCMD_CR) { + } + HBAPortPtr->CommandStatus |= HBA_PxCMD_FRE; + HBAPortPtr->CommandStatus |= HBA_PxCMD_ST; +} + +#define HBA_PxIS_TFES (1 << 30) + +bool ahciCommand(HBAPort *hbaPort, uint64_t Sector, void *Buffer, + uint32_t SectorCount, uint8_t command) { + hbaPort->InterruptStatus = (uint32_t)-1; + hbaPort->InterruptEnable = (uint32_t)-1; + HBACommandHeader *commandHeader = + (void *)(uintptr_t)hbaPort->CommandListBase; + commandHeader->CommandFISLength = sizeof(FisToDevice) / sizeof(uint32_t); + commandHeader->Write = 0; + commandHeader->ClearBusy = SectorCount ? 1 : 0; + commandHeader->PRDTLength = 1; + + HBACommandTable *CommandTable = + (void *)(uintptr_t)(commandHeader->CommandTableBaseAddress); + memset(CommandTable, 0, sizeof(HBACommandTable)); + + CommandTable->PRDTEntry[0].DataBaseAddress = LOWER(Buffer); + CommandTable->PRDTEntry[0].DataBaseAddressUpper = UPPER(Buffer); + CommandTable->PRDTEntry[0].ByteCount = + SectorCount ? 512 * SectorCount - 1 : 511; + CommandTable->PRDTEntry[0].InterruptOnCompletion = 0; // 1; + + FisToDevice *CommandFIS = (FisToDevice *)(&CommandTable->CommandFIS); + CommandFIS->FISType = FIS_TYPE_REG_H2D; + CommandFIS->PortMultiplier = 1 << 7; + CommandFIS->command = command; + CommandFIS->LBA0 = (uint8_t)(Sector); + CommandFIS->LBA1 = (uint8_t)(Sector >> 8); + CommandFIS->LBA2 = (uint8_t)(Sector >> 16); + CommandFIS->LBA3 = (uint8_t)(Sector >> 24); + CommandFIS->LBA4 = (uint8_t)(Sector >> 32); + CommandFIS->LBA5 = (uint8_t)(Sector >> 40); + CommandFIS->DeviceRegister = (1 << 6); + CommandFIS->countLow = SectorCount & 0xFF; + CommandFIS->countHigh = (SectorCount >> 8) & 0xFF; + CommandFIS->Control = 0; // 1 << 3; + uint64_t Spin = 0; + while ((hbaPort->TaskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && + Spin < 1000000) { + Spin++; + } + if (Spin == 1000000) { + printf("ahci command timeout\n"); + return false; + } + hbaPort->CommandIssue = 1; + while (true) { + if (hbaPort->CommandIssue == 0) { + break; + } + if (hbaPort->InterruptStatus & HBA_PxIS_TFES) { + return false; + } + } + printf("count: %i ", commandHeader->PRDBCount); + return true; +} + +#define OsOwnership (1 << 1) +#define BiosOwnership (1 << 0) + +void initializeSataController(PciDevice *pciDevice, ListElement **drives) { + if (pciDevice->programmingInterface != 1) { + return; + } + HBAMemory *hba = (void *)(uintptr_t)(pciDevice->bar5 & 0xFFFFFFF0); + if (!(hba->GlobalHostControl & (1 << 31))) { + printf("controller not in ahci mode!\n"); + return; + } + // hba->GlobalHostControl |= 1 << 31; + if (hba->HostCapabilitiesExtended & 1) { + printf("the os does not own the hba, getting it now...\n"); + yields(); + hba->BIOSHandoffControlStatus |= OsOwnership; + while (hba->BIOSHandoffControlStatus & BiosOwnership || + !(hba->BIOSHandoffControlStatus & OsOwnership)) { + } + } + // hba->GlobalHostControl |= 1; + // while (hba->GlobalHostControl & 1) { + //} + // hba->GlobalHostControl |= 1 << 31; + // sleep(1000); + // enabling bus mastering and memory access + // uint16_t command = pciConfigReadWord(pciDevice->bus, pciDevice->device, + // pciDevice->function, 4); + // command |= (1 << 1) | (1 << 2); + // pciConfigWriteByte(pciDevice->bus, pciDevice->device, + // pciDevice->function, + // 4, (uint8_t)command); + preparePorts(hba, drives); +} diff --git a/src/kernel/drivers/pci/hardDrive/ata.c b/src/kernel/drivers/pci/hardDrive/ata.c new file mode 100644 index 0000000..f339f11 --- /dev/null +++ b/src/kernel/drivers/pci/hardDrive/ata.c @@ -0,0 +1,25 @@ +#include +#include +#include + +void addIdentifyData(HardDrive *hardDrive, AtaIdentifyData *data) { + hardDrive->model = malloc(41); + for (int i = 0; i < 40; i += 2) { + hardDrive->model[i] = data->model[i + 1]; + hardDrive->model[i + 1] = data->model[i]; + } + hardDrive->model[40] = 0; + if (data->CommandSetActive.BigLba) { + hardDrive->sectorCount = *((uint32_t *)data->Max48BitLBA); + } else { + hardDrive->sectorCount = data->ObsoleteWord62; + } + hardDrive->sectorSize = 512; + if (data->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words) { + hardDrive->sectorSize = ((uint32_t)data->WordsPerLogicalSector[0] | + (uint32_t)data->WordsPerLogicalSector[1] << 16) + << 1; + } + printf("sector count: %i, sector size: %i\nmodel: %s\n", + hardDrive->sectorCount, hardDrive->sectorSize, hardDrive->model); +} diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index a9c7a4e..0e8c536 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -5,6 +5,8 @@ #include #include +extern void accessAHCIDrive(HardDrive *drive, uint64_t lba, void *buffer, + uint16_t count, uint8_t direction); void scanHardDrives() { ListElement *drives = NULL; for (ListElement *current = *getPciDevices(); current; diff --git a/src/kernel/drivers/pci/hardDrive/ideController.c b/src/kernel/drivers/pci/hardDrive/ideController.c index e5ac6df..5d7a010 100644 --- a/src/kernel/drivers/pci/hardDrive/ideController.c +++ b/src/kernel/drivers/pci/hardDrive/ideController.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -224,17 +225,11 @@ // any bit has to be set if it is a real device continue; } - char *model = malloc(41); - for (int i = 0; i < 40; i += 2) { - *((uint16_t *)&model[i]) = buffer[54 + i + 1]; - *((uint16_t *)&model[i + 1]) = buffer[54 + i]; - } - model[40] = 0; usedChannels |= 1 << channel; HardDrive *hardDrive = malloc(sizeof(HardDrive)); IdeInterface *interface = malloc(sizeof(IdeInterface)); hardDrive->interface = interface; - hardDrive->model = model; + addIdentifyData(hardDrive, (void *)buffer); hardDrive->access = ideDriveAccess; interface->channels = CHANNEL; interface->channel = channel; @@ -245,14 +240,7 @@ interface->sectors = *(uint16_t *)buffer + 12; interface->capabilities = *(uint16_t *)buffer + 98; interface->commandSets = *(uint32_t *)(buffer + 164); - if (interface->commandSets + (1 << 26)) { - hardDrive->size = *(uint32_t *)buffer + 200; - } else { - hardDrive->size = *(uint32_t *)buffer + 120; - } listAdd(drives, hardDrive); - printf("found a hard drive %i sectors big, model: %s\n", - hardDrive->size, model); } } if (!(usedChannels & 1)) { diff --git a/src/kernel/drivers/pci/hardDrive/sataController.c b/src/kernel/drivers/pci/hardDrive/sataController.c deleted file mode 100644 index 13008e3..0000000 --- a/src/kernel/drivers/pci/hardDrive/sataController.c +++ /dev/null @@ -1,287 +0,0 @@ -#include -#include -#include - -// information source: -// https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/serial-ata-ahci-spec-rev1_3.pdf - -#define SATA_ATA 0x00000101 -#define SATA_ATAPI 0xEB140101 -#define SATA_ENCLOSURE_MANAGEMENT_BRIDGE 0xC33C0101 -#define SATA_SIG_PM 0x96690101 - -#define AHCI_DEV_NULL 0 -#define AHCI_SATA_DEVICE 1 -#define AHCI_SEMB_DEVICE 2 -#define AHCI_DEV_PM 3 -#define AHCI_DEV_SATAPI 4 - -#define POWER_ACTIVE 1 -#define DEVICE_PRESENT 3 - -#define ATA_DEV_BUSY 0x80 -#define ATA_DEV_DRQ 0x08 - -typedef struct { - uint32_t commandListLower, commandListUpper; - uint32_t fisLower, fisUpper; - uint32_t interruptStatus, interruptEnable; - uint32_t command; - uint32_t reserved; - uint32_t taskFileData; - uint32_t signature; - uint32_t sataStatus, sataControl, sataError, sataActive; - uint32_t commandIssue; - uint32_t sataNotification; - uint32_t fisSwitchingControl; - uint32_t deviceSleep; - uint8_t reserved_[50]; - uint32_t vendorSpecific; -} PortControlRegisters; - -typedef struct { - uint32_t hostCapabilities, globalHostControl, interruptStatus, - implementedPorts, version, cccCtl, cccPts, enclosureManagementLocation, - enclosureManagementControl, hostCapabilitiesExtended, handoffStatus; - uint8_t reserved[116]; - uint8_t vendor[96]; - PortControlRegisters ports[32]; -} HbaMemoryRegisters; - -typedef struct { - uint8_t fisLength : 5, ATAPI : 1, write : 1, prefetchable : 1; - - uint8_t reset : 1, bist : 1, clearBusy : 1, reserved : 1, - portMultiplierPort : 4; - - uint16_t regionDescriptorCount; - - volatile uint32_t transferedBytes; - - uint32_t commandTableLower, commandTableUpper; - - uint32_t reserved_[4]; -} CommandHeader; - -typedef struct { - CommandHeader commandHeaders[32]; -} CommandListStructure; - -typedef struct { - uint32_t dataBaseLower, dataBaseUpper; - uint32_t reserved; - uint32_t byteCount : 22, reserved_ : 9, interrupt : 1; -} PhysicalRegionDescriptor; - -typedef struct { - uint8_t fis[64]; - uint8_t atapi[16]; - uint8_t reserved[48]; - PhysicalRegionDescriptor regionDescriptor[8]; -} CommandTable; - -typedef struct { - HbaMemoryRegisters *registers; - PortControlRegisters *port; -} SataInterface; - -#define FIS_TO_DEVICE_TYPE 0x27 - -typedef struct { - uint8_t type; - uint8_t portMultiplierPort : 4, reserved : 3, commandControl : 1; - - uint8_t command, featureLow; - - uint8_t lba0, lba1, lba2, device; - - uint8_t lba3, lba4, lba5, featureHigh; - - uint8_t countLow, countHigh, isochronousCommandCompletion, control; - - uint8_t reserved_[4]; -} FisToDevice; - -void *getPointer(uint32_t lower, uint32_t upper) { - return (void *)(uintptr_t)(lower | (uintptr_t)upper << 32); -} - -uint32_t getType(PortControlRegisters *registers) { - uint32_t status = registers->sataStatus; - uint8_t detectionStatus = status & 0xF; - uint8_t interfacePowerManagement = (status >> 8) & 0xF; - if (detectionStatus != DEVICE_PRESENT || - interfacePowerManagement != POWER_ACTIVE) { - return AHCI_DEV_NULL; - } - switch (registers->signature) { - case SATA_ATAPI: - return AHCI_DEV_SATAPI; - case SATA_ENCLOSURE_MANAGEMENT_BRIDGE: - return AHCI_SEMB_DEVICE; - case SATA_SIG_PM: - return AHCI_DEV_PM; - default: - return AHCI_SATA_DEVICE; - } -} - -int8_t findFreeCommandHeader(PortControlRegisters *port) { - uint32_t filledSlots = port->sataControl | port->commandIssue; - for (uint8_t i = 0; i < 32; i++) { - if (!(filledSlots & 1 >> i)) { - return i; - } - } - return -1; -} - -void insertLba(FisToDevice *fis, uint64_t lba) { - fis->lba0 = (uint8_t)lba; - fis->lba1 = (uint8_t)(lba >> 8); - fis->lba2 = (uint8_t)(lba >> 16); - fis->lba3 = (uint8_t)(lba >> 24); - fis->lba4 = (uint8_t)(lba >> 32); - fis->lba5 = (uint8_t)(lba >> 40); -} - -void setupFisToRead(FisToDevice *fis, uint16_t sectorCount, uint64_t lba, - uint8_t command) { - fis->type = FIS_TO_DEVICE_TYPE; - fis->commandControl = 1; - fis->command = command; - fis->device = 1 << 6; - fis->countLow = (uint8_t)sectorCount; - fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, lba); -} - -void sataIssueCommand(PortControlRegisters *port) { - while (port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - port->commandIssue = 1; - while (port->commandIssue == 1) { - yields(); - } -} - -void sataCommand(PortControlRegisters *port, uint8_t command, void *buffer, - uint64_t lba, uint16_t sectorCount) { - port->interruptStatus = -1; - CommandListStructure *commandList = - getPointer(port->commandListLower, port->commandListUpper); - int8_t slot = findFreeCommandHeader(port); - if (slot == -1) { - printf("sata command failed: no free command header slot found!\n"); - return; - } - CommandHeader *commandHeader = &(commandList->commandHeaders[slot]); - commandHeader->fisLength = sizeof(FisToDevice) / sizeof(uint32_t); - commandHeader->write = 0; - commandHeader->regionDescriptorCount = 1; - CommandTable *commandTable = getPointer(commandHeader->commandTableLower, - commandHeader->commandTableUpper); - memset(commandTable, 0, - sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * - sizeof(PhysicalRegionDescriptor)); - commandTable->regionDescriptor[0].dataBaseLower = (uintptr_t)buffer; - commandTable->regionDescriptor[0].dataBaseUpper = (uintptr_t)buffer >> 32; - commandTable->regionDescriptor[0].byteCount = 511; - commandTable->regionDescriptor[0].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, sectorCount, lba, command); - sataIssueCommand(port); -} - -void sataDriveAccess(HardDrive *hardDrive, uint64_t lba, void *buffer, - uint16_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - sataCommand(interface->port, ATA_CMD_READ_DMA_EXT, buffer, lba, - sectorCount); -} - -#define HBA_PxCMD_ST 0x0001 -#define HBA_PxCMD_FRE 0x0010 -#define HBA_PxCMD_FR 0x4000 -#define HBA_PxCMD_CR 0x8000 - -void disableCommands(PortControlRegisters *port) { - port->command &= ~(HBA_PxCMD_ST | HBA_PxCMD_FRE); - while (port->command & HBA_PxCMD_FR && port->command + HBA_PxCMD_CR) { - } -} - -void enableCommands(PortControlRegisters *port) { - while (port->command & HBA_PxCMD_CR) { - } - port->command |= HBA_PxCMD_ST | HBA_PxCMD_FRE; -} - -void relocatePort(PortControlRegisters *port) { - // call only once for each port, nothing is being freed here - disableCommands(port); - CommandListStructure *commandList = - mallocAligned(sizeof(CommandListStructure), 10); - port->commandListLower = (uintptr_t)commandList; - port->commandListUpper = (uintptr_t)commandList >> 32; - uintptr_t fis = (uintptr_t)mallocAligned(sizeof(CommandListStructure), 10); - port->fisLower = fis; - port->fisUpper = (uintptr_t)commandList >> 32; - memset(commandList, 0, sizeof(CommandListStructure)); - for (uint8_t i = 0; i < 32; i++) { - uint16_t size = 256; // sizeof(CommandTable) - commandList->commandHeaders[i].regionDescriptorCount = 8; - uintptr_t commandTable = (uintptr_t)mallocAligned(size, 8); - commandList->commandHeaders[i].commandTableLower = commandTable; - commandList->commandHeaders[i].commandTableUpper = commandTable >> 32; - memset((void *)commandTable, 0, size); - } - enableCommands(port); -} - -void sataDeviceInitialize(PortControlRegisters *port, ListElement **drives, - HbaMemoryRegisters *registers) { - HardDrive *hardDrive = malloc(sizeof(HardDrive)); - SataInterface *interface = malloc(sizeof(SataInterface)); - hardDrive->access = sataDriveAccess; - hardDrive->interface = interface; - interface->registers = registers; - interface->port = port; - relocatePort(interface->port); - uint8_t *buffer = malloc(512); - sataCommand(port, ATA_CMD_IDENTIFY, buffer, 0, 1); - char *model = malloc(41); - for (int i = 0; i < 40; i += 2) { - *((uint16_t *)&model[i]) = buffer[54 + i + 1]; - *((uint16_t *)&model[i + 1]) = buffer[54 + i]; - } - model[41] = 0; - printf("model: %s\n", model); - hardDrive->model = model; - free(buffer); - listAdd(drives, hardDrive); -} - -void initializeSataController(PciDevice *pciDevice, ListElement **drives) { - if (pciDevice->programmingInterface != 1) { - // todo - return; - } - HbaMemoryRegisters *registers = (void *)(uintptr_t)pciDevice->bar5; - for (uint8_t i = 0; i < 32; i++) { - if (!(registers->implementedPorts & (1 << i))) { - continue; - } - uint32_t type = getType(®isters->ports[i]); - if (type == AHCI_DEV_NULL) { - continue; - } - if (type != AHCI_SATA_DEVICE) { - printf("type %i not implemented yet...\n", type); - // todo - continue; - } - sataDeviceInitialize(®isters->ports[i], drives, registers); - } -} diff --git a/src/kernel/memory/alloc.c b/src/kernel/memory/alloc.c index 275d1fa..7f407e1 100644 --- a/src/kernel/memory/alloc.c +++ b/src/kernel/memory/alloc.c @@ -13,7 +13,8 @@ } #define getOffset() \ - (alignment ? alignmentBit - ((uintptr_t)(current + 1) & (alignmentMask)) \ + (alignment ? alignmentMask & (alignmentBit - ((uintptr_t)(current + 1) & \ + (alignmentMask))) \ : 0) void memmove(uint8_t *to, uint8_t *from, uintptr_t count) { diff --git a/src/kernel/memory/fileSystem.c b/src/kernel/memory/fileSystem.c index b88b4ff..9d4b9f7 100644 --- a/src/kernel/memory/fileSystem.c +++ b/src/kernel/memory/fileSystem.c @@ -8,7 +8,7 @@ void printFolderTree(FileSystemFolder *folder, char *prefix) { char *nextPrefix = stringCombine(prefix, " "); - for (ListElement *current = *folder->children; current; + for (ListElement *current = folder->children; current; current = current->next) { FileSystemTreeNode *child = current->data; printf("%s%s\n", prefix, child->name); @@ -153,9 +153,9 @@ uint32_t cluster = directory->firstDataClusterLower | directory->fistDataClusterUpper << 16; folder->cluster = cluster; - listAdd(parent->children, folder); + listAdd(&parent->children, folder); if (info->knownFolders[cluster]) { - folder->children = info->knownFolders[cluster]; + folder->children = *info->knownFolders[cluster]; return; } if (cluster == 0) { @@ -163,8 +163,8 @@ return; } folder->children = malloc(sizeof(ListElement **)); - info->knownFolders[cluster] = folder->children; - *folder->children = NULL; + info->knownFolders[cluster] = &folder->children; + folder->children = NULL; void *data = readClusterChain(info, cluster); scanFolder(info, data, folder); free(data); @@ -180,7 +180,7 @@ file->type = FS_FILE; file->subType = 0; file->size = directory->size; - listAdd(parent->children, file); + listAdd(&parent->children, file); } void setupChild(char *name, FatDirectoryEntry *directoryEntry, FatInfo *info, @@ -224,12 +224,17 @@ FatInfo *info; void mountDisk(HardDrive *drive) { + if (!drive) { + printf("no drive available to mount\n"); + yields(); + return; + } void *bootSector = malloc(512); drive->access(drive, 0, bootSector, 1, 0); FatBootSector *boot = bootSector; info = malloc(sizeof(FatInfo)); setupFatInfo(info, boot, drive); - rootFolder.children = malloc(sizeof(ListElement *)); + rootFolder.children = 0; void *data = malloc(info->clusterSize * info->rootDirectorySize); info->hardDrive->access(info->hardDrive, info->firstRootSector, data, info->rootDirectorySize, 0); @@ -242,10 +247,13 @@ printf("relative file paths not implemented yet!\n"); return NULL; } + if (rootFolder.children == NULL) { + return NULL; + } char *currentName = path + 1; FileSystemFolder *currentFolder = &rootFolder; while (strlen(currentName)) { - foreach (*currentFolder->children) { + foreach (currentFolder->children) { FileSystemTreeNode *node = current->data; uint16_t i; for (i = 0; currentName[i] != '/' && currentName[i] != 0; i++) { diff --git a/src/kernel/util/list.c b/src/kernel/util/list.c index c051fce..317e0bc 100644 --- a/src/kernel/util/list.c +++ b/src/kernel/util/list.c @@ -81,9 +81,15 @@ void *listGet(ListElement **list, uint32_t index) { ListElement *current = *list; - for (uint32_t i = 0; i < index; i++) { + if (!current) { + return NULL; + } + for (uint32_t i = 0; i < index && current; i++) { current = current->next; } + if (!current) { + return NULL; + } return current->data; }