1 /* 2 * Copyright 2022, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "X86PCIController.h" 8 #include "pci_acpi.h" 9 10 #include <AutoDeleterDrivers.h> 11 #include <util/AutoLock.h> 12 #include "acpi.h" 13 14 #include <string.h> 15 #include <new> 16 17 18 #define PCI_MECH1_REQ_PORT 0xCF8 19 #define PCI_MECH1_DATA_PORT 0xCFC 20 #define PCI_MECH1_REQ_DATA(bus, device, func, offset) \ 21 (0x80000000 | (bus << 16) | (device << 11) | (func << 8) | (offset & ~3)) 22 23 #define PCI_MECH2_ENABLE_PORT 0x0cf8 24 #define PCI_MECH2_FORWARD_PORT 0x0cfa 25 #define PCI_MECH2_CONFIG_PORT(dev, offset) \ 26 (uint16)(0xC00 | (dev << 8) | offset) 27 28 29 //#pragma mark - driver 30 31 32 float 33 X86PCIController::SupportsDevice(device_node* parent) 34 { 35 const char* bus; 36 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) < B_OK) 37 return -1.0f; 38 39 if (strcmp(bus, "root") == 0) 40 return 1.0f; 41 42 return 0.0; 43 } 44 45 46 status_t 47 X86PCIController::RegisterDevice(device_node* parent) 48 { 49 device_attr attrs[] = { 50 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "X86 PCI Host Controller"} }, 51 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, {.string = "bus_managers/pci/root/driver_v1"} }, 52 {} 53 }; 54 55 return gDeviceManager->register_node(parent, PCI_X86_DRIVER_MODULE_NAME, attrs, NULL, NULL); 56 } 57 58 59 status_t 60 X86PCIController::InitDriver(device_node* node, X86PCIController*& outDriver) 61 { 62 bool search_mech1 = true; 63 bool search_mech2 = true; 64 bool search_mechpcie = true; 65 void *config = NULL; 66 67 config = load_driver_settings("pci"); 68 if (config) { 69 const char *mech = get_driver_parameter(config, "mechanism", NULL, NULL); 70 if (mech) { 71 search_mech1 = search_mech2 = search_mechpcie = false; 72 if (strcmp(mech, "1") == 0) 73 search_mech1 = true; 74 else if (strcmp(mech, "2") == 0) 75 search_mech2 = true; 76 else if (strcmp(mech, "pcie") == 0) 77 search_mechpcie = true; 78 else 79 panic("Unknown pci config mechanism setting %s\n", mech); 80 } 81 unload_driver_settings(config); 82 } 83 84 // PCI configuration mechanism PCIe is the preferred one. 85 // If it doesn't work, try mechanism 1. 86 // If it doesn't work, try mechanism 2. 87 88 if (search_mechpcie) { 89 if (CreateDriver(node, new(std::nothrow) X86PCIControllerMethPcie(), outDriver) >= B_OK) 90 return B_OK; 91 } 92 if (search_mech1) { 93 if (CreateDriver(node, new(std::nothrow) X86PCIControllerMeth1(), outDriver) >= B_OK) 94 return B_OK; 95 } 96 if (search_mech2) { 97 if (CreateDriver(node, new(std::nothrow) X86PCIControllerMeth2(), outDriver) >= B_OK) 98 return B_OK; 99 } 100 101 dprintf("PCI: no configuration mechanism found\n"); 102 return B_ERROR; 103 } 104 105 106 status_t 107 X86PCIController::CreateDriver(device_node* node, X86PCIController* driverIn, 108 X86PCIController*& driverOut) 109 { 110 ObjectDeleter<X86PCIController> driver(driverIn); 111 if (!driver.IsSet()) 112 return B_NO_MEMORY; 113 114 CHECK_RET(driver->InitDriverInt(node)); 115 driverOut = driver.Detach(); 116 return B_OK; 117 } 118 119 120 status_t 121 X86PCIController::InitDriverInt(device_node* node) 122 { 123 fNode = node; 124 return B_OK; 125 } 126 127 128 void 129 X86PCIController::UninitDriver() 130 { 131 delete this; 132 } 133 134 135 //#pragma mark - PCI controller 136 137 138 status_t 139 X86PCIController::ReadIrq(uint8 bus, uint8 device, uint8 function, 140 uint8 pin, uint8& irq) 141 { 142 return B_UNSUPPORTED; 143 } 144 145 146 status_t 147 X86PCIController::WriteIrq(uint8 bus, uint8 device, uint8 function, 148 uint8 pin, uint8 irq) 149 { 150 return B_UNSUPPORTED; 151 } 152 153 154 status_t 155 X86PCIController::GetRange(uint32 index, pci_resource_range* range) 156 { 157 158 return B_BAD_INDEX; 159 } 160 161 162 //#pragma mark - X86PCIControllerMeth1 163 164 165 status_t 166 X86PCIControllerMeth1::InitDriverInt(device_node* node) 167 { 168 CHECK_RET(X86PCIController::InitDriverInt(node)); 169 170 // check for mechanism 1 171 out32(0x80000000, PCI_MECH1_REQ_PORT); 172 if (0x80000000 == in32(PCI_MECH1_REQ_PORT)) { 173 dprintf("PCI: mechanism 1 controller found\n"); 174 return B_OK; 175 } 176 return B_ERROR; 177 } 178 179 180 status_t 181 X86PCIControllerMeth1::ReadConfig( 182 uint8 bus, uint8 device, uint8 function, 183 uint16 offset, uint8 size, uint32 &value) 184 { 185 if (offset > 0xff) 186 return B_BAD_VALUE; 187 188 InterruptsSpinLocker lock(fLock); 189 out32(PCI_MECH1_REQ_DATA(bus, device, function, offset), PCI_MECH1_REQ_PORT); 190 switch (size) { 191 case 1: 192 value = in8(PCI_MECH1_DATA_PORT + (offset & 3)); 193 break; 194 case 2: 195 value = in16(PCI_MECH1_DATA_PORT + (offset & 3)); 196 break; 197 case 4: 198 value = in32(PCI_MECH1_DATA_PORT); 199 break; 200 default: 201 return B_ERROR; 202 } 203 204 return B_OK; 205 } 206 207 208 status_t 209 X86PCIControllerMeth1::WriteConfig( 210 uint8 bus, uint8 device, uint8 function, 211 uint16 offset, uint8 size, uint32 value) 212 { 213 if (offset > 0xff) 214 return B_BAD_VALUE; 215 216 InterruptsSpinLocker lock(fLock); 217 out32(PCI_MECH1_REQ_DATA(bus, device, function, offset), PCI_MECH1_REQ_PORT); 218 switch (size) { 219 case 1: 220 out8(value, PCI_MECH1_DATA_PORT + (offset & 3)); 221 break; 222 case 2: 223 out16(value, PCI_MECH1_DATA_PORT + (offset & 3)); 224 break; 225 case 4: 226 out32(value, PCI_MECH1_DATA_PORT); 227 break; 228 default: 229 return B_ERROR; 230 } 231 232 return B_OK; 233 } 234 235 236 status_t X86PCIControllerMeth1::GetMaxBusDevices(int32& count) 237 { 238 count = 32; 239 return B_OK; 240 } 241 242 243 //#pragma mark - X86PCIControllerMeth2 244 245 246 status_t 247 X86PCIControllerMeth2::InitDriverInt(device_node* node) 248 { 249 CHECK_RET(X86PCIController::InitDriverInt(node)); 250 251 // check for mechanism 2 252 out8(0x00, 0xCFB); 253 out8(0x00, 0xCF8); 254 out8(0x00, 0xCFA); 255 if (in8(0xCF8) == 0x00 && in8(0xCFA) == 0x00) { 256 dprintf("PCI: mechanism 2 controller found\n"); 257 return B_OK; 258 } 259 return B_ERROR; 260 } 261 262 263 status_t 264 X86PCIControllerMeth2::ReadConfig( 265 uint8 bus, uint8 device, uint8 function, 266 uint16 offset, uint8 size, uint32 &value) 267 { 268 if (offset > 0xff) 269 return B_BAD_VALUE; 270 271 InterruptsSpinLocker lock(fLock); 272 out8((uint8)(0xf0 | (function << 1)), PCI_MECH2_ENABLE_PORT); 273 out8(bus, PCI_MECH2_FORWARD_PORT); 274 switch (size) { 275 case 1: 276 value = in8(PCI_MECH2_CONFIG_PORT(device, offset)); 277 break; 278 case 2: 279 value = in16(PCI_MECH2_CONFIG_PORT(device, offset)); 280 break; 281 case 4: 282 value = in32(PCI_MECH2_CONFIG_PORT(device, offset)); 283 break; 284 default: 285 return B_ERROR; 286 } 287 out8(0, PCI_MECH2_ENABLE_PORT); 288 289 return B_OK; 290 } 291 292 293 status_t 294 X86PCIControllerMeth2::WriteConfig( 295 uint8 bus, uint8 device, uint8 function, 296 uint16 offset, uint8 size, uint32 value) 297 { 298 if (offset > 0xff) 299 return B_BAD_VALUE; 300 301 InterruptsSpinLocker lock(fLock); 302 out8((uint8)(0xf0 | (function << 1)), PCI_MECH2_ENABLE_PORT); 303 out8(bus, PCI_MECH2_FORWARD_PORT); 304 switch (size) { 305 case 1: 306 out8(value, PCI_MECH2_CONFIG_PORT(device, offset)); 307 break; 308 case 2: 309 out16(value, PCI_MECH2_CONFIG_PORT(device, offset)); 310 break; 311 case 4: 312 out32(value, PCI_MECH2_CONFIG_PORT(device, offset)); 313 break; 314 default: 315 return B_ERROR; 316 } 317 out8(0, PCI_MECH2_ENABLE_PORT); 318 319 return B_OK; 320 } 321 322 323 status_t X86PCIControllerMeth2::GetMaxBusDevices(int32& count) 324 { 325 count = 16; 326 return B_OK; 327 } 328 329 330 //#pragma mark - X86PCIControllerMethPcie 331 332 333 #define PCIE_VADDR(base, bus, slot, func, reg) ((base) + \ 334 ((((bus) & 0xff) << 20) | (((slot) & 0x1f) << 15) | \ 335 (((func) & 0x7) << 12) | ((reg) & 0xfff))) 336 337 338 status_t 339 X86PCIControllerMethPcie::InitDriverInt(device_node* node) 340 { 341 CHECK_RET(X86PCIController::InitDriverInt(node)); 342 343 acpi_init(); 344 struct acpi_table_mcfg* mcfg = 345 (struct acpi_table_mcfg*)acpi_find_table("MCFG"); 346 if (mcfg != NULL) { 347 struct acpi_mcfg_allocation* end = (struct acpi_mcfg_allocation*) 348 ((char*)mcfg + mcfg->Header.Length); 349 struct acpi_mcfg_allocation* alloc = (struct acpi_mcfg_allocation*) 350 (mcfg + 1); 351 for (; alloc < end; alloc++) { 352 dprintf("PCI: mechanism addr: %" B_PRIx64 ", seg: %x, start: " 353 "%x, end: %x\n", alloc->Address, alloc->PciSegment, 354 alloc->StartBusNumber, alloc->EndBusNumber); 355 if (alloc->PciSegment == 0) { 356 area_id mcfgArea = map_physical_memory("acpi mcfg", 357 alloc->Address, (alloc->EndBusNumber + 1) << 20, 358 B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA 359 | B_KERNEL_WRITE_AREA, (void **)&fPCIeBase); 360 if (mcfgArea < 0) 361 break; 362 fStartBusNumber = alloc->StartBusNumber; 363 fEndBusNumber = alloc->EndBusNumber; 364 dprintf("PCI: mechanism pcie controller found\n"); 365 return B_OK; 366 } 367 } 368 } 369 return B_ERROR; 370 } 371 372 373 status_t 374 X86PCIControllerMethPcie::ReadConfig( 375 uint8 bus, uint8 device, uint8 function, 376 uint16 offset, uint8 size, uint32 &value) 377 { 378 // fallback to mechanism 1 for out of range busses 379 if (bus < fStartBusNumber || bus > fEndBusNumber) { 380 return X86PCIControllerMeth1::ReadConfig(bus, device, function, offset, 381 size, value); 382 } 383 384 addr_t address = PCIE_VADDR(fPCIeBase, bus, device, function, offset); 385 386 switch (size) { 387 case 1: 388 value = *(uint8*)address; 389 break; 390 case 2: 391 value = *(uint16*)address; 392 break; 393 case 4: 394 value = *(uint32*)address; 395 break; 396 default: 397 return B_ERROR; 398 } 399 return B_OK; 400 } 401 402 403 status_t 404 X86PCIControllerMethPcie::WriteConfig( 405 uint8 bus, uint8 device, uint8 function, 406 uint16 offset, uint8 size, uint32 value) 407 { 408 // fallback to mechanism 1 for out of range busses 409 if (bus < fStartBusNumber || bus > fEndBusNumber) { 410 return X86PCIControllerMeth1::WriteConfig(bus, device, function, offset, 411 size, value); 412 } 413 414 addr_t address = PCIE_VADDR(fPCIeBase, bus, device, function, offset); 415 switch (size) { 416 case 1: 417 *(uint8*)address = value; 418 break; 419 case 2: 420 *(uint16*)address = value; 421 break; 422 case 4: 423 *(uint32*)address = value; 424 break; 425 default: 426 return B_ERROR; 427 } 428 429 return B_OK; 430 } 431 432 433 status_t X86PCIControllerMethPcie::GetMaxBusDevices(int32& count) 434 { 435 count = 32; 436 return B_OK; 437 } 438