OK, so I've added some debugging code in my PCI probe. I apparently can now get BARs (I think they're the BARs I'm looking for, even though I get strange results...). As an example, here's what my kernel reports when probing PCI devices:
Quote:
PCI: probe: found Intel Corporation 440FX - 82441FX PMC [Natoma] (Host bridge)
PCI: probe: codes: vendor = 8086h, device = 1237h, class = 6h, subclass = 0h, prog if=0h, rev=2h, status=0h, command=1h, bus = 0h, slot = 0h, function = 0h
PCI: probe: BARs (header == 0h): 0: 0h, 1: 0h, 2: 0h, 3: 0h, 4: 0h, 5: 0h
PCI: probe: found Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II] (ISA bridge)
PCI: probe: codes: vendor = 8086h, device = 7000h, class = 6h, subclass = 1h, prog if=0h, rev=0h, status=2h, command=1h, bus = 0h, slot = 1h, function = 0h
PCI: probe: BARs (header == 0h): 0: 0h, 1: 0h, 2: 0h, 3: 0h, 4: 0h, 5: 0h
PCI: probe: found Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II] (IDE interface)
PCI: probe: codes: vendor = 8086h, device = 7010h, class = 1h, subclass = 1h, prog if=0h, rev=0h, status=2h, command=1h, bus = 0h, slot = 1h, function = 1h
PCI: probe: BARs (header == 0h): 0: 0h, 1: 0h, 2: 0h, 3: 0h, 4: C641h, 5: 0h
PCI: probe: found Intel Corporation 82371AB/EB/MB PIIX4 ACPI (Host bridge)
PCI: probe: codes: vendor = 8086h, device = 7113h, class = 6h, subclass = 0h, prog if=0h, rev=3h, status=2h, command=1h, bus = 0h, slot = 1h, function = 3h
PCI: probe: BARs (header == 0h): 0: 0h, 1: 0h, 2: 0h, 3: 0h, 4: 0h, 5: 0h
PCI: probe: found Unknown vendor mPCIe-ICM485-2 2x Isolated RS485 PCI Express Mini Card (VGA compatible controller)
PCI: probe: codes: vendor = 1234h, device = 1111h, class = 3h, subclass = 0h, prog if=0h, rev=2h, status=0h, command=1h, bus = 0h, slot = 2h, function = 0h
PCI: probe: BARs (header == 0h): 0: FD000008h, 1: 0h, 2: FEBF4000h, 3: 0h, 4: 0h, 5: 0h
PCI: probe: found Intel Corporation 82540EM Gigabit Ethernet Controller (Ethernet controller)
PCI: probe: codes: vendor = 8086h, device = 100Eh, class = 2h, subclass = 0h, prog if=0h, rev=3h, status=0h, command=1h, bus = 0h, slot = 3h, function = 0h
PCI: probe: BARs (header == 0h): 0: FEBC0000h, 1: C601h, 2: 0h, 3: 0h, 4: 0h, 5: 0h
PCI: probe: found Intel Corporation 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (Audio device)
PCI: probe: codes: vendor = 8086h, device = 2668h, class = 4h, subclass = 3h, prog if=0h, rev=1h, status=0h, command=1h, bus = 0h, slot = 4h, function = 0h
PCI: probe: BARs (header == 0h): 0: FEBF0000h, 1: 0h, 2: 0h, 3: 0h, 4: 0h, 5: 0h
PCI: probe: found Intel Corporation 82801AA AC'97 Audio Controller (Multimedia audio controller)
PCI: probe: codes: vendor = 8086h, device = 2415h, class = 4h, subclass = 1h, prog if=0h, rev=1h, status=2h, command=1h, bus = 0h, slot = 5h, function = 0h
PCI: probe: BARs (header == 0h): 0: C001h, 1: C401h, 2: 0h, 3: 0h, 4: 0h, 5: 0h
PCI: probe: found Ensoniq NV5000SC (Multimedia audio controller)
PCI: probe: codes: vendor = 1274h, device = 5000h, class = 4h, subclass = 1h, prog if=0h, rev=0h, status=4h, command=1h, bus = 0h, slot = 6h, function = 0h
PCI: probe: BARs (header == 0h): 0: C501h, 1: 0h, 2: 0h, 3: 0h, 4: 0h, 5: 0h
I finally got the right BAR for the HDA device, at least. (I'm doing no bit masking whatsoever, even though the PCI article says I need to do so.) That is the confusing part, though. It says:
Quote:
Base address Registers (or BARs) can be used to hold memory addresses used by the device, or offsets for port addresses. Typically, memory address BARs need to be located in physical ram while I/O space BARs can reside at any memory address (even beyond physical memory). To distinguish between them, you can check the value of the lowest bit.
Does this mean I need to check bit zero, another bit, or a set of bits? It then goes on to say:
Quote:
When you want to retrieve the actual base address of a BAR, be sure to mask the lower bits. For 16-Bit Memory Space BARs, you calculate (BAR[x] & 0xFFF0). For 32-Bit Memory Space BARs, you calculate (BAR[x] & 0xFFFFFFF0). For 64-Bit Memory Space BARs, you calculate ((BAR[x] & 0xFFFFFFF0) + ((BAR[x+1] & 0xFFFFFFFF) << 32)) For I/O Space BARs, you calculate (BAR[x] & 0xFFFFFFFC).
Besides the minor typo there, does this mean what I think it means? Let's say I'm looking at BAR 0 of the gigabit controller. That BAR is FEBC0000. It also has another BAR, C601. Seems like a 64-bit address to me. To get the actual address, would I do:
Code:
((0xFEBC0000 & 0xFFFFFFF0) + ((0xC601 & 0xFFFFFFFF) << 32)) => 0xC601FEBC0000
If so, then I've finally fixed the major problem I'm having, and can now start actually working with PCI at last.
Edit: OK, a few more questions too.
1) What do I do about BARs that have holes? I.e.: the mPCIe-ICM485-2 2x Isolated RS485 PCI Express Mini Card has two bars: BAR zero, which is FD000008h, and BAR 2, FEBF4000h.
2) Why am I seeing so many devices with all six bars being all zeros?