acpi_status acpi_os_read_pci_configuration ( acpi_pci_id *pci_id, u32 reg, void *value, u32 width) { int result = 0; if (!value) return AE_ERROR; switch (width) { case 8: result = pci_config_read(pci_id->segment, pci_id->bus, pci_id->device, pci_id->function, reg, 1, value); break; case 16: result = pci_config_read(pci_id->segment, pci_id->bus, pci_id->device, pci_id->function, reg, 2, value); break; case 32: result = pci_config_read(pci_id->segment, pci_id->bus, pci_id->device, pci_id->function, reg, 4, value); break; default: BUG(); } return (result ? AE_ERROR : AE_OK); }
/** * \brief Initialize the PCI root complex driver. */ void pci_root_complex_init(void) { uint32_t rcba_addr; pci_config_addr_t pci = { .raw = 0 }; pci.dev = 31; pci.reg_off = 0xF0; /* Root Complex Base Address Register */ /* masked to clear non-address bits. */ rcba_addr = pci_config_read(pci) & ~0x3FFF; PROT_DOMAINS_INIT_ID(root_complex_drv); prot_domains_reg(&root_complex_drv, rcba_addr, 0x4000, 0, 0, false); SYSCALLS_INIT(pci_irq_agent_set_pirq); SYSCALLS_AUTHZ(pci_irq_agent_set_pirq, root_complex_drv); } /*---------------------------------------------------------------------------*/ /** * \brief Prevent further invocations of pci_irq_agent_set_pirq. */ void pci_root_complex_lock(void) { SYSCALLS_DEAUTHZ(pci_irq_agent_set_pirq, root_complex_drv); }
void smm_init(void) { uint32_t adr; uint32_t smi_en; unsigned if_backup; if_backup = cli(); /* adr = (1<<31) | (LPC_BUS << 16) | (LPC_DEVICE << 11) | (LPC_FUNC << 8) | LPC_OFFSET; outportl(CONFIG_ADDRESS, adr); pmbase = inportl(CONFIG_DATA); */ pmbase = pci_config_read(LPC_BUS, LPC_DEVICE, LPC_FUNC, LPC_OFFSET); pmbase &= 0xFF80; IFV printf("SMM: located pmbase : 0x%x \n", pmbase); if (pmbase != 0) { adr = pmbase+0x30; /* SMI_EN I/O register is at pmbase+0x30 */ /* read SMI_EN and display */ smi_en = inportl(adr); bak_smi_en = smi_en; IFVV printf("SMI_EN: 0x%x \n", smi_en); } if (if_backup) sti(); }
void pci_config_write_partial(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value, int size) { int remainder = offset & 3; offset &= (~(uint8_t)3); uint32_t current = pci_config_read(bus, device, function, offset); value <<= remainder; current |= value; pci_config_write(bus, device, function, offset, value); }
uint32_t pci_config_read_partial(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, int size) { int remainder = offset & 3; offset &= (~(uint8_t)3); uint32_t value = pci_config_read(bus, device, function, offset); value >>= remainder; value &= ( (1 << size) - 1 ); return value; }
/** * \brief Enable PCI command bits of the specified PCI configuration * register. * \param addr Address of PCI configuration register. * \param flags Flags used to enable PCI command bits. */ void pci_command_enable(pci_config_addr_t addr, uint32_t flags) { uint32_t data; addr.reg_off = 0x04; /* PCI COMMAND_REGISTER */ data = pci_config_read(addr); pci_config_write(addr, data | flags); }
/** * \brief Initialize a structure for a PCI device driver that performs * MMIO to address range 0. Assumes that device has already * been configured with an MMIO address range 0, e.g. by * firmware. * \param c_this Structure that will be initialized to represent the driver. * \param pci_addr PCI base address of device. * \param mmio_sz Size of MMIO region. * \param meta Base address of optional driver-defined metadata. * \param meta_sz Size of optional driver-defined metadata. */ void pci_init(pci_driver_t ATTR_KERN_ADDR_SPACE *c_this, pci_config_addr_t pci_addr, size_t mmio_sz, uintptr_t meta, size_t meta_sz) { uintptr_t mmio; /* The BAR value is masked to clear non-address bits. */ mmio = pci_config_read(pci_addr) & ~0xFFF; prot_domains_reg(c_this, mmio, mmio_sz, meta, meta_sz, false); }
/** * \brief Set current IRQ to PIRQ. The interrupt router can be * programmed to allow PIRQ[A:H] to be routed internally * to the 8259 as ISA compatible interrupts. See also * pci_irq_agent_set_pirq(). * \param pirq PIRQ to be used, PIRQ[A:H]. * \param pin IRQ to be used, IRQ[0:15]. * \param route_to_legacy Whether or not the interrupt should be routed to PIC 8259. */ void pci_pirq_set_irq(PIRQ pirq, uint8_t irq, uint8_t route_to_legacy) { pci_config_addr_t pci; uint32_t value; assert(pirq >= PIRQA && pirq <= PIRQH); assert(irq >= 0 && irq <= 0xF); assert(route_to_legacy == 0 || route_to_legacy == 1); pci.raw = 0; pci.bus = 0; pci.dev = 31; pci.func = 0; pci.reg_off = (pirq <= PIRQD) ? 0x60 : 0x64; /* PABCDRC and PEFGHRC Registers */ value = pci_config_read(pci); switch(pirq) { case PIRQA: case PIRQE: value &= ~0x8F; value |= irq; value |= (!route_to_legacy << 7); break; case PIRQB: case PIRQF: value &= ~0x8F00; value |= (irq << 8); value |= (!route_to_legacy << 15); break; case PIRQC: case PIRQG: value &= ~0x8F0000; value |= (irq << 16); value |= (!route_to_legacy << 23); break; case PIRQD: case PIRQH: value &= ~0x8F000000; value |= (irq << 24); value |= (!route_to_legacy << 31); } set_addr(pci); outl(PCI_CONFIG_DATA_PORT, value); }
int rtl8139_init(unsigned bus, unsigned slot) { uint16_t iobase; iobase = pci_config_read(bus, slot, 0, 0x10); if (iobase & 1) { // io-port: ignore 2 least significant bits iobase &= ~0x03; } IFV printf("rtl8139: iobase = 0x%x\n", iobase); uint8_t mac[6]; unsigned u; for (u=0; u<6; u++) { mac[u] = inportb(iobase + u); } IFV printf("rtl8139: mac = %x:%x:%x:%x:%x:%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return 1; // the driver was not loaded, so far, we just print some information }
/* ---------------------------------------------------- * Function: pci_dev_get_info * --------------------------------------------------*/ pci_dev_t * pci_dev_get_info(uint8_t bus, uint8_t slot, uint8_t func){ uint32_t tmp = pci_config_read(bus, slot, func, 0); if((tmp & 0xFFFF) == 0xFFFF){ return NULL; // Vendor ID of 0xFFFF signifies non-existent device. } pci_dev_t *dev = (pci_dev_t *) kmalloc(sizeof(pci_dev_t)); MALLOC_PANIC(dev); dev->dev_id = tmp >> 16; dev->vendor_id = tmp & 0xFFFF; tmp = pci_config_read(bus, slot, func, 2); dev->class_id = tmp >> 24; dev->subclass_id = tmp >> 16 & 0xFF; dev->prog_if = tmp >> 8 & 0xFF; dev->revision_id = tmp & 0xFF; tmp = pci_config_read(bus, slot, func, 3); dev->bist = tmp >> 24; dev->header_type = tmp >> 16 & 0x7F; // Bit 7 is the multi function flag. // We don't use it dev->latency = tmp >> 8 & 0xFF; dev->cache_line_size = tmp & 0x0FF; dev->bar0 = pci_config_read(bus, slot, func, 4); dev->bar1 = pci_config_read(bus, slot, func, 5); // The contents of the rest of the PCI device header depends on // the header type. // 0x00 - standard header. // 0x01 - PCI-PCI bridge header. // 0x02 - Card bus bridge header. // switch(dev->header_type){ case 0x00: dev->bar2 = pci_config_read(bus, slot, func, 6); dev->bar3 = pci_config_read(bus, slot, func, 7); dev->bar4 = pci_config_read(bus, slot, func, 8); dev->bar5 = pci_config_read(bus, slot, func, 9); tmp = pci_config_read(bus, slot, func, 11); dev->subsys_id = tmp >> 16; dev->subsys_vendor_id= tmp & 0xFFFF; tmp = pci_config_read(bus, slot, func, 15); dev->int_pin = (tmp >> 8) & 0xFF; dev->int_line = tmp & 0xFF; break; case 0x01: break; default: break; } dev->bus = bus; dev->slot = slot; dev->func = func; pci_dev_lookup_ids(dev); return dev; }