|
AquilaOS documentation
How it works, and its code
|
The PCI bus: finding devices, and reading and writing their configuration space. More...
#include <core/system.h>#include <core/module.h>#include <core/arch.h>#include <dev/pci.h>#include <cpu/io.h>#include <mm/mm.h>Go to the source code of this file.
Macros | |
| #define | PCI_COMMAND 0x04 |
| #define | PCI_COMMAND_IO 0x0001 |
| #define | PCI_COMMAND_MEMORY 0x0002 |
| #define | PCI_COMMAND_MASTER 0x0004 |
| #define | PCI_INTERRUPT_LINE 0x3C |
| #define | PCI_INTERRUPT_PIN 0x3D |
| #define | ALIGN_TO(x, a) |
| #define | PCI_STATUS 0x06 |
| #define | PCI_STATUS_CAP_LIST 0x10 |
| #define | PCI_CAPABILITIES 0x34 |
| #define | PCI_COMMAND_INTX_OFF 0x400 |
| #define | MSI_CTRL 2 |
| #define | MSI_ADDR 4 |
| #define | MSI_CTRL_ENABLE 0x0001 |
| #define | MSI_CTRL_MME 0x0070 |
| #define | MSI_CTRL_64BIT 0x0080 |
Functions | |
| static uint32_t | pci_read_dword (uint8_t bus, uint8_t dev, uint8_t func, uint16_t reg) |
| Reads a 32-bit configuration register, or returns all ones (no device) if there is no host bridge. | |
| static void | pci_write_dword (uint8_t bus, uint8_t dev, uint8_t func, uint16_t reg, uint32_t val) |
| Writes a 32-bit configuration register, if there is a host bridge. | |
| static uint16_t | get_vendor_id (uint8_t bus, uint8_t dev, uint8_t func) |
| Returns a function's vendor ID: all ones if there's no function. | |
| static uint16_t | get_device_id (uint8_t bus, uint8_t dev, uint8_t func) |
| Returns a function's device ID. | |
| static uint8_t | get_class_code (uint8_t bus, uint8_t dev, uint8_t func) |
| Returns a function's class code. | |
| static uint8_t | get_subclass_code (uint8_t bus, uint8_t dev, uint8_t func) |
| Returns a function's subclass code. | |
| static uint8_t | get_header_type (uint8_t bus, uint8_t dev, uint8_t func) |
| Returns a function's header type: bit 7 set for a device with several functions, the rest 0 for a device and 1 for a bridge. | |
| static uint32_t | get_bar (uint8_t bus, uint8_t dev, uint8_t func, uint8_t id) |
| Returns a function's base address register id, as it is. | |
| int | pci_device_scan (uint16_t vendor_id, uint16_t device_id, struct pci_dev *ref) |
| Finds a device by its vendor and device IDs, on bus 0. | |
| uint8_t | pci_reg8_read (struct pci_dev *dev, uint8_t off) |
| Reads an 8-bit configuration register. | |
| uint16_t | pci_reg16_read (struct pci_dev *dev, uint8_t off) |
| Reads a 16-bit configuration register. | |
| uint32_t | pci_reg32_read (struct pci_dev *dev, uint8_t off) |
| Reads a 32-bit configuration register. | |
| void | pci_reg8_write (struct pci_dev *dev, uint8_t off, uint8_t val) |
| Writes an 8-bit configuration register: the 32-bit register it's in is read, changed and written back. | |
| void | pci_reg16_write (struct pci_dev *dev, uint8_t off, uint16_t val) |
| Writes a 16-bit configuration register: the 32-bit register it's in is read, changed and written back. | |
| void | pci_reg32_write (struct pci_dev *dev, uint8_t off, uint32_t val) |
| Writes a 32-bit configuration register. | |
| static void | scan_device (uint8_t bus, uint8_t dev) |
| Prints the functions of a device, for debugging. | |
| static void | scan_bus (uint8_t bus) |
| Prints the devices of a bus, for debugging (nothing calls it). | |
| int | pci_prope () |
| The PCI module's initialization, which has nothing to do: drivers find their devices themselves. | |
| int | pci_scan_device (uint8_t class, uint8_t subclass, struct pci_dev *_dev, size_t nr) |
| Finds the functions of a class and subclass, on bus 0. | |
| uint32_t | pci_read_bar (struct pci_dev *dev, uint8_t id) |
| Reads a base address register as it is, flag bits included. | |
| int | pci_bar (struct pci_dev *dev, int id, struct pci_bar *bar) |
| Reads a base address register: what it decodes (memory or ports), its address, and its size. | |
| void | pci_enable (struct pci_dev *dev) |
| Turns a function's memory and port decoding on, and bus mastering, so that it can do DMA. | |
| int | pci_irq (struct pci_dev *dev) |
| Finds the IRQ that a function's interrupt pin comes to. | |
| static void | pci_assign (void) |
| Assigns addresses to the BARs that no firmware assigned, on bus 0's devices: each BAR in the host's window for its kind (memory or ports), aligned to its size. | |
| int | pci_host_set (struct pci_host *h) |
| Sets the platform's host bridge, from platform_init(). | |
| uint8_t | pci_cap_find (struct pci_dev *dev, uint8_t id) |
| Finds one of a function's capabilities. | |
| int | pci_msi_enable (struct pci_dev *dev, irq_handler_t handler, void *arg) |
| Has a function send its interrupts as messages (MSI) instead of on its interrupt line: one message, for an IRQ that goes to handler. | |
Variables | |
| static struct pci_host * | host |
| struct dev | pcidev |
The PCI bus: finding devices, and reading and writing their configuration space.
Every PCI function has a configuration space: who made it (vendor and device IDs), what it is (class and subclass), which memory and ports it decodes (its base address registers, BARs), its interrupt, and a list of capabilities. How that space is reached is the platform's: the host bridge (struct pci_host) that platform_init() gives pci_host_set(), with configuration mechanism #1 (conf1.c) or ECAM (ecam.c). Only bus 0 is scanned. See docs/kernel/devices.md.
Definition in file pci.c.
| #define ALIGN_TO | ( | x, | |
| a ) |
Definition at line 380 of file pci.c.
Referenced by pci_assign().
| #define MSI_ADDR 4 |
Definition at line 500 of file pci.c.
Referenced by pci_msi_enable().
| #define MSI_CTRL 2 |
Definition at line 499 of file pci.c.
Referenced by pci_msi_enable().
| #define MSI_CTRL_64BIT 0x0080 |
Definition at line 503 of file pci.c.
Referenced by pci_msi_enable().
| #define MSI_CTRL_ENABLE 0x0001 |
Definition at line 501 of file pci.c.
Referenced by pci_msi_enable().
| #define MSI_CTRL_MME 0x0070 |
Definition at line 502 of file pci.c.
Referenced by pci_msi_enable().
| #define PCI_CAPABILITIES 0x34 |
Definition at line 467 of file pci.c.
Referenced by pci_cap_find().
| #define PCI_COMMAND 0x04 |
Definition at line 290 of file pci.c.
Referenced by pci_bar(), pci_enable(), and pci_msi_enable().
| #define PCI_COMMAND_INTX_OFF 0x400 |
Definition at line 468 of file pci.c.
Referenced by pci_msi_enable().
| #define PCI_COMMAND_IO 0x0001 |
Definition at line 291 of file pci.c.
Referenced by pci_bar(), and pci_enable().
| #define PCI_COMMAND_MASTER 0x0004 |
Definition at line 293 of file pci.c.
Referenced by pci_enable().
| #define PCI_COMMAND_MEMORY 0x0002 |
Definition at line 292 of file pci.c.
Referenced by pci_bar(), and pci_enable().
| #define PCI_STATUS 0x06 |
Definition at line 465 of file pci.c.
Referenced by pci_cap_find().
| #define PCI_STATUS_CAP_LIST 0x10 |
Definition at line 466 of file pci.c.
Referenced by pci_cap_find().
Returns a function's base address register id, as it is.
Definition at line 74 of file pci.c.
References pci_dev::bus, pci_dev::func, get_bar(), and pci_read_dword().
Referenced by get_bar().
Returns a function's class code.
Definition at line 55 of file pci.c.
References pci_dev::bus, pci_dev::func, get_class_code(), and pci_read_dword().
Referenced by get_class_code(), pci_scan_device(), and scan_device().
Returns a function's device ID.
Definition at line 49 of file pci.c.
References pci_dev::bus, pci_dev::func, get_device_id(), and pci_read_dword().
Referenced by get_device_id(), pci_device_scan(), and scan_device().
Returns a function's header type: bit 7 set for a device with several functions, the rest 0 for a device and 1 for a bridge.
Definition at line 68 of file pci.c.
References pci_dev::bus, pci_dev::func, get_header_type(), and pci_read_dword().
Referenced by get_header_type(), and pci_assign().
Returns a function's subclass code.
Definition at line 61 of file pci.c.
References pci_dev::bus, pci_dev::func, get_subclass_code(), and pci_read_dword().
Referenced by get_subclass_code(), pci_scan_device(), and scan_device().
Returns a function's vendor ID: all ones if there's no function.
Definition at line 43 of file pci.c.
References pci_dev::bus, pci_dev::func, get_vendor_id(), and pci_read_dword().
Referenced by get_vendor_id(), pci_assign(), pci_device_scan(), pci_scan_device(), and scan_device().
|
static |
Assigns addresses to the BARs that no firmware assigned, on bus 0's devices: each BAR in the host's window for its kind (memory or ports), aligned to its size.
The addresses are the bus's.
Definition at line 385 of file pci.c.
References pci_bar::addr, ALIGN_TO, pci_dev::func, get_header_type(), get_vendor_id(), host, pci_bar::io, pci_host::io_base, pci_host::io_size, pci_host::mem_base, pci_host::mem_size, pci_assign(), pci_reg32_read(), pci_reg32_write(), printk(), and pci_bar::size.
Referenced by pci_assign(), and pci_host_set().
| int pci_bar | ( | struct pci_dev * | dev, |
| int | id, | ||
| struct pci_bar * | bar ) |
Reads a base address register: what it decodes (memory or ports), its address, and its size.
The size is found by writing all ones to the register and reading back what the device kept, with decoding turned off meanwhile. A 64-bit memory BAR uses the next register too.
| dev | the function |
| id | the BAR's number, 0 to 5 |
| bar | set to what the BAR decodes |
Definition at line 307 of file pci.c.
References pci_bar::addr, pci_bar::io, PCI_COMMAND, PCI_COMMAND_IO, PCI_COMMAND_MEMORY, pci_reg16_read(), pci_reg16_write(), pci_reg32_read(), pci_reg32_write(), and pci_bar::size.
Finds one of a function's capabilities.
| dev | the function |
| id | the capability (PCI_CAP_*) |
Definition at line 478 of file pci.c.
References pci_cap_find(), PCI_CAPABILITIES, pci_reg16_read(), pci_reg8_read(), PCI_STATUS, and PCI_STATUS_CAP_LIST.
Referenced by pci_cap_find(), and pci_msi_enable().
Finds a device by its vendor and device IDs, on bus 0.
| vendor_id | the vendor ID |
| device_id | the device ID |
| ref | if not NULL, set to the first function found |
Definition at line 87 of file pci.c.
References pci_dev::bus, pci_dev::dev, pci_dev::func, get_device_id(), get_vendor_id(), and pci_device_scan().
Referenced by e1000_probe(), and pci_device_scan().
| void pci_enable | ( | struct pci_dev * | dev | ) |
Turns a function's memory and port decoding on, and bus mastering, so that it can do DMA.
| dev | the function |
Definition at line 349 of file pci.c.
References PCI_COMMAND, PCI_COMMAND_IO, PCI_COMMAND_MASTER, PCI_COMMAND_MEMORY, pci_enable(), pci_reg16_read(), and pci_reg16_write().
Referenced by e1000_probe(), and pci_enable().
| int pci_host_set | ( | struct pci_host * | h | ) |
Sets the platform's host bridge, from platform_init().
Its configuration space is mapped if it is memory (ECAM), and the BARs no firmware assigned get addresses in its windows.
| h | the host bridge |
Definition at line 443 of file pci.c.
References ioaddr::addr, arch_mmio_map(), pci_host::config, host, pci_host::io_size, IOADDR_PORT, pci_host::mem_size, pci_host::name, pci_assign(), pci_host_set(), printk(), pci_host::size, and ioaddr::type.
Referenced by pci_host_set(), platform_init(), and x86_pc_pci_init().
| int pci_irq | ( | struct pci_dev * | dev | ) |
Finds the IRQ that a function's interrupt pin comes to.
If the host bridge says which IRQs INTA# to INTD# come to, the pin is swizzled by the device's slot, as a bridge's interrupt map does (INTA# of slot 1 is INTB#). Otherwise it is the interrupt line that the firmware wrote.
| dev | the function |
Definition at line 367 of file pci.c.
References host, pci_host::irq, pci_host::nirq, PCI_INTERRUPT_LINE, PCI_INTERRUPT_PIN, pci_irq(), and pci_reg8_read().
Referenced by ata_probe(), e1000_probe(), and pci_irq().
| int pci_msi_enable | ( | struct pci_dev * | dev, |
| irq_handler_t | handler, | ||
| void * | arg ) |
Has a function send its interrupts as messages (MSI) instead of on its interrupt line: one message, for an IRQ that goes to handler.
Its interrupt line (INTx) is turned off. If MSI isn't possible, the caller uses the line instead.
| dev | the function |
| handler | the interrupt's handler |
| arg | the handler's argument |
Definition at line 517 of file pci.c.
References pci_bar::addr, arch_msi_alloc(), MSI_ADDR, MSI_CTRL, MSI_CTRL_64BIT, MSI_CTRL_ENABLE, MSI_CTRL_MME, pci_cap_find(), PCI_CAP_MSI, PCI_COMMAND, PCI_COMMAND_INTX_OFF, pci_msi_enable(), pci_reg16_read(), pci_reg16_write(), and pci_reg32_write().
Referenced by e1000_probe(), and pci_msi_enable().
| int pci_prope | ( | ) |
The PCI module's initialization, which has nothing to do: drivers find their devices themselves.
Definition at line 220 of file pci.c.
References pci_prope().
Referenced by pci_prope().
Reads a base address register as it is, flag bits included.
| dev | the function |
| id | the BAR's number, 0 to 5 |
Definition at line 285 of file pci.c.
References pci_read_bar(), and pci_read_dword().
Referenced by ata_probe(), and pci_read_bar().
Reads a 32-bit configuration register, or returns all ones (no device) if there is no host bridge.
Definition at line 27 of file pci.c.
References pci_dev::bus, pci_dev::func, host, pci_read_dword(), and pci_host::read.
Referenced by get_bar(), get_class_code(), get_device_id(), get_header_type(), get_subclass_code(), get_vendor_id(), pci_read_bar(), pci_read_dword(), pci_reg16_read(), pci_reg16_write(), pci_reg32_read(), pci_reg8_read(), and pci_reg8_write().
Reads a 16-bit configuration register.
| dev | the function |
| off | the register's offset, a multiple of 2 |
Definition at line 130 of file pci.c.
References pci_read_dword(), and pci_reg16_read().
Referenced by ata_probe(), pci_bar(), pci_cap_find(), pci_enable(), pci_msi_enable(), and pci_reg16_read().
Writes a 16-bit configuration register: the 32-bit register it's in is read, changed and written back.
| dev | the function |
| off | the register's offset, a multiple of 2 |
| val | the value to write |
Definition at line 170 of file pci.c.
References pci_read_dword(), pci_reg16_write(), and pci_write_dword().
Referenced by ata_probe(), pci_bar(), pci_enable(), pci_msi_enable(), and pci_reg16_write().
Reads a 32-bit configuration register.
| dev | the function |
| off | the register's offset, a multiple of 4 |
Definition at line 142 of file pci.c.
References pci_read_dword(), and pci_reg32_read().
Referenced by pci_assign(), pci_bar(), and pci_reg32_read().
Writes a 32-bit configuration register.
| dev | the function |
| off | the register's offset, a multiple of 4 |
| val | the value to write |
Definition at line 184 of file pci.c.
References pci_reg32_write(), and pci_write_dword().
Referenced by pci_assign(), pci_bar(), pci_msi_enable(), and pci_reg32_write().
Reads an 8-bit configuration register.
| dev | the function |
| off | the register's offset |
Definition at line 118 of file pci.c.
References pci_read_dword(), and pci_reg8_read().
Referenced by pci_cap_find(), pci_irq(), and pci_reg8_read().
Writes an 8-bit configuration register: the 32-bit register it's in is read, changed and written back.
| dev | the function |
| off | the register's offset |
| val | the value to write |
Definition at line 155 of file pci.c.
References pci_read_dword(), pci_reg8_write(), and pci_write_dword().
Referenced by pci_reg8_write().
Finds the functions of a class and subclass, on bus 0.
| class | the class code |
| subclass | the subclass code |
| _dev | set to the functions found |
| nr | how many _dev can hold |
Definition at line 244 of file pci.c.
References pci_dev::bus, pci_dev::dev, pci_dev::func, get_class_code(), get_subclass_code(), get_vendor_id(), and pci_scan_device().
Referenced by ata_probe(), and pci_scan_device().
|
inlinestatic |
Writes a 32-bit configuration register, if there is a host bridge.
Definition at line 34 of file pci.c.
References pci_dev::bus, pci_dev::func, host, pci_write_dword(), and pci_host::write.
Referenced by pci_reg16_write(), pci_reg32_write(), pci_reg8_write(), and pci_write_dword().
|
static |
Prints the devices of a bus, for debugging (nothing calls it).
Definition at line 207 of file pci.c.
References pci_dev::bus, scan_bus(), and scan_device().
Referenced by scan_bus().
Prints the functions of a device, for debugging.
Definition at line 190 of file pci.c.
References pci_dev::bus, pci_dev::func, get_class_code(), get_device_id(), get_subclass_code(), get_vendor_id(), printk(), and scan_device().
Referenced by scan_bus(), and scan_device().
|
static |
Definition at line 23 of file pci.c.
Referenced by pci_assign(), pci_host_set(), pci_irq(), pci_read_dword(), and pci_write_dword().