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
GetPCI(pci_info & info,uint8 offset,uint8 size)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
SetPCI(pci_info & info,uint8 offset,uint8 size,uint32 value)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
GetEdidFromBIOS(edid1_raw & edidRaw)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
InitDevice(DeviceInfo & di)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
DeleteAreas(DeviceInfo & di)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*
GetNextSupportedDevice(uint32 & pciIndex,pci_info & pciInfo)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
init_hardware(void)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
init_driver(void)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
uninit_driver(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**
publish_devices(void)519 publish_devices(void)
520 {
521 return (const char**)gDeviceNames; // return list of supported devices
522 }
523
524
525 device_hooks*
find_device(const char * name)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
device_open(const char * name,uint32,void ** cookie)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
device_read(void * dev,off_t pos,void * buf,size_t * len)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
device_write(void * dev,off_t pos,const void * buf,size_t * len)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
device_close(void * dev)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
device_free(void * dev)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
device_ioctl(void * dev,uint32 msg,void * buffer,size_t bufferLength)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