Ahci: cap=0 and pi=0 but bios sees ahci hdd
Posted: Fri Sep 27, 2024 2:16 am
Hello, I am trying to write an AHCI driver for my os but i always get pi and cap 0
which suggest that there aren't any disks connected to device, but the bios shows the hdd i defined in the qemu run command.
Here is the qemu launch command:
qemu-system-x86_64 -hda $(FLOPPY_BIN) -drive id=disk,file=disk_image.raw,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -boot menu=on
$(FLOPPY_BIN) : The path to os's binary.
Here is my code for AHCI:
Did I miss something? I am stuck right now. I can't figure out why it dosen't work.
also in the qemu monitor the bar is set correctly and AHCI GHC = 0x80000000
which suggest that there aren't any disks connected to device, but the bios shows the hdd i defined in the qemu run command.
Here is the qemu launch command:
qemu-system-x86_64 -hda $(FLOPPY_BIN) -drive id=disk,file=disk_image.raw,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -boot menu=on
$(FLOPPY_BIN) : The path to os's binary.
Here is my code for AHCI:
Code: Select all
#include "arch/x86_64/io.h"
#include <ahci.h>
#include <stdint.h>
#include <stdio.h>
#include <pci.h>
linkedListNode* ahci_devices = NULL;
#define AHCI_PCI_CMD_REG_BITS 0b0000001101111111
void initialize_ahci(HBA_MEM *abar) {
// Enable AHCI by setting the AHCI Enable (AE) bit in the Global Host Control (GHC) register
abar->ghc |= (1 << 31); // Set the AHCI Enable bit
io_wait();
// Wait for AHCI controller to become ready
while (!(abar->ghc & (1 << 31))) {
printf("Ahci not ready");
}
// Check capabilities and configure ports
printf("AHCI GHC: 0x%x\n", abar->ghc);
printf("AHCI Capabilities: 0x%x\n", abar->cap);
// Example: Check and initialize ports if needed
}
// This function is responsible for setting up all pci devices and registering them in a linked list.
void setup_ahci_controllers() {
linkedListNode *head = listPCIDevices;
while (head) {
PCIDevice *device = (PCIDevice *)head->data;
if ((device->classCode == 0x06 || device->classCode == 0x01) && (device->subclass == 0x06 || device->subclass == 0x01)) {
HBA_MEM* abar = assign_bar(*device, AHCI_CONFIG_BAR_NUM);
if(abar == NULL){
continue;
}
printf("Abar addr: %d\n", abar);
uint16_t command_reg = pci_config_read_dword(device->bus, device->slot, device->function, PCI_OFFSET_COMMAND);
command_reg |= (uint16_t)AHCI_PCI_CMD_REG_BITS;
pci_config_write_dword(device->bus, device->slot, device->function, PCI_OFFSET_COMMAND, command_reg);
initialize_ahci(abar);
probe_port(abar);
append_node(&ahci_devices, device);
}
head = head->next;
}
}
// Check device type
static int check_type(HBA_PORT *port)
{
uint32_t ssts = port->ssts;
uint8_t ipm = (ssts >> 8) & 0x0F;
uint8_t det = ssts & 0x0F;
if (det != HBA_PORT_DET_PRESENT) // Check drive status
return AHCI_DEV_NULL;
if (ipm != HBA_PORT_IPM_ACTIVE)
return AHCI_DEV_NULL;
switch (port->sig)
{
case SATA_SIG_ATAPI:
return AHCI_DEV_SATAPI;
case SATA_SIG_SEMB:
return AHCI_DEV_SEMB;
case SATA_SIG_PM:
return AHCI_DEV_PM;
default:
return AHCI_DEV_SATA;
}
}
void probe_port(HBA_MEM *abar)
{
// Search disk in implemented ports
uint32_t pi = abar->pi;
printf("Pi: %x", pi);
int i = 0;
while (i<32)
{
if (pi & 1)
{
int dt = check_type(&abar->ports[i]);
if (dt == AHCI_DEV_SATA)
{
printf("SATA drive found at port %d\n", i);
}
else if (dt == AHCI_DEV_SATAPI)
{
printf("SATAPI drive found at port %d\n", i);
}
else if (dt == AHCI_DEV_SEMB)
{
printf("SEMB drive found at port %d\n", i);
}
else if (dt == AHCI_DEV_PM)
{
printf("PM drive found at port %d\n", i);
}
else
{
printf("No drive found at port %d\n", i);
}
}
pi >>= 1;
i ++;
}
}
also in the qemu monitor the bar is set correctly and AHCI GHC = 0x80000000