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-6/2008.
8*/
9
10
11#include "DriverInterface.h"
12#include "nv_macros.h"
13
14#include <graphic_driver.h>
15#include <KernelExport.h>
16#include <ISA.h>
17#include <PCI.h>
18#include <OS.h>
19#include <directories.h>
20#include <driver_settings.h>
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25
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))
28
29#define MAX_DEVICES	  8
30
31#ifndef __HAIKU__
32#	undef B_USER_CLONEABLE_AREA
33#	define B_USER_CLONEABLE_AREA 0
34#endif
35
36/* Tell the kernel what revision of the driver API we support */
37int32 api_version = B_CUR_DRIVER_API_VERSION;
38
39/* these structures are private to the kernel driver */
40typedef struct device_info device_info;
41
42typedef struct {
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 */
46} timer_info;
47
48struct device_info {
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 */
55};
56
57typedef struct {
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 */
62} DeviceData;
63
64/* prototypes for our private functions */
65static status_t open_hook(const char* name, uint32 flags, void** cookie);
66static status_t close_hook(void* dev);
67static status_t free_hook(void* dev);
68static status_t read_hook(void* dev, off_t pos, void* buf, size_t* len);
69static status_t write_hook(void* dev, off_t pos, const void* buf, size_t* len);
70static status_t control_hook(void* dev, uint32 msg, void *buf, size_t len);
71static status_t map_device(device_info *di);
72static void unmap_device(device_info *di);
73static void probe_devices(void);
74static int32 nv_interrupt(void *data);
75
76static DeviceData		*pd;
77static isa_module_info	*isa_bus = NULL;
78static pci_module_info	*pci_bus = NULL;
79static device_hooks graphics_device_hooks = {
80	open_hook,
81	close_hook,
82	free_hook,
83	control_hook,
84	read_hook,
85	write_hook,
86	NULL,
87	NULL,
88	NULL,
89	NULL
90};
91
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 */
96
97static uint16 nvidia_device_list[] = {
98#if 0
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)      */
125#endif
126	0
127};
128
129static struct {
130	uint16	vendor;
131	uint16	*devices;
132} SupportedDevices[] = {
133	{VENDOR_ID_NVIDIA, nvidia_device_list},
134	{0x0000, NULL}
135};
136
137static nv_settings sSettings = { // see comments in nvidia_gpgpu.settings
138	/* for driver */
139	DRIVER_PREFIX ".accelerant",
140	"none",					// primary
141	false,      			// dumprom
142	/* for accelerant */
143	0x00000000, 			// logmask
144	0,          			// memory
145	true,       			// usebios
146	true,       			// hardcursor
147	false,					// switchhead
148	false,					// pgm_panel
149	false,					// force_sync
150	true,					// force_ws
151	0,						// gpu_clk
152	0,						// ram_clk
153};
154
155
156static void
157dumprom(void *rom, uint32 size, pci_info pcii)
158{
159	int fd;
160	uint32 cnt;
161	char fname[64];
162
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);
166
167	fd = open (fname, O_WRONLY | O_CREAT, 0666);
168	if (fd < 0) return;
169
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);
174	close (fd);
175}
176
177
178/*! return 1 if vblank interrupt has occured */
179static int
180caused_vbi_crtc1(vuint32 * regs)
181{
182	return (NV_REG32(NV32_CRTC_INTS) & 0x00000001);
183}
184
185
186/*! clear the vblank interrupt */
187static void
188clear_vbi_crtc1(vuint32 * regs)
189{
190	NV_REG32(NV32_CRTC_INTS) = 0x00000001;
191}
192
193
194static void
195enable_vbi_crtc1(vuint32 * regs)
196{
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;
203}
204
205
206static void
207disable_vbi_crtc1(vuint32 * regs)
208{
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;
213}
214
215
216/*! return 1 if vblank interrupt has occured */
217static int
218caused_vbi_crtc2(vuint32 * regs)
219{
220	return (NV_REG32(NV32_CRTC2_INTS) & 0x00000001);
221}
222
223
224/*! clear the vblank interrupt */
225static void
226clear_vbi_crtc2(vuint32 * regs)
227{
228	NV_REG32(NV32_CRTC2_INTS) = 0x00000001;
229}
230
231
232static void
233enable_vbi_crtc2(vuint32 * regs)
234{
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;
241}
242
243
244static void
245disable_vbi_crtc2(vuint32 * regs)
246{
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;
251}
252
253
254//fixme:
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
259//kerneldriver...
260static void
261disable_vbi_all(vuint32 * regs)
262{
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;
267
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;
272
273	/* disable nVidia interrupt system hardware (b0-1) */
274	NV_REG32(NV32_MAIN_INTE) = 0x00000000;
275}
276
277
278static status_t
279map_device(device_info *di)
280{
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);
285	system_info sysinfo;
286
287	/* variables for making copy of ROM */
288	uint8* rom_temp;
289	area_id rom_area = -1;
290
291	/* Nvidia cards have registers in [0] and framebuffer in [1] */
292	int registers = 0;
293	int frame_buffer = 1;
294
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);
304
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*/
308 	{
309 		si->use_clone_bugfix = 1;
310 	}
311 	else
312 	{
313 		si->use_clone_bugfix = 0;
314 	}
315
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);
320
321	/* get a virtual memory address for the registers*/
322	si->regs_area = map_physical_memory(
323		buffer,
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;
331
332	/* if mapping registers to vmem failed then pass on error */
333	if (si->regs_area < 0) return si->regs_area;
334
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);
339
340	/* preserve ROM shadowing setting, we need to restore the current state later on. */
341	/* warning:
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);
349
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'!)
356	if (tmpUlong) {
357		/* ROM was assigned an adress, so enable ROM decoding - see PCI standard */
358		tmpUlong |= 0x00000001;
359		set_pci(PCI_rom_base, 4, tmpUlong);
360
361		rom_area = map_physical_memory(
362			buffer,
363			di->pcii.u.h0.rom_base_pci,
364			di->pcii.u.h0.rom_size,
365			B_ANY_KERNEL_ADDRESS,
366			B_READ_AREA,
367			(void **)&(rom_temp)
368		);
369
370		/* check if we got the BIOS and signature (might fail on laptops..) */
371		if (rom_area >= 0) {
372			if ((rom_temp[0] != 0x55) || (rom_temp[1] != 0xaa)) {
373				/* apparantly no ROM is mapped here */
374				delete_area(rom_area);
375				rom_area = -1;
376				/* force using ISA legacy map as fall-back */
377				tmpUlong = 0x00000000;
378			}
379		} else {
380			/* mapping failed: force using ISA legacy map as fall-back */
381			tmpUlong = 0x00000000;
382		}
383	}
384
385	if (!tmpUlong) {
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));
389	}
390
391	/* if mapping ROM to vmem failed then clean up and pass on error */
392	if (rom_area < 0) {
393		delete_area(si->regs_area);
394		si->regs_area = -1;
395		return rom_area;
396	}
397
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);
402
403	/* make a copy of ROM for future reference */
404	memcpy(si->rom_mirror, rom_temp, 65536);
405
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);
411
412	/* restore original ROM shadowing setting to prevent trouble starting (some) cards */
413	set_pci(NVCFG_ROMSHADOW, 4, tmpROMshadow);
414
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);
419
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,
427		&(si->framebuffer));
428
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,
437			&(si->framebuffer));
438	}
439
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);
443		si->regs_area = -1;
444		return si->fb_area;
445	}
446
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];
450
451	// remember settings for use here and in accelerant
452	si->settings = sSettings;
453
454	/* in any case, return the result */
455	return si->fb_area;
456}
457
458
459static void
460unmap_device(device_info *di)
461{
462	shared_info *si = di->si;
463	uint32	tmpUlong;
464	pci_info *pcii = &(di->pcii);
465
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;
477	di->regs = NULL;
478}
479
480
481static void
482probe_devices(void)
483{
484	uint32 pci_index = 0;
485	uint32 count = 0;
486	device_info *di = pd->di;
487	char tmp_name[B_OS_NAME_LENGTH];
488
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) {
492		int vendor = 0;
493
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 */
499				while (*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 */
516						di->is_open = 0;
517						/* mark areas as not yet created */
518						di->shared_area = -1;
519						/* mark pointer to shared data as invalid */
520						di->si = NULL;
521						/* inc pointer to device info */
522						di++;
523						/* inc count */
524						count++;
525						/* break out of these while loops */
526						goto next_device;
527					}
528					/* next supported device */
529					devices++;
530				}
531			}
532			vendor++;
533		}
534next_device:
535		/* next pci_info struct, please */
536		pci_index++;
537	}
538	/* propagate count */
539	pd->count = count;
540	/* terminate list of device names with a null pointer */
541	pd->device_names[pd->count] = NULL;
542}
543
544
545static uint32
546thread_interrupt_work(int32 *flags, vuint32 *regs, shared_info *si)
547{
548	uint32 handled = B_HANDLED_INTERRUPT;
549	/* release the vblank semaphore */
550	if (si->vblank >= 0) {
551		int32 blocked;
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;
555		}
556	}
557	return handled;
558}
559
560
561static int32
562nv_interrupt(void *data)
563{
564	int32 handled = B_UNHANDLED_INTERRUPT;
565	device_info *di = (device_info *)data;
566	shared_info *si = di->si;
567	int32 *flags = &(si->flags);
568	vuint32 *regs;
569
570	/* is someone already handling an interrupt for this device? */
571	if (atomic_or(flags, SKD_HANDLER_INSTALLED) & SKD_HANDLER_INSTALLED) goto exit0;
572
573	/* get regs */
574	regs = di->regs;
575
576	/* was it a VBI? */
577	/* note: si->ps.secondary_head was cleared by kerneldriver earlier! (at least) */
578	if (si->ps.secondary_head) {
579		//fixme:
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);
587		}
588	} else {
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);
594		}
595	}
596
597	/* note that we're not in the handler any more */
598	atomic_and(flags, ~SKD_HANDLER_INSTALLED);
599
600exit0:
601	return handled;
602}
603
604
605//	#pragma mark - device hooks
606
607
608static status_t
609open_hook(const char* name, uint32 flags, void** cookie)
610{
611	int32 index = 0;
612	device_info *di;
613	shared_info *si;
614	thread_id	thid;
615	thread_info	thinfo;
616	status_t	result = B_OK;
617	char shared_name[B_OS_NAME_LENGTH];
618	physical_entry map[1];
619	size_t net_buf_size;
620	void *unaligned_dma_buffer;
621
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))
626		index++;
627
628	/* for convienience */
629	di = &(pd->di[index]);
630
631	/* make sure no one else has write access to the common data */
632	AQUIRE_BEN(pd->kernel);
633
634	/* if it's already open for writing */
635	if (di->is_open) {
636		/* mark it open another time */
637		goto mark_as_open;
638	}
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;
650		goto done;
651	}
652
653	/* save a few dereferences */
654	si = di->si;
655
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)
672	{
673		/* free the already created shared_info area, and return the error */
674		result = si->unaligned_dma_area;
675		goto free_shared;
676	}
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));
683
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));
695	}
696	/* if there was an error, delete our other areas and pass on error*/
697	if (si->dma_area < 0)
698	{
699		/* free the already created areas, and return the error */
700		result = si->dma_area;
701		goto free_shared_and_uadma;
702	}
703
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;
711
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;
717
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)
721	{
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);
728		break;
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);
735		break;
736	default:
737		/* all other cards have own RAM: the amount of which is determined in the
738		 * accelerant. */
739		break;
740	}
741
742	/* map the device */
743	result = map_device(di);
744	if (result < 0) goto free_shared_and_alldma;
745
746	/* we will be returning OK status for sure now */
747	result = B_OK;
748
749	/* disable and clear any pending interrupts */
750	//fixme:
751	//distinquish between crtc1/crtc2 once all heads get seperate driver instances!
752	disable_vbi_all(di->regs);
753
754	/* preset we can't use INT related functions */
755	si->ps.int_assigned = false;
756
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;
760
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);
766
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 */
771	{
772		/* delete the semaphore as it won't be used */
773		delete_sem(si->vblank);
774		si->vblank = -1;
775	}
776	else
777	{
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 */
781		if (result != B_OK)
782		{
783			/* delete the semaphore as it won't be used */
784			delete_sem(si->vblank);
785			si->vblank = -1;
786		}
787		else
788		{
789			/* inform accelerant(s) we can use INT related functions */
790			si->ps.int_assigned = true;
791		}
792	}
793
794mark_as_open:
795	/* mark the device open */
796	di->is_open++;
797
798	/* send the cookie to the opener */
799	*cookie = di;
800
801	goto done;
802
803
804free_shared_and_alldma:
805	/* clean up our aligned DMA area */
806	delete_area(si->dma_area);
807	si->dma_area = -1;
808	si->dma_buffer = NULL;
809
810free_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;
815
816free_shared:
817	/* clean up our shared area */
818	delete_area(di->shared_area);
819	di->shared_area = -1;
820	di->si = NULL;
821
822done:
823	/* end of critical section */
824	RELEASE_BEN(pd->kernel);
825
826	/* all done, return the status */
827	return result;
828}
829
830
831static status_t
832read_hook(void* dev, off_t pos, void* buf, size_t* len)
833{
834	*len = 0;
835	return B_NOT_ALLOWED;
836}
837
838
839static status_t
840write_hook(void* dev, off_t pos, const void* buf, size_t* len)
841{
842	*len = 0;
843	return B_NOT_ALLOWED;
844}
845
846
847static status_t
848close_hook(void* dev)
849{
850	/* we don't do anything on close: there might be dup'd fd */
851	return B_NO_ERROR;
852}
853
854
855static status_t
856free_hook(void* dev)
857{
858	device_info *di = (device_info *)dev;
859	shared_info	*si = di->si;
860	vuint32 *regs = di->regs;
861
862	/* lock the driver */
863	AQUIRE_BEN(pd->kernel);
864
865	/* if opened multiple times, decrement the open count and exit */
866	if (di->is_open > 1)
867		goto unlock_and_exit;
868
869	/* disable and clear any pending interrupts */
870	//fixme:
871	//distinquish between crtc1/crtc2 once all heads get seperate driver instances!
872	disable_vbi_all(regs);
873
874	if (si->ps.int_assigned) {
875		/* remove interrupt handler */
876		remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, nv_interrupt, di);
877
878		/* delete the semaphores, ignoring any errors ('cause the owning
879		   team may have died on us) */
880		delete_sem(si->vblank);
881		si->vblank = -1;
882	}
883
884	/* free regs and framebuffer areas */
885	unmap_device(di);
886
887	/* clean up our aligned DMA area */
888	delete_area(si->dma_area);
889	si->dma_area = -1;
890	si->dma_buffer = NULL;
891
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;
896
897	/* clean up our shared area */
898	delete_area(di->shared_area);
899	di->shared_area = -1;
900	di->si = NULL;
901
902unlock_and_exit:
903	/* mark the device available */
904	di->is_open--;
905	/* unlock the driver */
906	RELEASE_BEN(pd->kernel);
907	/* all done */
908	return B_OK;
909}
910
911
912static status_t
913control_hook(void* dev, uint32 msg, void *buf, size_t len)
914{
915	device_info *di = (device_info *)dev;
916	status_t result = B_DEV_INVALID_IOCTL;
917	uint32 tmpUlong;
918
919	switch (msg) {
920		/* the only PUBLIC ioctl */
921		case B_GET_ACCELERANT_SIGNATURE:
922		{
923			strcpy((char* )buf, sSettings.accelerant);
924			result = B_OK;
925			break;
926		}
927
928		/* PRIVATE ioctl from here on */
929		case NV_GET_PRIVATE_DATA:
930		{
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;
934				result = B_OK;
935			}
936			break;
937		}
938
939		case NV_GET_PCI:
940		{
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);
945				result = B_OK;
946			}
947			break;
948		}
949
950		case NV_SET_PCI:
951		{
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);
956				result = B_OK;
957			}
958			break;
959		}
960
961		case NV_DEVICE_NAME:
962		{
963			nv_device_name *dn = (nv_device_name *)buf;
964			if (dn->magic == NV_PRIVATE_DATA_MAGIC) {
965				strcpy(dn->name, di->name);
966				result = B_OK;
967			}
968			break;
969		}
970
971		case NV_RUN_INTERRUPTS:
972		{
973			nv_set_vblank_int *vi = (nv_set_vblank_int *)buf;
974			if (vi->magic == NV_PRIVATE_DATA_MAGIC) {
975				vuint32 *regs = di->regs;
976				if (!(vi->crtc)) {
977					if (vi->do_it) {
978						enable_vbi_crtc1(regs);
979					} else {
980						disable_vbi_crtc1(regs);
981					}
982				} else {
983					if (vi->do_it) {
984						enable_vbi_crtc2(regs);
985					} else {
986						disable_vbi_crtc2(regs);
987					}
988				}
989				result = B_OK;
990			}
991			break;
992		}
993
994		case NV_ISA_OUT:
995		{
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);
999
1000				/* lock the driver:
1001				 * no other graphics card may have ISA I/O enabled when we enter */
1002				AQUIRE_BEN(pd->kernel);
1003
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);
1008
1009				if (io_isa->size == 1)
1010  					isa_bus->write_io_8(io_isa->adress, (uint8)io_isa->data);
1011   				else
1012   					isa_bus->write_io_16(io_isa->adress, io_isa->data);
1013  				result = B_OK;
1014
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);
1019
1020				/* end of critical section */
1021				RELEASE_BEN(pd->kernel);
1022   			}
1023			break;
1024		}
1025
1026		case NV_ISA_IN:
1027		{
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);
1031
1032				/* lock the driver:
1033				 * no other graphics card may have ISA I/O enabled when we enter */
1034				AQUIRE_BEN(pd->kernel);
1035
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);
1040
1041				if (io_isa->size == 1)
1042	   				io_isa->data = isa_bus->read_io_8(io_isa->adress);
1043	   			else
1044	   				io_isa->data = isa_bus->read_io_16(io_isa->adress);
1045   				result = B_OK;
1046
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);
1051
1052				/* end of critical section */
1053				RELEASE_BEN(pd->kernel);
1054   			}
1055			break;
1056		}
1057	}
1058
1059	return result;
1060}
1061
1062
1063//	#pragma mark - driver API
1064
1065
1066status_t
1067init_hardware(void)
1068{
1069	long index = 0;
1070	pci_info pcii;
1071	bool found = false;
1072
1073	/* choke if we can't find the PCI bus */
1074	if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK)
1075		return B_ERROR;
1076
1077	/* choke if we can't find the ISA bus */
1078	if (get_module(B_ISA_MODULE_NAME, (module_info **)&isa_bus) != B_OK)
1079	{
1080		put_module(B_PCI_MODULE_NAME);
1081		return B_ERROR;
1082	}
1083
1084	/* while there are more pci devices */
1085	while ((*pci_bus->get_nth_pci_info)(index, &pcii) == B_NO_ERROR) {
1086		int vendor = 0;
1087
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 */
1093				while (*devices) {
1094					/* if we match a supported device */
1095					if (*devices == pcii.device_id ) {
1096
1097						found = true;
1098						goto done;
1099					}
1100					/* next supported device */
1101					devices++;
1102				}
1103			}
1104			vendor++;
1105		}
1106		/* next pci_info struct, please */
1107		index++;
1108	}
1109
1110done:
1111	/* put away the module manager */
1112	put_module(B_PCI_MODULE_NAME);
1113	return found ? B_OK : B_ERROR;
1114}
1115
1116
1117status_t
1118init_driver(void)
1119{
1120	void *settings;
1121
1122	// get driver/accelerant settings
1123	settings = load_driver_settings(DRIVER_PREFIX ".settings");
1124	if (settings != NULL) {
1125		const char *item;
1126		char *end;
1127		uint32 value;
1128
1129		// for driver
1130		item = get_driver_parameter(settings, "accelerant", "", "");
1131		if (item[0] && strlen(item) < sizeof(sSettings.accelerant) - 1)
1132			strcpy (sSettings.accelerant, item);
1133
1134		item = get_driver_parameter(settings, "primary", "", "");
1135		if (item[0] && strlen(item) < sizeof(sSettings.primary) - 1)
1136			strcpy(sSettings.primary, item);
1137
1138		sSettings.dumprom = get_driver_boolean_parameter(settings,
1139			"dumprom", false, false);
1140
1141		// for accelerant
1142		item = get_driver_parameter(settings, "logmask",
1143			"0x00000000", "0x00000000");
1144		value = strtoul(item, &end, 0);
1145		if (*end == '\0')
1146			sSettings.logmask = value;
1147
1148		item = get_driver_parameter(settings, "memory", "0", "0");
1149		value = strtoul(item, &end, 0);
1150		if (*end == '\0')
1151			sSettings.memory = value;
1152
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);
1165
1166		item = get_driver_parameter(settings, "gpu_clk", "0", "0");
1167		value = strtoul(item, &end, 0);
1168		if (*end == '\0')
1169			sSettings.gpu_clk = value;
1170
1171		item = get_driver_parameter(settings, "ram_clk", "0", "0");
1172		value = strtoul(item, &end, 0);
1173		if (*end == '\0')
1174			sSettings.ram_clk = value;
1175
1176		unload_driver_settings(settings);
1177	}
1178
1179	/* get a handle for the pci bus */
1180	if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK)
1181		return B_ERROR;
1182
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);
1186		return B_ERROR;
1187	}
1188
1189	/* driver private data */
1190	pd = (DeviceData *)calloc(1, sizeof(DeviceData));
1191	if (!pd) {
1192		put_module(B_PCI_MODULE_NAME);
1193		return B_ERROR;
1194	}
1195	/* initialize the benaphore */
1196	INIT_BEN(pd->kernel);
1197	/* find all of our supported devices */
1198	probe_devices();
1199	return B_OK;
1200}
1201
1202
1203const char **
1204publish_devices(void)
1205{
1206	/* return the list of supported devices */
1207	return (const char **)pd->device_names;
1208}
1209
1210
1211device_hooks *
1212find_device(const char *name)
1213{
1214	int index = 0;
1215	while (pd->device_names[index]) {
1216		if (strcmp(name, pd->device_names[index]) == 0)
1217			return &graphics_device_hooks;
1218		index++;
1219	}
1220	return NULL;
1221
1222}
1223
1224
1225void
1226uninit_driver(void)
1227{
1228	/* free the driver data */
1229	DELETE_BEN(pd->kernel);
1230	free(pd);
1231	pd = NULL;
1232
1233	/* put the pci module away */
1234	put_module(B_PCI_MODULE_NAME);
1235	put_module(B_ISA_MODULE_NAME);
1236}
1237
1238