xref: /haiku/src/add-ons/accelerants/matrox/engine/mga_info.c (revision 5d9e40fe9252c8f9c5e5e41594545bfa4419fcc7)
1 /* Read initialisation information from card */
2 /* some bits are hacks, where PINS is not known */
3 /* Authors:
4    Mark Watson 2/2000,
5    Rudolf Cornelissen 10/2002-1/2004
6 */
7 
8 #define MODULE_BIT 0x00002000
9 
10 #include "mga_std.h"
11 
12 /* Parse the BIOS PINS structure if there */
13 status_t parse_pins ()
14 {
15 	uint8 pins_len = 0;
16 	uint8 *rom;
17 	uint8 *pins;
18 	uint8 chksum = 0;
19 	int i;
20 	status_t result = B_ERROR;
21 
22 	/* preset PINS read status to failed */
23 	si->ps.pins_status = B_ERROR;
24 
25 	/* check the validity of PINS */
26 	LOG(2,("INFO: Reading PINS info\n"));
27 	rom = (uint8 *) si->rom_mirror;
28 	/* check BIOS signature */
29 	if (rom[0]!=0x55 || rom[1]!=0xaa)
30 	{
31 		LOG(8,("INFO: BIOS signiture not found\n"));
32 		return B_ERROR;
33 	}
34 	LOG(2,("INFO: BIOS signiture $AA55 found OK\n"));
35 	/* check for a valid PINS struct adress */
36 	pins = rom + (rom[0x7FFC]|(rom[0x7FFD]<<8));
37 	if ((pins - rom) > 0x7F80)
38 	{
39 		LOG(8,("INFO: invalid PINS adress\n"));
40 		return B_ERROR;
41 	}
42 	/* checkout new PINS struct version if there */
43 	if ((pins[0] == 0x2E) && (pins[1] == 0x41))
44 	{
45 		pins_len = pins[2];
46 		if (pins_len < 3 || pins_len > 128)
47 		{
48 			LOG(8,("INFO: invalid PINS size\n"));
49 			return B_ERROR;
50 		}
51 
52 		/* calculate PINS checksum */
53 		for (i = 0; i < pins_len; i++)
54 		{
55 			chksum += pins[i];
56 		}
57 		if (chksum)
58 		{
59 			LOG(8,("INFO: PINS checksum error\n"));
60 			return B_ERROR;
61 		}
62 		LOG(2,("INFO: new PINS, version %u.%u, length %u\n", pins[5], pins[4], pins[2]));
63 		/* fill out the si->ps struct if possible */
64 		switch (pins[5])
65 		{
66 			case 2:
67 				result = pins2_read(pins, pins_len);
68 				break;
69 			case 3:
70 				result = pins3_read(pins, pins_len);
71 				break;
72 			case 4:
73 				result = pins4_read(pins, pins_len);
74 				break;
75 			case 5:
76 				result = pins5_read(pins, pins_len);
77 				break;
78 			default:
79 				LOG(8,("INFO: unknown PINS version\n"));
80 				return B_ERROR;
81 				break;
82 		}
83 	}
84 	/* checkout old 64 byte PINS struct version if there */
85 	else if ((pins[0] == 0x40) && (pins[1] == 0x00))
86 	{
87 		pins_len = 0x40;
88 		/* this PINS version has no checksum */
89 
90 		LOG(2,("INFO: old PINS found\n"));
91 		/* fill out the si->ps struct */
92 		result = pins1_read(pins, pins_len);
93 	}
94 	/* no valid PINS signature found */
95 	else
96 	{
97 		LOG(8,("INFO: no PINS signature found\n"));
98 		return B_ERROR;
99 	}
100 	/* check PINS read result */
101 	if (result == B_ERROR)
102 	{
103 		LOG(8,("INFO: PINS read/decode error\n"));
104 		return B_ERROR;
105 	}
106 	/* PINS scan succeeded */
107 	si->ps.pins_status = B_OK;
108 	LOG(2,("INFO: PINS scan completed succesfully\n"));
109 	return B_OK;
110 }
111 
112 status_t pins1_read(uint8 *pins, uint8 length)
113 {
114 	if (length != 64)
115 	{
116 		LOG(8,("INFO: wrong PINS length, expected 64, got %d\n", length));
117 		return B_ERROR;
118 	}
119 
120 //reset all for test:
121 //float:
122 	si->ps.f_ref = 0;
123 //uint32:
124 	si->ps.max_system_vco = 0;
125 	si->ps.min_system_vco = 0;
126 	si->ps.min_pixel_vco = 0;
127 	si->ps.min_video_vco = 0;
128 	si->ps.std_engine_clock_dh = 0;
129 	si->ps.max_dac1_clock_32 = 0;
130 	si->ps.max_dac1_clock_32dh = 0;
131 	si->ps.memory_size = 0;
132 	si->ps.mctlwtst_reg = 0;
133 	si->ps.memrdbk_reg = 0;
134 	si->ps.option2_reg = 0;
135 	si->ps.option3_reg = 0;
136 	si->ps.option4_reg = 0;
137 //uint8:
138 	si->ps.v3_option2_reg = 0;
139 	si->ps.v3_clk_div = 0;
140 	si->ps.v3_mem_type = 0;
141 //uint16:
142 	si->ps.v5_mem_type = 0;
143 //bools:
144 	si->ps.secondary_head = false;
145 	si->ps.secondary_tvout = false;
146 	si->ps.primary_dvi = false;
147 	si->ps.secondary_dvi = false;
148 	si->ps.sdram = true;
149 
150 //experimental: checkout!
151 	si->ps.max_dac1_clock_32 = pins[22];//ramdac
152 	si->ps.max_pixel_vco = (pins[25] << 8) | pins[24];//PCLK
153 	si->ps.std_engine_clock = (pins[29] << 8) | pins[28];
154 	if ((uint32)((pins[31] << 8) | pins[30]) < si->ps.std_engine_clock)
155 		si->ps.std_engine_clock = (pins[31] << 8) | pins[30];
156 	if ((uint32)((pins[33] << 8) | pins[32]) < si->ps.std_engine_clock)
157 		si->ps.std_engine_clock = (pins[33] << 8) | pins[32];
158 
159 //temp. test to see some vals..
160 	si->ps.max_video_vco = (pins[27] << 8) | pins[26];//LCLK
161 	//feature flags:
162 	si->ps.option_reg = (pins[53] << 24) | (pins[52] << 16) | (pins[51] << 8) | pins [50];
163 
164 	si->ps.max_dac2_clock = (pins[35] << 8) | pins[34];//clkmod
165 	si->ps.max_dac2_clock_8 = (pins[37] << 8) | pins[36];//testclk
166 	si->ps.max_dac2_clock_16 = (pins[39] << 8) | pins[38];//vgafreq1
167 	si->ps.max_dac2_clock_24 = (pins[41] << 8) | pins[40];//vgafreq2
168 	si->ps.max_dac2_clock_32 = (pins[55] << 8) | pins[54];//vga clock
169 	si->ps.max_dac2_clock_32dh = pins[58];//vid ctrl
170 
171 	si->ps.max_dac1_clock = (pins[29] << 8) | pins[28];//clkbase
172 	si->ps.max_dac1_clock_8 = (pins[31] << 8) | pins[30];//4mb
173 	si->ps.max_dac1_clock_16 = (pins[33] << 8) | pins[32];//8mb
174 	si->ps.max_dac1_clock_24 = pins[23];//ramdac type
175 
176 //test! Don't actually use the reported settings for now...
177 	return B_OK;
178 }
179 
180 status_t pins2_read(uint8 *pins, uint8 length)
181 {
182 	if (length != 64)
183 	{
184 		LOG(8,("INFO: wrong PINS length, expected 64, got %d\n", length));
185 		return B_ERROR;
186 	}
187 
188 	LOG(2,("INFO: PINS version 2 details not yet known\n"));
189 	return B_ERROR;
190 }
191 
192 /* pins v3 is used by G100 and G200. */
193 status_t pins3_read(uint8 *pins, uint8 length)
194 {
195 	/* used to calculate RAM refreshrate */
196 	float mclk_period;
197 	uint32 rfhcnt;
198 
199 	if (length != 64)
200 	{
201 		LOG(8,("INFO: wrong PINS length, expected 64, got %d\n", length));
202 		return B_ERROR;
203 	}
204 
205 	/* fill out the shared info si->ps struct */
206 	si->ps.max_pixel_vco = pins[36] + 100;
207 
208 	si->ps.max_dac1_clock_8 = pins[37] + 100;
209 	si->ps.max_dac1_clock_16 = pins[38] + 100;
210 	si->ps.max_dac1_clock_24 = pins[39] + 100;
211 	si->ps.max_dac1_clock_32 = pins[40] + 100;
212 
213 	si->ps.std_engine_clock = pins[44];
214 	if (pins [45] < si->ps.std_engine_clock) si->ps.std_engine_clock = pins[45];
215 	if (pins [46] < si->ps.std_engine_clock) si->ps.std_engine_clock = pins[46];
216 	if (pins [47] < si->ps.std_engine_clock) si->ps.std_engine_clock = pins[47];
217 	if ((si->ps.card_type == G200) && (pins[58] & 0x04))
218 	{
219 		/* G200 can work without divisor */
220 		si->ps.std_engine_clock *= 1;
221 	}
222 	else
223 	{
224 		if (pins[52] & 0x01)
225 			si->ps.std_engine_clock *= 3;
226 		else
227 			si->ps.std_engine_clock *= 2;
228 	}
229 
230 	if (pins[52] & 0x20) si->ps.f_ref = 14.31818;
231 	else si->ps.f_ref = 27.00000;
232 
233 	/* G100 and G200 support 2-16Mb RAM */
234 	si->ps.memory_size = 2 << ((pins[55] & 0xc0) >> 6);
235 	/* more memory specifics */
236 	si->ps.mctlwtst_reg = (pins[51] << 24) | (pins[50] << 16) | (pins[49] << 8) | pins [48];
237 	si->ps.memrdbk_reg =
238 		(pins[56] & 0x0f) | ((pins[56] & 0xf0) << 1) | ((pins[57] & 0x03) << 22) | ((pins[57] & 0xf0) << 21);
239 	/* Mark did this as one step in the above stuff, which must be wrong:
240 	((pins[p3_memrd+1]&0x03)>>2)<<16; //FIXME - ROR */
241 
242 	si->ps.v3_clk_div = pins[52];
243 	si->ps.v3_mem_type = pins[54];
244 	si->ps.v3_option2_reg = pins[58];
245 
246 	/* for cards using this version of PINS both functions are in maven */
247 	si->ps.secondary_head = !(pins[59] & 0x01);
248 	si->ps.secondary_tvout = !(pins[59] & 0x01);
249 
250 	/* setup via gathered info from pins */
251 	si->ps.option_reg = 0;
252 	/* calculate refresh timer info-bits for 15uS interval (or shorter). See G100/G200 specs */
253 	/* calculate std memory clock period (nS) */
254 	if ((si->ps.card_type == G200) && (pins[58] & 0x08))
255 	{
256 		/* G200 can work without Mclk divisor */
257 		mclk_period = 1000.0 / si->ps.std_engine_clock;
258 	}
259 	else
260 	{
261 		if (pins[52] & 0x02)
262 			/* this factor is only used on G200, not on G100 */
263 			mclk_period = 3000.0 / si->ps.std_engine_clock;
264 		else
265 			mclk_period = 2000.0 / si->ps.std_engine_clock;
266 	}
267 	/* calculate needed setting, 'round-down' result! */
268 	rfhcnt = (uint32)(((15000 / mclk_period) - 1) / 64);
269 	/* check for register limit */
270 	if (rfhcnt > 0x3f) rfhcnt = 0x3f;
271 	/* add to option register */
272 	si->ps.option_reg |= (rfhcnt << 15);
273 	/* the rest of the OPTION info for pins v3 comes via 'v3_clk_div' and 'v3_mem_type'. */
274 
275 	/* assuming the only possible panellink will be on the first head */
276 	si->ps.primary_dvi = !(pins[59] & 0x40);
277 	/* logical consequence of the above */
278 	si->ps.secondary_dvi = false;
279 
280 	/* indirect logical consequences, see also G100 and G200 specs */
281 	si->ps.max_system_vco = si->ps.max_pixel_vco;
282 	si->ps.max_dac1_clock = si->ps.max_dac1_clock_8;
283 	si->ps.max_dac1_clock_32dh = si->ps.max_dac1_clock_32;
284 	si->ps.std_engine_clock_dh = si->ps.std_engine_clock;
285 	si->ps.sdram = (si->ps.v3_clk_div & 0x10);
286 	/* not supported: */
287 	si->ps.max_dac2_clock_8 = 0;
288 	si->ps.max_dac2_clock_24 = 0;
289 	/* see G100, G200 and G400 specs */
290 	si->ps.min_system_vco = 50;
291 	si->ps.min_pixel_vco = 50;
292 	/* fixme: ehhh, no specs: confirm/tune these by testing?! */
293 	si->ps.max_video_vco = si->ps.max_pixel_vco;
294 	si->ps.min_video_vco = 50;
295 	/* assuming G100, G200 MAVEN has same specs as G400 MAVEN */
296 	si->ps.max_dac2_clock = 136;
297 	si->ps.max_dac2_clock_16 = 136;
298 	si->ps.max_dac2_clock_32dh = 136;
299 	si->ps.max_dac2_clock_32 = 136;
300 
301 	/* not used here: */
302 	si->ps.option2_reg = 0;
303 	si->ps.option3_reg = 0;
304 	si->ps.option4_reg = 0;
305 	si->ps.v5_mem_type = 0;
306 	return B_OK;
307 }
308 
309 /* pins v4 is used by G400 and G400MAX */
310 status_t pins4_read(uint8 *pins, uint8 length)
311 {
312 	/* used to calculate RAM refreshrate */
313 	float mclk_period;
314 	uint32 rfhcnt;
315 
316 	if (length != 128)
317 	{
318 		LOG(8,("INFO: wrong PINS length, expected 128, got %d\n", length));
319 		return B_ERROR;
320 	}
321 
322 	/* fill out the shared info si->ps struct */
323 	if (pins[39] == 0xff) si->ps.max_pixel_vco = 230;
324 	else si->ps.max_pixel_vco = 4 * pins[39];
325 
326 	if (pins[38] == 0xff) si->ps.max_system_vco = si->ps.max_pixel_vco;
327 	else si->ps.max_system_vco = 4 * pins[38];
328 
329 	if (pins[40] == 0xff) si->ps.max_dac1_clock_8 = si->ps.max_pixel_vco;
330 	else si->ps.max_dac1_clock_8 = 4 * pins[40];
331 
332 	if (pins[41] == 0xff) si->ps.max_dac1_clock_16 = si->ps.max_dac1_clock_8;
333 	else si->ps.max_dac1_clock_16 = 4 * pins[41];
334 
335 	if (pins[42] == 0xff) si->ps.max_dac1_clock_24 = si->ps.max_dac1_clock_16;
336 	else si->ps.max_dac1_clock_24 = 4 * pins[42];
337 
338 	if (pins[43] == 0xff) si->ps.max_dac1_clock_32 = si->ps.max_dac1_clock_24;
339 	else si->ps.max_dac1_clock_32 = 4 * pins[43];
340 
341 	if (pins[44] == 0xff) si->ps.max_dac2_clock_16 = si->ps.max_pixel_vco;
342 	else si->ps.max_dac2_clock_16 = 4 * pins[44];
343 
344 	if (pins[45] == 0xff) si->ps.max_dac2_clock_32 = si->ps.max_dac2_clock_16;
345 	else si->ps.max_dac2_clock_32 = 4 * pins[45];
346 
347 	/* verified against windows driver: */
348 	si->ps.std_engine_clock = 2 * pins[65];
349 
350 	if (pins[92] & 0x01) si->ps.f_ref = 14.31818;
351 	else si->ps.f_ref = 27.00000;
352 
353 	si->ps.memory_size = 4 << ((pins[92] >> 2) & 0x03);
354 	/* more memory specifics */
355 	si->ps.mctlwtst_reg = (pins[74] << 24) | (pins[73] << 16) | (pins[72] << 8) | pins [71];
356 	si->ps.option3_reg = (pins[70] << 24) | (pins[69] << 16) | (pins[68] << 8) | pins [67];
357 	/* mrsopcod field, msb is always zero.. */
358 	si->ps.memrdbk_reg =
359 		(pins[86] & 0x0f) | ((pins[86] & 0xf0) << 1) | ((pins[87] & 0x03) << 22) | ((pins[87] & 0xf0) << 21);
360 	si->ps.sdram = (pins[92] & 0x10);
361 
362 	/* setup via gathered info from pins */
363 	si->ps.option_reg = ((pins[53] & 0x38) << 7) | ((pins[53] & 0x40) << 22) | ((pins[53] & 0x80) << 15);
364 	/* calculate refresh timer info-bits for 15uS interval (or shorter). See G400 specs;
365 	 * the 15uS value was confirmed by Mark Watson for both G400 and G400MAX */
366 	/* calculate std memory clock period (nS) */
367 	switch ((si->ps.option3_reg & 0x0000e000) >> 13)
368 	{
369 	case 0:
370 		mclk_period = 3000.0 / (si->ps.std_engine_clock * 1);
371 		break;
372 	case 1:
373 		mclk_period = 5000.0 / (si->ps.std_engine_clock * 2);
374 		break;
375 	case 2:
376 		mclk_period = 9000.0 / (si->ps.std_engine_clock * 4);
377 		break;
378 	case 3:
379 		mclk_period = 2000.0 / (si->ps.std_engine_clock * 1);
380 		break;
381 	case 4:
382 		mclk_period = 3000.0 / (si->ps.std_engine_clock * 2);
383 		break;
384 	case 5:
385 		mclk_period = 1000.0 / (si->ps.std_engine_clock * 1);
386 		break;
387 	default:
388 		/* we choose the lowest refreshcount that could be needed (so assuming slowest clocked memory) */
389 		mclk_period = 3000.0 / (si->ps.std_engine_clock * 1);
390 		LOG(8,("INFO: undefined/unknown memory clock divider select, using failsafe for refresh\n"));
391 		break;
392 	}
393 	/* calculate needed setting, 'round-down' result! */
394 	rfhcnt = (uint32)(((15000 / mclk_period) - 1) / 64);
395 	/* check for register limit */
396 	if (rfhcnt > 0x3f) rfhcnt = 0x3f;
397 	/* add to option register */
398 	si->ps.option_reg |= (rfhcnt << 15);
399 
400 	/* for cards using this version of PINS both functions are in maven */
401 	si->ps.secondary_head = !(pins[91] & 0x01);
402 	si->ps.secondary_tvout = !(pins[91] & 0x01);
403 
404 	/* assuming the only possible panellink will be on the first head */
405 	si->ps.primary_dvi = !(pins[91] & 0x40);
406 	/* logical consequence of the above */
407 	si->ps.secondary_dvi = false;
408 
409 	/* indirect logical consequences, see also G100, G200 and G400 specs */
410 	si->ps.max_dac1_clock = si->ps.max_dac1_clock_8;
411 	si->ps.max_dac2_clock = si->ps.max_dac2_clock_16;
412 	si->ps.max_dac1_clock_32dh = si->ps.max_dac1_clock_32;
413 	si->ps.max_dac2_clock_32dh = si->ps.max_dac2_clock_32;
414 	si->ps.std_engine_clock_dh = si->ps.std_engine_clock;
415 	/* not supported: */
416 	si->ps.max_dac2_clock_8 = 0;
417 	si->ps.max_dac2_clock_24 = 0;
418 	/* see G100, G200 and G400 specs */
419 	si->ps.min_system_vco = 50;
420 	si->ps.min_pixel_vco = 50;
421 	/* fixme: ehhh, no specs: confirm/tune these by testing?! */
422 	si->ps.max_video_vco = si->ps.max_pixel_vco;
423 	si->ps.min_video_vco = 50;
424 
425 	/* not used here: */
426 	si->ps.option2_reg = 0;
427 	si->ps.option4_reg = 0;
428 	si->ps.v3_option2_reg = 0;
429 	si->ps.v3_clk_div = 0;
430 	si->ps.v3_mem_type = 0;
431 	si->ps.v5_mem_type = 0;
432 
433 	/* check for a G400MAX card */
434 	/* fixme: use the PCI configspace ID method if it exists... */
435 	if (si->ps.max_dac1_clock > 300)
436 	{
437 		si->ps.card_type = G400MAX;
438 		LOG(2,("INFO: G400MAX detected\n"));
439 	}
440 	return B_OK;
441 }
442 
443 /* pins v5 is used by G450 and G550 */
444 status_t pins5_read(uint8 *pins, uint8 length)
445 {
446 	unsigned int m_factor = 6;
447 
448 	if (length != 128)
449 	{
450 		LOG(8,("INFO: wrong PINS length, expected 128, got %d\n", length));
451 		return B_ERROR;
452 	}
453 
454 	/* fill out the shared info si->ps struct */
455 	if (pins[4] == 0x01) m_factor = 8;
456 	if (pins[4] >= 0x02) m_factor = 10;
457 
458 	si->ps.max_system_vco = m_factor * pins[36];
459 	si->ps.max_video_vco = m_factor * pins[37];
460 	si->ps.max_pixel_vco = m_factor * pins[38];
461 	si->ps.min_system_vco = m_factor * pins[121];
462 	si->ps.min_video_vco = m_factor * pins[122];
463 	si->ps.min_pixel_vco = m_factor * pins[123];
464 
465 	if (pins[39] == 0xff) si->ps.max_dac1_clock_8 = si->ps.max_pixel_vco;
466 	else si->ps.max_dac1_clock_8 = 4 * pins[39];
467 
468 	if (pins[40] == 0xff) si->ps.max_dac1_clock_16 = si->ps.max_dac1_clock_8;
469 	else si->ps.max_dac1_clock_16 = 4 * pins[40];
470 
471 	if (pins[41] == 0xff) si->ps.max_dac1_clock_24 = si->ps.max_dac1_clock_16;
472 	else si->ps.max_dac1_clock_24 = 4 * pins[41];
473 
474 	if (pins[42] == 0xff) si->ps.max_dac1_clock_32 = si->ps.max_dac1_clock_24;
475 	else si->ps.max_dac1_clock_32 = 4 * pins[42];
476 
477 	if (pins[124] == 0xff) si->ps.max_dac1_clock_32dh = si->ps.max_dac1_clock_32;
478 	else si->ps.max_dac1_clock_32dh = 4 * pins[124];
479 
480 	if (pins[43] == 0xff) si->ps.max_dac2_clock_16 = si->ps.max_video_vco;
481 	else si->ps.max_dac2_clock_16 = 4 * pins[43];
482 
483 	if (pins[44] == 0xff) si->ps.max_dac2_clock_32 = si->ps.max_dac2_clock_16;
484 	else si->ps.max_dac2_clock_32 = 4 * pins[44];
485 
486 	if (pins[125] == 0xff) si->ps.max_dac2_clock_32dh = si->ps.max_dac2_clock_32;
487 	else si->ps.max_dac2_clock_32dh = 4 * pins[125];
488 
489 	if (pins[118] == 0xff) si->ps.max_dac1_clock = si->ps.max_dac1_clock_8;
490 	else si->ps.max_dac1_clock = 4 * pins[118];
491 
492 	if (pins[119] == 0xff) si->ps.max_dac2_clock = si->ps.max_dac1_clock;
493 	else si->ps.max_dac2_clock = 4 * pins[119];
494 
495 	si->ps.std_engine_clock = 4 * pins[74];
496 	si->ps.std_engine_clock_dh = 4 * pins[92];
497 
498 	si->ps.memory_size = ((pins[114] & 0x03) + 1) * 8;
499 	if ((pins[114] & 0x07) > 3)
500 	{
501 		LOG(8,("INFO: unknown RAM size, defaulting to 8Mb\n"));
502 		si->ps.memory_size = 8;
503 	}
504 
505 	if (pins[110] & 0x01) si->ps.f_ref = 14.31818;
506 	else si->ps.f_ref = 27.00000;
507 
508 	/* make sure SGRAM functions only get enabled if SGRAM mounted */
509 	if ((pins[114] & 0x18) == 0x08) si->ps.sdram = false;
510 	else si->ps.sdram = true;
511 	/* more memory specifics */
512 	si->ps.v5_mem_type = (pins[115] << 8) | pins [114];
513 
514 	/* various registers */
515 	si->ps.option_reg = (pins[51] << 24) | (pins[50] << 16) | (pins[49] << 8) | pins [48];
516 	si->ps.option2_reg = (pins[55] << 24) | (pins[54] << 16) | (pins[53] << 8) | pins [52];
517 	si->ps.option3_reg = (pins[79] << 24) | (pins[78] << 16) | (pins[77] << 8) | pins [76];
518 	si->ps.option4_reg = (pins[87] << 24) | (pins[86] << 16) | (pins[85] << 8) | pins [84];
519 	si->ps.mctlwtst_reg = (pins[83] << 24) | (pins[82] << 16) | (pins[81] << 8) | pins [80];
520 	si->ps.memrdbk_reg = (pins[91] << 24) | (pins[90] << 16) | (pins[89] << 8) | pins [88];
521 
522 	si->ps.secondary_head = (pins[117] & 0x70);
523 	si->ps.secondary_tvout = (pins[117] & 0x40);
524 	si->ps.primary_dvi = (pins[117] & 0x02);
525 	si->ps.secondary_dvi = (pins[117] & 0x20);
526 
527 	/* not supported: */
528 	si->ps.max_dac2_clock_8 = 0;
529 	si->ps.max_dac2_clock_24 = 0;
530 
531 	/* not used here: */
532 	si->ps.v3_option2_reg = 0;
533 	si->ps.v3_clk_div = 0;
534 	si->ps.v3_mem_type = 0;
535 	return B_OK;
536 }
537 
538 /* fake_pins presumes the card was coldstarted by it's BIOS */
539 void fake_pins(void)
540 {
541 	LOG(8,("INFO: faking PINS\n"));
542 
543 	switch (si->ps.card_type)
544 	{
545 		case MIL1:
546 			pinsmil1_fake();
547 			break;
548 		case MIL2:
549 			pinsmil2_fake();
550 			break;
551 		case G100:
552 			pinsg100_fake();
553 			break;
554 		case G200:
555 			pinsg200_fake();
556 			break;
557 		case G400:
558 			pinsg400_fake();
559 			break;
560 		case G400MAX:
561 			pinsg400max_fake();
562 			break;
563 		case G450:
564 			pinsg450_fake();
565 			break;
566 		case G550:
567 			pinsg550_fake();
568 			break;
569 	}
570 
571 	/* find out if the card has a maven */
572 	si->ps.secondary_tvout = false;
573 	si->ps.secondary_head = false;
574 	/* only do I2C probe if the card has a chance */
575 	if (si->ps.card_type >= G100)
576 	{
577 		if (i2c_maven_probe() == B_OK)
578 		{
579 			si->ps.secondary_tvout = true;
580 			si->ps.secondary_head = true;
581 		}
582 	}
583 
584 	/* not used because no coldstart will be attempted */
585 	si->ps.std_engine_clock = 0;
586 	si->ps.std_engine_clock_dh = 0;
587 	si->ps.mctlwtst_reg = 0;
588 	si->ps.memrdbk_reg = 0;
589 	si->ps.option_reg = 0;
590 	si->ps.option2_reg = 0;
591 	si->ps.option3_reg = 0;
592 	si->ps.option4_reg = 0;
593 	si->ps.v3_option2_reg = 0;
594 	si->ps.v3_clk_div = 0;
595 	si->ps.v3_mem_type = 0;
596 	si->ps.v5_mem_type = 0;
597 }
598 
599 void pinsmil1_fake(void)
600 {
601 	/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
602 
603 	si->ps.f_ref = 14.31818;
604 	/* see MIL1 specs */
605 	si->ps.max_system_vco = 220;
606 	si->ps.min_system_vco = 110;
607 	si->ps.max_pixel_vco = 220;
608 	si->ps.min_pixel_vco = 110;
609 	/* no specs, assuming these */
610 	si->ps.max_video_vco = 0;
611 	si->ps.min_video_vco = 0;
612 	/* see MIL1 specs */
613 	si->ps.max_dac1_clock = 220;
614 	si->ps.max_dac1_clock_8 = 220;
615 	si->ps.max_dac1_clock_16 = 200;
616 	/* 'failsave' values */
617 	si->ps.max_dac1_clock_24 = 180;
618 	si->ps.max_dac1_clock_32 = 136;
619 	si->ps.max_dac1_clock_32dh = 0;
620 	/* see specs */
621 	si->ps.max_dac2_clock = 0;
622 	si->ps.max_dac2_clock_8 = 0;
623 	si->ps.max_dac2_clock_16 = 0;
624 	si->ps.max_dac2_clock_24 = 0;
625 	si->ps.max_dac2_clock_32 = 0;
626 	/* 'failsave' value */
627 	si->ps.max_dac2_clock_32dh = 0;
628 	si->ps.primary_dvi = false;
629 	si->ps.secondary_dvi = false;
630 	/*  presume 2Mb RAM mounted */
631 	//fixme: see if we can get this from OPTION or so...
632 	si->ps.memory_size = 2;
633 	//fixme: should be overrule-able via mga.settings for MIL1.
634 	//fail-safe mode for now:
635 	si->ps.sdram = true;
636 }
637 
638 void pinsmil2_fake(void)
639 {
640 	/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
641 
642 	si->ps.f_ref = 14.31818;
643 	/* see MIL2 specs */
644 	si->ps.max_system_vco = 220;
645 	si->ps.min_system_vco = 110;
646 	si->ps.max_pixel_vco = 220;
647 	si->ps.min_pixel_vco = 110;
648 	/* no specs, assuming these */
649 	si->ps.max_video_vco = 0;
650 	si->ps.min_video_vco = 0;
651 	/* see MIL2 specs */
652 	si->ps.max_dac1_clock = 220;
653 	si->ps.max_dac1_clock_8 = 220;
654 	si->ps.max_dac1_clock_16 = 200;
655 	/* 'failsave' values */
656 	si->ps.max_dac1_clock_24 = 180;
657 	si->ps.max_dac1_clock_32 = 136;
658 	si->ps.max_dac1_clock_32dh = 0;
659 	/* see specs */
660 	si->ps.max_dac2_clock = 0;
661 	si->ps.max_dac2_clock_8 = 0;
662 	si->ps.max_dac2_clock_16 = 0;
663 	si->ps.max_dac2_clock_24 = 0;
664 	si->ps.max_dac2_clock_32 = 0;
665 	/* 'failsave' value */
666 	si->ps.max_dac2_clock_32dh = 0;
667 	si->ps.primary_dvi = false;
668 	si->ps.secondary_dvi = false;
669 	/*  presume 4Mb RAM mounted */
670 	//fixme: see if we can get this from OPTION or so...
671 	si->ps.memory_size = 4;
672 	//fixme: should be overrule-able via mga.settings for MIL2.
673 	//fail-safe mode for now:
674 	si->ps.sdram = true;
675 }
676 
677 void pinsg100_fake(void)
678 {
679 	/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
680 
681 	//fixme: should be overrule-able via mga.settings.
682 	si->ps.f_ref = 27.000;
683 	/* see G100 specs */
684 	si->ps.max_system_vco = 230;
685 	si->ps.min_system_vco = 50;
686 	si->ps.max_pixel_vco = 230;
687 	si->ps.min_pixel_vco = 50;
688 	/* no specs, assuming these */
689 	si->ps.max_video_vco = 230;
690 	si->ps.min_video_vco = 50;
691 	/* see G100 specs */
692 	si->ps.max_dac1_clock = 230;
693 	si->ps.max_dac1_clock_8 = 230;
694 	si->ps.max_dac1_clock_16 = 230;
695 	/* 'failsave' values */
696 	si->ps.max_dac1_clock_24 = 180;
697 	si->ps.max_dac1_clock_32 = 136;
698 	si->ps.max_dac1_clock_32dh = 136;
699 	/* see specs */
700 	si->ps.max_dac2_clock = 136;
701 	si->ps.max_dac2_clock_8 = 0;
702 	si->ps.max_dac2_clock_16 = 136;
703 	si->ps.max_dac2_clock_24 = 0;
704 	si->ps.max_dac2_clock_32 = 136;
705 	/* 'failsave' value */
706 	si->ps.max_dac2_clock_32dh = 136;
707 	/* assuming the only possible panellink will be on the first head */
708 	//fixme: primary_dvi should be overrule-able via mga.settings for G100.
709 	si->ps.primary_dvi = false;
710 	si->ps.secondary_dvi = false;
711 	/*  presume 2Mb RAM mounted */
712 	si->ps.memory_size = 2;
713 	//fixme: should be overrule-able via mga.settings for G100.
714 	//fail-safe mode for now:
715 	si->ps.sdram = true;
716 }
717 
718 void pinsg200_fake(void)
719 {
720 	/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
721 
722 	//fixme: should be overrule-able via mga.settings.
723 	si->ps.f_ref = 27.000;
724 	/* see G200 specs */
725 	si->ps.max_system_vco = 250;
726 	si->ps.min_system_vco = 50;
727 	si->ps.max_pixel_vco = 250;
728 	si->ps.min_pixel_vco = 50;
729 	/* no specs, assuming these */
730 	si->ps.max_video_vco = 250;
731 	si->ps.min_video_vco = 50;
732 	/* see G200 specs */
733 	si->ps.max_dac1_clock = 250;
734 	si->ps.max_dac1_clock_8 = 250;
735 	si->ps.max_dac1_clock_16 = 250;
736 	/* 'failsave' values */
737 	si->ps.max_dac1_clock_24 = 180;
738 	si->ps.max_dac1_clock_32 = 136;
739 	si->ps.max_dac1_clock_32dh = 136;
740 	/* see specs */
741 	si->ps.max_dac2_clock = 136;
742 	si->ps.max_dac2_clock_8 = 0;
743 	si->ps.max_dac2_clock_16 = 136;
744 	si->ps.max_dac2_clock_24 = 0;
745 	si->ps.max_dac2_clock_32 = 136;
746 	/* 'failsave' value */
747 	si->ps.max_dac2_clock_32dh = 136;
748 	/* assuming the only possible panellink will be on the first head */
749 	//fixme: primary_dvi should be overrule-able via mga.settings for G100.
750 	si->ps.primary_dvi = false;
751 	si->ps.secondary_dvi = false;
752 	/*  presume 2Mb RAM mounted */
753 	si->ps.memory_size = 2;
754 	/* ask the G200 what type of RAM it has been set to by it's BIOS */
755 	si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
756 }
757 
758 void pinsg400_fake(void)
759 {
760 	/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
761 
762 	//fixme: should be overrule-able via mga.settings.
763 	si->ps.f_ref = 27.000;
764 	/* see G400 specs */
765 	si->ps.max_system_vco = 300;
766 	si->ps.min_system_vco = 50;
767 	si->ps.max_pixel_vco = 300;
768 	si->ps.min_pixel_vco = 50;
769 	/* no specs, assuming these */
770 	si->ps.max_video_vco = 300;
771 	si->ps.min_video_vco = 50;
772 	/* see G400 specs */
773 	si->ps.max_dac1_clock = 300;
774 	si->ps.max_dac1_clock_8 = 300;
775 	si->ps.max_dac1_clock_16 = 300;
776 	/* 'failsave' values */
777 	si->ps.max_dac1_clock_24 = 230;
778 	si->ps.max_dac1_clock_32 = 180;
779 	si->ps.max_dac1_clock_32dh = 136;
780 	/* see specs */
781 	si->ps.max_dac2_clock = 136;
782 	si->ps.max_dac2_clock_8 = 0;
783 	si->ps.max_dac2_clock_16 = 136;
784 	si->ps.max_dac2_clock_24 = 0;
785 	si->ps.max_dac2_clock_32 = 136;
786 	/* 'failsave' value */
787 	si->ps.max_dac2_clock_32dh = 136;
788 	/* assuming the only possible panellink will be on the first head */
789 	//fixme: primary_dvi should be overrule-able via mga.settings for G400.
790 	si->ps.primary_dvi = false;
791 	si->ps.secondary_dvi = false;
792 	/*  presume 4Mb RAM mounted */
793 	si->ps.memory_size = 4;
794 	/* ask the G400 what type of RAM it has been set to by it's BIOS */
795 	si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
796 }
797 
798 /* this routine is currently unused, because G400MAX is detected via pins! */
799 void pinsg400max_fake(void)
800 {
801 	/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
802 
803 	//fixme: should be overrule-able via mga.settings.
804 	si->ps.f_ref = 27.000;
805 	/* see G400MAX specs */
806 	si->ps.max_system_vco = 360;
807 	si->ps.min_system_vco = 50;
808 	si->ps.max_pixel_vco = 360;
809 	si->ps.min_pixel_vco = 50;
810 	/* no specs, assuming these */
811 	si->ps.max_video_vco = 360;
812 	si->ps.min_video_vco = 50;
813 	/* see G400MAX specs */
814 	si->ps.max_dac1_clock = 360;
815 	si->ps.max_dac1_clock_8 = 360;
816 	si->ps.max_dac1_clock_16 = 360;
817 	/* 'failsave' values */
818 	si->ps.max_dac1_clock_24 = 280;
819 	si->ps.max_dac1_clock_32 = 230;
820 	si->ps.max_dac1_clock_32dh = 136;
821 	/* see specs */
822 	si->ps.max_dac2_clock = 136;
823 	si->ps.max_dac2_clock_8 = 0;
824 	si->ps.max_dac2_clock_16 = 136;
825 	si->ps.max_dac2_clock_24 = 0;
826 	si->ps.max_dac2_clock_32 = 136;
827 	/* 'failsave' value */
828 	si->ps.max_dac2_clock_32dh = 136;
829 	/* assuming the only possible panellink will be on the first head */
830 	//fixme: primary_dvi should be overrule-able via mga.settings for G400MAX.
831 	si->ps.primary_dvi = false;
832 	si->ps.secondary_dvi = false;
833 	/*  presume 4Mb RAM mounted */
834 	si->ps.memory_size = 4;
835 	/* ask the G400MAX what type of RAM it has been set to by it's BIOS */
836 	si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
837 }
838 
839 void pinsg450_fake(void)
840 {
841 	/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
842 
843 	//fixme: should be overrule-able via mga.settings.
844 	si->ps.f_ref = 27.000;
845 	/* see G450 pins readouts for max ranges, then use a bit smaller ones */
846 	/* carefull not to take to high lower limits, and high should be >= 2x low. */
847 	si->ps.max_system_vco = 640;
848 	si->ps.min_system_vco = 320;
849 	si->ps.max_pixel_vco = 640;
850 	si->ps.min_pixel_vco = 320;
851 	si->ps.max_video_vco = 640;
852 	si->ps.min_video_vco = 320;
853 	si->ps.max_dac1_clock = 360;
854 	si->ps.max_dac1_clock_8 = 360;
855 	si->ps.max_dac1_clock_16 = 360;
856 	/* 'failsave' values */
857 	si->ps.max_dac1_clock_24 = 280;
858 	si->ps.max_dac1_clock_32 = 230;
859 	si->ps.max_dac1_clock_32dh = 180;
860 	/* see G450 pins readouts */
861 	si->ps.max_dac2_clock = 232;
862 	si->ps.max_dac2_clock_8 = 0;
863 	si->ps.max_dac2_clock_16 = 232;
864 	si->ps.max_dac2_clock_24 = 0;
865 	si->ps.max_dac2_clock_32 = 232;
866 	/* 'failsave' values */
867 	si->ps.max_dac2_clock_32dh = 180;
868 	//fixme: primary & secondary_dvi should be overrule-able via mga.settings for G450.
869 	si->ps.primary_dvi = false;
870 	si->ps.secondary_dvi = false;
871 	/*  presume 8Mb RAM mounted */
872 	si->ps.memory_size = 8;
873 	/* ask the G450 what type of RAM it has been set to by it's BIOS */
874 //todo:
875 //	si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
876 //fail-safe mode for now:
877 	si->ps.sdram = true;
878 }
879 
880 void pinsg550_fake(void)
881 {
882 	/* 'worst case' scenario defaults, overrule-able via mga.settings if needed */
883 
884 	//fixme: should be overrule-able via mga.settings.
885 	si->ps.f_ref = 27.000;
886 	/* see G550 pins readouts for max ranges, then use a bit smaller ones */
887 	/* carefull not to take to high lower limits, and high should be >= 2x low. */
888 	si->ps.max_system_vco = 768;
889 	si->ps.min_system_vco = 384;
890 	si->ps.max_pixel_vco = 960;
891 	si->ps.min_pixel_vco = 320;
892 	si->ps.max_video_vco = 960;
893 	si->ps.min_video_vco = 320;
894 	si->ps.max_dac1_clock = 360;
895 	si->ps.max_dac1_clock_8 = 360;
896 	si->ps.max_dac1_clock_16 = 360;
897 	/* 'failsave' values */
898 	si->ps.max_dac1_clock_24 = 280;
899 	si->ps.max_dac1_clock_32 = 230;
900 	si->ps.max_dac1_clock_32dh = 180;
901 	/* see G550 pins readouts */
902 	si->ps.max_dac2_clock = 232;
903 	si->ps.max_dac2_clock_8 = 0;
904 	si->ps.max_dac2_clock_16 = 232;
905 	si->ps.max_dac2_clock_24 = 0;
906 	si->ps.max_dac2_clock_32 = 232;
907 	/* 'failsave' values */
908 	si->ps.max_dac2_clock_32dh = 180;
909 	//fixme: primary & secondary_dvi should be overrule-able via mga.settings for G550.
910 	si->ps.primary_dvi = false;
911 	si->ps.secondary_dvi = false;
912 	/*  presume 8Mb RAM mounted */
913 	si->ps.memory_size = 8;
914 	/* ask the G550 what type of RAM it has been set to by it's BIOS */
915 //todo:
916 //	si->ps.sdram = !(CFGR(OPTION) & 0x00004000);
917 //fail-safe mode for now:
918 	si->ps.sdram = true;
919 }
920 
921 void dump_pins(void)
922 {
923 	LOG(2,("INFO: pinsdump follows:\n"));
924 	LOG(2,("f_ref: %fMhz\n", si->ps.f_ref));
925 	LOG(2,("max_system_vco: %dMhz\n", si->ps.max_system_vco));
926 	LOG(2,("min_system_vco: %dMhz\n", si->ps.min_system_vco));
927 	LOG(2,("max_pixel_vco: %dMhz\n", si->ps.max_pixel_vco));
928 	LOG(2,("min_pixel_vco: %dMhz\n", si->ps.min_pixel_vco));
929 	LOG(2,("max_video_vco: %dMhz\n", si->ps.max_video_vco));
930 	LOG(2,("min_video_vco: %dMhz\n", si->ps.min_video_vco));
931 	LOG(2,("std_engine_clock: %dMhz\n", si->ps.std_engine_clock));
932 	LOG(2,("std_engine_clock_dh: %dMhz\n", si->ps.std_engine_clock_dh));
933 	LOG(2,("max_dac1_clock: %dMhz\n", si->ps.max_dac1_clock));
934 	LOG(2,("max_dac1_clock_8: %dMhz\n", si->ps.max_dac1_clock_8));
935 	LOG(2,("max_dac1_clock_16: %dMhz\n", si->ps.max_dac1_clock_16));
936 	LOG(2,("max_dac1_clock_24: %dMhz\n", si->ps.max_dac1_clock_24));
937 	LOG(2,("max_dac1_clock_32: %dMhz\n", si->ps.max_dac1_clock_32));
938 	LOG(2,("max_dac1_clock_32dh: %dMhz\n", si->ps.max_dac1_clock_32dh));
939 	LOG(2,("max_dac2_clock: %dMhz\n", si->ps.max_dac2_clock));
940 	LOG(2,("max_dac2_clock_8: %dMhz\n", si->ps.max_dac2_clock_8));
941 	LOG(2,("max_dac2_clock_16: %dMhz\n", si->ps.max_dac2_clock_16));
942 	LOG(2,("max_dac2_clock_24: %dMhz\n", si->ps.max_dac2_clock_24));
943 	LOG(2,("max_dac2_clock_32: %dMhz\n", si->ps.max_dac2_clock_32));
944 	LOG(2,("max_dac2_clock_32dh: %dMhz\n", si->ps.max_dac2_clock_32dh));
945 	LOG(2,("secondary_head: "));
946 	if (si->ps.secondary_head) LOG(2,("present\n")); else LOG(2,("absent\n"));
947 	LOG(2,("secondary_tvout: "));
948 	if (si->ps.secondary_tvout) LOG(2,("present\n")); else LOG(2,("absent\n"));
949 	LOG(2,("primary_dvi: "));
950 	if (si->ps.primary_dvi) LOG(2,("present\n")); else LOG(2,("absent\n"));
951 	LOG(2,("secondary_dvi: "));
952 	if (si->ps.secondary_dvi) LOG(2,("present\n")); else LOG(2,("absent\n"));
953 	LOG(2,("card memory_size: %dMb\n", si->ps.memory_size));
954 	LOG(2,("mctlwtst register: $%08x\n", si->ps.mctlwtst_reg));
955 	LOG(2,("memrdbk register: $%08x\n", si->ps.memrdbk_reg));
956 	LOG(2,("option register: $%08x\n", si->ps.option_reg));
957 	LOG(2,("option2 register: $%08x\n", si->ps.option2_reg));
958 	LOG(2,("option3 register: $%08x\n", si->ps.option3_reg));
959 	LOG(2,("option4 register: $%08x\n", si->ps.option4_reg));
960 	LOG(2,("v3_option2_reg: $%02x\n", si->ps.v3_option2_reg));
961 	LOG(2,("v3_clock_div: $%02x\n", si->ps.v3_clk_div));
962 	LOG(2,("v3_mem_type: $%02x\n", si->ps.v3_mem_type));
963 	LOG(2,("v5_mem_type: $%04x\n", si->ps.v5_mem_type));
964 	LOG(2,("sdram: "));
965 	if (si->ps.sdram) LOG(2,("SDRAM card\n")); else LOG(2,("SGRAM card\n"));
966 	LOG(2,("INFO: end pinsdump.\n"));
967 }
968