[SOLVED] Issues configuring BARs
Posted: Sun Feb 23, 2014 1:23 am
Hello all,
I'm working on writing a driver for the Intel PIIX3 IDE interface. I've got it matched on the PCI bus and my driver is loaded, and it seems to properly identify the device and whatnot. The problem comes when I try to set the BAR addresses for the IO addresses. The code doesn't seem to properly make the write go through, as doing "info pci" in the QEMU monitor doesn't yield any changes, even on a BAR that's already been set. This is the code I use to do this:
And this is the code I use to write the BARs, with all values being correct and expected:
Does anybody know why this might be happening? Thanks for any pointers.
I'm working on writing a driver for the Intel PIIX3 IDE interface. I've got it matched on the PCI bus and my driver is loaded, and it seems to properly identify the device and whatnot. The problem comes when I try to set the BAR addresses for the IO addresses. The code doesn't seem to properly make the write go through, as doing "info pci" in the QEMU monitor doesn't yield any changes, even on a BAR that's already been set. This is the code I use to do this:
Code: Select all
#define pci_config_address(bus, device, function, reg) ((uint32_t) ((bus & 0xFF) << 16) | ((device & 0x1F) << 11) | ((function & 0x07) << 8) | (reg & 0xFF) | 0x80000000)
void pci_config_write_l(uint32_t address, uint32_t value) {
io_outl(0xCF8, address & 0xFFFFFFFC);
io_outl(0xCFC, value);
}
/*
* Updates the BAR of a specific function on a device, and updates the PCI
* config space.
*/
void pci_device_update_bar(pci_device_t *d, int function, int bar, uint32_t value) {
ASSERT(bar < 6);
// Calculate length and address to write to
uint32_t length = d->function[function].bar[bar].end - d->function[function].bar[bar].start;
uint32_t addr = pci_config_address(d->location.bus, d->location.device, function, (0x10 + (bar << 2)));
kprintf("PCI BAR UPDATE: bus %u, device %u, function %u, BAR %X, value 0x%X, address 0x%X\n", d->location.bus, d->location.device, function, (0x10 + (bar << 2)), value, addr);
// Do write to PCI config space
pci_config_write_l(addr, value);
// Reset flags
d->function[function].bar[bar].flags = 0;
// IO BAR
if(bar & 0x01) {
d->function[function].bar[bar].start = value & 0xFFFFFFFC;
d->function[function].bar[bar].end = (value & 0xFFFFFFFC) + length;
d->function[function].bar[bar].flags = kPCIBARFlagsIOAddress;
} else { // Memory address BAR
d->function[function].bar[bar].start = value & 0xFFFFFFF0;
d->function[function].bar[bar].end = (value & 0xFFFFFFF0) + length;
// Is this BAR prefetchable?
if(value & 0x8) {
d->function[function].bar[bar].flags = kPCIBARFlagsPrefetchable;
}
// Get BAR type
uint8_t type = (value & 0x6) >> 1;
// Is the BAR 64 bits?
if(type == 0x02) {
d->function[function].bar[bar].flags |= kPCIBARFlags64Bits;
} else if(type == 0x01) { // 16 bits?
d->function[function].bar[bar].flags |= kPCIBARFlags16Bits;
} else if(type == 0x00) { // 32 bits?
d->function[function].bar[bar].flags |= kPCIBARFlags32Bits;
}
}
}
Code: Select all
// Command task file for primary is at 0x1F0
pci_device_update_bar(piix3_device, 1, 0, (ATA_BUS_0_IOADDR | 0x0001));
// Control task file for primary is at 0x1F8
pci_device_update_bar(piix3_device, 1, 1, (ATA_BUS_0_CTRLADDR | 0x0001));
// Command task file for secondary is at 0x170
pci_device_update_bar(piix3_device, 1, 2, (ATA_BUS_1_IOADDR | 0x0001));
// Control task file for secondary is at 0x178
pci_device_update_bar(piix3_device, 1, 3, (ATA_BUS_1_CTRLADDR | 0x0001));