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