1 /* 2 * Copyright 2007-2012 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Gerald Zajac 7 */ 8 9 10 #include <AGP.h> 11 #include <KernelExport.h> 12 #include <PCI.h> 13 #include <drivers/bios.h> 14 #include <malloc.h> 15 #include <stdio.h> 16 #include <string.h> 17 #include <graphic_driver.h> 18 #include <boot_item.h> 19 20 #include "DriverInterface.h" 21 22 23 #undef TRACE 24 25 #ifdef ENABLE_DEBUG_TRACE 26 # define TRACE(x...) dprintf("i810: " x) 27 #else 28 # define TRACE(x...) ; 29 #endif 30 31 32 #define ACCELERANT_NAME "intel_810.accelerant" 33 34 #define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1)) 35 36 #define MAX_DEVICES 4 37 #define DEVICE_FORMAT "%04X_%04X_%02X%02X%02X" 38 39 #define VENDOR_ID 0x8086 // Intel vendor ID 40 41 42 struct ChipInfo { 43 uint16 chipID; // PCI device id of the chip 44 const char* chipName; // user recognizable name (must be < 32 chars) 45 }; 46 47 48 // This table maps a PCI device ID to a chip type identifier and the chip name. 49 50 static const ChipInfo chipTable[] = { 51 { 0x7121, "i810" }, 52 { 0x7123, "i810-dc100" }, 53 { 0x7125, "i810e" }, 54 { 0x1132, "i815" }, 55 { 0, NULL } 56 }; 57 58 59 struct DeviceInfo { 60 uint32 openCount; // how many times device has been opened 61 int32 flags; 62 area_id sharedArea; // shared between driver and accelerants 63 SharedInfo* sharedInfo; // pointer to shared info area memory 64 vuint8* regs; // pointer to memory mapped registers 65 const ChipInfo* pChipInfo; // info about the selected chip 66 pci_info pciInfo; // copy of pci info for this device 67 area_id gttArea; // area used for GTT 68 addr_t gttAddr; // virtual address of GTT 69 char name[B_OS_NAME_LENGTH]; // name of device 70 }; 71 72 73 static Benaphore gLock; 74 static DeviceInfo gDeviceInfo[MAX_DEVICES]; 75 static char* gDeviceNames[MAX_DEVICES + 1]; 76 static pci_module_info* gPCI; 77 78 79 // Prototypes for device hook functions. 80 static status_t device_open(const char* name, uint32 flags, void** cookie); 81 static status_t device_close(void* dev); 82 static status_t device_free(void* dev); 83 static status_t device_read(void* dev, off_t pos, void* buf, size_t* len); 84 static status_t device_write(void* dev, off_t pos, const void* buf, 85 size_t* len); 86 static status_t device_ioctl(void* dev, uint32 msg, void* buf, size_t len); 87 88 static device_hooks gDeviceHooks = 89 { 90 device_open, 91 device_close, 92 device_free, 93 device_ioctl, 94 device_read, 95 device_write, 96 NULL, 97 NULL, 98 NULL, 99 NULL 100 }; 101 102 103 // Video chip register definitions. 104 // ================================= 105 106 #define INTERRUPT_ENABLED 0x020a0 107 #define INTERRUPT_MASK 0x020a8 108 109 // Graphics address translation table. 110 #define PAGE_TABLE_CONTROL 0x02020 111 #define PAGE_TABLE_ENABLED 0x01 112 113 #define PTE_BASE 0x10000 114 #define PTE_VALID 0x01 115 116 117 // Macros for memory mapped I/O. 118 // ============================== 119 120 #define INREG16(addr) (*((vuint16*)(di.regs + (addr)))) 121 #define INREG32(addr) (*((vuint32*)(di.regs + (addr)))) 122 123 #define OUTREG16(addr, val) (*((vuint16*)(di.regs + (addr))) = (val)) 124 #define OUTREG32(addr, val) (*((vuint32*)(di.regs + (addr))) = (val)) 125 126 127 static inline uint32 128 GetPCI(pci_info& info, uint8 offset, uint8 size) 129 { 130 return gPCI->read_pci_config(info.bus, info.device, info.function, offset, 131 size); 132 } 133 134 135 static inline void 136 SetPCI(pci_info& info, uint8 offset, uint8 size, uint32 value) 137 { 138 gPCI->write_pci_config(info.bus, info.device, info.function, offset, size, 139 value); 140 } 141 142 143 static status_t 144 GetEdidFromBIOS(edid1_raw& edidRaw) 145 { 146 // Get the EDID info from the video BIOS, and return B_OK if successful. 147 148 #define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4) 149 #define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf) 150 151 bios_module_info* biosModule; 152 status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule); 153 if (status != B_OK) { 154 TRACE("GetEdidFromBIOS(): failed to get BIOS module: 0x%" B_PRIx32 "\n", 155 status); 156 return status; 157 } 158 159 bios_state* state; 160 status = biosModule->prepare(&state); 161 if (status != B_OK) { 162 TRACE("GetEdidFromBIOS(): bios_prepare() failed: 0x%" B_PRIx32 "\n", 163 status); 164 put_module(B_BIOS_MODULE_NAME); 165 return status; 166 } 167 168 bios_regs regs = {}; 169 regs.eax = 0x4f15; 170 regs.ebx = 0; // 0 = report DDC service 171 regs.ecx = 0; 172 regs.es = 0; 173 regs.edi = 0; 174 175 status = biosModule->interrupt(state, 0x10, ®s); 176 if (status == B_OK) { 177 // AH contains the error code, and AL determines whether or not the 178 // function is supported. 179 if (regs.eax != 0x4f) 180 status = B_NOT_SUPPORTED; 181 182 // Test if DDC is supported by the monitor. 183 if ((regs.ebx & 3) == 0) 184 status = B_NOT_SUPPORTED; 185 } 186 187 if (status == B_OK) { 188 edid1_raw* edid = (edid1_raw*)biosModule->allocate_mem(state, 189 sizeof(edid1_raw)); 190 if (edid == NULL) { 191 status = B_NO_MEMORY; 192 goto out; 193 } 194 195 regs.eax = 0x4f15; 196 regs.ebx = 1; // 1 = read EDID 197 regs.ecx = 0; 198 regs.edx = 0; 199 regs.es = ADDRESS_SEGMENT(edid); 200 regs.edi = ADDRESS_OFFSET(edid); 201 202 status = biosModule->interrupt(state, 0x10, ®s); 203 if (status == B_OK) { 204 if (regs.eax != 0x4f) { 205 status = B_NOT_SUPPORTED; 206 } else { 207 // Copy the EDID info to the caller's location, and compute the 208 // checksum of the EDID info while copying. 209 210 uint8 sum = 0; 211 uint8 allOr = 0; 212 uint8* dest = (uint8*)&edidRaw; 213 uint8* src = (uint8*)edid; 214 215 for (uint32 j = 0; j < sizeof(edidRaw); j++) { 216 sum += *src; 217 allOr |= *src; 218 *dest++ = *src++; 219 } 220 221 if (allOr == 0) { 222 TRACE("GetEdidFromBIOS(); EDID info contains only zeros\n"); 223 status = B_ERROR; 224 } else if (sum != 0) { 225 TRACE("GetEdidFromBIOS(); Checksum error in EDID info\n"); 226 status = B_ERROR; 227 } 228 } 229 } 230 } 231 232 out: 233 biosModule->finish(state); 234 put_module(B_BIOS_MODULE_NAME); 235 236 TRACE("GetEdidFromBIOS() status: 0x%" B_PRIx32 "\n", status); 237 return status; 238 } 239 240 241 static status_t 242 InitDevice(DeviceInfo& di) 243 { 244 // Perform initialization and mapping of the device, and return B_OK if 245 // sucessful; else, return error code. 246 247 TRACE("enter InitDevice()\n"); 248 249 // Create the area for shared info with NO user-space read or write 250 // permissions, to prevent accidental damage. 251 252 size_t sharedSize = (sizeof(SharedInfo) + 7) & ~7; 253 254 di.sharedArea = create_area("i810 shared info", 255 (void**) &(di.sharedInfo), 256 B_ANY_KERNEL_ADDRESS, 257 ROUND_TO_PAGE_SIZE(sharedSize), 258 B_FULL_LOCK, 0); 259 if (di.sharedArea < 0) 260 return di.sharedArea; // return error code 261 262 SharedInfo& si = *(di.sharedInfo); 263 memset(&si, 0, sharedSize); 264 si.regsArea = -1; // indicate area has not yet been created 265 si.videoMemArea = -1; 266 267 pci_info& pciInfo = di.pciInfo; 268 269 si.vendorID = pciInfo.vendor_id; 270 si.deviceID = pciInfo.device_id; 271 si.revision = pciInfo.revision; 272 strcpy(si.chipName, di.pChipInfo->chipName); 273 274 // Enable memory mapped IO and bus master. 275 276 SetPCI(pciInfo, PCI_command, 2, GetPCI(pciInfo, PCI_command, 2) 277 | PCI_command_io | PCI_command_memory | PCI_command_master); 278 279 // Map the MMIO register area. 280 281 phys_addr_t regsBase = pciInfo.u.h0.base_registers[1]; 282 uint32 regAreaSize = pciInfo.u.h0.base_register_sizes[1]; 283 284 si.regsArea = map_physical_memory("i810 mmio registers", 285 regsBase, 286 regAreaSize, 287 B_ANY_KERNEL_ADDRESS, 288 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 289 (void**)&di.regs); 290 291 if (si.regsArea < 0) { 292 TRACE("Unable to map MMIO, error: 0x%lx\n", si.regsArea); 293 return si.regsArea; 294 } 295 296 // Allocate memory for the GTT which must be 64K for the 810/815 chips. 297 298 uint32 gttSize = 64 * 1024; 299 di.gttArea = create_area("GTT memory", (void**) &(di.gttAddr), 300 B_ANY_KERNEL_ADDRESS, gttSize, B_FULL_LOCK | B_CONTIGUOUS, 301 B_READ_AREA | B_WRITE_AREA); 302 303 if (di.gttArea < B_OK) { 304 TRACE("Unable to create GTT, error: 0x%lx\n", di.gttArea); 305 return B_NO_MEMORY; 306 } 307 308 memset((void*)(di.gttAddr), 0, gttSize); 309 310 // Get the physical address of the GTT, and set GTT address in the chip. 311 312 physical_entry entry; 313 status_t status = get_memory_map((void *)(di.gttAddr), 314 B_PAGE_SIZE, &entry, 1); 315 if (status < B_OK) { 316 TRACE("Unable to get physical address of GTT, error: 0x%lx\n", status); 317 return status; 318 } 319 320 OUTREG32(PAGE_TABLE_CONTROL, entry.address | PAGE_TABLE_ENABLED); 321 INREG32(PAGE_TABLE_CONTROL); 322 323 // Allocate video memory to be used for the frame buffer. 324 325 si.videoMemSize = 4 * 1024 * 1024; 326 si.videoMemArea = create_area("video memory", (void**)&(si.videoMemAddr), 327 B_ANY_ADDRESS, si.videoMemSize, B_FULL_LOCK, 328 B_READ_AREA | B_WRITE_AREA); 329 if (si.videoMemArea < B_OK) { 330 TRACE("Unable to create video memory, error: 0x%lx\n", si.videoMemArea); 331 return B_NO_MEMORY; 332 } 333 334 // Get the physical address of each page of the video memory, and put 335 // the physical address of each page into the GTT table. 336 337 for (uint32 offset = 0; offset < si.videoMemSize; offset += B_PAGE_SIZE) { 338 status = get_memory_map((void *)(si.videoMemAddr + offset), 339 B_PAGE_SIZE, &entry, 1); 340 if (status < B_OK) { 341 TRACE("Unable to get physical address of video memory page, error:" 342 " 0x%lx offset: %ld\n", status, offset); 343 return status; 344 } 345 346 if (offset == 0) 347 si.videoMemPCI = entry.address; 348 349 OUTREG32(PTE_BASE + ((offset / B_PAGE_SIZE) * 4), 350 entry.address | PTE_VALID); 351 } 352 353 TRACE("InitDevice() exit OK\n"); 354 return B_OK; 355 } 356 357 358 static void 359 DeleteAreas(DeviceInfo& di) 360 { 361 // Delete all areas that were created. 362 363 if (di.sharedArea >= 0 && di.sharedInfo != NULL) { 364 SharedInfo& si = *(di.sharedInfo); 365 if (si.regsArea >= 0) 366 delete_area(si.regsArea); 367 if (si.videoMemArea >= 0) 368 delete_area(si.videoMemArea); 369 } 370 371 if (di.gttArea >= 0) 372 delete_area(di.gttArea); 373 di.gttArea = -1; 374 di.gttAddr = (addr_t)NULL; 375 376 if (di.sharedArea >= 0) 377 delete_area(di.sharedArea); 378 di.sharedArea = -1; 379 di.sharedInfo = NULL; 380 } 381 382 383 static const ChipInfo* 384 GetNextSupportedDevice(uint32& pciIndex, pci_info& pciInfo) 385 { 386 // Search the PCI devices for a device that is supported by this driver. 387 // The search starts at the device specified by argument pciIndex, and 388 // continues until a supported device is found or there are no more devices 389 // to examine. Argument pciIndex is incremented after each device is 390 // examined. 391 392 // If a supported device is found, return a pointer to the struct containing 393 // the chip info; else return NULL. 394 395 while (gPCI->get_nth_pci_info(pciIndex, &pciInfo) == B_OK) { 396 397 if (pciInfo.vendor_id == VENDOR_ID) { 398 399 // Search the table of supported devices to find a chip/device that 400 // matches device ID of the current PCI device. 401 402 const ChipInfo* pDevice = chipTable; 403 404 while (pDevice->chipID != 0) { // end of table? 405 if (pDevice->chipID == pciInfo.device_id) 406 return pDevice; // matching device/chip found 407 408 pDevice++; 409 } 410 } 411 412 pciIndex++; 413 } 414 415 return NULL; // no supported device found 416 } 417 418 419 // #pragma mark - Kernel Interface 420 421 422 status_t 423 init_hardware(void) 424 { 425 // Return B_OK if a device supported by this driver is found; otherwise, 426 // return B_ERROR so the driver will be unloaded. 427 428 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 429 if (status != B_OK) { 430 TRACE("PCI module unavailable, error 0x%lx\n", status); 431 return status; 432 } 433 434 // Check pci devices for a device supported by this driver. 435 436 uint32 pciIndex = 0; 437 pci_info pciInfo; 438 const ChipInfo* pDevice = GetNextSupportedDevice(pciIndex, pciInfo); 439 440 TRACE("init_hardware() - %s\n", 441 pDevice == NULL ? "no supported devices" : "device supported"); 442 443 put_module(B_PCI_MODULE_NAME); // put away the module manager 444 445 return (pDevice == NULL ? B_ERROR : B_OK); 446 } 447 448 449 status_t 450 init_driver(void) 451 { 452 // Get handle for the pci bus. 453 454 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 455 if (status != B_OK) { 456 TRACE("PCI module unavailable, error 0x%lx\n", status); 457 return status; 458 } 459 460 status = gLock.Init("i810 driver lock"); 461 if (status < B_OK) { 462 put_module(B_AGP_GART_MODULE_NAME); 463 put_module(B_PCI_MODULE_NAME); 464 return status; 465 } 466 467 // Get info about all the devices supported by this driver. 468 469 uint32 pciIndex = 0; 470 uint32 count = 0; 471 472 while (count < MAX_DEVICES) { 473 DeviceInfo& di = gDeviceInfo[count]; 474 475 const ChipInfo* pDevice = GetNextSupportedDevice(pciIndex, di.pciInfo); 476 if (pDevice == NULL) 477 break; // all supported devices have been obtained 478 479 // Compose device name. 480 sprintf(di.name, "graphics/" DEVICE_FORMAT, 481 di.pciInfo.vendor_id, di.pciInfo.device_id, 482 di.pciInfo.bus, di.pciInfo.device, di.pciInfo.function); 483 TRACE("init_driver() match found; name: %s\n", di.name); 484 485 gDeviceNames[count] = di.name; 486 di.openCount = 0; // mark driver as available for R/W open 487 di.sharedArea = -1; // indicate shared area not yet created 488 di.sharedInfo = NULL; 489 di.gttArea = -1; // indicate GTT area not yet created 490 di.gttAddr = (addr_t)NULL; 491 di.pChipInfo = pDevice; 492 count++; 493 pciIndex++; 494 } 495 496 gDeviceNames[count] = NULL; // terminate list with null pointer 497 498 TRACE("init_driver() %ld supported devices\n", count); 499 500 return B_OK; 501 } 502 503 504 void 505 uninit_driver(void) 506 { 507 // Free the driver data. 508 509 gLock.Delete(); 510 put_module(B_AGP_GART_MODULE_NAME); 511 put_module(B_PCI_MODULE_NAME); // put the pci module away 512 } 513 514 515 const char** 516 publish_devices(void) 517 { 518 return (const char**)gDeviceNames; // return list of supported devices 519 } 520 521 522 device_hooks* 523 find_device(const char* name) 524 { 525 int i = 0; 526 while (gDeviceNames[i] != NULL) { 527 if (strcmp(name, gDeviceNames[i]) == 0) 528 return &gDeviceHooks; 529 i++; 530 } 531 532 return NULL; 533 } 534 535 536 // #pragma mark - Device Hooks 537 538 539 static status_t 540 device_open(const char* name, uint32 /*flags*/, void** cookie) 541 { 542 status_t status = B_OK; 543 544 TRACE("device_open() - name: %s, cookie: 0x%" B_PRIXADDR "\n", name, 545 (addr_t)cookie); 546 547 // Find the device name in the list of devices. 548 549 int32 i = 0; 550 while (gDeviceNames[i] != NULL && (strcmp(name, gDeviceNames[i]) != 0)) 551 i++; 552 553 if (gDeviceNames[i] == NULL) 554 return B_BAD_VALUE; // device name not found in list of devices 555 556 DeviceInfo& di = gDeviceInfo[i]; 557 558 gLock.Acquire(); // make sure no one else has write access to common data 559 560 if (di.openCount == 0) { 561 status = InitDevice(di); 562 if (status < B_OK) 563 DeleteAreas(di); // error occurred; delete any areas created 564 } 565 566 gLock.Release(); 567 568 if (status == B_OK) { 569 di.openCount++; // mark device open 570 *cookie = &di; // send cookie to opener 571 } 572 573 TRACE("device_open() returning 0x%lx, open count: %ld\n", status, 574 di.openCount); 575 return status; 576 } 577 578 579 static status_t 580 device_read(void* dev, off_t pos, void* buf, size_t* len) 581 { 582 // Following 3 lines of code are here to eliminate "unused parameter" 583 // warnings. 584 (void)dev; 585 (void)pos; 586 (void)buf; 587 588 *len = 0; 589 return B_NOT_ALLOWED; 590 } 591 592 593 static status_t 594 device_write(void* dev, off_t pos, const void* buf, size_t* len) 595 { 596 // Following 3 lines of code are here to eliminate "unused parameter" 597 // warnings. 598 (void)dev; 599 (void)pos; 600 (void)buf; 601 602 *len = 0; 603 return B_NOT_ALLOWED; 604 } 605 606 607 static status_t 608 device_close(void* dev) 609 { 610 (void)dev; // avoid compiler warning for unused arg 611 612 TRACE("device_close()\n"); 613 return B_NO_ERROR; 614 } 615 616 617 static status_t 618 device_free(void* dev) 619 { 620 DeviceInfo& di = *((DeviceInfo*)dev); 621 622 TRACE("enter device_free()\n"); 623 624 gLock.Acquire(); // lock driver 625 626 // If opened multiple times, merely decrement the open count and exit. 627 628 if (di.openCount <= 1) 629 DeleteAreas(di); 630 631 if (di.openCount > 0) 632 di.openCount--; // mark device available 633 634 gLock.Release(); // unlock driver 635 636 TRACE("exit device_free() openCount: %ld\n", di.openCount); 637 return B_OK; 638 } 639 640 641 static status_t 642 device_ioctl(void* dev, uint32 msg, void* buffer, size_t bufferLength) 643 { 644 DeviceInfo& di = *((DeviceInfo*)dev); 645 646 TRACE("device_ioctl(); ioctl: %lu, buffer: 0x%" B_PRIXADDR ", " 647 "bufLen: %lu\n", msg, (addr_t)buffer, bufferLength); 648 649 switch (msg) { 650 case B_GET_ACCELERANT_SIGNATURE: 651 strcpy((char*)buffer, ACCELERANT_NAME); 652 TRACE("Intel 810 accelerant: %s\n", ACCELERANT_NAME); 653 return B_OK; 654 655 case INTEL_DEVICE_NAME: 656 strncpy((char*)buffer, di.name, B_OS_NAME_LENGTH); 657 ((char*)buffer)[B_OS_NAME_LENGTH -1] = '\0'; 658 return B_OK; 659 660 case INTEL_GET_SHARED_DATA: 661 if (bufferLength != sizeof(area_id)) 662 return B_BAD_DATA; 663 664 *((area_id*)buffer) = di.sharedArea; 665 return B_OK; 666 667 case INTEL_GET_EDID: 668 { 669 if (bufferLength != sizeof(edid1_raw)) 670 return B_BAD_DATA; 671 672 edid1_raw rawEdid; 673 status_t status = GetEdidFromBIOS(rawEdid); 674 if (status == B_OK) 675 user_memcpy((edid1_raw*)buffer, &rawEdid, sizeof(rawEdid)); 676 return status; 677 } 678 } 679 680 return B_DEV_INVALID_IOCTL; 681 } 682