How could I detect bar5 address from PCI Scan?

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
User avatar
gamingjam60
Member
Member
Posts: 47
Joined: Sat Aug 24, 2024 10:06 pm
Libera.chat IRC: gamingjam60
Location: India
GitHub: https://github.com/baponkar
Contact:

How could I detect bar5 address from PCI Scan?

Post by gamingjam60 »

I want to get bar5 address for pci devices like AHCI Disk Drive by following

Code: Select all

    // read the BAR0 to BAR5 (Base Address Register 0 to 5)
    uint32_t bar0 = pci_read(bus, device, function, 0x10); // Read BAR0 (Base Address Register 0)
    uint32_t bar1 = pci_read(bus, device, function, 0x14); // Read BAR1 (Base Address Register 1)
    uint32_t bar2 = pci_read(bus, device, function, 0x18); // Read BAR2 (Base Address Register 2)
    uint32_t bar3 = pci_read(bus, device, function, 0x1C); // Read BAR3 (Base Address Register 3)
    uint32_t bar4 = pci_read(bus, device, function, 0x20); // Read BAR4 (Base Address Register 4)
    uint32_t bar5 = pci_read(bus, device, function, 0x24); // Read BAR5 (Base Address Register 5)
    // uint32_t bar6 = pci_read(bus, device, function, 0x28); // Read BAR6 (Base Address Register 6) // not present in all devices

    pci_device.base_address_registers[0] = bar0;           
    pci_device.base_address_registers[1] = bar1;
    pci_device.base_address_registers[2] = bar2;
    pci_device.base_address_registers[3] = bar3;
    pci_device.base_address_registers[4] = bar4;
    pci_device.base_address_registers[5] = bar5 & 0xFFFFFFF0;   // This is a pointer to the AHCI controller's memory address
    // pci_device.base_address_registers[6] = bar6; // Not used in this example
    
where

Code: Select all

uint32_t pci_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) {
    uint32_t address = (1 << 31) | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC);
    outl(CONFIG_ADDRESS, address);  // Write CONFIG_ADDRESS
    return inl(CONFIG_DATA);        // Read CONFIG_DATA     
}
Is this correct to detect bar5 Address ?

Code: Select all

HBA_PORT_T* port = &abar->ports[0];
Because port->cmd & HBA_PxCMD_CR is giving 0
Octocontrabass
Member
Member
Posts: 5805
Joined: Mon Mar 25, 2013 7:01 pm

Re: How could I detect bar5 address from PCI Scan?

Post by Octocontrabass »

That looks correct to me.

Are you using volatile reads and writes for MMIO? Is MMIO enabled in the AHCI controller's PCI command register? Are you sure the device you're accessing has the correct class code for AHCI?
User avatar
gamingjam60
Member
Member
Posts: 47
Joined: Sat Aug 24, 2024 10:06 pm
Libera.chat IRC: gamingjam60
Location: India
GitHub: https://github.com/baponkar
Contact:

Re: How could I detect bar5 address from PCI Scan?

Post by gamingjam60 »

Octocontrabass wrote: Tue May 06, 2025 12:04 pm That looks correct to me.

Are you using volatile reads and writes for MMIO? Is MMIO enabled in the AHCI controller's PCI command register? Are you sure the device you're accessing has the correct class code for AHCI?
abar is showing it's value is 0xFEBD5000 which is higher than 4GB But My system has maximum 4GB System memory. This 0xFEBD5000 is a MMIO address. I have enabled Paging in Higher half virtual address(actually by limine) but do not have lower half virtual address which I can be able to enable for user space. But if I consider 0xFEBD5000 is a virtual address then it is fall into lower half which is not helps. Do I need to consider mapping 0xFEBD5000 address into another higher half virtual address then it can be usable to rebase the port?
Class and subclass are correct as per my knowledge.

Code: Select all

void portRebase(HBA_MEM_T *abar, int port_no)
{
	HBA_PORT_T* port = &abar->ports[0];

	uint64_t phys = (uint64_t) abar;
	uint64_t virt = (uint64_t) phys_to_vir(phys);

	// map_virtual_memory(void *phys_addr, uint64_t virt_addr, size_t size, uint64_t flags);
	map_virtual_memory((void *)phys, virt, sizeof(HBA_MEM_T), (PAGE_WRITE | PAGE_PRESENT));

	uint32_t AHCI_BASE = (uint32_t) virt;


	stopCMD(port);	// Stop command engine
	
 
	// Command list offset: 1K * port_no
	// Command list entry size = 32
	// Command list entry maximum count = 32
	// Command list maximum size = 32 * 32 = 1K per port
	port->clb = AHCI_BASE + (port_no << 10);
	port->clbu = 0;
	memset((void*) (uint64_t) (port->clb), 0, 0x400);
 
	// FIS offset: 32K + 256 * port_no
	// FIS entry size = 256 bytes per port
	port->fb = AHCI_BASE + (32 << 10) + (port_no << 8);
	port->fbu = 0;
	memset((void*) (uint64_t) (port->fb), 0, 0x100);
 
	// Command table offset: 40K + 8K * port_no
	// Command table size = 256 * 32 = 8K per port
	HBA_CMD_HEADER_T* cmd_header = (HBA_CMD_HEADER_T*) (uint64_t) (port->clb);
	for (size_t i = 0; i < 32; i++)
	{
        // 8 prdt entries per command table
        // 256 bytes per command table, 64+16+48+16*8
		cmd_header[i].prdtl = 8;	
                                  
		// Command table offset: 40K + 8K*port_no + cmd_header_index*256
		cmd_header[i].ctba = AHCI_BASE + (40 << 10) + (port_no << 13) + (i << 8);
		cmd_header[i].ctbau = 0;
		memset((void*) (uint64_t) cmd_header[i].ctba, 0, 0x100);
	}
    // Start command engine
	startCMD(port);	
}
]/code]
sebihepp
Member
Member
Posts: 223
Joined: Tue Aug 26, 2008 11:24 am
GitHub: https://github.com/sebihepp

Re: How could I detect bar5 address from PCI Scan?

Post by sebihepp »

The MMIO addresses in the PCI BARs are physical addresses. You first need to map them to a virtual address, then use this virtual address to acces them.
Post Reply