pci-bus: support I/O port BARs and per-function Subsystem IDs - #225
Merged
Conversation
Signed-off-by: Sol Astrius <sol@astrius.ink>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two related extensions needed by Linux drivers that match on strict subsystem IDs and/or probe via
inb/outbon the BAR. Both are purely additive — defaults preserve the existing behaviour for every device already in the tree.Per-function Subsystem Vendor / Subsystem Device ID
The PCI configuration Subsystem IDs at config-space offset
0x2C(§6.2.4) were hardcoded to0x510010DC(CERN/ECP/EDU) for every emulated function. Most Linux drivers ignore subsys IDs and match on vendor:device, so this was invisible — untilparport_pc, whose PCI table for the NetMos 9900 entry strictly requires0xA000:0x2000:{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900, 0xA000, 0x2000, 0, 0, netmos_9900 },Without the match,
parport_pcskips the device, noparport0/lp0nodes appear, and userspace can't reach the emulated port even thoughlspcicorrectly shows the MosChip MCS9900 ID.Add
subsys_vendor_id/subsys_device_idtopci_func_desc_tandpci_func_t. Default zero — the read handler falls back to the original0x510010DCplaceholder so existing devices that don't set these (sound-hda, nvme, rtl8169, usb-xhci, ata, bochs-display, pci-vfio) round-trip the same value they always have.I/O port BARs
The bus only emitted Memory-type BARs — every BAR allocation went through
pci_assign_mmio_addr(0x40000000+ range), and the BAR config read never setPCI_BAR_IO_SPACE. This worked for every existing device because all of them use memory-mapped registers.Fails for any Linux driver whose PCI probe path does:
On RISC-V (and other non-x86 platforms where Linux maps PCI I/O space to MMIO)
inb(addr)resolves to a memory access atPCI_IOBASE + addr. With a Memory BAR,pci_resource_startreturns e.g.0x40009000—inb()then reads atPCI_IOBASE + 0x40009000, way outside the legal I/O window, returns0xFF, the driver sees no data and skips the device.parport_pcis the canonical example. Linux's__parport_pc_probe_porttakes raw I/O addresses and feeds them throughinb/outb. There is no memory-mapped probe path. The same applies to many vintage / legacy PCI drivers (some serial chips, ISA-style PCI cards, GPIB controllers).Add I/O BAR support:
pci_func_desc_t.bar_io_mask: bitmap of BAR indices that should be declared I/O type. Default 0 = all Memory.pci_assign_io_addr: allocates frombus->io_addrrange (PCI_IO_ADDR_DEFAULT = 0x03000000, length0x10000) instead of the memory pool.pci_attach_bartakesis_io, threads to the right allocator.bus->io_addr) ORed withPCI_BAR_IO_SPACE(bit 0).bus->io_addr + (val & ~0x3).