Addition: Here port found from bar5 address which is use only to start and stop command engine not for rebasing memory registers.
Here my rebase function:
Code: Select all
void portRebase(HBA_PORT_T *port)
{
stopCMD(port);
// Allocate a physically contiguous region for this port:
// Make it large enough for CLB (1K), FB (1K), CTBA area (8K), plus margin.
const size_t ALLOC_SIZE = 64 * 1024; // 64 KiB to be safe
void *base_virt = (void *) malloc(ALLOC_SIZE);
if (!base_virt) {
printf("[AHCI] portRebase: malloc failed\n");
return;
}
// Convert to physical base (what HBA will use)
uintptr_t base_phys = vir_to_phys((uintptr_t)base_virt);
if (base_phys == 0) {
printf("[AHCI] portRebase: vir_to_phys returned 0\n");
return;
}
// Layout within the allocated block (choose simple contiguous layout)
// CLB: offset 0
uintptr_t clb_phys = base_phys + 0x0;
void *clb_virt = (void *)((uintptr_t)base_virt + 0x0); // virtual pointer for CPU
memset(clb_virt, 0, 0x400); // 1 KiB
// FB: offset 4K (use 4 KiB aligned area)
uintptr_t fb_phys = base_phys + 0x1000;
void *fb_virt = (void *)((uintptr_t)base_virt + 0x1000);
memset(fb_virt, 0, 0x100); // 256 bytes (FIS receive area), zeroed
// Command tables area: offset 8K (we'll allocate 8 KiB per port for command tables)
uintptr_t ctba_base_phys = base_phys + 0x2000;
void *ctba_base_virt = (void *)((uintptr_t)base_virt + 0x2000);
// Zero the whole CTBA area (32 * 256 = 8192)
memset(ctba_base_virt, 0, 0x2000);
// Program registers (hardware uses physical addresses)
port->clb = (uint32_t)(clb_phys & 0xFFFFFFFF);
port->clbu = (uint32_t)(clb_phys >> 32);
port->fb = (uint32_t)(fb_phys & 0xFFFFFFFF);
port->fbu = (uint32_t)(fb_phys >> 32);
// Now initialize each command header to point into the CTBA area
HBA_CMD_HEADER_T* cmd_header = (HBA_CMD_HEADER_T*) clb_virt; // CPU-side pointer into CLB area
for (int i = 0; i < 32; ++i) {
// Each command table sized 256 bytes (0x100) at sequential offsets
uintptr_t phys_ctba = ctba_base_phys + (i * 0x100);
cmd_header[i].ctba = (uint32_t)(phys_ctba & 0xFFFFFFFF);
cmd_header[i].ctbau = (uint32_t)(phys_ctba >> 32);
cmd_header[i].prdtl = 8; // example default
// Clear command table memory (use virtual)
void* virt_ctba = (void*)((uintptr_t)ctba_base_virt + (i * 0x100));
memset(virt_ctba, 0, 0x100);
}
// Start command engine after setting CLB/FB/CTBA
startCMD(port);
// printf("[AHCI] portRebase: done for port %d (phys base %x)\n", port_no, (unsigned long)base_phys);
}

