2 Copyright 1999, Be Incorporated. All Rights Reserved.
3 This file may be used under the terms of the Be Sample Code License.
7 Rudolf Cornelissen 3/2002-6/2008.
11 #include "DriverInterface.h"
12 #include "nv_macros.h"
14 #include <graphic_driver.h>
15 #include <KernelExport.h>
19 #include <directories.h>
20 #include <driver_settings.h>
26 #define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
27 #define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v))
32 # undef B_USER_CLONEABLE_AREA
33 # define B_USER_CLONEABLE_AREA 0
36 /* Tell the kernel what revision of the driver API we support */
37 int32 api_version
= B_CUR_DRIVER_API_VERSION
;
39 /* these structures are private to the kernel driver */
40 typedef struct device_info device_info
;
43 timer te
; /* timer entry for add_timer() */
44 device_info
*di
; /* pointer to the owning device */
45 bigtime_t when_target
; /* when we're supposed to wake up */
49 uint32 is_open
; /* a count of how many times the devices has been opened */
50 area_id shared_area
; /* the area shared between the driver and all of the accelerants */
51 shared_info
*si
; /* a pointer to the shared area, for convenience */
52 vuint32
*regs
; /* kernel's pointer to memory mapped registers */
53 pci_info pcii
; /* a convenience copy of the pci info for this device */
54 char name
[B_OS_NAME_LENGTH
]; /* where we keep the name of the device for publishing and comparing */
58 uint32 count
; /* number of devices actually found */
59 benaphore kernel
; /* for serializing opens/closes */
60 char *device_names
[MAX_DEVICES
+1]; /* device name pointer storage */
61 device_info di
[MAX_DEVICES
]; /* device specific stuff */
64 /* prototypes for our private functions */
65 static status_t
open_hook(const char* name
, uint32 flags
, void** cookie
);
66 static status_t
close_hook(void* dev
);
67 static status_t
free_hook(void* dev
);
68 static status_t
read_hook(void* dev
, off_t pos
, void* buf
, size_t* len
);
69 static status_t
write_hook(void* dev
, off_t pos
, const void* buf
, size_t* len
);
70 static status_t
control_hook(void* dev
, uint32 msg
, void *buf
, size_t len
);
71 static status_t
map_device(device_info
*di
);
72 static void unmap_device(device_info
*di
);
73 static void probe_devices(void);
74 static int32
nv_interrupt(void *data
);
76 static DeviceData
*pd
;
77 static isa_module_info
*isa_bus
= NULL
;
78 static pci_module_info
*pci_bus
= NULL
;
79 static device_hooks graphics_device_hooks
= {
92 #define VENDOR_ID_NVIDIA 0x10de /* Nvidia */
93 #define VENDOR_ID_ELSA 0x1048 /* Elsa GmbH */
94 #define VENDOR_ID_NVSTBSGS 0x12d2 /* Nvidia STB/SGS-Thompson */
95 #define VENDOR_ID_VARISYS 0x1888 /* Varisys Limited */
97 static uint16 nvidia_device_list
[] = {
99 // TODO: these cards are not yet supported
100 0x0191, /* Nvidia GeForce 8800 GTX (G80) */
101 0x0193, /* Nvidia GeForce 8800 GTS (G80) */
102 0x0194, /* Nvidia GeForce 8800 Ultra (G80) */
103 0x0400, /* Nvidia GeForce 8600 GTS (G84) */
104 0x0401, /* Nvidia GeForce 8600 GT (G84) */
105 0x0402, /* Nvidia GeForce 8600 GT (G84) */
106 0x0403, /* Nvidia GeForce 8600 GS (G84) */
107 0x0404, /* Nvidia GeForce 8400 GS (G84) */
108 0x0406, /* Nvidia GeForce 8300 GS (G84) */
109 0x0407, /* Nvidia GeForce 8600M GT */
110 0x0420, /* Nvidia GeForce 8400 SE (G86) */
111 0x0421, /* Nvidia GeForce 8500 GT (G86) */
112 0x0422, /* Nvidia GeForce 8400 GS (G86) */
113 0x0423, /* Nvidia GeForce 8300 GS (G86) */
114 0x0424, /* Nvidia GeForce 8400 GS (G86) */
115 0x0426, /* Nvidia GeForce 8400M GT (G86M) */
116 0x0600, /* Nvidia GeForce 8800 GTS 512 (G92) */
117 0x0602, /* Nvidia GeForce 8800 GT (G92) */
118 0x0606, /* Nvidia GeForce 8800 GS (G92) */
119 0x060d, /* Nvidia GeForce 8800 GS (G92) */
120 0x0611, /* Nvidia GeForce 8800 GT (G92) */
121 0x0642, /* Nvidia GeForce 8400 GS (G96) */
122 0x06e2, /* Nvidia GeForce 8400 (G98) */
123 0x06e3, /* Nvidia GeForce 8300 GS (G98) */
124 0x06e4, /* Nvidia GeForce 8400 GS (G98) */
132 } SupportedDevices
[] = {
133 {VENDOR_ID_NVIDIA
, nvidia_device_list
},
137 static nv_settings sSettings
= { // see comments in nvidia_gpgpu.settings
139 DRIVER_PREFIX
".accelerant",
143 0x00000000, // logmask
157 dumprom(void *rom
, uint32 size
, pci_info pcii
)
163 /* determine the romfile name: we need split-up per card in the system */
164 sprintf (fname
, kUserDirectory
"/" DRIVER_PREFIX
"." DEVICE_FORMAT
".rom",
165 pcii
.vendor_id
, pcii
.device_id
, pcii
.bus
, pcii
.device
, pcii
.function
);
167 fd
= open (fname
, O_WRONLY
| O_CREAT
, 0666);
170 /* apparantly max. 32kb may be written at once;
171 * the ROM size is a multiple of that anyway. */
172 for (cnt
= 0; (cnt
< size
); cnt
+= 32768)
173 write (fd
, ((void *)(((uint8
*)rom
) + cnt
)), 32768);
178 /*! return 1 if vblank interrupt has occured */
180 caused_vbi_crtc1(vuint32
* regs
)
182 return (NV_REG32(NV32_CRTC_INTS
) & 0x00000001);
186 /*! clear the vblank interrupt */
188 clear_vbi_crtc1(vuint32
* regs
)
190 NV_REG32(NV32_CRTC_INTS
) = 0x00000001;
195 enable_vbi_crtc1(vuint32
* regs
)
197 /* clear the vblank interrupt */
198 NV_REG32(NV32_CRTC_INTS
) = 0x00000001;
199 /* enable nVidia interrupt source vblank */
200 NV_REG32(NV32_CRTC_INTE
) |= 0x00000001;
201 /* enable nVidia interrupt system hardware (b0-1) */
202 NV_REG32(NV32_MAIN_INTE
) = 0x00000001;
207 disable_vbi_crtc1(vuint32
* regs
)
209 /* disable nVidia interrupt source vblank */
210 NV_REG32(NV32_CRTC_INTE
) &= 0xfffffffe;
211 /* clear the vblank interrupt */
212 NV_REG32(NV32_CRTC_INTS
) = 0x00000001;
216 /*! return 1 if vblank interrupt has occured */
218 caused_vbi_crtc2(vuint32
* regs
)
220 return (NV_REG32(NV32_CRTC2_INTS
) & 0x00000001);
224 /*! clear the vblank interrupt */
226 clear_vbi_crtc2(vuint32
* regs
)
228 NV_REG32(NV32_CRTC2_INTS
) = 0x00000001;
233 enable_vbi_crtc2(vuint32
* regs
)
235 /* clear the vblank interrupt */
236 NV_REG32(NV32_CRTC2_INTS
) = 0x00000001;
237 /* enable nVidia interrupt source vblank */
238 NV_REG32(NV32_CRTC2_INTE
) |= 0x00000001;
239 /* enable nVidia interrupt system hardware (b0-1) */
240 NV_REG32(NV32_MAIN_INTE
) = 0x00000001;
245 disable_vbi_crtc2(vuint32
* regs
)
247 /* disable nVidia interrupt source vblank */
248 NV_REG32(NV32_CRTC2_INTE
) &= 0xfffffffe;
249 /* clear the vblank interrupt */
250 NV_REG32(NV32_CRTC2_INTS
) = 0x00000001;
255 //dangerous code, on singlehead cards better not try accessing secondary head
256 //registers (card might react in unpredictable ways, though there's only a small
257 //chance we actually run into this).
258 //fix requires (some) card recognition code to be moved from accelerant to
261 disable_vbi_all(vuint32
* regs
)
263 /* disable nVidia interrupt source vblank */
264 NV_REG32(NV32_CRTC_INTE
) &= 0xfffffffe;
265 /* clear the vblank interrupt */
266 NV_REG32(NV32_CRTC_INTS
) = 0x00000001;
268 /* disable nVidia interrupt source vblank */
269 NV_REG32(NV32_CRTC2_INTE
) &= 0xfffffffe;
270 /* clear the vblank interrupt */
271 NV_REG32(NV32_CRTC2_INTS
) = 0x00000001;
273 /* disable nVidia interrupt system hardware (b0-1) */
274 NV_REG32(NV32_MAIN_INTE
) = 0x00000000;
279 map_device(device_info
*di
)
281 char buffer
[B_OS_NAME_LENGTH
]; /*memory for device name*/
282 shared_info
*si
= di
->si
;
283 uint32 tmpUlong
, tmpROMshadow
;
284 pci_info
*pcii
= &(di
->pcii
);
287 /* variables for making copy of ROM */
289 area_id rom_area
= -1;
291 /* Nvidia cards have registers in [0] and framebuffer in [1] */
293 int frame_buffer
= 1;
295 /* enable memory mapped IO, disable VGA I/O - this is defined in the PCI standard */
296 tmpUlong
= get_pci(PCI_command
, 2);
297 /* enable PCI access */
298 tmpUlong
|= PCI_command_memory
;
299 /* enable busmastering */
300 tmpUlong
|= PCI_command_master
;
301 /* disable ISA I/O access */
302 tmpUlong
&= ~PCI_command_io
;
303 set_pci(PCI_command
, 2, tmpUlong
);
305 /*work out which version of BeOS is running*/
306 get_system_info(&sysinfo
);
307 if (0)//sysinfo.kernel_build_date[0]=='J')/*FIXME - better ID version*/
309 si
->use_clone_bugfix
= 1;
313 si
->use_clone_bugfix
= 0;
316 /* work out a name for the register mapping */
317 sprintf(buffer
, DEVICE_FORMAT
" regs",
318 di
->pcii
.vendor_id
, di
->pcii
.device_id
,
319 di
->pcii
.bus
, di
->pcii
.device
, di
->pcii
.function
);
321 /* get a virtual memory address for the registers*/
322 si
->regs_area
= map_physical_memory(
324 /* WARNING: Nvidia needs to map regs as viewed from PCI space! */
325 di
->pcii
.u
.h0
.base_registers_pci
[registers
],
326 di
->pcii
.u
.h0
.base_register_sizes
[registers
],
327 B_ANY_KERNEL_ADDRESS
,
328 B_USER_CLONEABLE_AREA
| (si
->use_clone_bugfix
? B_READ_AREA
|B_WRITE_AREA
: 0),
329 (void **)&(di
->regs
));
330 si
->clone_bugfix_regs
= (uint32
*) di
->regs
;
332 /* if mapping registers to vmem failed then pass on error */
333 if (si
->regs_area
< 0) return si
->regs_area
;
335 /* work out a name for the ROM mapping*/
336 sprintf(buffer
, DEVICE_FORMAT
" rom",
337 di
->pcii
.vendor_id
, di
->pcii
.device_id
,
338 di
->pcii
.bus
, di
->pcii
.device
, di
->pcii
.function
);
340 /* preserve ROM shadowing setting, we need to restore the current state later on. */
342 * 'don't touch': (confirmed) NV04, NV05, NV05-M64, NV11 all shutoff otherwise.
343 * NV18, NV28 and NV34 keep working.
344 * confirmed NV28 and NV34 to use upper part of shadowed ROM for scratch purposes,
345 * however the actual ROM content (so the used part) is intact (confirmed). */
346 tmpROMshadow
= get_pci(NVCFG_ROMSHADOW
, 4);
347 /* temporary disable ROM shadowing, we want the guaranteed exact contents of the chip */
348 set_pci(NVCFG_ROMSHADOW
, 4, 0);
350 /* get ROM memory mapped base adress - this is defined in the PCI standard */
351 tmpUlong
= get_pci(PCI_rom_base
, 4);
352 //fixme?: if (!tmpUlong) try to map the ROM ourselves. Confirmed a PCIe system not
353 //having the ROM mapped on PCI and PCIe cards. Falling back to fetching from ISA
354 //legacy space will get us into trouble if we aren't the primary graphics card!!
355 //(as legacy space always has the primary card's ROM 'mapped'!)
357 /* ROM was assigned an adress, so enable ROM decoding - see PCI standard */
358 tmpUlong
|= 0x00000001;
359 set_pci(PCI_rom_base
, 4, tmpUlong
);
361 rom_area
= map_physical_memory(
363 di
->pcii
.u
.h0
.rom_base_pci
,
364 di
->pcii
.u
.h0
.rom_size
,
365 B_ANY_KERNEL_ADDRESS
,
370 /* check if we got the BIOS and signature (might fail on laptops..) */
372 if ((rom_temp
[0] != 0x55) || (rom_temp
[1] != 0xaa)) {
373 /* apparantly no ROM is mapped here */
374 delete_area(rom_area
);
376 /* force using ISA legacy map as fall-back */
377 tmpUlong
= 0x00000000;
380 /* mapping failed: force using ISA legacy map as fall-back */
381 tmpUlong
= 0x00000000;
386 /* ROM was not assigned an adress, fetch it from ISA legacy memory map! */
387 rom_area
= map_physical_memory(buffer
, 0x000c0000,
388 65536, B_ANY_KERNEL_ADDRESS
, B_READ_AREA
, (void **)&(rom_temp
));
391 /* if mapping ROM to vmem failed then clean up and pass on error */
393 delete_area(si
->regs_area
);
398 /* dump ROM to file if selected in nvidia.settings
399 * (ROM always fits in 64Kb: checked TNT1 - FX5950) */
400 if (sSettings
.dumprom
)
401 dumprom(rom_temp
, 65536, di
->pcii
);
403 /* make a copy of ROM for future reference */
404 memcpy(si
->rom_mirror
, rom_temp
, 65536);
406 /* disable ROM decoding - this is defined in the PCI standard, and delete the area */
407 tmpUlong
= get_pci(PCI_rom_base
, 4);
408 tmpUlong
&= 0xfffffffe;
409 set_pci(PCI_rom_base
, 4, tmpUlong
);
410 delete_area(rom_area
);
412 /* restore original ROM shadowing setting to prevent trouble starting (some) cards */
413 set_pci(NVCFG_ROMSHADOW
, 4, tmpROMshadow
);
415 /* work out a name for the framebuffer mapping*/
416 sprintf(buffer
, DEVICE_FORMAT
" framebuffer",
417 di
->pcii
.vendor_id
, di
->pcii
.device_id
,
418 di
->pcii
.bus
, di
->pcii
.device
, di
->pcii
.function
);
420 /* map the framebuffer into vmem, using Write Combining*/
421 si
->fb_area
= map_physical_memory(buffer
,
422 /* WARNING: Nvidia needs to map framebuffer as viewed from PCI space! */
423 di
->pcii
.u
.h0
.base_registers_pci
[frame_buffer
],
424 di
->pcii
.u
.h0
.base_register_sizes
[frame_buffer
],
425 B_ANY_KERNEL_BLOCK_ADDRESS
| B_MTR_WC
,
426 B_READ_AREA
| B_WRITE_AREA
,
429 /*if failed with write combining try again without*/
430 if (si
->fb_area
< 0) {
431 si
->fb_area
= map_physical_memory(buffer
,
432 /* WARNING: Nvidia needs to map framebuffer as viewed from PCI space! */
433 di
->pcii
.u
.h0
.base_registers_pci
[frame_buffer
],
434 di
->pcii
.u
.h0
.base_register_sizes
[frame_buffer
],
435 B_ANY_KERNEL_BLOCK_ADDRESS
,
436 B_READ_AREA
| B_WRITE_AREA
,
440 /* if there was an error, delete our other areas and pass on error*/
441 if (si
->fb_area
< 0) {
442 delete_area(si
->regs_area
);
447 //fixme: retest for card coldstart and PCI/virt_mem mapping!!
448 /* remember the DMA address of the frame buffer for BDirectWindow?? purposes */
449 si
->framebuffer_pci
= (void *) di
->pcii
.u
.h0
.base_registers_pci
[frame_buffer
];
451 // remember settings for use here and in accelerant
452 si
->settings
= sSettings
;
454 /* in any case, return the result */
460 unmap_device(device_info
*di
)
462 shared_info
*si
= di
->si
;
464 pci_info
*pcii
= &(di
->pcii
);
466 /* disable memory mapped IO */
467 tmpUlong
= get_pci(PCI_command
, 4);
468 tmpUlong
&= 0xfffffffc;
469 set_pci(PCI_command
, 4, tmpUlong
);
470 /* delete the areas */
471 if (si
->regs_area
>= 0)
472 delete_area(si
->regs_area
);
473 if (si
->fb_area
>= 0)
474 delete_area(si
->fb_area
);
475 si
->regs_area
= si
->fb_area
= -1;
476 si
->framebuffer
= NULL
;
484 uint32 pci_index
= 0;
486 device_info
*di
= pd
->di
;
487 char tmp_name
[B_OS_NAME_LENGTH
];
489 /* while there are more pci devices */
490 while (count
< MAX_DEVICES
491 && (*pci_bus
->get_nth_pci_info
)(pci_index
, &(di
->pcii
)) == B_OK
) {
494 /* if we match a supported vendor */
495 while (SupportedDevices
[vendor
].vendor
) {
496 if (SupportedDevices
[vendor
].vendor
== di
->pcii
.vendor_id
) {
497 uint16
*devices
= SupportedDevices
[vendor
].devices
;
498 /* while there are more supported devices */
500 /* if we match a supported device */
501 if (*devices
== di
->pcii
.device_id
) {
502 /* publish the device name */
503 sprintf(tmp_name
, DEVICE_FORMAT
,
504 di
->pcii
.vendor_id
, di
->pcii
.device_id
,
505 di
->pcii
.bus
, di
->pcii
.device
, di
->pcii
.function
);
506 /* tweak the exported name to show first in the alphabetically ordered /dev/
507 * hierarchy folder, so the system will use it as primary adaptor if requested
508 * via nvidia.settings. */
509 if (strcmp(tmp_name
, sSettings
.primary
) == 0)
510 sprintf(tmp_name
, "-%s", sSettings
.primary
);
511 /* add /dev/ hierarchy path */
512 sprintf(di
->name
, "graphics/%s", tmp_name
);
513 /* remember the name */
514 pd
->device_names
[count
] = di
->name
;
515 /* mark the driver as available for R/W open */
517 /* mark areas as not yet created */
518 di
->shared_area
= -1;
519 /* mark pointer to shared data as invalid */
521 /* inc pointer to device info */
525 /* break out of these while loops */
528 /* next supported device */
535 /* next pci_info struct, please */
538 /* propagate count */
540 /* terminate list of device names with a null pointer */
541 pd
->device_names
[pd
->count
] = NULL
;
546 thread_interrupt_work(int32
*flags
, vuint32
*regs
, shared_info
*si
)
548 uint32 handled
= B_HANDLED_INTERRUPT
;
549 /* release the vblank semaphore */
550 if (si
->vblank
>= 0) {
552 if ((get_sem_count(si
->vblank
, &blocked
) == B_OK
) && (blocked
< 0)) {
553 release_sem_etc(si
->vblank
, -blocked
, B_DO_NOT_RESCHEDULE
);
554 handled
= B_INVOKE_SCHEDULER
;
562 nv_interrupt(void *data
)
564 int32 handled
= B_UNHANDLED_INTERRUPT
;
565 device_info
*di
= (device_info
*)data
;
566 shared_info
*si
= di
->si
;
567 int32
*flags
= &(si
->flags
);
570 /* is someone already handling an interrupt for this device? */
571 if (atomic_or(flags
, SKD_HANDLER_INSTALLED
) & SKD_HANDLER_INSTALLED
) goto exit0
;
577 /* note: si->ps.secondary_head was cleared by kerneldriver earlier! (at least) */
578 if (si
->ps
.secondary_head
) {
580 //rewrite once we use one driver instance 'per head' (instead of 'per card')
581 if (caused_vbi_crtc1(regs
) || caused_vbi_crtc2(regs
)) {
582 /* clear the interrupt(s) */
583 clear_vbi_crtc1(regs
);
584 clear_vbi_crtc2(regs
);
585 /* release the semaphore */
586 handled
= thread_interrupt_work(flags
, regs
, si
);
589 if (caused_vbi_crtc1(regs
)) {
590 /* clear the interrupt */
591 clear_vbi_crtc1(regs
);
592 /* release the semaphore */
593 handled
= thread_interrupt_work(flags
, regs
, si
);
597 /* note that we're not in the handler any more */
598 atomic_and(flags
, ~SKD_HANDLER_INSTALLED
);
605 // #pragma mark - device hooks
609 open_hook(const char* name
, uint32 flags
, void** cookie
)
616 status_t result
= B_OK
;
617 char shared_name
[B_OS_NAME_LENGTH
];
618 physical_entry map
[1];
620 void *unaligned_dma_buffer
;
622 /* find the device name in the list of devices */
623 /* we're never passed a name we didn't publish */
624 while (pd
->device_names
[index
]
625 && (strcmp(name
, pd
->device_names
[index
]) != 0))
628 /* for convienience */
629 di
= &(pd
->di
[index
]);
631 /* make sure no one else has write access to the common data */
632 AQUIRE_BEN(pd
->kernel
);
634 /* if it's already open for writing */
636 /* mark it open another time */
639 /* create the shared_info area */
640 sprintf(shared_name
, DEVICE_FORMAT
" shared",
641 di
->pcii
.vendor_id
, di
->pcii
.device_id
,
642 di
->pcii
.bus
, di
->pcii
.device
, di
->pcii
.function
);
643 /* create this area with NO user-space read or write permissions, to prevent accidental damage */
644 di
->shared_area
= create_area(shared_name
, (void **)&(di
->si
), B_ANY_KERNEL_ADDRESS
,
645 ((sizeof(shared_info
) + (B_PAGE_SIZE
- 1)) & ~(B_PAGE_SIZE
- 1)), B_FULL_LOCK
,
646 B_USER_CLONEABLE_AREA
);
647 if (di
->shared_area
< 0) {
648 /* return the error */
649 result
= di
->shared_area
;
653 /* save a few dereferences */
656 /* create the DMA command buffer area */
657 //fixme? for R4.5 a workaround for cloning would be needed!
658 /* we want to setup a 1Mb buffer (size must be multiple of B_PAGE_SIZE) */
659 net_buf_size
= ((1 * 1024 * 1024) + (B_PAGE_SIZE
-1)) & ~(B_PAGE_SIZE
-1);
660 /* create the area that will hold the DMA command buffer */
661 si
->unaligned_dma_area
=
662 create_area("NV DMA cmd buffer",
663 (void **)&unaligned_dma_buffer
,
664 B_ANY_KERNEL_ADDRESS
,
665 2 * net_buf_size
, /* take twice the net size so we can have MTRR-WC even on old systems */
666 B_32_BIT_CONTIGUOUS
, /* GPU always needs access */
667 B_USER_CLONEABLE_AREA
| B_READ_AREA
| B_WRITE_AREA
);
668 // TODO: Physical aligning can be done without waste using the
669 // private create_area_etc().
670 /* on error, abort */
671 if (si
->unaligned_dma_area
< 0)
673 /* free the already created shared_info area, and return the error */
674 result
= si
->unaligned_dma_area
;
677 /* we (also) need the physical adress our DMA buffer is at, as this needs to be
678 * fed into the GPU's engine later on. Get an aligned adress so we can use MTRR-WC
679 * even on older CPU's. */
680 get_memory_map(unaligned_dma_buffer
, B_PAGE_SIZE
, map
, 1);
681 si
->dma_buffer_pci
= (void*)
682 ((map
[0].address
+ net_buf_size
- 1) & ~(net_buf_size
- 1));
684 /* map the net DMA command buffer into vmem, using Write Combining */
685 si
->dma_area
= map_physical_memory(
686 "NV aligned DMA cmd buffer", (addr_t
)si
->dma_buffer_pci
, net_buf_size
,
687 B_ANY_KERNEL_BLOCK_ADDRESS
| B_MTR_WC
,
688 B_READ_AREA
| B_WRITE_AREA
, &(si
->dma_buffer
));
689 /* if failed with write combining try again without */
690 if (si
->dma_area
< 0) {
691 si
->dma_area
= map_physical_memory(
692 "NV aligned DMA cmd buffer", (addr_t
)si
->dma_buffer_pci
,
693 net_buf_size
, B_ANY_KERNEL_BLOCK_ADDRESS
,
694 B_READ_AREA
| B_WRITE_AREA
, &(si
->dma_buffer
));
696 /* if there was an error, delete our other areas and pass on error*/
697 if (si
->dma_area
< 0)
699 /* free the already created areas, and return the error */
700 result
= si
->dma_area
;
701 goto free_shared_and_uadma
;
704 /* save the vendor and device IDs */
705 si
->vendor_id
= di
->pcii
.vendor_id
;
706 si
->device_id
= di
->pcii
.device_id
;
707 si
->revision
= di
->pcii
.revision
;
708 si
->bus
= di
->pcii
.bus
;
709 si
->device
= di
->pcii
.device
;
710 si
->function
= di
->pcii
.function
;
712 /* ensure that the accelerant's INIT_ACCELERANT function can be executed */
713 si
->accelerant_in_use
= false;
714 /* preset singlehead card to prevent early INT routine calls (once installed) to
715 * wrongly identify the INT request coming from us! */
716 si
->ps
.secondary_head
= false;
718 /* note the amount of system RAM the system BIOS assigned to the card if applicable:
719 * unified memory architecture (UMA) */
720 switch ((((uint32
)(si
->device_id
)) << 16) | si
->vendor_id
)
722 case 0x01a010de: /* Nvidia GeForce2 Integrated GPU */
723 /* device at bus #0, device #0, function #1 holds value at byte-index 0x7C */
724 si
->ps
.memory_size
= 1024 * 1024 *
725 (((((*pci_bus
->read_pci_config
)(0, 0, 1, 0x7c, 4)) & 0x000007c0) >> 6) + 1);
726 /* last 64kB RAM is used for the BIOS (or something else?) */
727 si
->ps
.memory_size
-= (64 * 1024);
729 case 0x01f010de: /* Nvidia GeForce4 MX Integrated GPU */
730 /* device at bus #0, device #0, function #1 holds value at byte-index 0x84 */
731 si
->ps
.memory_size
= 1024 * 1024 *
732 (((((*pci_bus
->read_pci_config
)(0, 0, 1, 0x84, 4)) & 0x000007f0) >> 4) + 1);
733 /* last 64kB RAM is used for the BIOS (or something else?) */
734 si
->ps
.memory_size
-= (64 * 1024);
737 /* all other cards have own RAM: the amount of which is determined in the
743 result
= map_device(di
);
744 if (result
< 0) goto free_shared_and_alldma
;
746 /* we will be returning OK status for sure now */
749 /* disable and clear any pending interrupts */
751 //distinquish between crtc1/crtc2 once all heads get seperate driver instances!
752 disable_vbi_all(di
->regs
);
754 /* preset we can't use INT related functions */
755 si
->ps
.int_assigned
= false;
757 /* create a semaphore for vertical blank management */
758 si
->vblank
= create_sem(0, di
->name
);
759 if (si
->vblank
< 0) goto mark_as_open
;
761 /* change the owner of the semaphores to the opener's team */
762 /* this is required because apps can't aquire kernel semaphores */
763 thid
= find_thread(NULL
);
764 get_thread_info(thid
, &thinfo
);
765 set_sem_owner(si
->vblank
, thinfo
.team
);
767 /* If there is a valid interrupt line assigned then set up interrupts */
768 if ((di
->pcii
.u
.h0
.interrupt_pin
== 0x00) ||
769 (di
->pcii
.u
.h0
.interrupt_line
== 0xff) || /* no IRQ assigned */
770 (di
->pcii
.u
.h0
.interrupt_line
<= 0x02)) /* system IRQ assigned */
772 /* delete the semaphore as it won't be used */
773 delete_sem(si
->vblank
);
778 /* otherwise install our interrupt handler */
779 result
= install_io_interrupt_handler(di
->pcii
.u
.h0
.interrupt_line
, nv_interrupt
, (void *)di
, 0);
780 /* bail if we couldn't install the handler */
783 /* delete the semaphore as it won't be used */
784 delete_sem(si
->vblank
);
789 /* inform accelerant(s) we can use INT related functions */
790 si
->ps
.int_assigned
= true;
795 /* mark the device open */
798 /* send the cookie to the opener */
804 free_shared_and_alldma
:
805 /* clean up our aligned DMA area */
806 delete_area(si
->dma_area
);
808 si
->dma_buffer
= NULL
;
810 free_shared_and_uadma
:
811 /* clean up our unaligned DMA area */
812 delete_area(si
->unaligned_dma_area
);
813 si
->unaligned_dma_area
= -1;
814 si
->dma_buffer_pci
= NULL
;
817 /* clean up our shared area */
818 delete_area(di
->shared_area
);
819 di
->shared_area
= -1;
823 /* end of critical section */
824 RELEASE_BEN(pd
->kernel
);
826 /* all done, return the status */
832 read_hook(void* dev
, off_t pos
, void* buf
, size_t* len
)
835 return B_NOT_ALLOWED
;
840 write_hook(void* dev
, off_t pos
, const void* buf
, size_t* len
)
843 return B_NOT_ALLOWED
;
848 close_hook(void* dev
)
850 /* we don't do anything on close: there might be dup'd fd */
858 device_info
*di
= (device_info
*)dev
;
859 shared_info
*si
= di
->si
;
860 vuint32
*regs
= di
->regs
;
862 /* lock the driver */
863 AQUIRE_BEN(pd
->kernel
);
865 /* if opened multiple times, decrement the open count and exit */
867 goto unlock_and_exit
;
869 /* disable and clear any pending interrupts */
871 //distinquish between crtc1/crtc2 once all heads get seperate driver instances!
872 disable_vbi_all(regs
);
874 if (si
->ps
.int_assigned
) {
875 /* remove interrupt handler */
876 remove_io_interrupt_handler(di
->pcii
.u
.h0
.interrupt_line
, nv_interrupt
, di
);
878 /* delete the semaphores, ignoring any errors ('cause the owning
879 team may have died on us) */
880 delete_sem(si
->vblank
);
884 /* free regs and framebuffer areas */
887 /* clean up our aligned DMA area */
888 delete_area(si
->dma_area
);
890 si
->dma_buffer
= NULL
;
892 /* clean up our unaligned DMA area */
893 delete_area(si
->unaligned_dma_area
);
894 si
->unaligned_dma_area
= -1;
895 si
->dma_buffer_pci
= NULL
;
897 /* clean up our shared area */
898 delete_area(di
->shared_area
);
899 di
->shared_area
= -1;
903 /* mark the device available */
905 /* unlock the driver */
906 RELEASE_BEN(pd
->kernel
);
913 control_hook(void* dev
, uint32 msg
, void *buf
, size_t len
)
915 device_info
*di
= (device_info
*)dev
;
916 status_t result
= B_DEV_INVALID_IOCTL
;
920 /* the only PUBLIC ioctl */
921 case B_GET_ACCELERANT_SIGNATURE
:
923 strcpy((char* )buf
, sSettings
.accelerant
);
928 /* PRIVATE ioctl from here on */
929 case NV_GET_PRIVATE_DATA
:
931 nv_get_private_data
*gpd
= (nv_get_private_data
*)buf
;
932 if (gpd
->magic
== NV_PRIVATE_DATA_MAGIC
) {
933 gpd
->shared_info_area
= di
->shared_area
;
941 nv_get_set_pci
*gsp
= (nv_get_set_pci
*)buf
;
942 if (gsp
->magic
== NV_PRIVATE_DATA_MAGIC
) {
943 pci_info
*pcii
= &(di
->pcii
);
944 gsp
->value
= get_pci(gsp
->offset
, gsp
->size
);
952 nv_get_set_pci
*gsp
= (nv_get_set_pci
*)buf
;
953 if (gsp
->magic
== NV_PRIVATE_DATA_MAGIC
) {
954 pci_info
*pcii
= &(di
->pcii
);
955 set_pci(gsp
->offset
, gsp
->size
, gsp
->value
);
963 nv_device_name
*dn
= (nv_device_name
*)buf
;
964 if (dn
->magic
== NV_PRIVATE_DATA_MAGIC
) {
965 strcpy(dn
->name
, di
->name
);
971 case NV_RUN_INTERRUPTS
:
973 nv_set_vblank_int
*vi
= (nv_set_vblank_int
*)buf
;
974 if (vi
->magic
== NV_PRIVATE_DATA_MAGIC
) {
975 vuint32
*regs
= di
->regs
;
978 enable_vbi_crtc1(regs
);
980 disable_vbi_crtc1(regs
);
984 enable_vbi_crtc2(regs
);
986 disable_vbi_crtc2(regs
);
996 nv_in_out_isa
*io_isa
= (nv_in_out_isa
*)buf
;
997 if (io_isa
->magic
== NV_PRIVATE_DATA_MAGIC
) {
998 pci_info
*pcii
= &(di
->pcii
);
1001 * no other graphics card may have ISA I/O enabled when we enter */
1002 AQUIRE_BEN(pd
->kernel
);
1004 /* enable ISA I/O access */
1005 tmpUlong
= get_pci(PCI_command
, 2);
1006 tmpUlong
|= PCI_command_io
;
1007 set_pci(PCI_command
, 2, tmpUlong
);
1009 if (io_isa
->size
== 1)
1010 isa_bus
->write_io_8(io_isa
->adress
, (uint8
)io_isa
->data
);
1012 isa_bus
->write_io_16(io_isa
->adress
, io_isa
->data
);
1015 /* disable ISA I/O access */
1016 tmpUlong
= get_pci(PCI_command
, 2);
1017 tmpUlong
&= ~PCI_command_io
;
1018 set_pci(PCI_command
, 2, tmpUlong
);
1020 /* end of critical section */
1021 RELEASE_BEN(pd
->kernel
);
1028 nv_in_out_isa
*io_isa
= (nv_in_out_isa
*)buf
;
1029 if (io_isa
->magic
== NV_PRIVATE_DATA_MAGIC
) {
1030 pci_info
*pcii
= &(di
->pcii
);
1033 * no other graphics card may have ISA I/O enabled when we enter */
1034 AQUIRE_BEN(pd
->kernel
);
1036 /* enable ISA I/O access */
1037 tmpUlong
= get_pci(PCI_command
, 2);
1038 tmpUlong
|= PCI_command_io
;
1039 set_pci(PCI_command
, 2, tmpUlong
);
1041 if (io_isa
->size
== 1)
1042 io_isa
->data
= isa_bus
->read_io_8(io_isa
->adress
);
1044 io_isa
->data
= isa_bus
->read_io_16(io_isa
->adress
);
1047 /* disable ISA I/O access */
1048 tmpUlong
= get_pci(PCI_command
, 2);
1049 tmpUlong
&= ~PCI_command_io
;
1050 set_pci(PCI_command
, 2, tmpUlong
);
1052 /* end of critical section */
1053 RELEASE_BEN(pd
->kernel
);
1063 // #pragma mark - driver API
1073 /* choke if we can't find the PCI bus */
1074 if (get_module(B_PCI_MODULE_NAME
, (module_info
**)&pci_bus
) != B_OK
)
1077 /* choke if we can't find the ISA bus */
1078 if (get_module(B_ISA_MODULE_NAME
, (module_info
**)&isa_bus
) != B_OK
)
1080 put_module(B_PCI_MODULE_NAME
);
1084 /* while there are more pci devices */
1085 while ((*pci_bus
->get_nth_pci_info
)(index
, &pcii
) == B_NO_ERROR
) {
1088 /* if we match a supported vendor */
1089 while (SupportedDevices
[vendor
].vendor
) {
1090 if (SupportedDevices
[vendor
].vendor
== pcii
.vendor_id
) {
1091 uint16
*devices
= SupportedDevices
[vendor
].devices
;
1092 /* while there are more supported devices */
1094 /* if we match a supported device */
1095 if (*devices
== pcii
.device_id
) {
1100 /* next supported device */
1106 /* next pci_info struct, please */
1111 /* put away the module manager */
1112 put_module(B_PCI_MODULE_NAME
);
1113 return found
? B_OK
: B_ERROR
;
1122 // get driver/accelerant settings
1123 settings
= load_driver_settings(DRIVER_PREFIX
".settings");
1124 if (settings
!= NULL
) {
1130 item
= get_driver_parameter(settings
, "accelerant", "", "");
1131 if (item
[0] && strlen(item
) < sizeof(sSettings
.accelerant
) - 1)
1132 strcpy (sSettings
.accelerant
, item
);
1134 item
= get_driver_parameter(settings
, "primary", "", "");
1135 if (item
[0] && strlen(item
) < sizeof(sSettings
.primary
) - 1)
1136 strcpy(sSettings
.primary
, item
);
1138 sSettings
.dumprom
= get_driver_boolean_parameter(settings
,
1139 "dumprom", false, false);
1142 item
= get_driver_parameter(settings
, "logmask",
1143 "0x00000000", "0x00000000");
1144 value
= strtoul(item
, &end
, 0);
1146 sSettings
.logmask
= value
;
1148 item
= get_driver_parameter(settings
, "memory", "0", "0");
1149 value
= strtoul(item
, &end
, 0);
1151 sSettings
.memory
= value
;
1153 sSettings
.hardcursor
= get_driver_boolean_parameter(settings
,
1154 "hardcursor", false, false);
1155 sSettings
.usebios
= get_driver_boolean_parameter(settings
,
1156 "usebios", false, false);
1157 sSettings
.switchhead
= get_driver_boolean_parameter(settings
,
1158 "switchhead", false, false);
1159 sSettings
.pgm_panel
= get_driver_boolean_parameter(settings
,
1160 "pgm_panel", false, false);
1161 sSettings
.force_sync
= get_driver_boolean_parameter(settings
,
1162 "force_sync", false, false);
1163 sSettings
.force_ws
= get_driver_boolean_parameter(settings
,
1164 "force_ws", false, false);
1166 item
= get_driver_parameter(settings
, "gpu_clk", "0", "0");
1167 value
= strtoul(item
, &end
, 0);
1169 sSettings
.gpu_clk
= value
;
1171 item
= get_driver_parameter(settings
, "ram_clk", "0", "0");
1172 value
= strtoul(item
, &end
, 0);
1174 sSettings
.ram_clk
= value
;
1176 unload_driver_settings(settings
);
1179 /* get a handle for the pci bus */
1180 if (get_module(B_PCI_MODULE_NAME
, (module_info
**)&pci_bus
) != B_OK
)
1183 /* get a handle for the isa bus */
1184 if (get_module(B_ISA_MODULE_NAME
, (module_info
**)&isa_bus
) != B_OK
) {
1185 put_module(B_PCI_MODULE_NAME
);
1189 /* driver private data */
1190 pd
= (DeviceData
*)calloc(1, sizeof(DeviceData
));
1192 put_module(B_PCI_MODULE_NAME
);
1195 /* initialize the benaphore */
1196 INIT_BEN(pd
->kernel
);
1197 /* find all of our supported devices */
1204 publish_devices(void)
1206 /* return the list of supported devices */
1207 return (const char **)pd
->device_names
;
1212 find_device(const char *name
)
1215 while (pd
->device_names
[index
]) {
1216 if (strcmp(name
, pd
->device_names
[index
]) == 0)
1217 return &graphics_device_hooks
;
1228 /* free the driver data */
1229 DELETE_BEN(pd
->kernel
);
1233 /* put the pci module away */
1234 put_module(B_PCI_MODULE_NAME
);
1235 put_module(B_ISA_MODULE_NAME
);