void __pci_parse(struct pci_device *pdev) { /* first determine header type */ uint8_t header = pci_config_read_byte(pdev, 0x0E); if (header == 0x00) { int need_eprom = 1; /* determine bars and iobases */ for(int i = 0; i < 6; i++) { /* there are 6 BARs read them, check if the first byte is 1 */ uint32_t r = pci_config_read_dword(pdev, 0x10 + i * 4); if (r & 1) pdev->iobase = r & 0xFFFFFFFC; else { pdev->membase = r; if (!r) continue; need_eprom = 0; pci_config_write_dword(pdev, 0x10 + i * 4, 0xffffffff); uint32_t size = pci_config_read_dword(pdev, 0x10 + i * 4); size &= 0xfffffff0; size = ~size; size += 1; pci_config_write_dword(pdev, 0x10 + i * 4, pdev->membase); pdev->memsize = size; if (pdev->memsize != 0) printk("membase: 0x%x size: %d\n", pdev->membase, size); } } if (need_eprom) { uint32_t eprom = pci_config_read_dword(pdev, 0x30); if (eprom) { pci_config_write_dword(pdev, 0x30, 0xffffffff); uint32_t size = pci_config_read_dword(pdev, 0x30); size &= 0xfffffff0; size = ~size; size += 1; pci_config_write_dword(pdev, 0x30, eprom); printk("eprom is 0x%x && size is 0x%x\n", eprom, size); } } /* read IRQ */ uint8_t irq = pci_config_read_byte(pdev, 0x3C); pdev->irq = irq; } else { pci_info(pdev, "unknown header!\n"); } }
// Writes an 8-bit value to a PCI device's configuration space. void pci_config_write_byte(uint32_t bus, uint32_t device, uint32_t function, uint32_t offset, uint8_t data) { uint32_t result = pci_config_read_dword(bus, device, function, offset); uint32_t t_offset = (offset & 0x03) * 8; result &= ~(0xFF << t_offset); result |= ((uint32_t)data << t_offset); pci_config_write_dword(bus, device, function, offset, data); }