1 /* 2 Copyright 1999, Be Incorporated. All Rights Reserved. 3 This file may be used under the terms of the Be Sample Code License. 4 5 Other authors: 6 Mark Watson; 7 Rudolf Cornelissen 3/2002-4/2006. 8 */ 9 10 /* standard kernel driver stuff */ 11 #include <KernelExport.h> 12 #include <ISA.h> 13 #include <PCI.h> 14 #include <OS.h> 15 #include <driver_settings.h> 16 #include <malloc.h> 17 #include <stdlib.h> // for strtoXX 18 #include "AGP.h" 19 20 /* this is for the standardized portion of the driver API */ 21 /* currently only one operation is defined: B_GET_ACCELERANT_SIGNATURE */ 22 #include <graphic_driver.h> 23 24 /* this is for sprintf() */ 25 #include <stdio.h> 26 27 /* this is for string compares */ 28 #include <string.h> 29 30 /* The private interface between the accelerant and the kernel driver. */ 31 #include "DriverInterface.h" 32 #include "macros.h" 33 34 #define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s)) 35 #define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v)) 36 37 #define MAX_DEVICES 8 38 39 #define DEVICE_FORMAT "%04x_%04x_%02x%02x%02x" // apsed 40 41 /* Tell the kernel what revision of the driver API we support */ 42 int32 api_version = B_CUR_DRIVER_API_VERSION; // apsed, was 2, is 2 in R5 43 44 /* these structures are private to the kernel driver */ 45 typedef struct device_info device_info; 46 47 typedef struct { 48 timer te; /* timer entry for add_timer() */ 49 device_info *di; /* pointer to the owning device */ 50 bigtime_t when_target; /* when we're supposed to wake up */ 51 } timer_info; 52 53 struct device_info { 54 uint32 is_open; /* a count of how many times the devices has been opened */ 55 area_id shared_area; /* the area shared between the driver and all of the accelerants */ 56 shared_info *si; /* a pointer to the shared area, for convenience */ 57 vuint32 *regs; /* kernel's pointer to memory mapped registers */ 58 pci_info pcii; /* a convenience copy of the pci info for this device */ 59 char name[B_OS_NAME_LENGTH]; /* where we keep the name of the device for publishing and comparing */ 60 }; 61 62 typedef struct { 63 uint32 count; /* number of devices actually found */ 64 benaphore kernel; /* for serializing opens/closes */ 65 char *device_names[MAX_DEVICES+1]; /* device name pointer storage */ 66 device_info di[MAX_DEVICES]; /* device specific stuff */ 67 } DeviceData; 68 69 /* prototypes for our private functions */ 70 static status_t open_hook (const char* name, uint32 flags, void** cookie); 71 static status_t close_hook (void* dev); 72 static status_t free_hook (void* dev); 73 static status_t read_hook (void* dev, off_t pos, void* buf, size_t* len); 74 static status_t write_hook (void* dev, off_t pos, const void* buf, size_t* len); 75 static status_t control_hook (void* dev, uint32 msg, void *buf, size_t len); 76 static status_t map_device(device_info *di); 77 static void unmap_device(device_info *di); 78 static void probe_devices(void); 79 static int32 eng_interrupt(void *data); 80 81 static DeviceData *pd; 82 static isa_module_info *isa_bus = NULL; 83 static pci_module_info *pci_bus = NULL; 84 static agp_gart_module_info *agp_bus = NULL; 85 static device_hooks graphics_device_hooks = { 86 open_hook, 87 close_hook, 88 free_hook, 89 control_hook, 90 read_hook, 91 write_hook, 92 NULL, 93 NULL, 94 NULL, 95 NULL 96 }; 97 98 #define VENDOR_ID_VIA 0x1106 /* Via */ 99 100 static uint16 via_device_list[] = { 101 0x3022, /* CLE266 Unichrome Pro (CLE3022) */ 102 0x3108, /* K8M800 Unichrome Pro (unknown chiptype) */ 103 0x3122, /* CLE266 Unichrome Pro (CLE3122) */ 104 0x3205, /* KM400 Unichrome (VT3205) */ 105 // 0x3344, /* P4M800 Pro (VT3344) */ 106 0x7205, /* KM400 Unichrome (VT7205) */ 107 0 108 }; 109 110 static struct { 111 uint16 vendor; 112 uint16 *devices; 113 } SupportedDevices[] = { 114 {VENDOR_ID_VIA, via_device_list}, 115 {0x0000, NULL} 116 }; 117 118 static settings current_settings = { // see comments in skel.settings 119 // for driver 120 DRIVER_PREFIX ".accelerant", 121 false, // dumprom 122 // for accelerant 123 0x00000000, // logmask 124 0, // memory 125 true, // usebios 126 true, // hardcursor 127 false, // switchhead 128 false, // force_pci 129 false, // unhide_fw 130 true, // pgm_panel 131 }; 132 133 static void dumprom (void *rom, uint32 size) 134 { 135 int fd; 136 uint32 cnt; 137 138 fd = open ("/boot/home/" DRIVER_PREFIX ".rom", O_WRONLY | O_CREAT, 0666); 139 if (fd < 0) return; 140 141 /* apparantly max. 32kb may be written at once; 142 * the ROM size is a multiple of that anyway. */ 143 for (cnt = 0; (cnt < size); cnt += 32768) 144 write (fd, ((void *)(((uint8 *)rom) + cnt)), 32768); 145 close (fd); 146 } 147 148 /* return 1 if vblank interrupt has occured */ 149 static int caused_vbi(vuint32 * regs) 150 { 151 // return (ENG_REG32(RG32_CRTC_INTS) & 0x00000001); 152 return 0; 153 } 154 155 /* clear the vblank interrupt */ 156 static void clear_vbi(vuint32 * regs) 157 { 158 // ENG_REG32(RG32_CRTC_INTS) = 0x00000001; 159 } 160 161 static void enable_vbi(vuint32 * regs) 162 { 163 /* clear the vblank interrupt */ 164 // ENG_REG32(RG32_CRTC_INTS) = 0x00000001; 165 /* enable nVidia interrupt source vblank */ 166 // ENG_REG32(RG32_CRTC_INTE) |= 0x00000001; 167 /* enable nVidia interrupt system hardware (b0-1) */ 168 // ENG_REG32(RG32_MAIN_INTE) = 0x00000001; 169 } 170 171 static void disable_vbi(vuint32 * regs) 172 { 173 /* disable nVidia interrupt source vblank */ 174 // ENG_REG32(RG32_CRTC_INTE) &= 0xfffffffe; 175 /* clear the vblank interrupt */ 176 // ENG_REG32(RG32_CRTC_INTS) = 0x00000001; 177 /* disable nVidia interrupt system hardware (b0-1) */ 178 // ENG_REG32(RG32_MAIN_INTE) = 0x00000000; 179 } 180 181 /* 182 init_hardware() - Returns B_OK if one is 183 found, otherwise returns B_ERROR so the driver will be unloaded. 184 */ 185 status_t 186 init_hardware(void) { 187 long pci_index = 0; 188 pci_info pcii; 189 bool found_one = false; 190 191 /* choke if we can't find the PCI bus */ 192 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK) 193 return B_ERROR; 194 195 /* choke if we can't find the ISA bus */ 196 if (get_module(B_ISA_MODULE_NAME, (module_info **)&isa_bus) != B_OK) 197 { 198 put_module(B_PCI_MODULE_NAME); 199 return B_ERROR; 200 } 201 202 /* while there are more pci devices */ 203 while ((*pci_bus->get_nth_pci_info)(pci_index, &pcii) == B_NO_ERROR) { 204 int vendor = 0; 205 206 /* if we match a supported vendor */ 207 while (SupportedDevices[vendor].vendor) { 208 if (SupportedDevices[vendor].vendor == pcii.vendor_id) { 209 uint16 *devices = SupportedDevices[vendor].devices; 210 /* while there are more supported devices */ 211 while (*devices) { 212 /* if we match a supported device */ 213 if (*devices == pcii.device_id ) { 214 215 found_one = true; 216 goto done; 217 } 218 /* next supported device */ 219 devices++; 220 } 221 } 222 vendor++; 223 } 224 /* next pci_info struct, please */ 225 pci_index++; 226 } 227 228 done: 229 /* put away the module manager */ 230 put_module(B_PCI_MODULE_NAME); 231 return (found_one ? B_OK : B_ERROR); 232 } 233 234 status_t 235 init_driver(void) { 236 void *settings_handle; 237 238 // get driver/accelerant settings, apsed 239 settings_handle = load_driver_settings (DRIVER_PREFIX ".settings"); 240 if (settings_handle != NULL) { 241 const char *item; 242 char *end; 243 uint32 value; 244 245 // for driver 246 item = get_driver_parameter (settings_handle, "accelerant", "", ""); 247 if ((strlen (item) > 0) && (strlen (item) < sizeof (current_settings.accelerant) - 1)) { 248 strcpy (current_settings.accelerant, item); 249 } 250 current_settings.dumprom = get_driver_boolean_parameter (settings_handle, "dumprom", false, false); 251 252 // for accelerant 253 item = get_driver_parameter (settings_handle, "logmask", "0x00000000", "0x00000000"); 254 value = strtoul (item, &end, 0); 255 if (*end == '\0') current_settings.logmask = value; 256 257 item = get_driver_parameter (settings_handle, "memory", "0", "0"); 258 value = strtoul (item, &end, 0); 259 if (*end == '\0') current_settings.memory = value; 260 261 current_settings.hardcursor = get_driver_boolean_parameter (settings_handle, "hardcursor", false, false); 262 current_settings.usebios = get_driver_boolean_parameter (settings_handle, "usebios", false, false); 263 current_settings.switchhead = get_driver_boolean_parameter (settings_handle, "switchhead", false, false); 264 current_settings.force_pci = get_driver_boolean_parameter (settings_handle, "force_pci", false, false); 265 current_settings.unhide_fw = get_driver_boolean_parameter (settings_handle, "unhide_fw", false, false); 266 current_settings.pgm_panel = get_driver_boolean_parameter (settings_handle, "pgm_panel", false, false); 267 268 unload_driver_settings (settings_handle); 269 } 270 271 /* get a handle for the pci bus */ 272 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK) 273 return B_ERROR; 274 275 /* get a handle for the isa bus */ 276 if (get_module(B_ISA_MODULE_NAME, (module_info **)&isa_bus) != B_OK) 277 { 278 put_module(B_PCI_MODULE_NAME); 279 return B_ERROR; 280 } 281 282 /* get a handle for the agp bus if it exists */ 283 get_module(B_AGP_GART_MODULE_NAME, (module_info **)&agp_bus); 284 285 /* driver private data */ 286 pd = (DeviceData *)calloc(1, sizeof(DeviceData)); 287 if (!pd) { 288 if (agp_bus) 289 put_module(B_AGP_GART_MODULE_NAME); 290 put_module(B_ISA_MODULE_NAME); 291 put_module(B_PCI_MODULE_NAME); 292 return B_ERROR; 293 } 294 /* initialize the benaphore */ 295 INIT_BEN(pd->kernel); 296 /* find all of our supported devices */ 297 probe_devices(); 298 return B_OK; 299 } 300 301 const char ** 302 publish_devices(void) { 303 /* return the list of supported devices */ 304 return (const char **)pd->device_names; 305 } 306 307 device_hooks * 308 find_device(const char *name) { 309 int index = 0; 310 while (pd->device_names[index]) { 311 if (strcmp(name, pd->device_names[index]) == 0) 312 return &graphics_device_hooks; 313 index++; 314 } 315 return NULL; 316 317 } 318 319 void uninit_driver(void) { 320 321 /* free the driver data */ 322 DELETE_BEN(pd->kernel); 323 free(pd); 324 pd = NULL; 325 326 /* put the pci module away */ 327 put_module(B_PCI_MODULE_NAME); 328 put_module(B_ISA_MODULE_NAME); 329 330 /* put the agp module away if it's there */ 331 if (agp_bus) 332 put_module(B_AGP_GART_MODULE_NAME); 333 } 334 335 static status_t map_device(device_info *di) 336 { 337 char buffer[B_OS_NAME_LENGTH]; /*memory for device name*/ 338 shared_info *si = di->si; 339 uint32 tmpUlong; 340 pci_info *pcii = &(di->pcii); 341 system_info sysinfo; 342 343 /*storage for the physical to virtual table (used for dma buffer)*/ 344 // physical_entry physical_memory[2]; 345 // #define G400_DMA_BUFFER_SIZE 1024*1024 346 347 /* variables for making copy of ROM */ 348 uint8* rom_temp; 349 area_id rom_area; 350 351 /* Nvidia cards have registers in [0] and framebuffer in [1] */ 352 int registers = 1; 353 int frame_buffer = 0; 354 // int pseudo_dma = 2; 355 356 /* enable memory mapped IO, disable VGA I/O - this is defined in the PCI standard */ 357 tmpUlong = get_pci(PCI_command, 2); 358 /* enable PCI access */ 359 tmpUlong |= PCI_command_memory; 360 /* enable busmastering */ 361 tmpUlong |= PCI_command_master; 362 /* disable ISA I/O access */ 363 tmpUlong &= ~PCI_command_io; 364 set_pci(PCI_command, 2, tmpUlong); 365 366 /*work out which version of BeOS is running*/ 367 get_system_info(&sysinfo); 368 if (0)//sysinfo.kernel_build_date[0]=='J')/*FIXME - better ID version*/ 369 { 370 si->use_clone_bugfix = 1; 371 } 372 else 373 { 374 si->use_clone_bugfix = 0; 375 } 376 377 /* work out a name for the register mapping */ 378 sprintf(buffer, DEVICE_FORMAT " regs", 379 di->pcii.vendor_id, di->pcii.device_id, 380 di->pcii.bus, di->pcii.device, di->pcii.function); 381 382 /* get a virtual memory address for the registers*/ 383 si->regs_area = map_physical_memory( 384 buffer, 385 /* WARNING: Nvidia needs to map regs as viewed from PCI space! */ 386 (void *) di->pcii.u.h0.base_registers_pci[registers], 387 di->pcii.u.h0.base_register_sizes[registers], 388 B_ANY_KERNEL_ADDRESS, 389 (si->use_clone_bugfix ? B_READ_AREA|B_WRITE_AREA : 0), 390 (void **)&(di->regs)); 391 si->clone_bugfix_regs = (uint32 *) di->regs; 392 393 /* if mapping registers to vmem failed then pass on error */ 394 if (si->regs_area < 0) return si->regs_area; 395 396 /* work out a name for the ROM mapping*/ 397 sprintf(buffer, DEVICE_FORMAT " rom", 398 di->pcii.vendor_id, di->pcii.device_id, 399 di->pcii.bus, di->pcii.device, di->pcii.function); 400 401 /* disable ROM shadowing, we want the guaranteed exact contents of the chip */ 402 /* warning: 403 * don't touch: (confirmed) NV04, NV05, NV05-M64, NV11 all shutoff otherwise. 404 * NV18, NV28 and NV34 keep working. 405 * confirmed NV28 and NV34 to use upper part of shadowed ROM for scratch purposes, 406 * however the actual ROM content (so the used part) is intact (confirmed). */ 407 //set_pci(ENCFG_ROMSHADOW, 4, 0); 408 409 /* get ROM memory mapped base adress - this is defined in the PCI standard */ 410 tmpUlong = get_pci(PCI_rom_base, 4); 411 if (tmpUlong) 412 { 413 /* ROM was assigned an adress, so enable ROM decoding - see PCI standard */ 414 tmpUlong |= 0x00000001; 415 set_pci(PCI_rom_base, 4, tmpUlong); 416 417 rom_area = map_physical_memory( 418 buffer, 419 (void *)di->pcii.u.h0.rom_base_pci, 420 di->pcii.u.h0.rom_size, 421 B_ANY_KERNEL_ADDRESS, 422 B_READ_AREA, 423 (void **)&(rom_temp) 424 ); 425 426 /* check if we got the BIOS signature (might fail on laptops..) */ 427 if (rom_temp[0]!=0x55 || rom_temp[1]!=0xaa) 428 { 429 /* apparantly no ROM is mapped here */ 430 delete_area(rom_area); 431 rom_area = -1; 432 /* force using ISA legacy map as fall-back */ 433 tmpUlong = 0x00000000; 434 } 435 } 436 437 if (!tmpUlong) 438 { 439 /* ROM was not assigned an adress, fetch it from ISA legacy memory map! */ 440 rom_area = map_physical_memory( 441 buffer, 442 (void *)0x000c0000, 443 65536, 444 B_ANY_KERNEL_ADDRESS, 445 B_READ_AREA, 446 (void **)&(rom_temp) 447 ); 448 } 449 450 /* if mapping ROM to vmem failed then clean up and pass on error */ 451 if (rom_area < 0) { 452 delete_area(si->regs_area); 453 si->regs_area = -1; 454 return rom_area; 455 } 456 457 /* dump ROM to file if selected in skel.settings 458 * (ROM always fits in 64Kb: checked TNT1 - FX5950) */ 459 if (current_settings.dumprom) dumprom (rom_temp, 65536); 460 /* make a copy of ROM for future reference */ 461 memcpy (si->rom_mirror, rom_temp, 65536); 462 463 /* disable ROM decoding - this is defined in the PCI standard, and delete the area */ 464 tmpUlong = get_pci(PCI_rom_base, 4); 465 tmpUlong &= 0xfffffffe; 466 set_pci(PCI_rom_base, 4, tmpUlong); 467 delete_area(rom_area); 468 469 /* work out a name for the framebuffer mapping*/ 470 sprintf(buffer, DEVICE_FORMAT " framebuffer", 471 di->pcii.vendor_id, di->pcii.device_id, 472 di->pcii.bus, di->pcii.device, di->pcii.function); 473 474 /* map the framebuffer into vmem, using Write Combining*/ 475 si->fb_area = map_physical_memory( 476 buffer, 477 /* WARNING: Nvidia needs to map framebuffer as viewed from PCI space! */ 478 (void *) di->pcii.u.h0.base_registers_pci[frame_buffer], 479 di->pcii.u.h0.base_register_sizes[frame_buffer], 480 B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC, 481 B_READ_AREA + B_WRITE_AREA, 482 &(si->framebuffer)); 483 484 /*if failed with write combining try again without*/ 485 if (si->fb_area < 0) { 486 si->fb_area = map_physical_memory( 487 buffer, 488 /* WARNING: Nvidia needs to map framebuffer as viewed from PCI space! */ 489 (void *) di->pcii.u.h0.base_registers_pci[frame_buffer], 490 di->pcii.u.h0.base_register_sizes[frame_buffer], 491 B_ANY_KERNEL_BLOCK_ADDRESS, 492 B_READ_AREA + B_WRITE_AREA, 493 &(si->framebuffer)); 494 } 495 496 /* if there was an error, delete our other areas and pass on error*/ 497 if (si->fb_area < 0) 498 { 499 delete_area(si->regs_area); 500 si->regs_area = -1; 501 return si->fb_area; 502 } 503 //fixme: retest for card coldstart and PCI/virt_mem mapping!! 504 /* remember the DMA address of the frame buffer for BDirectWindow?? purposes */ 505 si->framebuffer_pci = (void *) di->pcii.u.h0.base_registers_pci[frame_buffer]; 506 507 // remember settings for use here and in accelerant 508 si->settings = current_settings; 509 510 /* in any case, return the result */ 511 return si->fb_area; 512 } 513 514 static void unmap_device(device_info *di) { 515 shared_info *si = di->si; 516 uint32 tmpUlong; 517 pci_info *pcii = &(di->pcii); 518 519 /* disable memory mapped IO */ 520 tmpUlong = get_pci(PCI_command, 4); 521 tmpUlong &= 0xfffffffc; 522 set_pci(PCI_command, 4, tmpUlong); 523 /* delete the areas */ 524 if (si->regs_area >= 0) delete_area(si->regs_area); 525 if (si->fb_area >= 0) delete_area(si->fb_area); 526 si->regs_area = si->fb_area = -1; 527 si->framebuffer = NULL; 528 di->regs = NULL; 529 } 530 531 static void probe_devices(void) { 532 uint32 pci_index = 0; 533 uint32 count = 0; 534 device_info *di = pd->di; 535 536 /* while there are more pci devices */ 537 while ((count < MAX_DEVICES) && ((*pci_bus->get_nth_pci_info)(pci_index, &(di->pcii)) == B_NO_ERROR)) { 538 int vendor = 0; 539 540 /* if we match a supported vendor */ 541 while (SupportedDevices[vendor].vendor) { 542 if (SupportedDevices[vendor].vendor == di->pcii.vendor_id) { 543 uint16 *devices = SupportedDevices[vendor].devices; 544 /* while there are more supported devices */ 545 while (*devices) { 546 /* if we match a supported device */ 547 if (*devices == di->pcii.device_id ) { 548 /* publish the device name */ 549 sprintf(di->name, "graphics/" DEVICE_FORMAT, 550 di->pcii.vendor_id, di->pcii.device_id, 551 di->pcii.bus, di->pcii.device, di->pcii.function); 552 553 /* remember the name */ 554 pd->device_names[count] = di->name; 555 /* mark the driver as available for R/W open */ 556 di->is_open = 0; 557 /* mark areas as not yet created */ 558 di->shared_area = -1; 559 /* mark pointer to shared data as invalid */ 560 di->si = NULL; 561 /* inc pointer to device info */ 562 di++; 563 /* inc count */ 564 count++; 565 /* break out of these while loops */ 566 goto next_device; 567 } 568 /* next supported device */ 569 devices++; 570 } 571 } 572 vendor++; 573 } 574 next_device: 575 /* next pci_info struct, please */ 576 pci_index++; 577 } 578 /* propagate count */ 579 pd->count = count; 580 /* terminate list of device names with a null pointer */ 581 pd->device_names[pd->count] = NULL; 582 } 583 584 static uint32 thread_interrupt_work(int32 *flags, vuint32 *regs, shared_info *si) { 585 uint32 handled = B_HANDLED_INTERRUPT; 586 /* release the vblank semaphore */ 587 if (si->vblank >= 0) { 588 int32 blocked; 589 if ((get_sem_count(si->vblank, &blocked) == B_OK) && (blocked < 0)) { 590 release_sem_etc(si->vblank, -blocked, B_DO_NOT_RESCHEDULE); 591 handled = B_INVOKE_SCHEDULER; 592 } 593 } 594 return handled; 595 } 596 597 static int32 598 eng_interrupt(void *data) 599 { 600 int32 handled = B_UNHANDLED_INTERRUPT; 601 device_info *di = (device_info *)data; 602 shared_info *si = di->si; 603 int32 *flags = &(si->flags); 604 vuint32 *regs; 605 606 /* is someone already handling an interrupt for this device? */ 607 if (atomic_or(flags, SKD_HANDLER_INSTALLED) & SKD_HANDLER_INSTALLED) { 608 goto exit0; 609 } 610 /* get regs */ 611 regs = di->regs; 612 613 /* was it a VBI? */ 614 if (caused_vbi(regs)) { 615 /*clear the interrupt*/ 616 clear_vbi(regs); 617 /*release the semaphore*/ 618 handled = thread_interrupt_work(flags, regs, si); 619 } 620 621 /* note that we're not in the handler any more */ 622 atomic_and(flags, ~SKD_HANDLER_INSTALLED); 623 624 exit0: 625 return handled; 626 } 627 628 static status_t open_hook (const char* name, uint32 flags, void** cookie) { 629 int32 index = 0; 630 device_info *di; 631 shared_info *si; 632 thread_id thid; 633 thread_info thinfo; 634 status_t result = B_OK; 635 vuint32 *regs; 636 char shared_name[B_OS_NAME_LENGTH]; 637 638 /* find the device name in the list of devices */ 639 /* we're never passed a name we didn't publish */ 640 while (pd->device_names[index] && (strcmp(name, pd->device_names[index]) != 0)) index++; 641 642 /* for convienience */ 643 di = &(pd->di[index]); 644 645 /* make sure no one else has write access to the common data */ 646 AQUIRE_BEN(pd->kernel); 647 648 /* if it's already open for writing */ 649 if (di->is_open) { 650 /* mark it open another time */ 651 goto mark_as_open; 652 } 653 /* create the shared area */ 654 sprintf(shared_name, DEVICE_FORMAT " shared", 655 di->pcii.vendor_id, di->pcii.device_id, 656 di->pcii.bus, di->pcii.device, di->pcii.function); 657 /* create this area with NO user-space read or write permissions, to prevent accidental dammage */ 658 di->shared_area = create_area(shared_name, (void **)&(di->si), B_ANY_KERNEL_ADDRESS, ((sizeof(shared_info) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1)), B_FULL_LOCK, 0); 659 if (di->shared_area < 0) { 660 /* return the error */ 661 result = di->shared_area; 662 goto done; 663 } 664 665 /* save a few dereferences */ 666 si = di->si; 667 668 /* save the vendor and device IDs */ 669 si->vendor_id = di->pcii.vendor_id; 670 si->device_id = di->pcii.device_id; 671 si->revision = di->pcii.revision; 672 si->bus = di->pcii.bus; 673 si->device = di->pcii.device; 674 si->function = di->pcii.function; 675 676 /* device at bus #0, device #0, function #0 holds byte value at byte-index 0xf6 */ 677 si->ps.chip_rev = ((*pci_bus->read_pci_config)(0, 0, 0, 0xf6, 1)); 678 679 /* map the device */ 680 result = map_device(di); 681 if (result < 0) goto free_shared; 682 result = B_OK; 683 684 /* create a semaphore for vertical blank management */ 685 si->vblank = create_sem(0, di->name); 686 if (si->vblank < 0) { 687 result = si->vblank; 688 goto unmap; 689 } 690 691 /* change the owner of the semaphores to the opener's team */ 692 /* this is required because apps can't aquire kernel semaphores */ 693 thid = find_thread(NULL); 694 get_thread_info(thid, &thinfo); 695 set_sem_owner(si->vblank, thinfo.team); 696 697 /* assign local regs pointer for SAMPLExx() macros */ 698 regs = di->regs; 699 700 /* disable and clear any pending interrupts */ 701 disable_vbi(regs); 702 703 /* If there is a valid interrupt line assigned then set up interrupts */ 704 if ((di->pcii.u.h0.interrupt_pin == 0x00) || 705 (di->pcii.u.h0.interrupt_line == 0xff) || /* no IRQ assigned */ 706 (di->pcii.u.h0.interrupt_line <= 0x02)) /* system IRQ assigned */ 707 { 708 /* we are aborting! */ 709 /* Note: the R4 graphics driver kit lacks this statement!! */ 710 result = B_ERROR; 711 /* interrupt does not exist so exit without installing our handler */ 712 goto delete_the_sem; 713 } 714 else 715 { 716 /* otherwise install our interrupt handler */ 717 result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line, eng_interrupt, (void *)di, 0); 718 /* bail if we couldn't install the handler */ 719 if (result != B_OK) goto delete_the_sem; 720 } 721 722 mark_as_open: 723 /* mark the device open */ 724 di->is_open++; 725 726 /* send the cookie to the opener */ 727 *cookie = di; 728 729 goto done; 730 731 732 delete_the_sem: 733 delete_sem(si->vblank); 734 735 unmap: 736 unmap_device(di); 737 738 free_shared: 739 /* clean up our shared area */ 740 delete_area(di->shared_area); 741 di->shared_area = -1; 742 di->si = NULL; 743 744 done: 745 /* end of critical section */ 746 RELEASE_BEN(pd->kernel); 747 748 /* all done, return the status */ 749 return result; 750 } 751 752 /* ---------- 753 read_hook - does nothing, gracefully 754 ----- */ 755 static status_t 756 read_hook (void* dev, off_t pos, void* buf, size_t* len) 757 { 758 *len = 0; 759 return B_NOT_ALLOWED; 760 } 761 762 /* ---------- 763 write_hook - does nothing, gracefully 764 ----- */ 765 static status_t 766 write_hook (void* dev, off_t pos, const void* buf, size_t* len) 767 { 768 *len = 0; 769 return B_NOT_ALLOWED; 770 } 771 772 /* ---------- 773 close_hook - does nothing, gracefully 774 ----- */ 775 static status_t 776 close_hook (void* dev) 777 { 778 /* we don't do anything on close: there might be dup'd fd */ 779 return B_NO_ERROR; 780 } 781 782 /* ----------- 783 free_hook - close down the device 784 ----------- */ 785 static status_t 786 free_hook (void* dev) { 787 device_info *di = (device_info *)dev; 788 shared_info *si = di->si; 789 vuint32 *regs = di->regs; 790 791 /* lock the driver */ 792 AQUIRE_BEN(pd->kernel); 793 794 /* if opened multiple times, decrement the open count and exit */ 795 if (di->is_open > 1) 796 goto unlock_and_exit; 797 798 /* disable and clear any pending interrupts */ 799 disable_vbi(regs); 800 801 /* remove interrupt handler */ 802 remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, eng_interrupt, di); 803 804 /* delete the semaphores, ignoring any errors ('cause the owning team may have died on us) */ 805 delete_sem(si->vblank); 806 si->vblank = -1; 807 808 /* free regs and framebuffer areas */ 809 unmap_device(di); 810 811 /* clean up our shared area */ 812 delete_area(di->shared_area); 813 di->shared_area = -1; 814 di->si = NULL; 815 816 unlock_and_exit: 817 /* mark the device available */ 818 di->is_open--; 819 /* unlock the driver */ 820 RELEASE_BEN(pd->kernel); 821 /* all done */ 822 return B_OK; 823 } 824 825 /* ----------- 826 control_hook - where the real work is done 827 ----------- */ 828 static status_t 829 control_hook (void* dev, uint32 msg, void *buf, size_t len) { 830 device_info *di = (device_info *)dev; 831 status_t result = B_DEV_INVALID_IOCTL; 832 uint32 tmpUlong; 833 834 switch (msg) { 835 /* the only PUBLIC ioctl */ 836 case B_GET_ACCELERANT_SIGNATURE: { 837 char *sig = (char *)buf; 838 strcpy(sig, current_settings.accelerant); 839 result = B_OK; 840 } break; 841 842 /* PRIVATE ioctl from here on */ 843 case ENG_GET_PRIVATE_DATA: { 844 eng_get_private_data *gpd = (eng_get_private_data *)buf; 845 if (gpd->magic == VIA_PRIVATE_DATA_MAGIC) { 846 gpd->shared_info_area = di->shared_area; 847 result = B_OK; 848 } 849 } break; 850 case ENG_GET_PCI: { 851 eng_get_set_pci *gsp = (eng_get_set_pci *)buf; 852 if (gsp->magic == VIA_PRIVATE_DATA_MAGIC) { 853 pci_info *pcii = &(di->pcii); 854 gsp->value = get_pci(gsp->offset, gsp->size); 855 result = B_OK; 856 } 857 } break; 858 case ENG_SET_PCI: { 859 eng_get_set_pci *gsp = (eng_get_set_pci *)buf; 860 if (gsp->magic == VIA_PRIVATE_DATA_MAGIC) { 861 pci_info *pcii = &(di->pcii); 862 set_pci(gsp->offset, gsp->size, gsp->value); 863 result = B_OK; 864 } 865 } break; 866 case ENG_DEVICE_NAME: { // apsed 867 eng_device_name *dn = (eng_device_name *)buf; 868 if (dn->magic == VIA_PRIVATE_DATA_MAGIC) { 869 strcpy(dn->name, di->name); 870 result = B_OK; 871 } 872 } break; 873 case ENG_RUN_INTERRUPTS: { 874 eng_set_bool_state *ri = (eng_set_bool_state *)buf; 875 if (ri->magic == VIA_PRIVATE_DATA_MAGIC) { 876 vuint32 *regs = di->regs; 877 if (ri->do_it) { 878 enable_vbi(regs); 879 } else { 880 disable_vbi(regs); 881 } 882 result = B_OK; 883 } 884 } break; 885 case ENG_GET_NTH_AGP_INFO: { 886 eng_nth_agp_info *nai = (eng_nth_agp_info *)buf; 887 if (nai->magic == VIA_PRIVATE_DATA_MAGIC) { 888 nai->exist = false; 889 nai->agp_bus = false; 890 if (agp_bus) { 891 nai->agp_bus = true; 892 if ((*agp_bus->get_nth_agp_info)(nai->index, &(nai->agpi)) == B_NO_ERROR) { 893 nai->exist = true; 894 } 895 } 896 result = B_OK; 897 } 898 } break; 899 case ENG_ENABLE_AGP: { 900 eng_cmd_agp *nca = (eng_cmd_agp *)buf; 901 if (nca->magic == VIA_PRIVATE_DATA_MAGIC) { 902 if (agp_bus) { 903 nca->agp_bus = true; 904 nca->cmd = agp_bus->set_agp_mode(nca->cmd); 905 } else { 906 nca->agp_bus = false; 907 nca->cmd = 0; 908 } 909 result = B_OK; 910 } 911 } break; 912 case ENG_ISA_OUT: { 913 eng_in_out_isa *io_isa = (eng_in_out_isa *)buf; 914 if (io_isa->magic == VIA_PRIVATE_DATA_MAGIC) { 915 pci_info *pcii = &(di->pcii); 916 917 /* lock the driver: 918 * no other graphics card may have ISA I/O enabled when we enter */ 919 AQUIRE_BEN(pd->kernel); 920 921 /* enable ISA I/O access */ 922 tmpUlong = get_pci(PCI_command, 2); 923 tmpUlong |= PCI_command_io; 924 set_pci(PCI_command, 2, tmpUlong); 925 926 if (io_isa->size == 1) 927 isa_bus->write_io_8(io_isa->adress, (uint8)io_isa->data); 928 else 929 isa_bus->write_io_16(io_isa->adress, io_isa->data); 930 result = B_OK; 931 932 /* disable ISA I/O access */ 933 tmpUlong = get_pci(PCI_command, 2); 934 tmpUlong &= ~PCI_command_io; 935 set_pci(PCI_command, 2, tmpUlong); 936 937 /* end of critical section */ 938 RELEASE_BEN(pd->kernel); 939 } 940 } break; 941 case ENG_ISA_IN: { 942 eng_in_out_isa *io_isa = (eng_in_out_isa *)buf; 943 if (io_isa->magic == VIA_PRIVATE_DATA_MAGIC) { 944 pci_info *pcii = &(di->pcii); 945 946 /* lock the driver: 947 * no other graphics card may have ISA I/O enabled when we enter */ 948 AQUIRE_BEN(pd->kernel); 949 950 /* enable ISA I/O access */ 951 tmpUlong = get_pci(PCI_command, 2); 952 tmpUlong |= PCI_command_io; 953 set_pci(PCI_command, 2, tmpUlong); 954 955 if (io_isa->size == 1) 956 io_isa->data = isa_bus->read_io_8(io_isa->adress); 957 else 958 io_isa->data = isa_bus->read_io_16(io_isa->adress); 959 result = B_OK; 960 961 /* disable ISA I/O access */ 962 tmpUlong = get_pci(PCI_command, 2); 963 tmpUlong &= ~PCI_command_io; 964 set_pci(PCI_command, 2, tmpUlong); 965 966 /* end of critical section */ 967 RELEASE_BEN(pd->kernel); 968 } 969 } break; 970 } 971 return result; 972 } 973