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