1 #include <KernelExport.h> 2 #include <PCI.h> 3 #include "util/kernel_cpp.h" 4 #include "pci_priv.h" 5 #include "pci.h" 6 7 static PCI *pcidb; 8 9 void 10 pci_init(void) 11 { 12 pcidb = new PCI; 13 } 14 15 void 16 pci_uninit(void) 17 { 18 delete pcidb; 19 } 20 21 long 22 pci_get_nth_pci_info(long index, pci_info *outInfo) 23 { 24 return pcidb->GetNthPciInfo(index, outInfo); 25 } 26 27 28 PCI::PCI() 29 { 30 fRootBus.parent = 0; 31 fRootBus.bus = 0; 32 fRootBus.child = 0; 33 34 DiscoverBus(&fRootBus); 35 36 RefreshDeviceInfo(&fRootBus); 37 } 38 39 40 PCI::~PCI() 41 { 42 } 43 44 45 status_t 46 PCI::GetNthPciInfo(long index, pci_info *outInfo) 47 { 48 long curindex = 0; 49 return GetNthPciInfo(&fRootBus, &curindex, index, outInfo); 50 } 51 52 53 status_t 54 PCI::GetNthPciInfo(PCIBus *bus, long *curindex, long wantindex, pci_info *outInfo) 55 { 56 // maps tree structure to linear indexed view 57 PCIDev *dev = bus->child; 58 while (dev) { 59 if (*curindex == wantindex) { 60 *outInfo = dev->info; 61 return B_OK; 62 } 63 *curindex += 1; 64 if (dev->child && B_OK == GetNthPciInfo(dev->child, curindex, wantindex, outInfo)) 65 return B_OK; 66 dev = dev->next; 67 } 68 return B_ERROR; 69 } 70 71 72 void 73 PCI::DiscoverBus(PCIBus *bus) 74 { 75 dprintf("PCI: DiscoverBus, bus %u\n", bus->bus); 76 77 for (int dev = 0; dev < gMaxBusDevices; dev++) { 78 uint16 vendor_id = pci_read_config(bus->bus, dev, 0, PCI_vendor_id, 2); 79 if (vendor_id == 0xffff) 80 continue; 81 82 uint8 type = pci_read_config(bus->bus, dev, 0, PCI_header_type, 1); 83 int nfunc = (type & PCI_multifunction) ? 8 : 1; 84 for (int func = 0; func < nfunc; func++) 85 DiscoverDevice(bus, dev, func); 86 } 87 } 88 89 90 void 91 PCI::DiscoverDevice(PCIBus *bus, uint8 dev, uint8 func) 92 { 93 dprintf("PCI: DiscoverDevice, bus %u, dev %u, func %u\n", bus->bus, dev, func); 94 95 uint16 device_id = pci_read_config(bus->bus, dev, func, PCI_device_id, 2); 96 if (device_id == 0xffff) 97 return; 98 99 PCIDev *newdev = CreateDevice(bus, dev, func); 100 101 uint8 base_class = pci_read_config(bus->bus, dev, func, PCI_class_base, 1); 102 uint8 sub_class = pci_read_config(bus->bus, dev, func, PCI_class_sub, 1); 103 if (base_class == PCI_bridge && sub_class == PCI_pci) { 104 uint8 secondary_bus = pci_read_config(bus->bus, dev, func, PCI_secondary_bus, 1); 105 PCIBus *newbus = CreateBus(newdev, secondary_bus); 106 DiscoverBus(newbus); 107 } 108 } 109 110 111 PCIBus * 112 PCI::CreateBus(PCIDev *parent, uint8 bus) 113 { 114 PCIBus *newbus = new PCIBus; 115 newbus->parent = parent; 116 newbus->bus = bus; 117 newbus->child = 0; 118 119 // append 120 parent->child = newbus; 121 122 return newbus; 123 } 124 125 126 PCIDev * 127 PCI::CreateDevice(PCIBus *parent, uint8 dev, uint8 func) 128 { 129 dprintf("PCI: CreateDevice, bus %u, dev %u, func %u:\n", parent->bus, dev, func); 130 131 PCIDev *newdev = new PCIDev; 132 newdev->next = 0; 133 newdev->parent = parent; 134 newdev->child = 0; 135 newdev->bus = parent->bus; 136 newdev->dev = dev; 137 newdev->func = func; 138 139 ReadPciBasicInfo(newdev); 140 141 dprintf("PCI: vendor 0x%04x, device 0x%04x, class_base 0x%02x, class_sub 0x%02x\n", 142 newdev->info.vendor_id, newdev->info.device_id, newdev->info.class_base, newdev->info.class_sub); 143 144 // append 145 if (parent->child == 0) { 146 parent->child = newdev; 147 } else { 148 PCIDev *sub = parent->child; 149 while (sub->next) 150 sub = sub->next; 151 sub->next = newdev; 152 } 153 154 return newdev; 155 } 156 157 158 uint32 159 PCI::BarSize(uint32 bits, uint32 mask) 160 { 161 bits &= mask; 162 if (!bits) 163 return 0; 164 uint32 size = 1; 165 while (!(bits & size)) 166 size <<= 1; 167 return size; 168 } 169 170 171 void 172 PCI::GetBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags) 173 { 174 uint32 oldvalue = pci_read_config(dev->bus, dev->dev, dev->func, offset, 4); 175 pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, 0xffffffff); 176 uint32 newvalue = pci_read_config(dev->bus, dev->dev, dev->func, offset, 4); 177 pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, oldvalue); 178 179 *address = oldvalue & PCI_address_memory_32_mask; 180 if (size) 181 *size = BarSize(newvalue, PCI_address_memory_32_mask); 182 if (flags) 183 *flags = newvalue & 0xf; 184 } 185 186 187 void 188 PCI::GetRomBarInfo(PCIDev *dev, uint8 offset, uint32 *address, uint32 *size, uint8 *flags) 189 { 190 uint32 oldvalue = pci_read_config(dev->bus, dev->dev, dev->func, offset, 4); 191 pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, 0xfffffffe); // LSB must be 0 192 uint32 newvalue = pci_read_config(dev->bus, dev->dev, dev->func, offset, 4); 193 pci_write_config(dev->bus, dev->dev, dev->func, offset, 4, oldvalue); 194 195 *address = oldvalue & PCI_rom_address_mask; 196 if (size) 197 *size = BarSize(newvalue, PCI_rom_address_mask); 198 if (flags) 199 *flags = newvalue & 0xf; 200 } 201 202 203 void 204 PCI::ReadPciBasicInfo(PCIDev *dev) 205 { 206 dev->info.vendor_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_vendor_id, 2); 207 dev->info.device_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_device_id, 2); 208 dev->info.bus = dev->bus; 209 dev->info.device = dev->dev; 210 dev->info.function = dev->func; 211 dev->info.revision = pci_read_config(dev->bus, dev->dev, dev->func, PCI_revision, 1); 212 dev->info.class_api = pci_read_config(dev->bus, dev->dev, dev->func, PCI_class_api, 1); 213 dev->info.class_sub = pci_read_config(dev->bus, dev->dev, dev->func, PCI_class_sub, 1); 214 dev->info.class_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_class_base, 1); 215 dev->info.line_size = pci_read_config(dev->bus, dev->dev, dev->func, PCI_line_size, 1); 216 dev->info.latency = pci_read_config(dev->bus, dev->dev, dev->func, PCI_latency, 1); 217 dev->info.header_type = pci_read_config(dev->bus, dev->dev, dev->func, PCI_header_type, 1); 218 dev->info.header_type &= PCI_header_type_mask; // this masks off the multifunction bit 219 dev->info.bist = pci_read_config(dev->bus, dev->dev, dev->func, PCI_bist, 1); 220 dev->info.reserved = 0; 221 } 222 223 224 void 225 PCI::ReadPciHeaderInfo(PCIDev *dev) 226 { 227 switch (dev->info.header_type) { 228 case 0: 229 dev->info.u.h0.cardbus_cis = pci_read_config(dev->bus, dev->dev, dev->func, PCI_cardbus_cis, 4); 230 dev->info.u.h0.subsystem_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_subsystem_id, 2); 231 dev->info.u.h0.subsystem_vendor_id = pci_read_config(dev->bus, dev->dev, dev->func, PCI_subsystem_vendor_id, 2); 232 GetRomBarInfo(dev, PCI_rom_base, &dev->info.u.h0.rom_base_pci, &dev->info.u.h0.rom_size); 233 dev->info.u.h0.rom_base = (ulong)pci_ram_address((void *)dev->info.u.h0.rom_base_pci); 234 for (int i = 0; i < 6; i++) { 235 GetBarInfo(dev, PCI_base_registers + 4*i, 236 &dev->info.u.h0.base_registers_pci[i], 237 &dev->info.u.h0.base_register_sizes[i], 238 &dev->info.u.h0.base_register_flags[i]); 239 dev->info.u.h0.base_registers[i] = (ulong)pci_ram_address((void *)dev->info.u.h0.base_registers_pci[i]); 240 } 241 dev->info.u.h0.interrupt_line = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1); 242 dev->info.u.h0.interrupt_pin = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1); 243 dev->info.u.h0.min_grant = pci_read_config(dev->bus, dev->dev, dev->func, PCI_min_grant, 1); 244 dev->info.u.h0.max_latency = pci_read_config(dev->bus, dev->dev, dev->func, PCI_max_latency, 1); 245 break; 246 case 1: 247 for (int i = 0; i < 2; i++) { 248 GetBarInfo(dev, PCI_base_registers + 4*i, 249 &dev->info.u.h1.base_registers_pci[i], 250 &dev->info.u.h1.base_register_sizes[i], 251 &dev->info.u.h1.base_register_flags[i]); 252 dev->info.u.h1.base_registers[i] = (ulong)pci_ram_address((void *)dev->info.u.h1.base_registers_pci[i]); 253 } 254 dev->info.u.h1.primary_bus = pci_read_config(dev->bus, dev->dev, dev->func, PCI_primary_bus, 1); 255 dev->info.u.h1.secondary_bus = pci_read_config(dev->bus, dev->dev, dev->func, PCI_secondary_bus, 1); 256 dev->info.u.h1.subordinate_bus = pci_read_config(dev->bus, dev->dev, dev->func, PCI_subordinate_bus, 1); 257 dev->info.u.h1.secondary_latency = pci_read_config(dev->bus, dev->dev, dev->func, PCI_secondary_latency, 1); 258 dev->info.u.h1.io_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_base, 1); 259 dev->info.u.h1.io_limit = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_limit, 1); 260 dev->info.u.h1.secondary_status = pci_read_config(dev->bus, dev->dev, dev->func, PCI_secondary_status, 2); 261 dev->info.u.h1.memory_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_memory_base, 2); 262 dev->info.u.h1.memory_limit = pci_read_config(dev->bus, dev->dev, dev->func, PCI_memory_limit, 2); 263 dev->info.u.h1.prefetchable_memory_base = pci_read_config(dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit, 2); 264 dev->info.u.h1.prefetchable_memory_limit = pci_read_config(dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit, 2); 265 dev->info.u.h1.prefetchable_memory_base_upper32 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_base_upper32, 4); 266 dev->info.u.h1.prefetchable_memory_limit_upper32 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_prefetchable_memory_limit_upper32, 4); 267 dev->info.u.h1.io_base_upper16 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_base_upper16, 2); 268 dev->info.u.h1.io_limit_upper16 = pci_read_config(dev->bus, dev->dev, dev->func, PCI_io_limit_upper16, 2); 269 GetRomBarInfo(dev, PCI_bridge_rom_base, &dev->info.u.h1.rom_base_pci); 270 dev->info.u.h1.rom_base = (ulong)pci_ram_address((void *)dev->info.u.h1.rom_base_pci); 271 dev->info.u.h1.interrupt_line = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_line, 1); 272 dev->info.u.h1.interrupt_pin = pci_read_config(dev->bus, dev->dev, dev->func, PCI_interrupt_pin, 1); 273 dev->info.u.h1.bridge_control = pci_read_config(dev->bus, dev->dev, dev->func, PCI_bridge_control, 2); 274 break; 275 default: 276 dprintf("PCI: Header type unknown (%d)\n", dev->info.header_type); 277 break; 278 } 279 } 280 281 282 void 283 PCI::RefreshDeviceInfo(PCIBus *bus) 284 { 285 for (PCIDev *dev = bus->child; dev; dev = dev->next) { 286 ReadPciBasicInfo(dev); 287 ReadPciHeaderInfo(dev); 288 if (dev->child) 289 RefreshDeviceInfo(dev->child); 290 } 291 } 292