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