1/*
2 * (C) Copyright IBM Corporation 2005
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file mga_bios.c
27 * Routines for processing the PInS data stored in the MGA BIOS.
28 *
29 * The structure of this code was inspired by similar routines in the Linux
30 * kernel matroxfb code.  Specifically, the routines in matroxfb_misc.c.  In
31 * addition, that code was used in place of documentation about the structure
32 * of the PInS data for non-G450 cards.
33 *
34 * \author Ian Romanick <idr@us.ibm.com>
35 */
36
37#ifdef HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41/* All drivers should typically include these */
42#include "xf86.h"
43#include "xf86_OSproc.h"
44
45/* All drivers need this */
46
47#include "compiler.h"
48
49/* Drivers that need to access the PCI config space directly need this */
50#include "xf86Pci.h"
51
52#include <X11/Xmd.h>
53
54#include "mga.h"
55
56#if defined(DEBUG)
57#define BIOS_DEBUG
58#endif
59
60/**
61 * Read a little-endian, unaligned data value and return as 16-bit.
62 */
63static __inline__ CARD16 get_u16( const CARD8 * data )
64{
65    CARD16 temp;
66
67    temp = data[1];
68    temp <<= 8;
69    temp += data[0];
70    return temp;
71}
72
73
74/**
75 * Read a little-endian, unaligned data value and return as 32-bit.
76 */
77static __inline__ CARD32 get_u32( const CARD8 * data )
78{
79    CARD32 temp;
80
81
82    temp = data[3];
83    temp <<= 8;
84    temp += data[2];
85    temp <<= 8;
86    temp += data[1];
87    temp <<= 8;
88    temp += data[0];
89
90    return temp;
91}
92
93
94/**
95 * Parse version 0x01XX of the BIOS PInS structure.
96 *
97 * Version 0x01XX of the BIOS PInS structure is only found in Millennium cards.
98 *
99 * \todo
100 * There used to be an "OverclockMem" option that would scale the memory clock
101 * by 12 instead 10.  Add support for this back in.
102 */
103static void mga_parse_bios_ver_1( struct mga_bios_values * bios,
104				  const CARD8 * bios_data )
105{
106    unsigned maxdac;
107
108    if ( get_u16( & bios_data[24] ) ) {
109	maxdac = get_u16( & bios_data[24] ) * 10;
110    }
111    else {
112	/* There is some disagreement here between the Linux kernel matroxfb
113	 * driver and the old X.org mga driver.  matroxfb has case-statements
114	 * for 0 and 1 (with the values below), and the mga driver has
115	 * case-statements for 1 and 2 (with the values below).  The default
116	 * value for the mga driver is 17500, but the default value for the
117	 * matroxfb driver is 240000.
118	 */
119
120	switch( bios_data[22] ) {
121	case 0:  maxdac = 175000; break;
122	case 1:  maxdac = 220000; break;
123	case 2:  maxdac = 250000; break;
124	default: maxdac = 240000; break;
125	}
126    }
127
128    if ( get_u16( & bios_data[28] ) ) {
129	bios->mem_clock = get_u16( & bios_data[28] ) * 10;
130    }
131
132    if ( (bios_data[48] & 0x01) == 0 ) {
133	bios->fast_bitblt = TRUE;
134    }
135
136    bios->pixel.max_freq = maxdac;
137}
138
139
140/**
141 * Parse version 0x02XX of the BIOS PInS structure.
142 *
143 * Version 0x02XX of the BIOS PInS structure is only found in Millennium II
144 * and Mystique cards.
145 */
146static void mga_parse_bios_ver_2( struct mga_bios_values * bios,
147				  const CARD8 * bios_data )
148{
149    if ( bios_data[41] != 0xff ) {
150	const unsigned maxdac = (bios_data[41] + 100) * 1000;
151
152	bios->pixel.max_freq = maxdac;
153	bios->system.max_freq = maxdac;
154    }
155
156    if ( bios_data[43] != 0xff ) {
157	const unsigned system_pll = (bios_data[43] + 100) * 1000;
158	bios->mem_clock = system_pll;
159    }
160}
161
162
163/**
164 * Parse version 0x03XX of the BIOS PInS structure.
165 *
166 * Version 0x03XX of the BIOS PInS structure is only found in G100 and G200
167 * cards.
168 */
169static void mga_parse_bios_ver_3( struct mga_bios_values * bios,
170				  const CARD8 * bios_data )
171{
172    if ( bios_data[36] != 0xff ) {
173	const unsigned maxdac = (bios_data[36] + 100) * 1000;
174
175	bios->pixel.max_freq = maxdac;
176	bios->system.max_freq = maxdac;
177    }
178
179    if ( (bios_data[52] & 0x20) != 0 ) {
180	bios->pll_ref_freq = 14318;
181    }
182}
183
184
185/**
186 * Parse version 0x04XX of the BIOS PInS structure.
187 *
188 * Version 0x04XX of the BIOS PInS structure is only found in G400 cards.
189 */
190static void mga_parse_bios_ver_4( struct mga_bios_values * bios,
191				  const CARD8 * bios_data )
192{
193    if ( bios_data[39] != 0xff ) {
194	const unsigned maxdac = bios_data[39] * 4 * 1000;
195
196	bios->pixel.max_freq = maxdac;
197	bios->system.max_freq = maxdac;
198    }
199
200    if ( bios_data[38] != 0xff ) {
201	const unsigned maxdac = bios_data[38] * 4 * 1000;
202
203	bios->system.max_freq = maxdac;
204    }
205
206    if ( (bios_data[92] & 0x01) != 0 ) {
207	bios->pll_ref_freq = 14318;
208    }
209
210    bios->host_interface = (bios_data[95] >> 3) & 0x07;
211
212    if ( bios_data[65] != 0xff ) {
213	const unsigned system_pll = bios_data[65] * 4 * 1000;
214	bios->mem_clock = system_pll;
215    }
216}
217
218
219/**
220 * Parse version 0x05XX of the BIOS PInS structure.
221 *
222 * Version 0x05XX of the BIOS PInS structure is only found in G450 and G550
223 * cards.
224 */
225static void mga_parse_bios_ver_5( struct mga_bios_values * bios,
226				  const CARD8 * bios_data )
227{
228    const unsigned scale = (bios_data[4] != 0) ? 8000 : 6000;
229
230
231    if ( bios_data[38] != 0xff ) {
232	const unsigned maxdac = bios_data[38] * scale;
233
234	bios->pixel.max_freq = maxdac;
235	bios->system.max_freq = maxdac;
236	bios->video.max_freq = maxdac;
237    }
238
239    if ( bios_data[36] != 0xff ) {
240	const unsigned maxdac = bios_data[36] * scale;
241
242	bios->system.max_freq = maxdac;
243	bios->video.max_freq = maxdac;
244    }
245
246    if ( bios_data[37] != 0xff ) {
247	const unsigned maxdac = bios_data[37] * scale;
248
249	bios->video.max_freq = maxdac;
250    }
251
252
253    if ( bios_data[123] != 0xff ) {
254	const unsigned mindac = bios_data[123] * scale;
255
256	bios->pixel.min_freq = mindac;
257	bios->system.min_freq = mindac;
258	bios->video.min_freq = mindac;
259    }
260
261    if ( bios_data[121] != 0xff ) {
262	const unsigned mindac = bios_data[121] * scale;
263
264	bios->system.min_freq = mindac;
265	bios->video.min_freq = mindac;
266    }
267
268    if ( bios_data[122] != 0xff ) {
269	const unsigned mindac = bios_data[122] * scale;
270
271	bios->video.min_freq = mindac;
272    }
273
274
275    if ( bios_data[92] != 0xff ) {
276	const unsigned system_pll = bios_data[92] * 4 * 1000;
277	bios->mem_clock = system_pll;
278    }
279
280    if ( (bios_data[110] & 0x01) != 0 ) {
281	bios->pll_ref_freq = 14318;
282    }
283
284    bios->host_interface = (bios_data[113] >> 3) & 0x07;
285}
286
287
288/**
289 * Read the BIOS data from the card and initialize internal values.
290 */
291
292Bool mga_read_and_process_bios( ScrnInfoPtr pScrn )
293{
294    CARD8  bios_data[0x20000];
295    unsigned offset;
296    MGAPtr pMga = MGAPTR(pScrn);
297#ifndef XSERVER_LIBPCIACCESS
298    Bool pciBIOS = TRUE;
299#endif
300    static const unsigned expected_length[] = { 0, 64, 64, 64, 128, 128 };
301    unsigned version;
302    unsigned pins_len;
303    const CARD8 * pins_data;
304    int err;
305#ifdef BIOS_DEBUG
306    static const char * const host_interface_strings[8] = {
307	"Reserved",
308	"Reserved",
309	"Reserved",
310	"Hybrid (AGP 4x on data transfers only)",
311	"PCI",
312	"AGP 1x",
313	"AGP 2x",
314	"AGP 4x"
315    };
316#endif
317
318
319    /* Initialize the stored BIOS data to some reasonable values for the
320     * card at hand.  This is done now so that even if the PInS data block
321     * isn't found or can't be read we'll still have some reasonable values
322     * to use.
323     */
324    if (pMga->chip_attribs)
325	(void) memcpy(& pMga->bios, & pMga->chip_attribs->default_bios_values,
326                      sizeof(struct mga_bios_values));
327
328
329    /* If the BIOS address was probed, it was found from the PCI config space
330     * If it was given in the config file, try to guess when it looks like it
331     * might be controlled by the PCI config space.
332     */
333
334#ifdef XSERVER_LIBPCIACCESS
335    err = pci_device_read_rom(pMga->PciInfo, bios_data);
336#else
337    if (pMga->BiosFrom == X_DEFAULT) {
338	pciBIOS = FALSE;
339    }
340    else if (pMga->BiosFrom == X_CONFIG && pMga->BiosAddress < 0x100000) {
341	pciBIOS = TRUE;
342    }
343
344    if (pciBIOS) {
345	rlen = xf86ReadPciBIOS(0, pMga->PciTag, pMga->framebuffer_bar,
346			       bios_data, sizeof(bios_data));
347    }
348    else {
349	rlen = xf86ReadDomainMemory(pMga->PciTag, pMga->BiosAddress,
350				    sizeof(bios_data), bios_data);
351    }
352
353    err = rlen < (bios_data[2] << 9);
354#endif
355
356    if (err) {
357	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
358		   "Could not retrieve video BIOS!\n");
359	return FALSE;
360    }
361
362    /* Get the output mode set by the BIOS */
363    pMga->BiosOutputMode = bios_data[0x7ff1];
364
365    /* Get the video BIOS info block */
366    if (strncmp((char *)(&bios_data[45]), "MATROX", 6)) {
367	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
368		   "Video BIOS info block not detected!\n");
369	return FALSE;
370    }
371
372#if X_BYTE_ORDER == X_BIG_ENDIAN
373    /* The offset information that is included in the BIOS on PC Matrox cards
374     * is not there on PowerPC cards.  Instead, we have to search the BIOS
375     * image for the magic signature.  This is the 16-bit value 0x412d.  This
376     * value is followed by the length of the PInS block.  We know that this
377     * must (currently) be either 0x80 or 0x40.
378     *
379     * Happy hunting.
380     */
381    for (offset = 0 ; offset < 0x7ffc ; offset++) {
382	if ((bios_data[offset] == 0x2e) && (bios_data[offset+1] == 0x41)
383	    && ((bios_data[offset+2] == 0x80) || (bios_data[offset+2] == 0x40))) {
384	    break;
385	}
386    }
387
388    if (offset == 0x7ffc) {
389	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
390		   "Video BIOS PInS data not found!\n");
391	return FALSE;
392    }
393#else
394    /* Get the info block offset */
395    offset = (unsigned)((bios_data[0x7ffd] << 8) | bios_data[0x7ffc]);
396#endif
397
398    /* Let the world know what we are up to */
399    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
400	       "Video BIOS info block at offset 0x%05lX\n",
401	       (long)(offset));
402
403
404    /* Determine the version of the PInS block.  This will determine how the
405     * data is processed.  Only the first version of the PInS data structure
406     * did *NOT* have the initial 0x412e (in little-endian order!) signature.
407     */
408
409    pins_data = & bios_data[ offset ];
410    if ( (pins_data[0] == 0x2e) && (pins_data[1] == 0x41) ) {
411	version = pins_data[5];
412	pins_len = pins_data[2];
413    }
414    else {
415	version = 1;
416	pins_len = get_u16( pins_data );
417    }
418
419
420    if ( (version < 1) || (version > 5) ) {
421	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
422		   "PInS data version (%u) not supported.\n", version);
423	return FALSE;
424    }
425
426    if ( pins_len != expected_length[ version ] ) {
427	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
428		   "PInS data length (%u) does not match expected length (%u)"
429		   " for version %u.X.\n",
430		   pins_len, expected_length[ version ], version);
431	return FALSE;
432    }
433
434    switch( version ) {
435    case 1:  mga_parse_bios_ver_1( & pMga->bios, pins_data ); break;
436    case 2:  mga_parse_bios_ver_2( & pMga->bios, pins_data ); break;
437    case 3:  mga_parse_bios_ver_3( & pMga->bios, pins_data ); break;
438    case 4:  mga_parse_bios_ver_4( & pMga->bios, pins_data ); break;
439    case 5:  mga_parse_bios_ver_5( & pMga->bios, pins_data ); break;
440    }
441
442#ifdef BIOS_DEBUG
443    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
444	       "system VCO = [%u, %u]\n",
445	       pMga->bios.system.min_freq, pMga->bios.system.max_freq);
446    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
447	       "pixel VCO  = [%u, %u]\n",
448	       pMga->bios.pixel.min_freq,  pMga->bios.pixel.max_freq);
449    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
450	       "video VCO  = [%u, %u]\n",
451	       pMga->bios.video.min_freq,  pMga->bios.video.max_freq);
452    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
453	       "memory clock = %ukHz\n", pMga->bios.mem_clock);
454    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
455	       "PLL reference frequency = %ukHz\n",
456	       pMga->bios.pll_ref_freq);
457    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
458	       "%s fast bitblt\n",
459	       (pMga->bios.fast_bitblt) ? "Has" : "Does not have");
460    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
461	       "Host interface: %s (%u)\n",
462	       host_interface_strings[ pMga->bios.host_interface ],
463	       pMga->bios.host_interface);
464#endif
465
466    return TRUE;
467}
468