1 /*****************************************************************************\ 2 * Tseng Labs ET6000, ET6100 and ET6300 graphics driver for BeOS 5. 3 * Copyright (c) 2003-2004, Evgeniy Vladimirovich Bobkov. 4 \*****************************************************************************/ 5 6 /* standard kernel driver stuff */ 7 #include <KernelExport.h> 8 #include <PCI.h> 9 #include <OS.h> 10 #include <malloc.h> 11 12 /* this is for the standardized portion of the driver API */ 13 /* currently only one operation is defined: B_GET_ACCELERANT_SIGNATURE */ 14 #include <graphic_driver.h> 15 16 /* this is for sprintf() */ 17 #include <stdio.h> 18 19 /* this is for string compares */ 20 #include <string.h> 21 22 /* The private interface between the accelerant and the kernel driver. */ 23 #include "DriverInterface.h" 24 25 #include "setmode.h" 26 #include "acl.h" 27 #include "bits.h" 28 29 /*****************************************************************************/ 30 #if DEBUG > 0 31 #define ddprintf(a) dprintf a 32 #else 33 #define ddprintf(a) 34 #endif 35 36 #define MAX_DEVICES 8 37 38 /* Tell the kernel what revision of the driver API we support */ 39 int32 api_version = 2; 40 41 /*****************************************************************************/ 42 /* This structure is private to the kernel driver */ 43 typedef struct { 44 uint32 isOpen; /* a count of how many times the devices has been opened */ 45 area_id sharedArea; /* the area shared between the driver and all of the accelerants */ 46 ET6000SharedInfo *si; /* a pointer to the shared area, for convenience */ 47 #if DEBUG > 0 48 uint32 interrupt_count; /* if we're debugging, a count of how many times 49 the interrupt handler has been called for this device */ 50 #endif 51 pci_info pcii; /* a convenience copy of the pci info for this device */ 52 char name[B_OS_NAME_LENGTH]; /* where we keep the name of the device for publishing and comparing */ 53 } ET6000DeviceInfo; 54 /*****************************************************************************/ 55 typedef struct { 56 #if DEBUG > 0 57 uint32 total_interrupts; /* total number of interrupts seen by our handler */ 58 #endif 59 uint32 count; /* number of devices actually found */ 60 benaphore kernel; /* for serializing opens/closes */ 61 char *deviceNames[MAX_DEVICES+1]; /* device name pointer storage */ 62 ET6000DeviceInfo di[MAX_DEVICES]; /* device specific stuff */ 63 } DeviceData; 64 /*****************************************************************************/ 65 static DeviceData *pd; 66 /*****************************************************************************/ 67 /* prototypes for our private functions */ 68 static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie); 69 static status_t et6000CloseHook(void* dev); 70 static status_t et6000FreeHook(void* dev); 71 static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len); 72 static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len); 73 static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len); 74 static status_t et6000MapDevice(ET6000DeviceInfo *di); 75 static void et6000UnmapDevice(ET6000DeviceInfo *di); 76 static void et6000ProbeDevices(void); 77 static int32 et6000Interrupt(void *data); 78 79 #if DEBUG > 0 80 static int et6000dump(int argc, char **argv); 81 #endif 82 /*****************************************************************************/ 83 static pci_module_info *pci_bus; 84 85 #define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s)) 86 87 #define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v)) 88 /*****************************************************************************/ 89 static device_hooks et6000DeviceHooks = { 90 et6000OpenHook, 91 et6000CloseHook, 92 et6000FreeHook, 93 et6000ControlHook, 94 et6000ReadHook, 95 et6000WriteHook, 96 NULL, 97 NULL, 98 NULL, 99 NULL 100 }; 101 /*****************************************************************************/ 102 #define TSENG_VENDOR_ID 0x100C /* Tseng Labs Inc */ 103 104 static uint16 et6000DeviceList[] = { 105 0x3208, /* ET6000/ET6100 */ 106 0x4702, /* ET6300 */ 107 0 108 }; 109 110 static struct { 111 uint16 vendor; 112 uint16 *devices; 113 } supportedDevices[] = { 114 {TSENG_VENDOR_ID, et6000DeviceList}, 115 {0x0000, NULL} 116 }; 117 /*****************************************************************************/ 118 /* 119 * Returns B_OK if one is found, otherwise returns 120 * B_ERROR so the driver will be unloaded. 121 */ 122 status_t init_hardware(void) { 123 long pciIndex = 0; 124 pci_info pcii; 125 bool foundOne = FALSE; 126 127 /* choke if we can't find the PCI bus */ 128 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK) 129 return B_ERROR; 130 131 /* while there are more pci devices */ 132 while ((*pci_bus->get_nth_pci_info)(pciIndex, &pcii) == B_NO_ERROR) { 133 int vendor = 0; 134 135 ddprintf(("ET6000 init_hardware(): checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, pcii.vendor_id, pcii.device_id)); 136 /* if we match a supported vendor */ 137 while (supportedDevices[vendor].vendor) { 138 if (supportedDevices[vendor].vendor == pcii.vendor_id) { 139 uint16 *devices = supportedDevices[vendor].devices; 140 /* while there are more supported devices */ 141 while (*devices) { 142 /* if we match a supported device */ 143 if (*devices == pcii.device_id) { 144 ddprintf(("ET6000: we support this device\n")); 145 foundOne = TRUE; 146 goto done; 147 } 148 /* next supported device */ 149 devices++; 150 } 151 } 152 vendor++; 153 } 154 /* next pci_info struct, please */ 155 pciIndex++; 156 } 157 ddprintf(("ET6000: init_hardware - no supported devices\n")); 158 159 done: 160 /* put away the module manager */ 161 put_module(B_PCI_MODULE_NAME); 162 return (foundOne ? B_OK : B_ERROR); 163 } 164 /*****************************************************************************/ 165 static void et6000ProbeDevices(void) { 166 uint32 pciIndex = 0; 167 uint32 count = 0; 168 ET6000DeviceInfo *di = pd->di; 169 170 /* while there are more pci devices */ 171 while ((count < MAX_DEVICES) && 172 ((*pci_bus->get_nth_pci_info)(pciIndex, &(di->pcii)) == B_NO_ERROR)) 173 { 174 int vendor = 0; 175 176 ddprintf(("ET6000: checking pci index %ld, device 0x%04x/0x%04x\n", pciIndex, di->pcii.vendor_id, di->pcii.device_id)); 177 /* if we match a supported vendor */ 178 while (supportedDevices[vendor].vendor) { 179 if (supportedDevices[vendor].vendor == di->pcii.vendor_id) { 180 uint16 *devices = supportedDevices[vendor].devices; 181 /* while there are more supported devices */ 182 while (*devices) { 183 /* if we match a supported device */ 184 if (*devices == di->pcii.device_id) { 185 /* publish the device name */ 186 sprintf(di->name, "graphics/%04X_%04X_%02X%02X%02X", 187 di->pcii.vendor_id, di->pcii.device_id, 188 di->pcii.bus, di->pcii.device, di->pcii.function); 189 ddprintf(("ET6000: making /dev/%s\n", di->name)); 190 /* remember the name */ 191 pd->deviceNames[count] = di->name; 192 /* mark the driver as available for R/W open */ 193 di->isOpen = 0; 194 /* mark areas as not yet created */ 195 di->sharedArea = -1; 196 /* mark pointer to shared data as invalid */ 197 di->si = NULL; 198 /* inc pointer to device info */ 199 di++; 200 /* inc count */ 201 count++; 202 /* break out of these while loops */ 203 goto next_device; 204 } 205 /* next supported device */ 206 devices++; 207 } 208 } 209 vendor++; 210 } 211 next_device: 212 /* next pci_info struct, please */ 213 pciIndex++; 214 } 215 /* propagate count */ 216 pd->count = count; 217 /* terminate list of device names with a null pointer */ 218 pd->deviceNames[pd->count] = NULL; 219 ddprintf(("SKD et6000ProbeDevices: %ld supported devices\n", pd->count)); 220 } 221 /*****************************************************************************/ 222 status_t init_driver(void) { 223 /* get a handle for the pci bus */ 224 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK) 225 return B_ERROR; 226 227 /* driver private data */ 228 pd = (DeviceData *)calloc(1, sizeof(DeviceData)); 229 if (!pd) { 230 put_module(B_PCI_MODULE_NAME); 231 return B_ERROR; 232 } 233 /* initialize the benaphore */ 234 INIT_BEN(pd->kernel); 235 236 /* find all of our supported devices */ 237 et6000ProbeDevices(); 238 239 #if DEBUG > 0 240 add_debugger_command("et6000dump", et6000dump, "dump ET6000 kernel driver persistant data"); 241 #endif 242 243 return B_OK; 244 } 245 /*****************************************************************************/ 246 const char **publish_devices(void) { 247 /* return the list of supported devices */ 248 return (const char **)pd->deviceNames; 249 } 250 /*****************************************************************************/ 251 device_hooks *find_device(const char *name) { 252 int index = 0; 253 while (pd->deviceNames[index]) { 254 if (strcmp(name, pd->deviceNames[index]) == 0) 255 return &et6000DeviceHooks; 256 index++; 257 } 258 return NULL; 259 } 260 /*****************************************************************************/ 261 void uninit_driver(void) { 262 263 #if DEBUG > 0 264 remove_debugger_command("et6000dump", et6000dump); 265 #endif 266 267 /* free the driver data */ 268 DELETE_BEN(pd->kernel); 269 free(pd); 270 pd = NULL; 271 272 /* put the pci module away */ 273 put_module(B_PCI_MODULE_NAME); 274 } 275 /*****************************************************************************/ 276 static int32 et6000Interrupt(void *data) { 277 int32 handled = B_UNHANDLED_INTERRUPT; 278 ET6000DeviceInfo *di = (ET6000DeviceInfo *)data; 279 ET6000SharedInfo *si = di->si; 280 int32 *flags = &(si->flags); 281 282 #if DEBUG > 0 283 pd->total_interrupts++; 284 #endif 285 286 /* is someone already handling an interrupt for this device? */ 287 if (atomic_or(flags, ET6000_HANDLER_INSTALLED) & ET6000_HANDLER_INSTALLED) { 288 #if DEBUG > 0 289 kprintf("ET6000: Already in handler!\n"); 290 #endif 291 goto exit0; 292 } 293 294 switch (et6000aclInterruptCause(si->mmRegs)) { 295 case ET6000_ACL_INT_CAUSE_NONE: 296 handled = B_UNHANDLED_INTERRUPT; 297 break; 298 case ET6000_ACL_INT_CAUSE_READ: 299 et6000aclReadInterruptClear(si->mmRegs); 300 handled = B_HANDLED_INTERRUPT; 301 break; 302 case ET6000_ACL_INT_CAUSE_WRITE: 303 et6000aclWriteInterruptClear(si->mmRegs); 304 handled = B_HANDLED_INTERRUPT; 305 break; 306 case ET6000_ACL_INT_CAUSE_BOTH: /* Can it be at all? */ 307 et6000aclReadInterruptClear(si->mmRegs); 308 et6000aclWriteInterruptClear(si->mmRegs); 309 handled = B_HANDLED_INTERRUPT; 310 break; 311 } 312 313 #if DEBUG > 0 314 /* increment the counter for this device */ 315 if (handled == B_HANDLED_INTERRUPT) 316 di->interrupt_count++; 317 #endif 318 319 /* note that we're not in the handler any more */ 320 atomic_and(flags, ~ET6000_HANDLER_INSTALLED); 321 322 exit0: 323 return handled; 324 } 325 /*****************************************************************************/ 326 static uint32 et6000GetOnboardMemorySize(uint16 pciConfigSpace, 327 volatile void *memory) 328 { 329 uint32 memSize = 0; 330 331 ioSet8(0x3d8, 0x00, 0xa0); /* Set the KEY for color modes */ 332 ioSet8(0x3b8, 0x00, 0xa0); /* Set the KEY for monochrome modes */ 333 334 switch (ioGet8(0x3C2) & 0x03) { 335 case 0x00: /* onboard memory is of DRAM type */ 336 memSize = 1024*1024 * ((ioGet8(pciConfigSpace + 0x45) & 0x03) + 1); 337 break; 338 case 0x03: /* onboard memory is of MDRAM type */ 339 memSize = /* number*8 of 32kb banks per channel */ 340 ((ioGet8(pciConfigSpace + 0x47) & 0x07) + 1) * 8 * 32*1024; 341 if (ioGet8(pciConfigSpace + 0x45) & 0x04) /* If 2 channels */ 342 memSize *= 2; 343 break; 344 default: /* onboard memory is of unknown type */ 345 memSize = 4196*1024; /* Let it be of maximum possible size */ 346 } 347 348 /* 349 * This algorithm would fail to recongize 2.25Mb of onboard 350 * memory - it would detect 2.5Mb instead. It needs to be fixed. 351 */ 352 if (memSize == 2621440) { /* If 2.5Mb detected */ 353 uint8 pci40 = ioGet8(pciConfigSpace+0x40); 354 et6000EnableLinearMemoryMapping(pciConfigSpace); 355 356 /* Check whether the memory beyond 2.25Mb really exists */ 357 *(volatile uint32 *)((uint32)memory + 2359296) = 0xaa55aa55; 358 if (*(volatile uint32 *)((uint32)memory + 2359296) != 0xaa55aa55) 359 memSize = 2359296; /* It's 2.25Mb */ 360 361 ioSet8(pciConfigSpace+0x40, 0x00, pci40); /* Restore */ 362 } 363 364 return memSize; 365 } 366 /*****************************************************************************/ 367 static status_t et6000MapDevice(ET6000DeviceInfo *di) { 368 char buffer[B_OS_NAME_LENGTH]; 369 ET6000SharedInfo *si = di->si; 370 uint32 tmpUlong; 371 pci_info *pcii = &(di->pcii); 372 373 /* Enable memory space access and I/O space access */ 374 tmpUlong = get_pci(PCI_command, 4); 375 tmpUlong |= 0x00000003; 376 set_pci(PCI_command, 4, tmpUlong); 377 378 /* Enable ROM decoding */ 379 tmpUlong = get_pci(PCI_rom_base, 4); 380 tmpUlong |= 0x00000001; 381 set_pci(PCI_rom_base, 4, tmpUlong); 382 383 /* PCI header base address in I/O space */ 384 si->pciConfigSpace = (uint16)di->pcii.u.h0.base_registers[1]; 385 386 sprintf(buffer, "%04X_%04X_%02X%02X%02X videomemory", 387 di->pcii.vendor_id, di->pcii.device_id, 388 di->pcii.bus, di->pcii.device, di->pcii.function); 389 390 /* 391 * We map the whole graphics card memory area (which consist of RAM memory 392 * and memory mapped registers) at once. Memory mapped registers must not 393 * be cacheble, so the whole area is mapped with B_UNCACHED_MEMORY. 394 * We certainly could map separately the RAM memory with write combining 395 * and the memory mapped registers with B_UNCACHED_MEMORY. 396 */ 397 si->memoryArea = map_physical_memory(buffer, 398 di->pcii.u.h0.base_registers[0], 399 di->pcii.u.h0.base_register_sizes[0], 400 B_ANY_KERNEL_BLOCK_ADDRESS | B_UNCACHED_MEMORY, 401 B_READ_AREA + B_WRITE_AREA, 402 &(si->memory)); 403 404 si->framebuffer = si->memory; 405 si->mmRegs = (void *)((uint32)si->memory + 0x003fff00); 406 si->emRegs = (void *)((uint32)si->memory + 0x003fe000); 407 408 /* remember the physical addresses */ 409 si->physMemory = si->physFramebuffer = 410 (void *) di->pcii.u.h0.base_registers_pci[0]; 411 412 si->memSize = et6000GetOnboardMemorySize(si->pciConfigSpace, si->memory); 413 414 /* in any case, return the result */ 415 return si->memoryArea; 416 } 417 /*****************************************************************************/ 418 static void et6000UnmapDevice(ET6000DeviceInfo *di) { 419 ET6000SharedInfo *si = di->si; 420 421 ddprintf(("et6000UnmapDevice(%08lx) begins...\n", (uint32)di)); 422 ddprintf((" memoryArea: %ld\n", si->memoryArea)); 423 424 if (si->memoryArea >= 0) 425 delete_area(si->memoryArea); 426 si->memoryArea = -1; 427 si->framebuffer = NULL; 428 si->physFramebuffer = NULL; 429 si->memory = NULL; 430 si->physMemory = NULL; 431 432 ddprintf(("et6000UnmapDevice() ends.\n")); 433 } 434 /*****************************************************************************/ 435 static status_t et6000OpenHook(const char* name, uint32 flags, void** cookie) { 436 int32 index = 0; 437 ET6000DeviceInfo *di; 438 ET6000SharedInfo *si; 439 status_t result = B_OK; 440 char shared_name[B_OS_NAME_LENGTH]; 441 442 ddprintf(("SKD et6000OpenHook(%s, %ld, 0x%08lx)\n", name, flags, (uint32)cookie)); 443 444 /* find the device name in the list of devices */ 445 /* we're never passed a name we didn't publish */ 446 while(pd->deviceNames[index] && 447 (strcmp(name, pd->deviceNames[index]) != 0)) 448 { 449 index++; 450 } 451 452 /* for convienience */ 453 di = &(pd->di[index]); 454 455 /* make sure no one else has write access to the common data */ 456 AQUIRE_BEN(pd->kernel); 457 458 /* if it's already open for writing */ 459 if (di->isOpen) { 460 /* mark it open another time */ 461 goto mark_as_open; 462 } 463 /* create the shared area */ 464 sprintf(shared_name, "%04X_%04X_%02X%02X%02X shared", 465 di->pcii.vendor_id, di->pcii.device_id, 466 di->pcii.bus, di->pcii.device, di->pcii.function); 467 /* create this area with NO user-space read or write permissions, to prevent accidental dammage */ 468 di->sharedArea = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(ET6000SharedInfo) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK, 469 B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_CLONEABLE_AREA); 470 if (di->sharedArea < 0) { 471 /* return the error */ 472 result = di->sharedArea; 473 goto done; 474 } 475 476 /* save a few dereferences */ 477 si = di->si; 478 479 /* save the vendor and device IDs */ 480 si->vendor_id = di->pcii.vendor_id; 481 si->device_id = di->pcii.device_id; 482 si->revision = di->pcii.revision; 483 484 si->pixelClockMax16 = 135000; 485 si->pixelClockMax24 = 135000; 486 if (si->vendor_id == 0x100C) { /* Tseng Labs, Inc. */ 487 switch (si->device_id) { 488 case 0x3208:/* ET6000/ET6100 */ 489 if (si->revision < 0x70) { /* ET6000 */ 490 si->pixelClockMax16 = 135000; 491 si->pixelClockMax24 = 135000; 492 } 493 else { /* ET6100 */ 494 si->pixelClockMax16 = 175000; 495 si->pixelClockMax24 = 175000; 496 } 497 break; 498 case 0x4702: /* ET6300 */ 499 si->pixelClockMax16 = 220000; 500 si->pixelClockMax24 = 220000; 501 break; 502 } 503 } 504 505 /* map the device */ 506 result = et6000MapDevice(di); 507 if (result < 0) 508 goto free_shared; 509 result = B_OK; 510 511 /* 512 * Clear any pending interrupts and disable interrupts. Driver 513 * currently does not use interrupts and unlikely will in future. 514 */ 515 et6000aclReadInterruptClear(si->mmRegs); 516 et6000aclWriteInterruptClear(si->mmRegs); 517 et6000aclMasterInterruptDisable(si->mmRegs); 518 519 /* Install the interrupt handler */ 520 result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, 521 et6000Interrupt, (void *)di, 0); 522 /* bail if we couldn't install the handler */ 523 if (result != B_OK) 524 goto unmap; 525 526 mark_as_open: 527 /* mark the device open */ 528 di->isOpen++; 529 530 /* send the cookie to the opener */ 531 *cookie = di; 532 533 goto done; 534 535 unmap: 536 et6000UnmapDevice(di); 537 538 free_shared: 539 /* clean up our shared area */ 540 delete_area(di->sharedArea); 541 di->sharedArea = -1; 542 di->si = NULL; 543 544 done: 545 /* end of critical section */ 546 RELEASE_BEN(pd->kernel); 547 548 /* all done, return the status */ 549 ddprintf(("et6000OpenHook returning 0x%08lx\n", result)); 550 551 return result; 552 } 553 /*****************************************************************************/ 554 /* 555 * et6000ReadHook - does nothing, gracefully 556 */ 557 static status_t et6000ReadHook(void* dev, off_t pos, void* buf, size_t* len) 558 { 559 *len = 0; 560 return B_NOT_ALLOWED; 561 } 562 563 /*****************************************************************************/ 564 /* 565 * et6000WriteHook - does nothing, gracefully 566 */ 567 static status_t et6000WriteHook(void* dev, off_t pos, const void* buf, size_t* len) 568 { 569 *len = 0; 570 return B_NOT_ALLOWED; 571 } 572 /*****************************************************************************/ 573 /* 574 * et6000CloseHook - does nothing, gracefully 575 */ 576 static status_t et6000CloseHook(void* dev) 577 { 578 ddprintf(("SKD et6000CloseHook(%08lx)\n", (uint32)dev)); 579 /* we don't do anything on close: there might be dup'd fd */ 580 return B_NO_ERROR; 581 } 582 /*****************************************************************************/ 583 /* 584 * et6000FreeHook - close down the device 585 */ 586 static status_t et6000FreeHook(void* dev) { 587 ET6000DeviceInfo *di = (ET6000DeviceInfo *)dev; 588 ET6000SharedInfo *si = di->si; 589 590 ddprintf(("SKD et6000FreeHook() begins...\n")); 591 /* lock the driver */ 592 AQUIRE_BEN(pd->kernel); 593 594 /* if opened multiple times, decrement the open count and exit */ 595 if (di->isOpen > 1) 596 goto unlock_and_exit; 597 598 /* Clear any pending interrupts and disable interrupts. */ 599 et6000aclReadInterruptClear(si->mmRegs); 600 et6000aclWriteInterruptClear(si->mmRegs); 601 et6000aclMasterInterruptDisable(si->mmRegs); 602 603 /* Remove the interrupt handler */ 604 remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, et6000Interrupt, di); 605 606 /* free framebuffer area */ 607 et6000UnmapDevice(di); 608 609 /* clean up our shared area */ 610 delete_area(di->sharedArea); 611 di->sharedArea = -1; 612 di->si = NULL; 613 614 unlock_and_exit: 615 /* mark the device available */ 616 di->isOpen--; 617 /* unlock the driver */ 618 RELEASE_BEN(pd->kernel); 619 ddprintf(("SKD et6000FreeHook() ends.\n")); 620 /* all done */ 621 return B_OK; 622 } 623 /*****************************************************************************/ 624 /* 625 * et6000ControlHook - where the real work is done 626 */ 627 static status_t et6000ControlHook(void* dev, uint32 msg, void *buf, size_t len) { 628 ET6000DeviceInfo *di = (ET6000DeviceInfo *)dev; 629 status_t result = B_DEV_INVALID_IOCTL; 630 631 /* ddprintf(("ioctl: %d, buf: 0x%08x, len: %d\n", msg, buf, len)); */ 632 switch (msg) { 633 /* the only PUBLIC ioctl */ 634 case B_GET_ACCELERANT_SIGNATURE: { 635 char *sig = (char *)buf; 636 strcpy(sig, "et6000.accelerant"); 637 result = B_OK; 638 } break; 639 640 /* PRIVATE ioctl from here on */ 641 case ET6000_GET_PRIVATE_DATA: { 642 ET6000GetPrivateData *gpd = (ET6000GetPrivateData *)buf; 643 if (gpd->magic == ET6000_PRIVATE_DATA_MAGIC) { 644 gpd->sharedInfoArea = di->sharedArea; 645 result = B_OK; 646 } 647 } break; 648 649 case ET6000_GET_PCI: { 650 ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf; 651 if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) { 652 pci_info *pcii = &(di->pcii); 653 gsp->value = get_pci(gsp->offset, gsp->size); 654 result = B_OK; 655 } 656 } break; 657 658 case ET6000_SET_PCI: { 659 ET6000GetSetPCI *gsp = (ET6000GetSetPCI *)buf; 660 if (gsp->magic == ET6000_PRIVATE_DATA_MAGIC) { 661 pci_info *pcii = &(di->pcii); 662 set_pci(gsp->offset, gsp->size, gsp->value); 663 result = B_OK; 664 } 665 } break; 666 667 case ET6000_DEVICE_NAME: { /* Needed for cloning */ 668 ET6000DeviceName *dn = (ET6000DeviceName *)buf; 669 if(dn->magic == ET6000_PRIVATE_DATA_MAGIC) { 670 strncpy(dn->name, di->name, B_OS_NAME_LENGTH); 671 result = B_OK; 672 } 673 } break; 674 675 case ET6000_PROPOSE_DISPLAY_MODE: { 676 ET6000DisplayMode *dm = (ET6000DisplayMode *)buf; 677 if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) { 678 result = et6000ProposeMode(&dm->mode, dm->memSize); 679 } 680 } break; 681 682 case ET6000_SET_DISPLAY_MODE: { 683 ET6000DisplayMode *dm = (ET6000DisplayMode *)buf; 684 if(dm->magic == ET6000_PRIVATE_DATA_MAGIC) { 685 result = et6000SetMode(&dm->mode, dm->pciConfigSpace); 686 } 687 } break; 688 } 689 return result; 690 } 691 /*****************************************************************************/ 692 #if DEBUG > 0 693 static int et6000dump(int argc, char **argv) { 694 int i; 695 696 kprintf("ET6000 Kernel Driver Persistant Data\n\nThere are %ld card(s)\n", pd->count); 697 kprintf("Driver wide benahpore: %ld/%ld\n", pd->kernel.ben, pd->kernel.sem); 698 699 kprintf("Total seen interrupts: %ld\n", pd->total_interrupts); 700 for (i = 0; i < pd->count; i++) { 701 ET6000DeviceInfo *di = &(pd->di[i]); 702 uint16 device_id = di->pcii.device_id; 703 ET6000SharedInfo *si = di->si; 704 kprintf(" device_id: 0x%04x\n", device_id); 705 kprintf(" interrupt count: %ld\n", di->interrupt_count); 706 if (si) { 707 kprintf(" flags:"); 708 } 709 kprintf("\n"); 710 } 711 return 1; /* the magic number for success */ 712 } 713 #endif 714 /*****************************************************************************/ 715