1/*
2	Copyright 2007-2011 Haiku, Inc.  All rights reserved.
3	Distributed under the terms of the MIT license.
4
5	Authors:
6	Gerald Zajac
7*/
8
9#include <KernelExport.h>
10#include <PCI.h>
11#include <drivers/bios.h>
12#include <malloc.h>
13#include <stdio.h>
14#include <string.h>
15#include <graphic_driver.h>
16#include <boot_item.h>
17
18#include "DriverInterface.h"
19
20
21#undef TRACE
22
23#ifdef ENABLE_DEBUG_TRACE
24#	define TRACE(x...) dprintf("ati: " x)
25#else
26#	define TRACE(x...) ;
27#endif
28
29
30#define ATI_ACCELERANT_NAME    "ati.accelerant"
31
32#define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1))
33
34#define VESA_MODES_BOOT_INFO "vesa_modes/v1"
35
36#define SKD_HANDLER_INSTALLED 0x80000000
37#define MAX_DEVICES		4
38#define DEVICE_FORMAT	"%04X_%04X_%02X%02X%02X"
39
40#define M64_BIOS_SIZE		0x10000		// 64KB
41#define R128_BIOS_SIZE		0x10000		// 64KB
42
43int32 api_version = B_CUR_DRIVER_API_VERSION;	// revision of driver API used
44
45#define VENDOR_ID 0x1002	// ATI vendor ID
46
47// Mach64 register definitions.
48#define M64_CLOCK_INTERNAL	4
49#define M64_CONFIG_CHIP_ID	0x0CE0		// offset in register area
50#define M64_CFG_CHIP_TYPE	0x0000FFFF
51
52
53struct ChipInfo {
54	uint16		chipID;			// PCI device id of the chip
55	ChipType	chipType;		// assigned chip type identifier
56	const char*	chipName;		// user recognizable name for chip
57								//   (must be < 32 chars)
58};
59
60
61// Names for chip types.
62
63static char sRage128_GL[]		 = "RAGE 128 GL";
64static char sRage128_VR[]		 = "RAGE 128 VR";
65static char sRage128_Pro_GL[]	 = "RAGE 128 PRO GL";
66static char sRage128_Pro_VR[]	 = "RAGE 128 PRO VR";
67static char sRage128_Pro_Ultra[] = "RAGE 128 PRO Ultra";
68
69// This table maps a PCI device ID to a chip type identifier and the chip name.
70// The table is split into two groups of chips, the Mach64 and Rage128 chips,
71// with each group ordered by the chip ID.
72
73static const ChipInfo chipTable[] = {
74	{ 0x4742, MACH64_264GTPRO,		"3D RAGE PRO, AGP"		},		// GB
75	{ 0x4744, MACH64_264GTPRO,		"3D RAGE PRO, AGP"		},		// GD
76	{ 0x4749, MACH64_264GTPRO,		"3D RAGE PRO, PCI"		},		// GI
77	{ 0x474C, MACH64_264XL,			"3D RAGE XC, PCI"		},		// GL
78	{ 0x474D, MACH64_264XL,			"3D RAGE XL, AGP"		},		// GM
79	{ 0x474E, MACH64_264XL,			"3D RAGE XC, AGP"		},		// GN
80	{ 0x474F, MACH64_264XL,			"3D RAGE XL, PCI"		},		// GO
81	{ 0x4750, MACH64_264GTPRO,		"3D RAGE PRO, PCI"		},		// GP
82	{ 0x4751, MACH64_264GTPRO,		"3D RAGE PRO, PCI"		},		// GQ
83	{ 0x4752, MACH64_264XL,			"3D RAGE XL, PCI"		},		// GR
84	{ 0x4753, MACH64_264XL,			"3D RAGE XC, PCI"		},		// GS
85	{ 0x4754, MACH64_264GT,			"3D RAGE II"			},		// GT
86	{ 0x4755, MACH64_264GTDVD,		"3D RAGE II+"			},		// GU
87	{ 0x4756, MACH64_264GT2C,		"3D RAGE IIC, PCI"		},		// GV
88	{ 0x4757, MACH64_264GT2C,		"3D RAGE IIC, AGP"		},		// GW
89	{ 0x4759, MACH64_264GT2C,		"3D RAGE IIC, PCI"		},		// GY
90	{ 0x475A, MACH64_264GT2C,		"3D RAGE IIC, AGP"		},		// GZ
91	{ 0x4C42, MACH64_264LTPRO,		"3D RAGE LT PRO, AGP"	},		// LB
92	{ 0x4C44, MACH64_264LTPRO,		"3D RAGE LT PRO, AGP"	},		// LD
93	{ 0x4C47, MACH64_264LT,			"3D RAGE LT"			},		// LG
94	{ 0x4C49, MACH64_264LTPRO,		"3D RAGE LT PRO, PCI"	},		// LI
95	{ 0x4C4D, MACH64_MOBILITY,		"3D RAGE Mobility, AGP"	},		// LM
96	{ 0x4C4E, MACH64_MOBILITY,		"3D RAGE Mobility, AGP"	},		// LN
97	{ 0x4C50, MACH64_264LTPRO,		"3D RAGE LT PRO, PCI"	},		// LP
98	{ 0x4C51, MACH64_264LTPRO,		"3D RAGE LT PRO, PCI"	},		// LQ
99	{ 0x4C52, MACH64_MOBILITY,		"3D RAGE Mobility, PCI"	},		// LR
100	{ 0x4C53, MACH64_MOBILITY,		"3D RAGE Mobility, PCI"	},		// LS
101	{ 0x5654, MACH64_264VT,			"264VT2"				},		// VT
102	{ 0x5655, MACH64_264VT3,		"264VT3"				},		// VU
103	{ 0x5656, MACH64_264VT4,		"264VT4"				},		// VV
104
105	{ 0x4C45, RAGE128_MOBILITY,		"RAGE 128 Mobility 3"	},		// LE
106	{ 0x4C46, RAGE128_MOBILITY,		"RAGE 128 Mobility 3"	},		// LF
107	{ 0x4D46, RAGE128_MOBILITY,		"RAGE 128 Mobility 4"	},		// MF
108	{ 0x4D4C, RAGE128_MOBILITY,		"RAGE 128 Mobility 4"	},		// ML
109	{ 0x5041, RAGE128_PRO_GL,		sRage128_Pro_GL			},		// PA
110	{ 0x5042, RAGE128_PRO_GL,		sRage128_Pro_GL			},		// PB
111	{ 0x5043, RAGE128_PRO_GL,		sRage128_Pro_GL			},		// PC
112	{ 0x5044, RAGE128_PRO_GL,		sRage128_Pro_GL			},		// PD
113	{ 0x5045, RAGE128_PRO_GL,		sRage128_Pro_GL			},		// PE
114	{ 0x5046, RAGE128_PRO_GL,		sRage128_Pro_GL			},		// PF
115	{ 0x5047, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PG
116	{ 0x5048, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PH
117	{ 0x5049, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PI
118	{ 0x504A, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PJ
119	{ 0x504B, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PK
120	{ 0x504C, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PL
121	{ 0x504D, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PM
122	{ 0x504E, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PN
123	{ 0x504F, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PO
124	{ 0x5050, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PP
125	{ 0x5051, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PQ
126	{ 0x5052, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PR
127	{ 0x5053, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PS
128	{ 0x5054, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PT
129	{ 0x5055, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PU
130	{ 0x5056, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PV
131	{ 0x5057, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PW
132	{ 0x5058, RAGE128_PRO_VR,		sRage128_Pro_VR			},		// PX
133	{ 0x5245, RAGE128_GL,			sRage128_GL				},		// RE
134	{ 0x5246, RAGE128_GL,			sRage128_GL				},		// RF
135	{ 0x5247, RAGE128_GL,			sRage128_GL				},		// RG
136	{ 0x524B, RAGE128_VR,			sRage128_VR				},		// RK
137	{ 0x524C, RAGE128_VR,			sRage128_VR				},		// RL
138	{ 0x5345, RAGE128_VR,			sRage128_VR				},		// SE
139	{ 0x5346, RAGE128_VR,			sRage128_VR				},		// SF
140	{ 0x5347, RAGE128_VR,			sRage128_VR				},		// SG
141	{ 0x5348, RAGE128_VR,			sRage128_VR				},		// SH
142	{ 0x534B, RAGE128_GL,			sRage128_GL				},		// SK
143	{ 0x534C, RAGE128_GL,			sRage128_GL				},		// SL
144	{ 0x534D, RAGE128_GL,			sRage128_GL				},		// SM
145	{ 0x534E, RAGE128_GL,			sRage128_GL				},		// SN
146	{ 0x5446, RAGE128_PRO_ULTRA,	sRage128_Pro_Ultra		},		// TF
147	{ 0x544C, RAGE128_PRO_ULTRA,	sRage128_Pro_Ultra		},		// TL
148	{ 0x5452, RAGE128_PRO_ULTRA,	sRage128_Pro_Ultra		},		// TR
149	{ 0x5453, RAGE128_PRO_ULTRA,	sRage128_Pro_Ultra		},		// TS
150	{ 0x5454, RAGE128_PRO_ULTRA,	sRage128_Pro_Ultra		},		// TT
151	{ 0x5455, RAGE128_PRO_ULTRA,	sRage128_Pro_Ultra		},		// TU
152	{ 0,	  ATI_NONE,				NULL }
153};
154
155
156struct DeviceInfo {
157	uint32			openCount;		// count of how many times device has been opened
158	int32			flags;
159	area_id 		sharedArea;		// area shared between driver and all accelerants
160	SharedInfo* 	sharedInfo;		// pointer to shared info area memory
161	vuint8*	 		regs;			// pointer to memory mapped registers
162	const ChipInfo*	pChipInfo;		// info about the selected chip
163	pci_info		pciInfo;		// copy of pci info for this device
164	char			name[B_OS_NAME_LENGTH]; // name of device
165};
166
167
168static Benaphore		gLock;
169static DeviceInfo		gDeviceInfo[MAX_DEVICES];
170static char*			gDeviceNames[MAX_DEVICES + 1];
171static pci_module_info*	gPCI;
172
173
174// Prototypes for device hook functions.
175
176static status_t device_open(const char* name, uint32 flags, void** cookie);
177static status_t device_close(void* dev);
178static status_t device_free(void* dev);
179static status_t device_read(void* dev, off_t pos, void* buf, size_t* len);
180static status_t device_write(void* dev, off_t pos, const void* buf, size_t* len);
181static status_t device_ioctl(void* dev, uint32 msg, void* buf, size_t len);
182
183static device_hooks gDeviceHooks =
184{
185	device_open,
186	device_close,
187	device_free,
188	device_ioctl,
189	device_read,
190	device_write,
191	NULL,
192	NULL,
193	NULL,
194	NULL
195};
196
197
198
199static inline uint32
200GetPCI(pci_info& info, uint8 offset, uint8 size)
201{
202	return gPCI->read_pci_config(info.bus, info.device, info.function, offset,
203		size);
204}
205
206
207static inline void
208SetPCI(pci_info& info, uint8 offset, uint8 size, uint32 value)
209{
210	gPCI->write_pci_config(info.bus, info.device, info.function, offset, size,
211		value);
212}
213
214
215// Functions for dealing with Vertical Blanking Interrupts.  Currently, I do
216// not know the commands to handle these operations;  thus, these functions
217// currently do nothing.
218
219static bool
220InterruptIsVBI()
221{
222	// return true only if a vertical blanking interrupt has occured
223	return false;
224}
225
226
227static void
228ClearVBI()
229{
230}
231
232static void
233EnableVBI()
234{
235}
236
237static void
238DisableVBI()
239{
240}
241
242
243
244static status_t
245GetEdidFromBIOS(edid1_raw& edidRaw)
246{
247	// Get the EDID info from the video BIOS, and return B_OK if successful.
248
249#define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4)
250#define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf)
251
252	bios_module_info* biosModule;
253	status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule);
254	if (status != B_OK) {
255		TRACE("GetEdidFromBIOS(): failed to get BIOS module: 0x%" B_PRIx32 "\n",
256			status);
257		return status;
258	}
259
260	bios_state* state;
261	status = biosModule->prepare(&state);
262	if (status != B_OK) {
263		TRACE("GetEdidFromBIOS(): bios_prepare() failed: 0x%" B_PRIx32 "\n",
264			status);
265		put_module(B_BIOS_MODULE_NAME);
266		return status;
267	}
268
269	bios_regs regs = {};
270	regs.eax = 0x4f15;
271	regs.ebx = 0;			// 0 = report DDC service
272	regs.ecx = 0;
273	regs.es = 0;
274	regs.edi = 0;
275
276	status = biosModule->interrupt(state, 0x10, &regs);
277	if (status == B_OK) {
278		// AH contains the error code, and AL determines whether or not the
279		// function is supported.
280		if (regs.eax != 0x4f)
281			status = B_NOT_SUPPORTED;
282
283		// Test if DDC is supported by the monitor.
284		if ((regs.ebx & 3) == 0)
285			status = B_NOT_SUPPORTED;
286	}
287
288	if (status == B_OK) {
289		edid1_raw* edid = (edid1_raw*)biosModule->allocate_mem(state,
290			sizeof(edid1_raw));
291		if (edid == NULL) {
292			status = B_NO_MEMORY;
293			goto out;
294		}
295
296		regs.eax = 0x4f15;
297		regs.ebx = 1;		// 1 = read EDID
298		regs.ecx = 0;
299		regs.edx = 0;
300		regs.es  = ADDRESS_SEGMENT(edid);
301		regs.edi = ADDRESS_OFFSET(edid);
302
303		status = biosModule->interrupt(state, 0x10, &regs);
304		if (status == B_OK) {
305			if (regs.eax != 0x4f) {
306				status = B_NOT_SUPPORTED;
307			} else {
308				// Copy the EDID info to the caller's location, and compute the
309				// checksum of the EDID info while copying.
310
311				uint8 sum = 0;
312				uint8 allOr = 0;
313				uint8* dest = (uint8*)&edidRaw;
314				uint8* src = (uint8*)edid;
315
316				for (uint32 j = 0; j < sizeof(edidRaw); j++) {
317					sum += *src;
318					allOr |= *src;
319					*dest++ = *src++;
320				}
321
322				if (allOr == 0) {
323					TRACE("GetEdidFromBIOS(); EDID info contains only zeros\n");
324					status = B_ERROR;
325				} else if (sum != 0) {
326					TRACE("GetEdidFromBIOS(); Checksum error in EDID info\n");
327					status = B_ERROR;
328				}
329			}
330		}
331	}
332
333out:
334	biosModule->finish(state);
335	put_module(B_BIOS_MODULE_NAME);
336	return status;
337}
338
339
340static status_t
341SetVesaDisplayMode(uint16 mode)
342{
343	// Set the VESA display mode, and return B_OK if successful.
344
345#define SET_MODE_MASK				0x01ff
346#define SET_MODE_LINEAR_BUFFER		(1 << 14)
347
348	bios_module_info* biosModule;
349	status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule);
350	if (status != B_OK) {
351		TRACE("SetVesaDisplayMode(0x%x): failed to get BIOS module: 0x%" B_PRIx32
352			"\n", mode, status);
353		return status;
354	}
355
356	bios_state* state;
357	status = biosModule->prepare(&state);
358	if (status != B_OK) {
359		TRACE("SetVesaDisplayMode(0x%x): bios_prepare() failed: 0x%" B_PRIx32
360			"\n", mode, status);
361		put_module(B_BIOS_MODULE_NAME);
362		return status;
363	}
364
365	bios_regs regs = {};
366	regs.eax = 0x4f02;
367	regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER;
368
369	status = biosModule->interrupt(state, 0x10, &regs);
370	if (status != B_OK) {
371		TRACE("SetVesaDisplayMode(0x%x): BIOS interrupt failed\n", mode);
372	}
373
374	if (status == B_OK && (regs.eax & 0xffff) != 0x4f) {
375		TRACE("SetVesaDisplayMode(0x%x): BIOS returned 0x%04" B_PRIx32 "\n",
376			mode, regs.eax & 0xffff);
377		status = B_ERROR;
378	}
379
380	biosModule->finish(state);
381	put_module(B_BIOS_MODULE_NAME);
382	return status;
383}
384
385
386
387// Macros for accessing BIOS info.
388
389#define BIOS8(v)  (romAddr[v])
390#define BIOS16(v) (romAddr[v] | \
391				  (romAddr[(v) + 1] << 8))
392#define BIOS32(v) (romAddr[v] | \
393				  (romAddr[(v) + 1] << 8) | \
394				  (romAddr[(v) + 2] << 16) | \
395				  (romAddr[(v) + 3] << 24))
396
397
398static status_t
399Mach64_GetBiosParameters(DeviceInfo& di, uint8& clockType)
400{
401	// Get some clock parameters from the video BIOS, and if Mobility chip,
402	// also get the LCD panel width & height.
403
404	// In case mapping the ROM area fails or other error occurs, set default
405	// values for the parameters which will be obtained from the BIOS ROM.
406
407	clockType = M64_CLOCK_INTERNAL;
408
409	SharedInfo& si = *(di.sharedInfo);
410	M64_Params& params = si.m64Params;
411	params.clockNumberToProgram = 3;
412
413	si.panelX = 0;
414	si.panelY = 0;
415
416	// Map the ROM area.  The Mach64 chips do not assign a ROM address in the
417	// PCI info;  thus, access the ROM via the ISA legacy memory map.
418
419	uint8* romAddr;
420	area_id romArea = map_physical_memory("ATI Mach64 ROM",
421#if defined(__x86__) || defined(__x86_64__)
422		0x000c0000,
423#else
424		di.pciInfo.u.h0.rom_base,
425#endif
426		M64_BIOS_SIZE,
427		B_ANY_KERNEL_ADDRESS,
428		B_KERNEL_READ_AREA,
429		(void**)&(romAddr));
430
431	if (romArea < 0) {
432		TRACE("Mach64_GetBiosParameters(), ROM mapping error: %" B_PRId32 "\n",
433			romArea);
434		return romArea;		// ROM mapping failed; return error code
435	}
436
437	// Check if we have the BIOS signature (might fail on laptops..).
438
439	if (BIOS8(0) != 0x55 || BIOS8(1) != 0xaa) {
440		TRACE("Mach64_GetBiosParameters(), ROM does not contain BIOS signature\n");
441		delete_area(romArea);
442		return B_ERROR;
443	}
444
445	// Get clock info from BIOS.
446
447	uint32 romTable = BIOS16(0x48);
448	uint32 clockTable = BIOS16(romTable + 16);
449	clockType = BIOS8(clockTable);
450	params.clockNumberToProgram = BIOS8(clockTable + 6);
451	params.maxPixelClock = BIOS16(clockTable + 4) * 10;
452	params.refFreq = BIOS16(clockTable + 8);
453	params.refDivider = BIOS16(clockTable + 10);
454
455	// If Mobility chip, get the LCD panel width & height.
456
457	if (si.chipType == MACH64_MOBILITY) {
458		uint32 lcdTable = BIOS16(0x78);
459		if (BIOS32(lcdTable) == 0x544d5224) {	// is LCD table signature correct?
460			uint32 lcdPanelInfo = BIOS16(lcdTable + 10);
461			si.panelX = BIOS16(lcdPanelInfo + 25);
462			si.panelY = BIOS16(lcdPanelInfo + 27);
463			TRACE("Mobility LCD Panel size: %dx%d\n", si.panelX, si.panelY);
464		} else {
465			TRACE("Mobility LCD table signature 0x%x in BIOS is incorrect\n",
466				 BIOS32(lcdTable));
467		}
468	}
469
470	delete_area(romArea);
471
472	return B_OK;
473}
474
475
476
477static status_t
478Rage128_GetBiosParameters(DeviceInfo& di)
479{
480	// Get the PLL parameters from the video BIOS, and if Mobility chips, also
481	// get the LCD panel width & height and a few other related parameters.
482
483	// In case mapping the ROM area fails or other error occurs, set default
484	// values for the parameters which will be obtained from the BIOS ROM.
485	// The default PLL parameters values probably will not work for all chips.
486	// For example, reference freq can be 29.50MHz, 28.63MHz, or 14.32MHz.
487
488	SharedInfo& si = *(di.sharedInfo);
489	R128_PLLParams& pll = si.r128PLLParams;
490	pll.reference_freq = 2950;
491	pll.reference_div = 65;
492	pll.min_pll_freq = 12500;
493	pll.max_pll_freq = 25000;
494	pll.xclk = 10300;
495
496	si.panelX = 0;
497	si.panelY = 0;
498	si.panelPowerDelay = 1;
499
500	// Map the ROM area.  The Rage128 chips do not assign a ROM address in the
501	// PCI info;  thus, access the ROM via the ISA legacy memory map.
502
503	uint8* romAddr;
504	area_id romArea = map_physical_memory("ATI Rage128 ROM",
505#if defined(__x86__) || defined(__x86_64__)
506		0x000c0000,
507#else
508		di.pciInfo.u.h0.rom_base,
509#endif
510		R128_BIOS_SIZE,
511		B_ANY_KERNEL_ADDRESS,
512		B_KERNEL_READ_AREA,
513		(void**)&(romAddr));
514
515	if (romArea < 0) {
516		TRACE("Rage128_GetBiosParameters(), ROM mapping error: %" B_PRId32
517			"\n", romArea);
518		return romArea;		// ROM mapping failed; return error code
519	}
520
521	// Check if we got the BIOS signature (might fail on laptops..).
522
523	if (BIOS8(0) != 0x55 || BIOS8(1) != 0xaa) {
524		TRACE("Rage128_GetBiosParameters(), ROM does not contain BIOS signature\n");
525		delete_area(romArea);
526		return B_ERROR;
527	}
528
529	// Get the PLL values from the mapped ROM area.
530
531	uint16 biosHeader = BIOS16(0x48);
532	uint16 pllInfoBlock = BIOS16(biosHeader + 0x30);
533
534	pll.reference_freq = BIOS16(pllInfoBlock + 0x0e);
535	pll.reference_div = BIOS16(pllInfoBlock + 0x10);
536	pll.min_pll_freq = BIOS32(pllInfoBlock + 0x12);
537	pll.max_pll_freq = BIOS32(pllInfoBlock + 0x16);
538	pll.xclk = BIOS16(pllInfoBlock + 0x08);
539
540	TRACE("PLL parameters: rf=%d rd=%d min=%" B_PRId32 " max=%" B_PRId32
541		"; xclk=%d\n",
542		pll.reference_freq, pll.reference_div, pll.min_pll_freq,
543		pll.max_pll_freq, pll.xclk);
544
545	// If Mobility chip, get the LCD panel width & height and a few other
546	// related parameters.
547
548	if (si.chipType == RAGE128_MOBILITY) {
549		// There should be direct access to the start of the FP info table, but
550		// until we find out where that offset is stored, we must search for
551		// the ATI signature string: "M3      ".
552
553		int i;
554		for (i = 4; i < R128_BIOS_SIZE - 8; i++) {
555			if (BIOS8(i) == 'M' &&
556					BIOS8(i + 1) == '3' &&
557					BIOS8(i + 2) == ' ' &&
558					BIOS8(i + 3) == ' ' &&
559					BIOS8(i + 4) == ' ' &&
560					BIOS8(i + 5) == ' ' &&
561					BIOS8(i + 6) == ' ' &&
562					BIOS8(i + 7) == ' ') {
563				int fpHeader = i - 2;
564
565				// Assume that only one panel is attached and supported.
566
567				for (i = fpHeader + 20; i < fpHeader + 84; i += 2) {
568					if (BIOS16(i) != 0) {
569						int fpStart = BIOS16(i);
570						si.panelX = BIOS16(fpStart + 25);
571						si.panelY = BIOS16(fpStart + 27);
572						si.panelPowerDelay = BIOS8(fpStart + 56);
573						TRACE("LCD Panel size: %dx%d  Panel type: 0x%x   power delay: %d\n",
574							si.panelX, si.panelY, BIOS16(fpStart + 29),
575							si.panelPowerDelay);
576						break;
577					}
578				}
579
580				break;
581			}
582		}
583	}
584
585	delete_area(romArea);
586
587	return B_OK;
588}
589
590
591static status_t
592MapDevice(DeviceInfo& di)
593{
594	SharedInfo& si = *(di.sharedInfo);
595	pci_info& pciInfo = di.pciInfo;
596
597	// Enable memory mapped IO and bus master.
598
599	SetPCI(pciInfo, PCI_command, 2, GetPCI(pciInfo, PCI_command, 2)
600		| PCI_command_io | PCI_command_memory | PCI_command_master);
601
602	// Enable ROM decoding
603
604	if (di.pciInfo.u.h0.rom_size > 0) {
605		SetPCI(pciInfo, PCI_rom_base, 4,
606			GetPCI(pciInfo, PCI_rom_base, 4) | 0x00000001);
607	}
608
609	// Map the video memory.
610
611	phys_addr_t videoRamAddr = pciInfo.u.h0.base_registers[0];
612	uint32 videoRamSize = pciInfo.u.h0.base_register_sizes[0];
613	si.videoMemPCI = videoRamAddr;
614	char frameBufferAreaName[] = "ATI frame buffer";
615
616	si.videoMemArea = map_physical_memory(
617		frameBufferAreaName,
618		videoRamAddr,
619		videoRamSize,
620		B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC,
621		B_READ_AREA + B_WRITE_AREA,
622		(void**)&(si.videoMemAddr));
623
624	if (si.videoMemArea < 0) {
625		// Try to map this time without write combining.
626		si.videoMemArea = map_physical_memory(
627			frameBufferAreaName,
628			videoRamAddr,
629			videoRamSize,
630			B_ANY_KERNEL_BLOCK_ADDRESS,
631			B_READ_AREA + B_WRITE_AREA,
632			(void**)&(si.videoMemAddr));
633	}
634
635	if (si.videoMemArea < 0)
636		return si.videoMemArea;
637
638	// Map the MMIO register area.
639
640	phys_addr_t regsBase = pciInfo.u.h0.base_registers[2];
641	uint32 regAreaSize = pciInfo.u.h0.base_register_sizes[2];
642
643	// If the register area address or size is not in the PCI info, it should
644	// be at the end of the video memory.  Check if it is there.
645
646	if (MACH64_FAMILY(si.chipType) && (regsBase == 0 || regAreaSize == 0)) {
647		uint32 regsOffset = 0x7ff000;	// offset to regs area in video memory
648		addr_t regs = addr_t(si.videoMemAddr) + regsOffset;
649		uint32 chipInfo = *((vuint32*)(regs + M64_CONFIG_CHIP_ID));
650
651		if (si.deviceID != (chipInfo & M64_CFG_CHIP_TYPE)) {
652			// Register area not found;  delete any other areas that were
653			// created.
654			delete_area(si.videoMemArea);
655			si.videoMemArea = -1;
656			TRACE("Mach64 register area not found\n");
657			return B_ERROR;
658		}
659
660		// Adjust params for creating register area below.
661
662		regsBase = videoRamAddr + regsOffset;
663		regAreaSize = 0x1000;
664		TRACE("Register address is at end of frame buffer memory at 0x%"
665			B_PRIxPHYSADDR "\n", regsBase);
666	}
667
668	si.regsArea = map_physical_memory("ATI mmio registers",
669		regsBase,
670		regAreaSize,
671		B_ANY_KERNEL_ADDRESS,
672		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_CLONEABLE_AREA,
673		(void**)&di.regs);
674
675	// If there was an error, delete other areas.
676	if (si.regsArea < 0) {
677		delete_area(si.videoMemArea);
678		si.videoMemArea = -1;
679	}
680
681	return si.regsArea;
682}
683
684
685static void
686UnmapDevice(DeviceInfo& di)
687{
688	SharedInfo& si = *(di.sharedInfo);
689
690	if (si.regsArea >= 0)
691		delete_area(si.regsArea);
692	if (si.videoMemArea >= 0)
693		delete_area(si.videoMemArea);
694
695	si.regsArea = si.videoMemArea = -1;
696	si.videoMemAddr = (addr_t)NULL;
697	di.regs = NULL;
698}
699
700
701static int32
702InterruptHandler(void* data)
703{
704	int32 handled = B_UNHANDLED_INTERRUPT;
705	DeviceInfo& di = *((DeviceInfo*)data);
706	int32* flags = &(di.flags);
707
708	// Is someone already handling an interrupt for this device?
709	if (atomic_or(flags, SKD_HANDLER_INSTALLED) & SKD_HANDLER_INSTALLED)
710		return B_UNHANDLED_INTERRUPT;
711
712	if (InterruptIsVBI()) {	// was interrupt a VBI?
713		ClearVBI();			// clear interrupt
714
715		handled = B_HANDLED_INTERRUPT;
716
717		// Release vertical blanking semaphore.
718		sem_id& sem = di.sharedInfo->vertBlankSem;
719
720		if (sem >= 0) {
721			int32 blocked;
722			if ((get_sem_count(sem, &blocked) == B_OK) && (blocked < 0)) {
723				release_sem_etc(sem, -blocked, B_DO_NOT_RESCHEDULE);
724				handled = B_INVOKE_SCHEDULER;
725			}
726		}
727	}
728
729	atomic_and(flags, ~SKD_HANDLER_INSTALLED);	// note we're not in handler anymore
730
731	return handled;
732}
733
734
735static void
736InitInterruptHandler(DeviceInfo& di)
737{
738	SharedInfo& si = *(di.sharedInfo);
739
740	DisableVBI();					// disable & clear any pending interrupts
741	si.bInterruptAssigned = false;	// indicate interrupt not assigned yet
742
743	// Create a semaphore for vertical blank management.
744	si.vertBlankSem = create_sem(0, di.name);
745	if (si.vertBlankSem < 0)
746		return;
747
748	// Change the owner of the semaphores to the calling team (usually the
749	// app_server).  This is required because apps can't aquire kernel
750	// semaphores.
751
752	thread_id threadID = find_thread(NULL);
753	thread_info threadInfo;
754	status_t status = get_thread_info(threadID, &threadInfo);
755	if (status == B_OK)
756		status = set_sem_owner(si.vertBlankSem, threadInfo.team);
757
758	// If there is a valid interrupt assigned, set up interrupts.
759
760	if (status == B_OK && di.pciInfo.u.h0.interrupt_pin != 0x00
761		&& di.pciInfo.u.h0.interrupt_line != 0xff) {
762		// We have a interrupt line to use.
763
764		status = install_io_interrupt_handler(di.pciInfo.u.h0.interrupt_line,
765			InterruptHandler, (void*)(&di), 0);
766
767		if (status == B_OK)
768			si.bInterruptAssigned = true;	// we can use interrupt related functions
769	}
770
771	if (status != B_OK) {
772		// Interrupt does not exist; thus delete semaphore as it won't be used.
773		delete_sem(si.vertBlankSem);
774		si.vertBlankSem = -1;
775	}
776}
777
778
779static status_t
780InitDevice(DeviceInfo& di)
781{
782	// Perform initialization and mapping of the device, and return B_OK if
783	// sucessful;  else, return error code.
784
785	// Get the table of VESA modes that the chip supports.  Note that we will
786	// need this table only for chips that are currently connected to a laptop
787	// display or a monitor connected via a DVI interface.
788
789	size_t vesaModeTableSize = 0;
790	VesaMode* vesaModes = (VesaMode*)get_boot_item(VESA_MODES_BOOT_INFO,
791		&vesaModeTableSize);
792
793	size_t sharedSize = (sizeof(SharedInfo) + 7) & ~7;
794
795	// Create the area for shared info with NO user-space read or write
796	// permissions, to prevent accidental damage.
797
798	di.sharedArea = create_area("ATI shared info",
799		(void**) &(di.sharedInfo),
800		B_ANY_KERNEL_ADDRESS,
801		ROUND_TO_PAGE_SIZE(sharedSize + vesaModeTableSize),
802		B_FULL_LOCK,
803		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_CLONEABLE_AREA);
804	if (di.sharedArea < 0)
805		return di.sharedArea;	// return error code
806
807	SharedInfo& si = *(di.sharedInfo);
808
809	memset(&si, 0, sharedSize);
810
811	if (vesaModes != NULL) {
812		si.vesaModeTableOffset = sharedSize;
813		si.vesaModeCount = vesaModeTableSize / sizeof(VesaMode);
814
815		memcpy((uint8*)&si + si.vesaModeTableOffset, vesaModes,
816			vesaModeTableSize);
817	}
818
819	pci_info& pciInfo = di.pciInfo;
820
821	si.vendorID = pciInfo.vendor_id;
822	si.deviceID = pciInfo.device_id;
823	si.revision = pciInfo.revision;
824	si.chipType = di.pChipInfo->chipType;
825	strcpy(si.chipName, di.pChipInfo->chipName);
826
827	TRACE("Chip revision: 0x%x\n", si.revision);
828
829	// 264GT has two chip versions.  If version is non-zero, chip is 264GTB.
830
831	if (si.chipType == MACH64_264GT && si.revision & 0x7)
832		si.chipType = MACH64_264GTB;
833
834	// 264VT has two chip versions.  If version is non-zero, chip is 264VTB.
835
836	if (si.chipType == MACH64_264VT && si.revision & 0x7)
837		si.chipType = MACH64_264VTB;
838
839	status_t status = MapDevice(di);
840
841	// If device mapped without any error, get the bios parameters from the
842	// chip's BIOS ROM.
843
844	if (status >= 0) {
845		if (MACH64_FAMILY(si.chipType)) {
846			uint8 clockType;
847			Mach64_GetBiosParameters(di, clockType);
848
849			// All chips supported by this driver should have an internal clock.
850			// If the clock is not an internal clock, the video chip is not
851			// supported.
852
853			if (clockType != M64_CLOCK_INTERNAL) {
854				TRACE("Video chip clock type %d not supported\n", clockType);
855				status = B_UNSUPPORTED;
856			}
857		}
858		else if (RAGE128_FAMILY(si.chipType))
859			Rage128_GetBiosParameters(di);
860	}
861
862	if (status < 0) {
863		delete_area(di.sharedArea);
864		di.sharedArea = -1;
865		di.sharedInfo = NULL;
866		return status;		// return error code
867	}
868
869	InitInterruptHandler(di);
870
871	TRACE("Interrupt assigned:  %s\n", si.bInterruptAssigned ? "yes" : "no");
872	return B_OK;
873}
874
875
876static const ChipInfo*
877GetNextSupportedDevice(uint32& pciIndex, pci_info& pciInfo)
878{
879	// Search the PCI devices for a device that is supported by this driver.
880	// The search starts at the device specified by argument pciIndex, and
881	// continues until a supported device is found or there are no more devices
882	// to examine.  Argument pciIndex is incremented after each device is
883	// examined.
884
885	// If a supported device is found, return a pointer to the struct containing
886	// the chip info; else return NULL.
887
888	while (gPCI->get_nth_pci_info(pciIndex, &pciInfo) == B_OK) {
889
890		if (pciInfo.vendor_id == VENDOR_ID) {
891
892			// Search the table of supported devices to find a chip/device that
893			// matches device ID of the current PCI device.
894
895			const ChipInfo* pDevice = chipTable;
896
897			while (pDevice->chipID != 0) {	// end of table?
898				if (pDevice->chipID == pciInfo.device_id) {
899					// Matching device/chip found.  If chip is 264VT, reject it
900					// if its version is zero since the mode can not be set on
901					// that chip.
902
903					if (pDevice->chipType == MACH64_264VT
904							&& (pciInfo.revision & 0x7) == 0)
905						break;
906
907					return pDevice;		// matching device/chip found
908				}
909
910				pDevice++;
911			}
912		}
913
914		pciIndex++;
915	}
916
917	return NULL;		// no supported device found
918}
919
920
921
922//	#pragma mark - Kernel Interface
923
924
925status_t
926init_hardware(void)
927{
928	// Return B_OK if a device supported by this driver is found; otherwise,
929	// return B_ERROR so the driver will be unloaded.
930
931	if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI) != B_OK)
932		return B_ERROR;		// unable to access PCI bus
933
934	// Check pci devices for a device supported by this driver.
935
936	uint32 pciIndex = 0;
937	pci_info pciInfo;
938	const ChipInfo* pDevice = GetNextSupportedDevice(pciIndex, pciInfo);
939
940	TRACE("init_hardware() - %s\n",
941		pDevice == NULL ? "no supported devices" : "device supported");
942
943	put_module(B_PCI_MODULE_NAME);		// put away the module manager
944
945	return (pDevice == NULL ? B_ERROR : B_OK);
946}
947
948
949status_t
950init_driver(void)
951{
952	// Get handle for the pci bus.
953
954	if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI) != B_OK)
955		return B_ERROR;
956
957	status_t status = gLock.Init("ATI driver lock");
958	if (status < B_OK)
959		return status;
960
961	// Get info about all the devices supported by this driver.
962
963	uint32 pciIndex = 0;
964	uint32 count = 0;
965
966	while (count < MAX_DEVICES) {
967		DeviceInfo& di = gDeviceInfo[count];
968
969		const ChipInfo* pDevice = GetNextSupportedDevice(pciIndex, di.pciInfo);
970		if (pDevice == NULL)
971			break;			// all supported devices have been obtained
972
973		// Compose device name.
974		sprintf(di.name, "graphics/" DEVICE_FORMAT,
975				  di.pciInfo.vendor_id, di.pciInfo.device_id,
976				  di.pciInfo.bus, di.pciInfo.device, di.pciInfo.function);
977		TRACE("init_driver() match found; name: %s\n", di.name);
978
979		gDeviceNames[count] = di.name;
980		di.openCount = 0;		// mark driver as available for R/W open
981		di.sharedArea = -1;		// indicate shared area not yet created
982		di.sharedInfo = NULL;
983		di.pChipInfo = pDevice;
984		count++;
985		pciIndex++;
986	}
987
988	gDeviceNames[count] = NULL;	// terminate list with null pointer
989
990	TRACE("init_driver() %" B_PRIu32 " supported devices\n", count);
991
992	return B_OK;
993}
994
995
996void
997uninit_driver(void)
998{
999	// Free the driver data.
1000
1001	gLock.Delete();
1002	put_module(B_PCI_MODULE_NAME);	// put the pci module away
1003}
1004
1005
1006const char**
1007publish_devices(void)
1008{
1009	return (const char**)gDeviceNames;	// return list of supported devices
1010}
1011
1012
1013device_hooks*
1014find_device(const char* name)
1015{
1016	int i = 0;
1017	while (gDeviceNames[i] != NULL) {
1018		if (strcmp(name, gDeviceNames[i]) == 0)
1019			return &gDeviceHooks;
1020		i++;
1021	}
1022
1023	return NULL;
1024}
1025
1026
1027
1028//	#pragma mark - Device Hooks
1029
1030
1031static status_t
1032device_open(const char* name, uint32 /*flags*/, void** cookie)
1033{
1034	status_t status = B_OK;
1035
1036	TRACE("device_open() - name: %s\n", name);
1037
1038	// Find the device name in the list of devices.
1039
1040	int32 i = 0;
1041	while (gDeviceNames[i] != NULL && (strcmp(name, gDeviceNames[i]) != 0))
1042		i++;
1043
1044	if (gDeviceNames[i] == NULL)
1045		return B_BAD_VALUE;		// device name not found in list of devices
1046
1047	DeviceInfo& di = gDeviceInfo[i];
1048
1049	gLock.Acquire();	// make sure no one else has write access to common data
1050
1051	if (di.openCount == 0)
1052		status = InitDevice(di);
1053
1054	gLock.Release();
1055
1056	if (status == B_OK) {
1057		di.openCount++;		// mark device open
1058		*cookie = &di;		// send cookie to opener
1059	}
1060
1061	TRACE("device_open() returning 0x%" B_PRIx32 ",  open count: %" B_PRIu32 "\n", status,
1062		di.openCount);
1063	return status;
1064}
1065
1066
1067static status_t
1068device_read(void* dev, off_t pos, void* buf, size_t* len)
1069{
1070	// Following 3 lines of code are here to eliminate "unused parameter"
1071	// warnings.
1072	(void)dev;
1073	(void)pos;
1074	(void)buf;
1075
1076	*len = 0;
1077	return B_NOT_ALLOWED;
1078}
1079
1080
1081static status_t
1082device_write(void* dev, off_t pos, const void* buf, size_t* len)
1083{
1084	// Following 3 lines of code are here to eliminate "unused parameter"
1085	// warnings.
1086	(void)dev;
1087	(void)pos;
1088	(void)buf;
1089
1090	*len = 0;
1091	return B_NOT_ALLOWED;
1092}
1093
1094
1095static status_t
1096device_close(void* dev)
1097{
1098	(void)dev;		// avoid compiler warning for unused arg
1099
1100	return B_NO_ERROR;
1101}
1102
1103
1104static status_t
1105device_free(void* dev)
1106{
1107	DeviceInfo& di = *((DeviceInfo*)dev);
1108	SharedInfo& si = *(di.sharedInfo);
1109	pci_info& pciInfo = di.pciInfo;
1110
1111	TRACE("enter device_free()\n");
1112
1113	gLock.Acquire();		// lock driver
1114
1115	// If opened multiple times, merely decrement the open count and exit.
1116
1117	if (di.openCount <= 1) {
1118		DisableVBI();		// disable & clear any pending interrupts
1119
1120		if (si.bInterruptAssigned) {
1121			remove_io_interrupt_handler(pciInfo.u.h0.interrupt_line,
1122				InterruptHandler, &di);
1123		}
1124
1125		// Delete the semaphores, ignoring any errors because the owning team
1126		// may have died.
1127		if (si.vertBlankSem >= 0)
1128			delete_sem(si.vertBlankSem);
1129		si.vertBlankSem = -1;
1130
1131		UnmapDevice(di);	// free regs and frame buffer areas
1132
1133		delete_area(di.sharedArea);
1134		di.sharedArea = -1;
1135		di.sharedInfo = NULL;
1136	}
1137
1138	if (di.openCount > 0)
1139		di.openCount--;		// mark device available
1140
1141	gLock.Release();	// unlock driver
1142
1143	TRACE("exit device_free() openCount: %" B_PRIu32 "\n", di.openCount);
1144	return B_OK;
1145}
1146
1147
1148static status_t
1149device_ioctl(void* dev, uint32 msg, void* buffer, size_t bufferLength)
1150{
1151	DeviceInfo& di = *((DeviceInfo*)dev);
1152
1153	TRACE("device_ioctl(); ioctl: %" B_PRIu32 ", buffer: %#08" B_PRIxADDR
1154		", bufLen: %" B_PRIuSIZE "\n", msg, (addr_t)buffer, bufferLength);
1155
1156	switch (msg) {
1157		case B_GET_ACCELERANT_SIGNATURE:
1158		{
1159			status_t status = user_strlcpy((char*)buffer, ATI_ACCELERANT_NAME,
1160				bufferLength);
1161			if (status < B_OK)
1162				return status;
1163
1164			return B_OK;
1165		}
1166
1167		case ATI_DEVICE_NAME:
1168		{
1169			status_t status = user_strlcpy((char*)buffer, di.name,
1170				B_OS_NAME_LENGTH);
1171			if (status < B_OK)
1172				return status;
1173
1174			return B_OK;
1175		}
1176
1177		case ATI_GET_SHARED_DATA:
1178			if (bufferLength != sizeof(area_id))
1179				return B_BAD_DATA;
1180
1181			return user_memcpy(buffer, &di.sharedArea, sizeof(area_id));
1182
1183		case ATI_GET_EDID:
1184		{
1185			if (bufferLength != sizeof(edid1_raw))
1186				return B_BAD_DATA;
1187
1188			edid1_raw rawEdid;
1189			status_t status = GetEdidFromBIOS(rawEdid);
1190			if (status != B_OK)
1191				return status;
1192
1193			return user_memcpy((edid1_raw*)buffer, &rawEdid, sizeof(rawEdid));
1194		}
1195
1196		case ATI_SET_VESA_DISPLAY_MODE:
1197		{
1198			if (bufferLength != sizeof(uint16))
1199				return B_BAD_DATA;
1200
1201			uint16 value;
1202			status_t status = user_memcpy(&value, buffer, sizeof(uint16));
1203			if (status < B_OK)
1204				return status;
1205
1206			return SetVesaDisplayMode(value);
1207		}
1208
1209		case ATI_RUN_INTERRUPTS:
1210		{
1211			if (bufferLength != sizeof(bool))
1212				return B_BAD_DATA;
1213
1214			bool value;
1215			status_t res = user_memcpy(&value, buffer, sizeof(bool));
1216			if (res < B_OK)
1217				return res;
1218
1219			if (value)
1220				EnableVBI();
1221			else
1222				DisableVBI();
1223
1224			return B_OK;
1225		}
1226	}
1227
1228	return B_DEV_INVALID_IOCTL;
1229}
1230