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
43 int32 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
53 struct 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
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
GetPCI(pci_info & info,uint8 offset,uint8 size)200 GetPCI(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
207 static inline void
SetPCI(pci_info & info,uint8 offset,uint8 size,uint32 value)208 SetPCI(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
219 static bool
InterruptIsVBI()220 InterruptIsVBI()
221 {
222 // return true only if a vertical blanking interrupt has occured
223 return false;
224 }
225
226
227 static void
ClearVBI()228 ClearVBI()
229 {
230 }
231
232 static void
EnableVBI()233 EnableVBI()
234 {
235 }
236
237 static void
DisableVBI()238 DisableVBI()
239 {
240 }
241
242
243
244 static status_t
GetEdidFromBIOS(edid1_raw & edidRaw)245 GetEdidFromBIOS(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, ®s);
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, ®s);
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
333 out:
334 biosModule->finish(state);
335 put_module(B_BIOS_MODULE_NAME);
336 return status;
337 }
338
339
340 static status_t
SetVesaDisplayMode(uint16 mode)341 SetVesaDisplayMode(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, ®s);
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
398 static status_t
Mach64_GetBiosParameters(DeviceInfo & di,uint8 & clockType)399 Mach64_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
477 static status_t
Rage128_GetBiosParameters(DeviceInfo & di)478 Rage128_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
591 static status_t
MapDevice(DeviceInfo & di)592 MapDevice(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_WRITE_COMBINING_MEMORY,
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
685 static void
UnmapDevice(DeviceInfo & di)686 UnmapDevice(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
701 static int32
InterruptHandler(void * data)702 InterruptHandler(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
735 static void
InitInterruptHandler(DeviceInfo & di)736 InitInterruptHandler(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
779 static status_t
InitDevice(DeviceInfo & di)780 InitDevice(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
876 static const ChipInfo*
GetNextSupportedDevice(uint32 & pciIndex,pci_info & pciInfo)877 GetNextSupportedDevice(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
925 status_t
init_hardware(void)926 init_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
949 status_t
init_driver(void)950 init_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
996 void
uninit_driver(void)997 uninit_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
1006 const char**
publish_devices(void)1007 publish_devices(void)
1008 {
1009 return (const char**)gDeviceNames; // return list of supported devices
1010 }
1011
1012
1013 device_hooks*
find_device(const char * name)1014 find_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
1031 static status_t
device_open(const char * name,uint32,void ** cookie)1032 device_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
1067 static status_t
device_read(void * dev,off_t pos,void * buf,size_t * len)1068 device_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
1081 static status_t
device_write(void * dev,off_t pos,const void * buf,size_t * len)1082 device_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
1095 static status_t
device_close(void * dev)1096 device_close(void* dev)
1097 {
1098 (void)dev; // avoid compiler warning for unused arg
1099
1100 return B_NO_ERROR;
1101 }
1102
1103
1104 static status_t
device_free(void * dev)1105 device_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
1148 static status_t
device_ioctl(void * dev,uint32 msg,void * buffer,size_t bufferLength)1149 device_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