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, 259 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_CLONEABLE_AREA); 260 if (di.sharedArea < 0) 261 return di.sharedArea; // return error code 262 263 SharedInfo& si = *(di.sharedInfo); 264 memset(&si, 0, sharedSize); 265 si.regsArea = -1; // indicate area has not yet been created 266 si.videoMemArea = -1; 267 268 pci_info& pciInfo = di.pciInfo; 269 270 si.vendorID = pciInfo.vendor_id; 271 si.deviceID = pciInfo.device_id; 272 si.revision = pciInfo.revision; 273 strcpy(si.chipName, di.pChipInfo->chipName); 274 275 // Enable memory mapped IO and bus master. 276 277 SetPCI(pciInfo, PCI_command, 2, GetPCI(pciInfo, PCI_command, 2) 278 | PCI_command_io | PCI_command_memory | PCI_command_master); 279 280 // Map the MMIO register area. 281 282 phys_addr_t regsBase = pciInfo.u.h0.base_registers[1]; 283 uint32 regAreaSize = pciInfo.u.h0.base_register_sizes[1]; 284 285 si.regsArea = map_physical_memory("i810 mmio registers", 286 regsBase, 287 regAreaSize, 288 B_ANY_KERNEL_ADDRESS, 289 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_CLONEABLE_AREA, 290 (void**)&di.regs); 291 292 if (si.regsArea < 0) { 293 TRACE("Unable to map MMIO, error: 0x%" B_PRIx32 "\n", si.regsArea); 294 return si.regsArea; 295 } 296 297 // Allocate memory for the GTT which must be 64K for the 810/815 chips. 298 299 uint32 gttSize = 64 * 1024; 300 di.gttArea = create_area("GTT memory", (void**) &(di.gttAddr), 301 B_ANY_KERNEL_ADDRESS, gttSize, B_FULL_LOCK | B_CONTIGUOUS, 302 B_READ_AREA | B_WRITE_AREA); 303 304 if (di.gttArea < B_OK) { 305 TRACE("Unable to create GTT, error: 0x%" B_PRIx32 "\n", di.gttArea); 306 return B_NO_MEMORY; 307 } 308 309 memset((void*)(di.gttAddr), 0, gttSize); 310 311 // Get the physical address of the GTT, and set GTT address in the chip. 312 313 physical_entry entry; 314 status_t status = get_memory_map((void *)(di.gttAddr), 315 B_PAGE_SIZE, &entry, 1); 316 if (status < B_OK) { 317 TRACE("Unable to get physical address of GTT, " 318 "error: 0x%" B_PRIx32 "\n", status); 319 return status; 320 } 321 322 OUTREG32(PAGE_TABLE_CONTROL, entry.address | PAGE_TABLE_ENABLED); 323 INREG32(PAGE_TABLE_CONTROL); 324 325 // Allocate video memory to be used for the frame buffer. 326 327 si.videoMemSize = 4 * 1024 * 1024; 328 si.videoMemArea = create_area("video memory", (void**)&(si.videoMemAddr), 329 B_ANY_ADDRESS, si.videoMemSize, B_FULL_LOCK, 330 B_READ_AREA | B_WRITE_AREA); 331 if (si.videoMemArea < B_OK) { 332 TRACE("Unable to create video memory, error: 0x%" B_PRIx32 "\n", 333 si.videoMemArea); 334 return B_NO_MEMORY; 335 } 336 337 // Get the physical address of each page of the video memory, and put 338 // the physical address of each page into the GTT table. 339 340 for (uint32 offset = 0; offset < si.videoMemSize; offset += B_PAGE_SIZE) { 341 status = get_memory_map((void *)(si.videoMemAddr + offset), 342 B_PAGE_SIZE, &entry, 1); 343 if (status < B_OK) { 344 TRACE("Unable to get physical address of video memory page, error:" 345 " 0x%" B_PRIx32 " offset: %" B_PRId32 "\n", status, offset); 346 return status; 347 } 348 349 if (offset == 0) 350 si.videoMemPCI = entry.address; 351 352 OUTREG32(PTE_BASE + ((offset / B_PAGE_SIZE) * 4), 353 entry.address | PTE_VALID); 354 } 355 356 TRACE("InitDevice() exit OK\n"); 357 return B_OK; 358 } 359 360 361 static void 362 DeleteAreas(DeviceInfo& di) 363 { 364 // Delete all areas that were created. 365 366 if (di.sharedArea >= 0 && di.sharedInfo != NULL) { 367 SharedInfo& si = *(di.sharedInfo); 368 if (si.regsArea >= 0) 369 delete_area(si.regsArea); 370 if (si.videoMemArea >= 0) 371 delete_area(si.videoMemArea); 372 } 373 374 if (di.gttArea >= 0) 375 delete_area(di.gttArea); 376 di.gttArea = -1; 377 di.gttAddr = (addr_t)NULL; 378 379 if (di.sharedArea >= 0) 380 delete_area(di.sharedArea); 381 di.sharedArea = -1; 382 di.sharedInfo = NULL; 383 } 384 385 386 static const ChipInfo* 387 GetNextSupportedDevice(uint32& pciIndex, pci_info& pciInfo) 388 { 389 // Search the PCI devices for a device that is supported by this driver. 390 // The search starts at the device specified by argument pciIndex, and 391 // continues until a supported device is found or there are no more devices 392 // to examine. Argument pciIndex is incremented after each device is 393 // examined. 394 395 // If a supported device is found, return a pointer to the struct containing 396 // the chip info; else return NULL. 397 398 while (gPCI->get_nth_pci_info(pciIndex, &pciInfo) == B_OK) { 399 400 if (pciInfo.vendor_id == VENDOR_ID) { 401 402 // Search the table of supported devices to find a chip/device that 403 // matches device ID of the current PCI device. 404 405 const ChipInfo* pDevice = chipTable; 406 407 while (pDevice->chipID != 0) { // end of table? 408 if (pDevice->chipID == pciInfo.device_id) 409 return pDevice; // matching device/chip found 410 411 pDevice++; 412 } 413 } 414 415 pciIndex++; 416 } 417 418 return NULL; // no supported device found 419 } 420 421 422 // #pragma mark - Kernel Interface 423 424 425 status_t 426 init_hardware(void) 427 { 428 // Return B_OK if a device supported by this driver is found; otherwise, 429 // return B_ERROR so the driver will be unloaded. 430 431 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 432 if (status != B_OK) { 433 TRACE("PCI module unavailable, error 0x%" B_PRIx32 "\n", status); 434 return status; 435 } 436 437 // Check pci devices for a device supported by this driver. 438 439 uint32 pciIndex = 0; 440 pci_info pciInfo; 441 const ChipInfo* pDevice = GetNextSupportedDevice(pciIndex, pciInfo); 442 443 TRACE("init_hardware() - %s\n", 444 pDevice == NULL ? "no supported devices" : "device supported"); 445 446 put_module(B_PCI_MODULE_NAME); // put away the module manager 447 448 return (pDevice == NULL ? B_ERROR : B_OK); 449 } 450 451 452 status_t 453 init_driver(void) 454 { 455 // Get handle for the pci bus. 456 457 status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI); 458 if (status != B_OK) { 459 TRACE("PCI module unavailable, error 0x%" B_PRIx32 "\n", status); 460 return status; 461 } 462 463 status = gLock.Init("i810 driver lock"); 464 if (status < B_OK) { 465 put_module(B_AGP_GART_MODULE_NAME); 466 put_module(B_PCI_MODULE_NAME); 467 return status; 468 } 469 470 // Get info about all the devices supported by this driver. 471 472 uint32 pciIndex = 0; 473 uint32 count = 0; 474 475 while (count < MAX_DEVICES) { 476 DeviceInfo& di = gDeviceInfo[count]; 477 478 const ChipInfo* pDevice = GetNextSupportedDevice(pciIndex, di.pciInfo); 479 if (pDevice == NULL) 480 break; // all supported devices have been obtained 481 482 // Compose device name. 483 sprintf(di.name, "graphics/" DEVICE_FORMAT, 484 di.pciInfo.vendor_id, di.pciInfo.device_id, 485 di.pciInfo.bus, di.pciInfo.device, di.pciInfo.function); 486 TRACE("init_driver() match found; name: %s\n", di.name); 487 488 gDeviceNames[count] = di.name; 489 di.openCount = 0; // mark driver as available for R/W open 490 di.sharedArea = -1; // indicate shared area not yet created 491 di.sharedInfo = NULL; 492 di.gttArea = -1; // indicate GTT area not yet created 493 di.gttAddr = (addr_t)NULL; 494 di.pChipInfo = pDevice; 495 count++; 496 pciIndex++; 497 } 498 499 gDeviceNames[count] = NULL; // terminate list with null pointer 500 501 TRACE("init_driver() %" B_PRIu32 " supported devices\n", count); 502 503 return B_OK; 504 } 505 506 507 void 508 uninit_driver(void) 509 { 510 // Free the driver data. 511 512 gLock.Delete(); 513 put_module(B_AGP_GART_MODULE_NAME); 514 put_module(B_PCI_MODULE_NAME); // put the pci module away 515 } 516 517 518 const char** 519 publish_devices(void) 520 { 521 return (const char**)gDeviceNames; // return list of supported devices 522 } 523 524 525 device_hooks* 526 find_device(const char* name) 527 { 528 int i = 0; 529 while (gDeviceNames[i] != NULL) { 530 if (strcmp(name, gDeviceNames[i]) == 0) 531 return &gDeviceHooks; 532 i++; 533 } 534 535 return NULL; 536 } 537 538 539 // #pragma mark - Device Hooks 540 541 542 static status_t 543 device_open(const char* name, uint32 /*flags*/, void** cookie) 544 { 545 status_t status = B_OK; 546 547 TRACE("device_open() - name: %s, cookie: 0x%" B_PRIXADDR "\n", name, 548 (addr_t)cookie); 549 550 // Find the device name in the list of devices. 551 552 int32 i = 0; 553 while (gDeviceNames[i] != NULL && (strcmp(name, gDeviceNames[i]) != 0)) 554 i++; 555 556 if (gDeviceNames[i] == NULL) 557 return B_BAD_VALUE; // device name not found in list of devices 558 559 DeviceInfo& di = gDeviceInfo[i]; 560 561 gLock.Acquire(); // make sure no one else has write access to common data 562 563 if (di.openCount == 0) { 564 status = InitDevice(di); 565 if (status < B_OK) 566 DeleteAreas(di); // error occurred; delete any areas created 567 } 568 569 gLock.Release(); 570 571 if (status == B_OK) { 572 di.openCount++; // mark device open 573 *cookie = &di; // send cookie to opener 574 } 575 576 TRACE("device_open() returning 0x%" B_PRIx32 ", " 577 "open count: %" B_PRId32 "\n", status, di.openCount); 578 return status; 579 } 580 581 582 static status_t 583 device_read(void* dev, off_t pos, void* buf, size_t* len) 584 { 585 // Following 3 lines of code are here to eliminate "unused parameter" 586 // warnings. 587 (void)dev; 588 (void)pos; 589 (void)buf; 590 591 *len = 0; 592 return B_NOT_ALLOWED; 593 } 594 595 596 static status_t 597 device_write(void* dev, off_t pos, const void* buf, size_t* len) 598 { 599 // Following 3 lines of code are here to eliminate "unused parameter" 600 // warnings. 601 (void)dev; 602 (void)pos; 603 (void)buf; 604 605 *len = 0; 606 return B_NOT_ALLOWED; 607 } 608 609 610 static status_t 611 device_close(void* dev) 612 { 613 (void)dev; // avoid compiler warning for unused arg 614 615 TRACE("device_close()\n"); 616 return B_NO_ERROR; 617 } 618 619 620 static status_t 621 device_free(void* dev) 622 { 623 DeviceInfo& di = *((DeviceInfo*)dev); 624 625 TRACE("enter device_free()\n"); 626 627 gLock.Acquire(); // lock driver 628 629 // If opened multiple times, merely decrement the open count and exit. 630 631 if (di.openCount <= 1) 632 DeleteAreas(di); 633 634 if (di.openCount > 0) 635 di.openCount--; // mark device available 636 637 gLock.Release(); // unlock driver 638 639 TRACE("exit device_free() openCount: %" B_PRId32 "\n", di.openCount); 640 return B_OK; 641 } 642 643 644 static status_t 645 device_ioctl(void* dev, uint32 msg, void* buffer, size_t bufferLength) 646 { 647 DeviceInfo& di = *((DeviceInfo*)dev); 648 649 TRACE("device_ioctl(); ioctl: %" B_PRIu32 ", buffer: 0x%" B_PRIXADDR ", " 650 "bufLen: %lu\n", msg, (addr_t)buffer, bufferLength); 651 652 switch (msg) { 653 case B_GET_ACCELERANT_SIGNATURE: 654 strcpy((char*)buffer, ACCELERANT_NAME); 655 TRACE("Intel 810 accelerant: %s\n", ACCELERANT_NAME); 656 return B_OK; 657 658 case INTEL_DEVICE_NAME: 659 strncpy((char*)buffer, di.name, B_OS_NAME_LENGTH); 660 ((char*)buffer)[B_OS_NAME_LENGTH -1] = '\0'; 661 return B_OK; 662 663 case INTEL_GET_SHARED_DATA: 664 if (bufferLength != sizeof(area_id)) 665 return B_BAD_DATA; 666 667 *((area_id*)buffer) = di.sharedArea; 668 return B_OK; 669 670 case INTEL_GET_EDID: 671 { 672 if (bufferLength != sizeof(edid1_raw)) 673 return B_BAD_DATA; 674 675 edid1_raw rawEdid; 676 status_t status = GetEdidFromBIOS(rawEdid); 677 if (status == B_OK) 678 user_memcpy((edid1_raw*)buffer, &rawEdid, sizeof(rawEdid)); 679 return status; 680 } 681 } 682 683 return B_DEV_INVALID_IOCTL; 684 } 685