swissChili | e849174 | 2021-04-08 20:38:06 -0700 | [diff] [blame] | 1 | #include <dri/pci/pci.h> |
swissChili | ca26848 | 2021-05-28 18:31:46 -0700 | [diff] [blame] | 2 | #include <dri/pci/vendors.h> |
| 3 | #include <io.h> |
| 4 | #include <log.h> |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 5 | #include <alloc.h> |
| 6 | |
| 7 | static uint num_drivers, size_drivers; |
| 8 | static struct pci_device_driver *drivers; |
swissChili | 0d24883 | 2021-04-08 18:16:02 -0700 | [diff] [blame] | 9 | |
swissChili | 9321498 | 2021-05-28 21:32:26 -0700 | [diff] [blame] | 10 | uint pci_config_readd(uchar bus, uchar slot, uchar func, uchar offset) |
swissChili | 0d24883 | 2021-04-08 18:16:02 -0700 | [diff] [blame] | 11 | { |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 12 | uint address = |
| 13 | (bus << 16) | (slot << 11) | (func << 8) | (offset << 2) | 0x80000000; |
swissChili | ca26848 | 2021-05-28 18:31:46 -0700 | [diff] [blame] | 14 | |
| 15 | outl(PCI_CONFIG_ADDRESS, address); |
| 16 | |
| 17 | return inl(PCI_CONFIG_DATA); |
| 18 | } |
| 19 | |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 20 | struct pci_device pci_check_device(uchar bus, uchar slot, uchar func) |
swissChili | ca26848 | 2021-05-28 18:31:46 -0700 | [diff] [blame] | 21 | { |
swissChili | b35a5cf | 2021-05-30 12:22:18 -0700 | [diff] [blame] | 22 | uint vendor_device = pci_config_readd(bus, slot, func, 0); |
| 23 | ushort vendor = vendor_device & 0xffff; |
swissChili | ca26848 | 2021-05-28 18:31:46 -0700 | [diff] [blame] | 24 | |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 25 | struct pci_device device; |
| 26 | device.valid = false; |
swissChili | 77eb147 | 2021-05-28 21:40:00 -0700 | [diff] [blame] | 27 | |
swissChili | b35a5cf | 2021-05-30 12:22:18 -0700 | [diff] [blame] | 28 | if (vendor != 0xffff) |
swissChili | 0d24883 | 2021-04-08 18:16:02 -0700 | [diff] [blame] | 29 | { |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 30 | device.valid = true; |
swissChili | b35a5cf | 2021-05-30 12:22:18 -0700 | [diff] [blame] | 31 | |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 32 | device.device_id = vendor_device >> 16; |
| 33 | device.vendor = pci_vendor_by_id(vendor); |
| 34 | |
| 35 | // 3rd dword |
| 36 | uint class_subclass = pci_config_readd(bus, slot, func, 2); |
| 37 | device.class = class_subclass >> 24; |
| 38 | device.subclass = (class_subclass >> 16) & 0xff; |
| 39 | device.prog_if = (class_subclass >> 8) & 0xff; |
swissChili | ca26848 | 2021-05-28 18:31:46 -0700 | [diff] [blame] | 40 | } |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 41 | |
| 42 | return device; |
swissChili | ca26848 | 2021-05-28 18:31:46 -0700 | [diff] [blame] | 43 | } |
| 44 | |
| 45 | struct pci_vendor *pci_vendor_by_id(ushort id) |
| 46 | { |
| 47 | // Find vendor using binary search |
| 48 | |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 49 | uint start = 0, max = pci_num_vendors; |
swissChili | ca26848 | 2021-05-28 18:31:46 -0700 | [diff] [blame] | 50 | |
| 51 | while (true) |
| 52 | { |
| 53 | if (max == start) |
| 54 | // Can't find one |
| 55 | return NULL; |
| 56 | |
| 57 | uint guess = (max - start) / 2 + start; |
| 58 | |
| 59 | if (pci_vendors[guess].id == id) |
| 60 | return &pci_vendors[guess]; |
| 61 | else if (pci_vendors[guess].id > id) |
| 62 | max = guess; |
| 63 | else |
| 64 | start = guess; |
| 65 | } |
swissChili | 0d24883 | 2021-04-08 18:16:02 -0700 | [diff] [blame] | 66 | } |
swissChili | 402a383 | 2021-05-29 21:41:31 -0700 | [diff] [blame] | 67 | |
| 68 | void pci_print_devices() |
| 69 | { |
| 70 | kprintf("Enumerating PCI devices:\n"); |
| 71 | for (int bus = 0; bus < 0xff; bus++) |
| 72 | { |
| 73 | for (int slot = 0; slot < 32; slot++) |
| 74 | { |
| 75 | for (int func = 0; func < 8; func++) |
| 76 | { |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 77 | struct pci_device dev = pci_check_device(bus, slot, func); |
swissChili | 402a383 | 2021-05-29 21:41:31 -0700 | [diff] [blame] | 78 | |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 79 | if (dev.valid) |
swissChili | 402a383 | 2021-05-29 21:41:31 -0700 | [diff] [blame] | 80 | { |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 81 | kprintf("%d %d %d --- d:0x%x --- %d:%d:%d --- %s\n", bus, |
| 82 | slot, func, dev.device_id, dev.class, dev.subclass, |
| 83 | dev.prog_if, dev.vendor->name); |
swissChili | 402a383 | 2021-05-29 21:41:31 -0700 | [diff] [blame] | 84 | } |
| 85 | } |
| 86 | } |
| 87 | } |
| 88 | } |
swissChili | 5fe85a1 | 2021-05-31 08:10:27 -0700 | [diff] [blame] | 89 | |
| 90 | void pci_register_device_driver(struct pci_device_driver driver) |
| 91 | { |
| 92 | if (num_drivers == size_drivers) |
| 93 | { |
| 94 | size_drivers += 8; |
| 95 | drivers = realloc(drivers, sizeof(struct pci_device_driver) * size_drivers); |
| 96 | } |
| 97 | |
| 98 | driver.loaded = 0; |
| 99 | drivers[num_drivers++] = driver; |
| 100 | } |
| 101 | |
| 102 | void pci_init() |
| 103 | { |
| 104 | num_drivers = 0; |
| 105 | size_drivers = 4; |
| 106 | drivers = malloc(sizeof(struct pci_device_driver) * size_drivers); |
| 107 | } |
| 108 | |
| 109 | void pci_load() |
| 110 | { |
| 111 | for (int bus = 0; bus < 0xff; bus++) |
| 112 | { |
| 113 | for (int slot = 0; slot < 32; slot++) |
| 114 | { |
| 115 | for (int func = 0; func < 8; func++) |
| 116 | { |
| 117 | struct pci_device dev = pci_check_device(bus, slot, func); |
| 118 | |
| 119 | // Do any drivers support this? |
| 120 | |
| 121 | for (int i = 0; i < num_drivers; i++) |
| 122 | { |
| 123 | if (drivers[i].supports(&dev)) |
| 124 | { |
| 125 | drivers[i].loaded++; |
| 126 | drivers[i].dev = dev; |
| 127 | drivers[i].init(dev, bus, slot, func); |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | void pci_print_drivers() |
| 136 | { |
| 137 | kprintf("Enumerating PCI device drivers:\n"); |
| 138 | for (int i = 0; i < num_drivers; i++) |
| 139 | { |
| 140 | for (int j = 0; j < drivers[i].loaded; j++) |
| 141 | { |
| 142 | struct pci_device_driver d = drivers[i]; |
| 143 | kprintf("Driver: %s, vendor: %s\n", d.generic_name, d.dev.vendor->name); |
| 144 | } |
| 145 | } |
| 146 | } |