<title>SPARC Architectural Model: Device and Utility API
</title>
<body bgcolor=
"#FFFFFF" LANG=
"en-US">
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);
This is an abstract class that defines the interface between modules connected to a PCI Bus.
This configuration is an example:
schizo24
<-
> schizo24A
<-
> sample24A1
<-
> schizo24B
<-
> sample24B1
<p> schizo24
is a PCI host bridge at AID=
24 (
0x18).
<br>schizo24A
is PCI bus#
0 on leaf A of the schizo.
<br>schizo24B
is PCI bus#
0 on leaf B. (Leaf B is NOT bus#
1!)
<br>sample24A1 is PCI device
1 on schizo24A.
<br>sample24B1 is PCI device
1 on schizo24B.
<p>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
<p>Both schizo and pci_bus export the PciBusIf interface.
<p>PCI devices, like sample, call the PciBusIf interface, and they export a PciDevIf interface.
<p><b>busif_access
</b>: 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.
<p><b>busif_dma_out
</b> and
<b>busif_dma_in
</b>: 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.
<p><b>busif_add_device
</b> and
<b>busif_delete_device
</b> 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.
<p><b>busif_map
</b> and
<b>busif_unmap
</b> manage PCI address space mappings for devices.
This is used for PCI I/O, mem32, and mem64 spaces (but not config space.)
<p><b>busif_add_interrupt
</b> and
<b>busif_free_interrupt
</b> 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.
<p><b>busif_interrupt_in
</b> requests an interrupt. Called by a PCI device.
<p><b>busif_set_int_pin
</b> requests an interrupt on pin A, B, C, or D.
The host bridge assigns interrupt resources automatically.