93 if (_vendor_id != 0xFFFF) {
95 if (_vendor_id == vendor_id && _device_id == device_id) {
158 oval = (oval & ~(0xFFUL << (off & 3) * 8)) | ((
uint32_t) val << (off & 3) * 8);
173 oval = (oval & ~(0xFFFFUL << (off & 2) * 8)) | ((
uint32_t) val << (off & 2) * 8);
195 if (vendor_id != 0xFFFF) {
201 printk(
" -> Vendor ID: %x, Device ID: %x, Class: %x, Subclass: %x\n", vendor_id, device_id, class_code, subclass_code);
254 for (
uint8_t func = 0; func < 8; ++func) {
257 if (vendor_id != 0xFFFF) {
261 if (class_code ==
class && subclass_code == subclass) {
264 _dev[idx].
func = func;
290#define PCI_COMMAND 0x04
291#define PCI_COMMAND_IO 0x0001
292#define PCI_COMMAND_MEMORY 0x0002
293#define PCI_COMMAND_MASTER 0x0004
294#define PCI_INTERRUPT_LINE 0x3C
322 if (!bar->
io && (lo & 0x6) == 0x4) {
335 sized |= 0xFFFFFFFF00000000ULL | 0xFFFF0000;
338 bar->
size = ~sized + 1;
340 return size_lo ? 0 : -1;
356#define PCI_INTERRUPT_PIN 0x3D
374 if (pin < 1 || pin > 4)
380#define ALIGN_TO(x, a) (((x) + (a) - 1) & ~((uint64_t) (a) - 1))
389 for (
uint8_t slot = 0; slot < 32; ++slot) {
390 for (
uint8_t func = 0; func < 8; ++func) {
398 for (
int id = 0;
id < 6; ++id) {
401 int wide = !(lo & 1) && (lo & 0x6) == 0x4;
417 printk(
"pci: %d:%d.%d BAR %d: %s at %p, %ld bytes\n", 0, slot, func,
id,
420 printk(
"pci: %d:%d.%d BAR %d: no room for %ld bytes\n", 0, slot, func,
id, bar.
size);
465#define PCI_STATUS 0x06
466#define PCI_STATUS_CAP_LIST 0x10
467#define PCI_CAPABILITIES 0x34
468#define PCI_COMMAND_INTX_OFF 0x400
487 for (
int i = 0; off && i < 48; ++i) {
501#define MSI_CTRL_ENABLE 0x0001
502#define MSI_CTRL_MME 0x0070
503#define MSI_CTRL_64BIT 0x0080
int arch_msi_alloc(irq_handler_t handler, void *arg, uint64_t *addr, uint32_t *data)
Gets an IRQ for a device's MSI, and installs its handler.
void(*) irq_handler_t(void *arg)
#define MODULE_INIT(name, i, f)
int pci_irq(struct pci_dev *dev)
Finds the IRQ that a function's interrupt pin comes to.
int pci_prope()
The PCI module's initialization, which has nothing to do: drivers find their devices themselves.
static struct pci_host * host
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 w...
uint16_t pci_reg16_read(struct pci_dev *dev, uint8_t off)
Reads a 16-bit configuration register.
#define PCI_COMMAND_INTX_OFF
uint32_t pci_reg32_read(struct pci_dev *dev, uint8_t off)
Reads a 32-bit configuration register.
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.
void pci_reg32_write(struct pci_dev *dev, uint8_t off, uint32_t val)
Writes a 32-bit configuration register.
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.
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.
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,...
uint32_t pci_read_bar(struct pci_dev *dev, uint8_t id)
Reads a base address register as it is, flag bits included.
#define PCI_INTERRUPT_PIN
#define PCI_STATUS_CAP_LIST
static uint8_t get_class_code(uint8_t bus, uint8_t dev, uint8_t func)
Returns a function's class code.
int pci_host_set(struct pci_host *h)
Sets the platform's host bridge, from platform_init().
#define PCI_INTERRUPT_LINE
#define PCI_COMMAND_MASTER
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.
#define PCI_COMMAND_MEMORY
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.
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...
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.
static uint8_t get_subclass_code(uint8_t bus, uint8_t dev, uint8_t func)
Returns a function's subclass code.
static void scan_device(uint8_t bus, uint8_t dev)
Prints the functions of a device, for debugging.
static uint16_t get_device_id(uint8_t bus, uint8_t dev, uint8_t func)
Returns a function's device ID.
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.
uint8_t pci_cap_find(struct pci_dev *dev, uint8_t id)
Finds one of a function's capabilities.
uint8_t pci_reg8_read(struct pci_dev *dev, uint8_t off)
Reads an 8-bit configuration register.
static void scan_bus(uint8_t bus)
Prints the devices of a bus, for debugging (nothing calls it).
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 dev...
void * arch_mmio_map(uintptr_t paddr, size_t size)
Maps a device's registers into the kernel's address space, uncached (memory-mapped I/O).
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
unsigned long long int uint64_t
unsigned short int uint16_t
A device driver: its operations, any of which may be NULL.
An installed handler, on its interrupt's list.
A base address register (BAR): where the device's registers are, how big they are,...
A PCI function: its bus, device (slot) and function numbers.
The host bridge, which the platform describes (platform_init() sets it): how its configuration space ...
uint32_t(*) read(struct pci_host *host, struct pci_dev *dev, uint16_t reg)
void(*) write(struct pci_host *host, struct pci_dev *dev, uint16_t reg, uint32_t val)