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