virtual int busif_access(pci_space_t, uint64_t paddr, uint64_t offset, bool_t wr, uint32_t size, uint64_t* buf); virtual int busif_add_device(const char *devname, int device, int function); virtual int busif_delete_device(const char *devname); virtual int busif_map(const char *devname, pci_space_t, uint64_t base, uint64_t size); virtual int busif_unmap(const char *devname, pci_space_t); virtual int busif_add_interrupt(const char *device_name, int *device_number, int *slot_irl, const char **host); virtual int busif_free_interrupt(int dev_number); virtual int busif_interrupt_in(bool set, int dev_type, int dev_number, int line); virtual int busif_set_int_pin(int pin, bool raise, int device, module_t *caller); virtual int busif_dma_out(uint64_t vaddr, void *data, long count, module_t *caller); virtual int busif_dma_in(uint64_t vaddr, void *data, long count, module_t *caller);
schizo24 <-> schizo24A <-> sample24A1 <-> schizo24B <-> sample24B1
schizo24 is a PCI host bridge at AID=24 (0x18).
schizo24A is PCI bus#0 on leaf A of the schizo.
schizo24B is PCI bus#0 on leaf B. (Leaf B is NOT bus#1!)
sample24A1 is PCI device 1 on schizo24A.
sample24B1 is PCI device 1 on schizo24B.
The configuration file looks like this:
sysconf schizo schizo24 aid=24 pciA=schizo24A pciB=schizo24B
sysconf pci_bus schizo24A bridge=schizo24
sysconf sample sample24A1 bus=schizo24A dev=1 fun=0
sysconf pci_bus schizo24B bridge=schizo24
sysconf sample sample24B1 bus=schizo24B dev=1 fun=0
Both schizo and pci_bus export the PciBusIf interface.
PCI devices, like sample, call the PciBusIf interface, and they export a PciDevIf interface.
busif_access: I/O access in the downstream direction (from CPU to device). A CPU read or write first goes to a schizo based on the address range (determined by aid). The schizo routes the access to either pciA or pciB depending on the address range. The pci_bus routes the access to one of its devices depending on the device PCI address range (see PciDev::dev_set_space). The last access is done through the PciDevIf interface.
busif_dma_out and busif_dma_in: I/O access in the upstream direction. DMA works with PCI addresses. The host bridge (schizo) has an IOMMU which translates PCI addresses into physical memory addresses.
busif_add_device and busif_delete_device attach or detach devices on a bus. A device attaches itself to a bus when it detects that the bus has been configured. The bus maps the device into the PCI configuration space.
busif_map and busif_unmap manage PCI address space mappings for devices. This is used for PCI I/O, mem32, and mem64 spaces (but not config space.)
busif_add_interrupt and busif_free_interrupt manage interrupt resources in the host bridge (schizo). A PCI device makes a request for an interrupt vector. The pci_bus simply forwards it towards the bridge.
busif_interrupt_in requests an interrupt. Called by a PCI device.
busif_set_int_pin requests an interrupt on pin A, B, C, or D. The host bridge assigns interrupt resources automatically.