diff --git a/:w b/:w deleted file mode 100644 index 31145b6..0000000 --- a/:w +++ /dev/null @@ -1,284 +0,0 @@ -#include <_stdio.h> -#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 fisBaseLower, fisBaseHigher; - 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 *)(lower | (uint64_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, void *buffer) { - uint64_t bufferPosition = (uint64_t)buffer; - fis->lba0 = (uint8_t)bufferPosition; - fis->lba1 = (uint8_t)(bufferPosition >> 8); - fis->lba2 = (uint8_t)(bufferPosition >> 16); - fis->lba3 = (uint8_t)(bufferPosition >> 24); - fis->lba4 = (uint8_t)(bufferPosition >> 32); - fis->lba5 = (uint8_t)(bufferPosition >> 40); -} - -void setupFisToRead(FisToDevice *fis, void *buffer, uint8_t sectorCount) { - fis->type = FIS_TO_DEVICE_TYPE; - fis->commandControl = 1; - fis->command = ATA_CMD_READ_DMA_EXT; - fis->device = 1 << 6; - fis->countLow = (uint8_t)sectorCount; - fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, buffer); -} - -void sataDriveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, - uint8_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - CommandListStructure *commandList = getPointer( - interface->port->commandListLower, interface->port->commandListUpper); - interface->port->interruptStatus = -1; // clear pending interrupts - int8_t slot = findFreeCommandHeader(interface->port); - if (slot == -1) { - printf("sata access failed: no free command header spot found!\n"); - return; - } - CommandHeader *commandHeader = &(commandList->commandHeaders[slot]); - printf("interface: %x\ncommand header: %x\ncommandList: %x\n", interface, - commandHeader, commandList); - yields(); - commandHeader->fisLength = sizeof(FisToDevice) / sizeof(uint32_t); - printf("size: %i\n", commandHeader->fisLength); - commandHeader->write = 0; // read - commandHeader->regionDescriptorCount = ((sectorCount - 1) >> 4) + 1; - - CommandTable *commandTable = getPointer(commandHeader->commandTableLower, - commandHeader->commandTableUpper); - memset(commandTable, 0, - sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * - sizeof(PhysicalRegionDescriptor)); - uint32_t i; - void *currentPosition = buffer; - for (i = 0; i < commandHeader->regionDescriptorCount - 1; i++) { - commandTable->regionDescriptor[i].dataBaseLower = currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - ((uint64_t)currentPosition) >> 32; - commandTable->regionDescriptor[i].byteCount = 8 * 1024 - 1; - commandTable->regionDescriptor[i].interrupt = 1; - currentPosition += 8 * 1024; - sectorCount -= 16; - } - commandTable->regionDescriptor[i].dataBaseLower = (uint64_t)currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - (uint64_t)currentPosition >> 32; - commandTable->regionDescriptor[i].byteCount = (sectorCount << 9) - 1; - commandTable->regionDescriptor[i].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, buffer, sectorCount); - printf("waiting."); - while (interface->port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - printf(".."); - yields(); - - uint32_t slotMask = 1 << slot; - interface->port->commandIssue |= slotMask; - while (1) { - if (!(interface->port->commandIssue & slotMask)) { - break; - } - } - printf("\n"); -} - -#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 - CommandListStructure *commandList = - mallocAligned(sizeof(CommandListStructure), 10); - disableCommands(port); - port->commandListLower = commandList; - port->commandListUpper = (uint64_t)commandList >> 32; - memset(commandList, 0, sizeof(CommandListStructure)); - for (uint8_t i = 0; i < 2; i++) { - uint16_t size = 256; // sizeof(CommandTable) - commandList->commandHeaders[i].regionDescriptorCount = 8; - uint64_t commandTable = (uint64_t)mallocAligned(size, 7); - commandList->commandHeaders[i].commandTableLower = commandTable; - commandList->commandHeaders[i].commandTableUpper = commandTable >> 32; - memset((void *)commandTable, 0, size); - } - enableCommands(port); -} - -void initializeSataController(PciDevice *pciDevice, ListElement **drives) { - if (pciDevice->programmingInterface != 1) { - // todo - return; - } - HbaMemoryRegisters *registers = (HbaMemoryRegisters *)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; - } - HardDrive *hardDrive = malloc(sizeof(HardDrive)); - SataInterface *interface = malloc(sizeof(SataInterface)); - hardDrive->access = sataDriveAccess; - hardDrive->interface = interface; - interface->registers = registers; - interface->port = ®isters->ports[i]; - relocatePort(interface->port); - listAdd(drives, hardDrive); - printf("device on port %i has type %x\n", i, type); - } -} diff --git a/:w b/:w deleted file mode 100644 index 31145b6..0000000 --- a/:w +++ /dev/null @@ -1,284 +0,0 @@ -#include <_stdio.h> -#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 fisBaseLower, fisBaseHigher; - 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 *)(lower | (uint64_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, void *buffer) { - uint64_t bufferPosition = (uint64_t)buffer; - fis->lba0 = (uint8_t)bufferPosition; - fis->lba1 = (uint8_t)(bufferPosition >> 8); - fis->lba2 = (uint8_t)(bufferPosition >> 16); - fis->lba3 = (uint8_t)(bufferPosition >> 24); - fis->lba4 = (uint8_t)(bufferPosition >> 32); - fis->lba5 = (uint8_t)(bufferPosition >> 40); -} - -void setupFisToRead(FisToDevice *fis, void *buffer, uint8_t sectorCount) { - fis->type = FIS_TO_DEVICE_TYPE; - fis->commandControl = 1; - fis->command = ATA_CMD_READ_DMA_EXT; - fis->device = 1 << 6; - fis->countLow = (uint8_t)sectorCount; - fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, buffer); -} - -void sataDriveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, - uint8_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - CommandListStructure *commandList = getPointer( - interface->port->commandListLower, interface->port->commandListUpper); - interface->port->interruptStatus = -1; // clear pending interrupts - int8_t slot = findFreeCommandHeader(interface->port); - if (slot == -1) { - printf("sata access failed: no free command header spot found!\n"); - return; - } - CommandHeader *commandHeader = &(commandList->commandHeaders[slot]); - printf("interface: %x\ncommand header: %x\ncommandList: %x\n", interface, - commandHeader, commandList); - yields(); - commandHeader->fisLength = sizeof(FisToDevice) / sizeof(uint32_t); - printf("size: %i\n", commandHeader->fisLength); - commandHeader->write = 0; // read - commandHeader->regionDescriptorCount = ((sectorCount - 1) >> 4) + 1; - - CommandTable *commandTable = getPointer(commandHeader->commandTableLower, - commandHeader->commandTableUpper); - memset(commandTable, 0, - sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * - sizeof(PhysicalRegionDescriptor)); - uint32_t i; - void *currentPosition = buffer; - for (i = 0; i < commandHeader->regionDescriptorCount - 1; i++) { - commandTable->regionDescriptor[i].dataBaseLower = currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - ((uint64_t)currentPosition) >> 32; - commandTable->regionDescriptor[i].byteCount = 8 * 1024 - 1; - commandTable->regionDescriptor[i].interrupt = 1; - currentPosition += 8 * 1024; - sectorCount -= 16; - } - commandTable->regionDescriptor[i].dataBaseLower = (uint64_t)currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - (uint64_t)currentPosition >> 32; - commandTable->regionDescriptor[i].byteCount = (sectorCount << 9) - 1; - commandTable->regionDescriptor[i].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, buffer, sectorCount); - printf("waiting."); - while (interface->port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - printf(".."); - yields(); - - uint32_t slotMask = 1 << slot; - interface->port->commandIssue |= slotMask; - while (1) { - if (!(interface->port->commandIssue & slotMask)) { - break; - } - } - printf("\n"); -} - -#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 - CommandListStructure *commandList = - mallocAligned(sizeof(CommandListStructure), 10); - disableCommands(port); - port->commandListLower = commandList; - port->commandListUpper = (uint64_t)commandList >> 32; - memset(commandList, 0, sizeof(CommandListStructure)); - for (uint8_t i = 0; i < 2; i++) { - uint16_t size = 256; // sizeof(CommandTable) - commandList->commandHeaders[i].regionDescriptorCount = 8; - uint64_t commandTable = (uint64_t)mallocAligned(size, 7); - commandList->commandHeaders[i].commandTableLower = commandTable; - commandList->commandHeaders[i].commandTableUpper = commandTable >> 32; - memset((void *)commandTable, 0, size); - } - enableCommands(port); -} - -void initializeSataController(PciDevice *pciDevice, ListElement **drives) { - if (pciDevice->programmingInterface != 1) { - // todo - return; - } - HbaMemoryRegisters *registers = (HbaMemoryRegisters *)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; - } - HardDrive *hardDrive = malloc(sizeof(HardDrive)); - SataInterface *interface = malloc(sizeof(SataInterface)); - hardDrive->access = sataDriveAccess; - hardDrive->interface = interface; - interface->registers = registers; - interface->port = ®isters->ports[i]; - relocatePort(interface->port); - listAdd(drives, hardDrive); - printf("device on port %i has type %x\n", i, type); - } -} diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 554c61c..28eae99 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -23,7 +23,7 @@ char *model; uint32_t size; void *interface; - void (*access)(struct HardDrive *, uint32_t, void *, uint8_t, uint8_t); + void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point } HardDrive; diff --git a/:w b/:w deleted file mode 100644 index 31145b6..0000000 --- a/:w +++ /dev/null @@ -1,284 +0,0 @@ -#include <_stdio.h> -#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 fisBaseLower, fisBaseHigher; - 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 *)(lower | (uint64_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, void *buffer) { - uint64_t bufferPosition = (uint64_t)buffer; - fis->lba0 = (uint8_t)bufferPosition; - fis->lba1 = (uint8_t)(bufferPosition >> 8); - fis->lba2 = (uint8_t)(bufferPosition >> 16); - fis->lba3 = (uint8_t)(bufferPosition >> 24); - fis->lba4 = (uint8_t)(bufferPosition >> 32); - fis->lba5 = (uint8_t)(bufferPosition >> 40); -} - -void setupFisToRead(FisToDevice *fis, void *buffer, uint8_t sectorCount) { - fis->type = FIS_TO_DEVICE_TYPE; - fis->commandControl = 1; - fis->command = ATA_CMD_READ_DMA_EXT; - fis->device = 1 << 6; - fis->countLow = (uint8_t)sectorCount; - fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, buffer); -} - -void sataDriveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, - uint8_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - CommandListStructure *commandList = getPointer( - interface->port->commandListLower, interface->port->commandListUpper); - interface->port->interruptStatus = -1; // clear pending interrupts - int8_t slot = findFreeCommandHeader(interface->port); - if (slot == -1) { - printf("sata access failed: no free command header spot found!\n"); - return; - } - CommandHeader *commandHeader = &(commandList->commandHeaders[slot]); - printf("interface: %x\ncommand header: %x\ncommandList: %x\n", interface, - commandHeader, commandList); - yields(); - commandHeader->fisLength = sizeof(FisToDevice) / sizeof(uint32_t); - printf("size: %i\n", commandHeader->fisLength); - commandHeader->write = 0; // read - commandHeader->regionDescriptorCount = ((sectorCount - 1) >> 4) + 1; - - CommandTable *commandTable = getPointer(commandHeader->commandTableLower, - commandHeader->commandTableUpper); - memset(commandTable, 0, - sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * - sizeof(PhysicalRegionDescriptor)); - uint32_t i; - void *currentPosition = buffer; - for (i = 0; i < commandHeader->regionDescriptorCount - 1; i++) { - commandTable->regionDescriptor[i].dataBaseLower = currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - ((uint64_t)currentPosition) >> 32; - commandTable->regionDescriptor[i].byteCount = 8 * 1024 - 1; - commandTable->regionDescriptor[i].interrupt = 1; - currentPosition += 8 * 1024; - sectorCount -= 16; - } - commandTable->regionDescriptor[i].dataBaseLower = (uint64_t)currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - (uint64_t)currentPosition >> 32; - commandTable->regionDescriptor[i].byteCount = (sectorCount << 9) - 1; - commandTable->regionDescriptor[i].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, buffer, sectorCount); - printf("waiting."); - while (interface->port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - printf(".."); - yields(); - - uint32_t slotMask = 1 << slot; - interface->port->commandIssue |= slotMask; - while (1) { - if (!(interface->port->commandIssue & slotMask)) { - break; - } - } - printf("\n"); -} - -#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 - CommandListStructure *commandList = - mallocAligned(sizeof(CommandListStructure), 10); - disableCommands(port); - port->commandListLower = commandList; - port->commandListUpper = (uint64_t)commandList >> 32; - memset(commandList, 0, sizeof(CommandListStructure)); - for (uint8_t i = 0; i < 2; i++) { - uint16_t size = 256; // sizeof(CommandTable) - commandList->commandHeaders[i].regionDescriptorCount = 8; - uint64_t commandTable = (uint64_t)mallocAligned(size, 7); - commandList->commandHeaders[i].commandTableLower = commandTable; - commandList->commandHeaders[i].commandTableUpper = commandTable >> 32; - memset((void *)commandTable, 0, size); - } - enableCommands(port); -} - -void initializeSataController(PciDevice *pciDevice, ListElement **drives) { - if (pciDevice->programmingInterface != 1) { - // todo - return; - } - HbaMemoryRegisters *registers = (HbaMemoryRegisters *)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; - } - HardDrive *hardDrive = malloc(sizeof(HardDrive)); - SataInterface *interface = malloc(sizeof(SataInterface)); - hardDrive->access = sataDriveAccess; - hardDrive->interface = interface; - interface->registers = registers; - interface->port = ®isters->ports[i]; - relocatePort(interface->port); - listAdd(drives, hardDrive); - printf("device on port %i has type %x\n", i, type); - } -} diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 554c61c..28eae99 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -23,7 +23,7 @@ char *model; uint32_t size; void *interface; - void (*access)(struct HardDrive *, uint32_t, void *, uint8_t, uint8_t); + void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point } HardDrive; diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index ecb1a2f..47205be 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -21,7 +21,7 @@ break; } } - void *buffer = malloc(2000); + void *buffer = malloc(512); for (ListElement *current = drives; current; current = current->next) { HardDrive *hardDrive = current->data; hardDrive->access(hardDrive, 0, buffer, 1, 0); diff --git a/:w b/:w deleted file mode 100644 index 31145b6..0000000 --- a/:w +++ /dev/null @@ -1,284 +0,0 @@ -#include <_stdio.h> -#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 fisBaseLower, fisBaseHigher; - 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 *)(lower | (uint64_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, void *buffer) { - uint64_t bufferPosition = (uint64_t)buffer; - fis->lba0 = (uint8_t)bufferPosition; - fis->lba1 = (uint8_t)(bufferPosition >> 8); - fis->lba2 = (uint8_t)(bufferPosition >> 16); - fis->lba3 = (uint8_t)(bufferPosition >> 24); - fis->lba4 = (uint8_t)(bufferPosition >> 32); - fis->lba5 = (uint8_t)(bufferPosition >> 40); -} - -void setupFisToRead(FisToDevice *fis, void *buffer, uint8_t sectorCount) { - fis->type = FIS_TO_DEVICE_TYPE; - fis->commandControl = 1; - fis->command = ATA_CMD_READ_DMA_EXT; - fis->device = 1 << 6; - fis->countLow = (uint8_t)sectorCount; - fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, buffer); -} - -void sataDriveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, - uint8_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - CommandListStructure *commandList = getPointer( - interface->port->commandListLower, interface->port->commandListUpper); - interface->port->interruptStatus = -1; // clear pending interrupts - int8_t slot = findFreeCommandHeader(interface->port); - if (slot == -1) { - printf("sata access failed: no free command header spot found!\n"); - return; - } - CommandHeader *commandHeader = &(commandList->commandHeaders[slot]); - printf("interface: %x\ncommand header: %x\ncommandList: %x\n", interface, - commandHeader, commandList); - yields(); - commandHeader->fisLength = sizeof(FisToDevice) / sizeof(uint32_t); - printf("size: %i\n", commandHeader->fisLength); - commandHeader->write = 0; // read - commandHeader->regionDescriptorCount = ((sectorCount - 1) >> 4) + 1; - - CommandTable *commandTable = getPointer(commandHeader->commandTableLower, - commandHeader->commandTableUpper); - memset(commandTable, 0, - sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * - sizeof(PhysicalRegionDescriptor)); - uint32_t i; - void *currentPosition = buffer; - for (i = 0; i < commandHeader->regionDescriptorCount - 1; i++) { - commandTable->regionDescriptor[i].dataBaseLower = currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - ((uint64_t)currentPosition) >> 32; - commandTable->regionDescriptor[i].byteCount = 8 * 1024 - 1; - commandTable->regionDescriptor[i].interrupt = 1; - currentPosition += 8 * 1024; - sectorCount -= 16; - } - commandTable->regionDescriptor[i].dataBaseLower = (uint64_t)currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - (uint64_t)currentPosition >> 32; - commandTable->regionDescriptor[i].byteCount = (sectorCount << 9) - 1; - commandTable->regionDescriptor[i].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, buffer, sectorCount); - printf("waiting."); - while (interface->port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - printf(".."); - yields(); - - uint32_t slotMask = 1 << slot; - interface->port->commandIssue |= slotMask; - while (1) { - if (!(interface->port->commandIssue & slotMask)) { - break; - } - } - printf("\n"); -} - -#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 - CommandListStructure *commandList = - mallocAligned(sizeof(CommandListStructure), 10); - disableCommands(port); - port->commandListLower = commandList; - port->commandListUpper = (uint64_t)commandList >> 32; - memset(commandList, 0, sizeof(CommandListStructure)); - for (uint8_t i = 0; i < 2; i++) { - uint16_t size = 256; // sizeof(CommandTable) - commandList->commandHeaders[i].regionDescriptorCount = 8; - uint64_t commandTable = (uint64_t)mallocAligned(size, 7); - commandList->commandHeaders[i].commandTableLower = commandTable; - commandList->commandHeaders[i].commandTableUpper = commandTable >> 32; - memset((void *)commandTable, 0, size); - } - enableCommands(port); -} - -void initializeSataController(PciDevice *pciDevice, ListElement **drives) { - if (pciDevice->programmingInterface != 1) { - // todo - return; - } - HbaMemoryRegisters *registers = (HbaMemoryRegisters *)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; - } - HardDrive *hardDrive = malloc(sizeof(HardDrive)); - SataInterface *interface = malloc(sizeof(SataInterface)); - hardDrive->access = sataDriveAccess; - hardDrive->interface = interface; - interface->registers = registers; - interface->port = ®isters->ports[i]; - relocatePort(interface->port); - listAdd(drives, hardDrive); - printf("device on port %i has type %x\n", i, type); - } -} diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 554c61c..28eae99 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -23,7 +23,7 @@ char *model; uint32_t size; void *interface; - void (*access)(struct HardDrive *, uint32_t, void *, uint8_t, uint8_t); + void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point } HardDrive; diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index ecb1a2f..47205be 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -21,7 +21,7 @@ break; } } - void *buffer = malloc(2000); + void *buffer = malloc(512); for (ListElement *current = drives; current; current = current->next) { HardDrive *hardDrive = current->data; hardDrive->access(hardDrive, 0, buffer, 1, 0); diff --git a/src/kernel/drivers/pci/hardDrive/ideController.c b/src/kernel/drivers/pci/hardDrive/ideController.c index 51bb464..f7d2c5d 100644 --- a/src/kernel/drivers/pci/hardDrive/ideController.c +++ b/src/kernel/drivers/pci/hardDrive/ideController.c @@ -114,8 +114,9 @@ #define CHANNEL channels[channel] -void ideDriveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, - uint8_t sectorCount, uint8_t direction) { +void ideDriveAccess(HardDrive *hardDrive, uint64_t lbaIn, void *buffer, + uint16_t sectorCount, uint8_t direction) { + uint32_t lba = lbaIn; uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; IdeInterface *interface = hardDrive->interface; diff --git a/:w b/:w deleted file mode 100644 index 31145b6..0000000 --- a/:w +++ /dev/null @@ -1,284 +0,0 @@ -#include <_stdio.h> -#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 fisBaseLower, fisBaseHigher; - 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 *)(lower | (uint64_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, void *buffer) { - uint64_t bufferPosition = (uint64_t)buffer; - fis->lba0 = (uint8_t)bufferPosition; - fis->lba1 = (uint8_t)(bufferPosition >> 8); - fis->lba2 = (uint8_t)(bufferPosition >> 16); - fis->lba3 = (uint8_t)(bufferPosition >> 24); - fis->lba4 = (uint8_t)(bufferPosition >> 32); - fis->lba5 = (uint8_t)(bufferPosition >> 40); -} - -void setupFisToRead(FisToDevice *fis, void *buffer, uint8_t sectorCount) { - fis->type = FIS_TO_DEVICE_TYPE; - fis->commandControl = 1; - fis->command = ATA_CMD_READ_DMA_EXT; - fis->device = 1 << 6; - fis->countLow = (uint8_t)sectorCount; - fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, buffer); -} - -void sataDriveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, - uint8_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - CommandListStructure *commandList = getPointer( - interface->port->commandListLower, interface->port->commandListUpper); - interface->port->interruptStatus = -1; // clear pending interrupts - int8_t slot = findFreeCommandHeader(interface->port); - if (slot == -1) { - printf("sata access failed: no free command header spot found!\n"); - return; - } - CommandHeader *commandHeader = &(commandList->commandHeaders[slot]); - printf("interface: %x\ncommand header: %x\ncommandList: %x\n", interface, - commandHeader, commandList); - yields(); - commandHeader->fisLength = sizeof(FisToDevice) / sizeof(uint32_t); - printf("size: %i\n", commandHeader->fisLength); - commandHeader->write = 0; // read - commandHeader->regionDescriptorCount = ((sectorCount - 1) >> 4) + 1; - - CommandTable *commandTable = getPointer(commandHeader->commandTableLower, - commandHeader->commandTableUpper); - memset(commandTable, 0, - sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * - sizeof(PhysicalRegionDescriptor)); - uint32_t i; - void *currentPosition = buffer; - for (i = 0; i < commandHeader->regionDescriptorCount - 1; i++) { - commandTable->regionDescriptor[i].dataBaseLower = currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - ((uint64_t)currentPosition) >> 32; - commandTable->regionDescriptor[i].byteCount = 8 * 1024 - 1; - commandTable->regionDescriptor[i].interrupt = 1; - currentPosition += 8 * 1024; - sectorCount -= 16; - } - commandTable->regionDescriptor[i].dataBaseLower = (uint64_t)currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - (uint64_t)currentPosition >> 32; - commandTable->regionDescriptor[i].byteCount = (sectorCount << 9) - 1; - commandTable->regionDescriptor[i].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, buffer, sectorCount); - printf("waiting."); - while (interface->port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - printf(".."); - yields(); - - uint32_t slotMask = 1 << slot; - interface->port->commandIssue |= slotMask; - while (1) { - if (!(interface->port->commandIssue & slotMask)) { - break; - } - } - printf("\n"); -} - -#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 - CommandListStructure *commandList = - mallocAligned(sizeof(CommandListStructure), 10); - disableCommands(port); - port->commandListLower = commandList; - port->commandListUpper = (uint64_t)commandList >> 32; - memset(commandList, 0, sizeof(CommandListStructure)); - for (uint8_t i = 0; i < 2; i++) { - uint16_t size = 256; // sizeof(CommandTable) - commandList->commandHeaders[i].regionDescriptorCount = 8; - uint64_t commandTable = (uint64_t)mallocAligned(size, 7); - commandList->commandHeaders[i].commandTableLower = commandTable; - commandList->commandHeaders[i].commandTableUpper = commandTable >> 32; - memset((void *)commandTable, 0, size); - } - enableCommands(port); -} - -void initializeSataController(PciDevice *pciDevice, ListElement **drives) { - if (pciDevice->programmingInterface != 1) { - // todo - return; - } - HbaMemoryRegisters *registers = (HbaMemoryRegisters *)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; - } - HardDrive *hardDrive = malloc(sizeof(HardDrive)); - SataInterface *interface = malloc(sizeof(SataInterface)); - hardDrive->access = sataDriveAccess; - hardDrive->interface = interface; - interface->registers = registers; - interface->port = ®isters->ports[i]; - relocatePort(interface->port); - listAdd(drives, hardDrive); - printf("device on port %i has type %x\n", i, type); - } -} diff --git a/src/include/hardDrive.h b/src/include/hardDrive.h index 554c61c..28eae99 100644 --- a/src/include/hardDrive.h +++ b/src/include/hardDrive.h @@ -23,7 +23,7 @@ char *model; uint32_t size; void *interface; - void (*access)(struct HardDrive *, uint32_t, void *, uint8_t, uint8_t); + void (*access)(struct HardDrive *, uint64_t, void *, uint16_t, uint8_t); // todo: mount point } HardDrive; diff --git a/src/kernel/drivers/pci/hardDrive/hardDrive.c b/src/kernel/drivers/pci/hardDrive/hardDrive.c index ecb1a2f..47205be 100644 --- a/src/kernel/drivers/pci/hardDrive/hardDrive.c +++ b/src/kernel/drivers/pci/hardDrive/hardDrive.c @@ -21,7 +21,7 @@ break; } } - void *buffer = malloc(2000); + void *buffer = malloc(512); for (ListElement *current = drives; current; current = current->next) { HardDrive *hardDrive = current->data; hardDrive->access(hardDrive, 0, buffer, 1, 0); diff --git a/src/kernel/drivers/pci/hardDrive/ideController.c b/src/kernel/drivers/pci/hardDrive/ideController.c index 51bb464..f7d2c5d 100644 --- a/src/kernel/drivers/pci/hardDrive/ideController.c +++ b/src/kernel/drivers/pci/hardDrive/ideController.c @@ -114,8 +114,9 @@ #define CHANNEL channels[channel] -void ideDriveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, - uint8_t sectorCount, uint8_t direction) { +void ideDriveAccess(HardDrive *hardDrive, uint64_t lbaIn, void *buffer, + uint16_t sectorCount, uint8_t direction) { + uint32_t lba = lbaIn; uint8_t accessMode = 0, head = 0, sector = 0, cylinder = 0; uint32_t lbaIo[6] = {0, 0, 0, 0, 0, 0}; IdeInterface *interface = hardDrive->interface; diff --git a/src/kernel/drivers/pci/hardDrive/sataController.c b/src/kernel/drivers/pci/hardDrive/sataController.c index f9e5e9f..b65e27b 100644 --- a/src/kernel/drivers/pci/hardDrive/sataController.c +++ b/src/kernel/drivers/pci/hardDrive/sataController.c @@ -136,81 +136,69 @@ return -1; } -void insertLba(FisToDevice *fis, void *buffer) { - uint64_t bufferPosition = (uint64_t)buffer; - fis->lba0 = (uint8_t)bufferPosition; - fis->lba1 = (uint8_t)(bufferPosition >> 8); - fis->lba2 = (uint8_t)(bufferPosition >> 16); - fis->lba3 = (uint8_t)(bufferPosition >> 24); - fis->lba4 = (uint8_t)(bufferPosition >> 32); - fis->lba5 = (uint8_t)(bufferPosition >> 40); +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, void *buffer, uint8_t sectorCount) { +void setupFisToRead(FisToDevice *fis, uint16_t sectorCount, uint64_t lba, + uint8_t command) { fis->type = FIS_TO_DEVICE_TYPE; fis->commandControl = 1; - fis->command = ATA_CMD_READ_DMA_EXT; + fis->command = command; fis->device = 1 << 6; fis->countLow = (uint8_t)sectorCount; fis->countHigh = (uint8_t)(sectorCount >> 8); - insertLba(fis, buffer); + insertLba(fis, lba); } -void sataCommand(PortControlRegisters *port, uint8_t command, void *buffer); +void sataIssueCommand(PortControlRegisters *port) { + while (port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { + yields(); + } + port->commandIssue = 1; + while (port->commandIssue == 1) { + yields(); + } +} -void sataDriveAccess(HardDrive *hardDrive, uint32_t lba, void *buffer, - uint8_t sectorCount, uint8_t direction) { - SataInterface *interface = hardDrive->interface; - sataCommand(interface->port, ATA_CMD_READ_DMA_EXT, buffer); - return; - CommandListStructure *commandList = getPointer( - interface->port->commandListLower, interface->port->commandListUpper); - interface->port->interruptStatus = -1; // clear pending interrupts - int8_t slot = findFreeCommandHeader(interface->port); +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 access failed: no free command header spot found!\n"); + 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; // read - commandHeader->regionDescriptorCount = ((sectorCount - 1) >> 4) + 1; - + commandHeader->write = 0; + commandHeader->regionDescriptorCount = 1; CommandTable *commandTable = getPointer(commandHeader->commandTableLower, commandHeader->commandTableUpper); memset(commandTable, 0, sizeof(CommandTable) + (commandHeader->regionDescriptorCount - 1) * sizeof(PhysicalRegionDescriptor)); - uint32_t i; - void *currentPosition = buffer; - for (i = 0; i < commandHeader->regionDescriptorCount - 1; i++) { - commandTable->regionDescriptor[i].dataBaseLower = currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - ((uint64_t)currentPosition) >> 32; - commandTable->regionDescriptor[i].byteCount = 8 * 1024 - 1; - commandTable->regionDescriptor[i].interrupt = 1; - currentPosition += 8 * 1024; - sectorCount -= 16; - } - commandTable->regionDescriptor[i].dataBaseLower = (uint64_t)currentPosition; - commandTable->regionDescriptor[i].dataBaseUpper = - (uint64_t)currentPosition >> 32; - commandTable->regionDescriptor[i].byteCount = (sectorCount << 9) - 1; - commandTable->regionDescriptor[i].interrupt = 1; + commandTable->regionDescriptor[0].dataBaseLower = (uint64_t)buffer; + commandTable->regionDescriptor[0].dataBaseUpper = (uint64_t)buffer >> 32; + commandTable->regionDescriptor[0].byteCount = 511; + commandTable->regionDescriptor[0].interrupt = 1; FisToDevice *fis = (void *)&(commandTable->fis); - setupFisToRead(fis, buffer, sectorCount); - printf("waiting."); - while (interface->port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - printf(".."); - yields(); + setupFisToRead(fis, sectorCount, lba, command); + sataIssueCommand(port); +} - uint32_t slotMask = 1 << slot; - interface->port->commandIssue |= slotMask; - while (interface->port->commandIssue & slotMask) { - } - printf("\n"); +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 @@ -252,45 +240,6 @@ enableCommands(port); } -void sataCommand(PortControlRegisters *port, uint8_t command, void *buffer) { - port->interruptStatus = -1; - CommandListStructure *commandList = - getPointer(port->commandListLower, port->commandListUpper); - int8_t slot = findFreeCommandHeader(port); - if (slot == -1) { - printf("sata access 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 = (uint64_t)buffer; - commandTable->regionDescriptor[0].dataBaseUpper = 0; - commandTable->regionDescriptor[0].byteCount = 511; - commandTable->regionDescriptor[0].interrupt = 1; - FisToDevice *fis = (void *)&(commandTable->fis); - fis->type = FIS_TO_DEVICE_TYPE; - fis->command = command; - fis->device = 0; - fis->commandControl = 1; - fis->device = 1 << 6; - fis->countLow = 1; - insertLba(fis, buffer); - while (port->taskFileData & (ATA_DEV_BUSY | ATA_DEV_DRQ)) { - yields(); - } - port->commandIssue = 1; - while (port->commandIssue == 1) { - yields(); - } -} - void sataDeviceInitialize(PortControlRegisters *port, ListElement **drives, HbaMemoryRegisters *registers) { HardDrive *hardDrive = malloc(sizeof(HardDrive)); @@ -301,7 +250,7 @@ interface->port = port; relocatePort(interface->port); uint8_t *buffer = malloc(512); - sataCommand(port, ATA_CMD_IDENTIFY, buffer); + 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];