uint32_t pci_device_get_memory_size(struct pci_address* addr, uint32_t bar_offset) { // Save the original BAR so we can restore it once we're done uint32_t orig_bar = pci_read_dword(addr, bar_offset); // Writing all 1s to the BAR register makes the device // write the size of the memory region it occupies into the BAR pci_write_dword(addr, bar_offset, 0xFFFFFFFF); // Read the size from the BAR uint32_t size = pci_read_dword(addr, bar_offset); // Reset the BAR to the original value pci_write_dword(addr, bar_offset, orig_bar); // The size is actually inversed, so NOT the entire thing, // ignoring bit 0 as it's only used to indicate whether the device // uses port I/O or is memory mapped return ~(size & ~1); }
static void process_uhci(struct pci_address* addr, pci_device* dev) { uint8_t revision = pci_read_byte(addr, 0x60); if(revision != UHCI_REV_1_0) { // This host controller indicates that it supports a version // of the USB specification that is *not* 1.0. Ignore it KWARN("Detected UHCI with unsupported revision, ignoring..."); return; } // Bit 0 indicates whether it's memory mapped or port I/O bool memory_mapped = (dev->base_addr4 & 0x1) == 1; // Beore we initialize the card, make sure the cards I/O is disabled uint16_t cmd = pci_read_word(addr, PCI_COMMAND_REG_OFFSET); cmd = (cmd & ~0x1); pci_write_word(addr, PCI_COMMAND_REG_OFFSET, cmd); // THe USB book I'm reading is telling me to null out the // capabilities register as well as the two registers marked as "reserved" // Not sure why, TODO: Investigate! :-S pci_write_dword(addr, PCI_CAPS_OFF_REG_OFFSET, 0x00000000); pci_write_dword(addr, 0x38, 0x00000000); // Set the IRQ pci_write_byte(addr, PCI_IRQ_REG_OFFSET, UHCI_IRQ); // Now try to get the size of the address space //uint32_t size = pci_device_get_memory_size(addr, PCI_BASE_ADDR4_REG_OFFSET); // Enable bus mastering and I/O access pci_write_word(addr, 0x04, memory_mapped ? 0x06 : 0x05); // Disable legacy support and clear current status pci_write_word(addr, PCI_LEG_SUP_REG_OFFSET, PCI_LEGACY_PTS | // Clear Sequence ended bit PCI_LEGACY_TBY64W | PCI_LEGACY_TBY64R | PCI_LEGACY_TBY60W | PCI_LEGACY_TBY60R); // Clear status // The device is now ready for the UHCI driver to take over uhci_init(dev->base_addr4, dev, addr, UHCI_IRQ); }
void pci_reg32_write(struct pci_dev *dev, uint8_t off, uint8_t val) { pci_write_dword(dev->bus, dev->dev, dev->func, off, val); }
void pci_reg16_write(struct pci_dev *dev, uint8_t off, uint8_t val) { uint32_t oval = pci_read_dword(dev->bus, dev->dev, dev->func, off); oval = (oval & (~0xFFFFUL << (off & 2) * 8)) | (val << (off & 2) * 8); pci_write_dword(dev->bus, dev->dev, dev->func, off, oval); }
void pci_config_write_dword(struct pci_device *pdev, uint32_t offset, uint32_t dword) { pci_write_dword(pdev->bus, pdev->slot, pdev->func, offset, dword); }