Ahci: cap=0 and pi=0 but bios sees ahci hdd

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
galbb12
Posts: 1
Joined: Fri Sep 27, 2024 2:07 am

Ahci: cap=0 and pi=0 but bios sees ahci hdd

Post by galbb12 »

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:

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 ++;
	}
}
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
Octocontrabass
Member
Member
Posts: 5440
Joined: Mon Mar 25, 2013 7:01 pm

Re: Ahci: cap=0 and pi=0 but bios sees ahci hdd

Post by Octocontrabass »

galbb12 wrote: Fri Sep 27, 2024 2:16 am

Code: Select all

    if ((device->classCode == 0x06 || device->classCode == 0x01) && (device->subclass == 0x06 || device->subclass == 0x01)) {
These combinations of class and subclass will catch several non-AHCI devices. Are you sure you're accessing the right device?

Have you tried using QEMU's trace log (--trace "ahci_*") to see what QEMU thinks you're doing with the AHCI controller?
Post Reply