NV50: Add NV_ARCH/CHIPSET defines for G80/G84
[nouveau] / src / nv_bios.c
1 /*
2  * Copyright 2005-2006 Erik Waling
3  * Copyright 2006 Stephane Marchesin
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  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23
24 #include "nv_include.h"
25 #include "nvreg.h"
26
27 #define DEBUGLEVEL 6
28 /*#define PERFORM_WRITE*/
29
30 /* TODO: 
31  *       * PLL algorithms.
32  */
33
34 #include <byteswap.h>
35 typedef struct {
36         Bool execute;
37         Bool repeat;
38 } init_exec_t;
39
40 typedef struct {
41         unsigned char *data;
42         unsigned int  length;
43
44         CARD16      init_tbls_offset;
45         CARD16      macro_index_offset;    
46         CARD16      macro_offset; 
47         CARD16      condition_offset;
48         CARD16      io_flag_condition_offset;
49 } bios_t;
50
51
52 typedef struct {
53         char* name;
54         unsigned char id;
55         int length;
56         int length_offset;
57         int length_multiplier;
58         Bool (*handler)(ScrnInfoPtr pScrn, bios_t *, CARD16, init_exec_t *);
59 } init_tbl_entry_t;
60
61 typedef struct {
62         unsigned char id[2];
63         unsigned short length;
64         unsigned short offset;
65 } bit_entry_t;
66
67 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec);
68
69 /* #define MACRO_SIZE              8 */
70 #define CONDITION_SIZE          12
71 #define IO_FLAG_CONDITION_SIZE  9 
72
73 void still_alive()
74 {
75         sync();
76 //      usleep(200000);
77 }
78
79 static int nv_valid_reg(CARD32 reg)
80 {
81         #define WITHIN(x,y,z) ((x>=y)&&(x<y+z))
82         if (WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
83                 return 1;
84         if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE))
85                 return 1;
86         if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE))
87                 return 1;
88         if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
89                 return 1;
90         if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
91                 return 1;
92         if (WITHIN(reg,NV_PGRAPH_OFFSET,NV_PGRAPH_SIZE))
93                 return 1;
94         if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
95                 return 1;
96         if (WITHIN(reg,NV_PTIMER_OFFSET,NV_PTIMER_SIZE))
97                 return 1;
98         if (WITHIN(reg,NV_PVIDEO_OFFSET,NV_PVIDEO_SIZE))
99                 return 1;
100         if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
101                 return 1;
102         if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
103                 return 1;
104         if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
105                 return 1;
106         if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
107                 return 1;
108         if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
109                 return 1;
110         if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
111                 return 1;
112         #undef WITHIN
113         return 0;
114 }
115
116 static int nv32_rd(ScrnInfoPtr pScrn, CARD32 reg, CARD32 *data)
117 {
118         NVPtr pNv = NVPTR(pScrn);
119         *data=pNv->REGS[reg/4];
120         return 1;
121 }
122
123 static int nv32_wr(ScrnInfoPtr pScrn, CARD32 reg, CARD32 data)
124 {
125 #ifdef PERFORM_WRITE
126         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "nv32_wr reg 0x%X value 0x%X\n",reg,data);
127         still_alive();
128         if (!nv_valid_reg(reg))
129         {
130                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "========= unknown reg 0x%X ==========\n",reg);
131                 return 0;
132         }
133
134         NVPtr pNv = NVPTR(pScrn);
135         pNv->REGS[reg/4]=data;
136 #endif
137         return 1;
138 }
139
140 void nv_set_crtc_index(ScrnInfoPtr pScrn, CARD8 index)
141 {
142 #ifdef PERFORM_WRITE
143         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "nv_set_crtc_index index 0x%X\n",index);
144         still_alive();
145         NVPtr pNv = NVPTR(pScrn);
146         volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
147         VGA_WR08(ptr, 0x3D4, index);
148 #endif
149 }
150
151 CARD8 nv_rd_crtc_data(ScrnInfoPtr pScrn)
152 {
153         NVPtr pNv = NVPTR(pScrn);
154         volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
155         return VGA_RD08(ptr, 0x3D5);
156 }
157
158 void nv_wr_crtc_data(ScrnInfoPtr pScrn, CARD8 val)
159 {
160 #ifdef PERFORM_WRITE
161         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "nv_wr_crtc_data value 0x%X\n",val);
162         still_alive();
163         NVPtr pNv = NVPTR(pScrn);
164         volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
165         VGA_WR08(ptr, 0x3D5, val);
166 #endif
167 }
168
169 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
170 {
171         /* INIT_PROG   opcode: 0x31
172          * 
173          * offset      (8  bit): opcode
174          * offset + 1  (32 bit): reg
175          * offset + 5  (32 bit): and mask
176          * offset + 9  (8  bit): shift right
177          * offset + 10 (8  bit): number of configurations
178          * offset + 11 (32 bit): register
179          * offset + 15 (32 bit): configuration 1
180          * ...
181          * 
182          * Starting at offset + 15 there are "number of configurations"
183          * 32 bit values. To find out which configuration value to use
184          * read "CRTC reg" on the CRTC controller with index "CRTC index"
185          * and bitwise AND this value with "and mask" and then bit shift the
186          * result "shift right" bits to the right.
187          * Assign "register" with appropriate configuration value.
188          */
189
190         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
191         CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
192         CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
193         CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
194         CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
195         CARD8 configuration;
196         CARD32 configval, tmp;
197
198         if (iexec->execute) {
199                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%04X\n", offset, 
200                                 reg);
201
202                 nv32_rd(pScrn, reg, &tmp);
203                 configuration = (tmp & and) >> shiftr;
204
205                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONFIGURATION TO USE: 0x%02X\n", 
206                                 offset, configuration);
207
208                 if (configuration <= nr) {
209
210                         configval = 
211                                 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
212
213                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, 
214                                         reg2, configval);
215                         
216                         if (nv32_rd(pScrn, reg2, &tmp)) {
217                                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", 
218                                                 offset, tmp);
219                         }
220                         nv32_wr(pScrn, reg2, configval);
221                 }
222         }
223         return TRUE;
224 }
225
226 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
227 {
228         /* INIT_IO_RESTRICT_PROG   opcode: 0x32
229          * 
230          * offset      (8  bit): opcode
231          * offset + 1  (16 bit): CRTC reg
232          * offset + 3  (8  bit): CRTC index
233          * offset + 4  (8  bit): and mask
234          * offset + 5  (8  bit): shift right
235          * offset + 6  (8  bit): number of configurations
236          * offset + 7  (32 bit): register
237          * offset + 11 (32 bit): configuration 1
238          * ...
239          * 
240          * Starting at offset + 11 there are "number of configurations"
241          * 32 bit values. To find out which configuration value to use
242          * read "CRTC reg" on the CRTC controller with index "CRTC index"
243          * and bitwise AND this value with "and mask" and then bit shift the
244          * result "shift right" bits to the right.
245          * Assign "register" with appropriate configuration value.
246          */
247
248         NVPtr pNv = NVPTR(pScrn);
249         volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
250         CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
251         CARD8  index = *((CARD8 *) (&bios->data[offset + 3]));
252         CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
253         CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
254         CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
255         CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
256         CARD8 configuration;
257         CARD32 configval, tmp;
258
259         if (iexec->execute) {
260                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset, 
261                                 crtcreg, index);
262
263                 VGA_WR08(ptr,crtcreg, index);
264                 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
265
266                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONFIGURATION TO USE: 0x%02X\n", 
267                                 offset, configuration);
268
269                 if (configuration <= nr) {
270                         configval = 
271                                 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
272
273                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, 
274                                         reg, configval);
275                         
276                         if (nv32_rd(pScrn, reg, &tmp)) {
277                                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", 
278                                                 offset, tmp);
279                         }
280                         nv32_wr(pScrn, reg, configval);
281                 }
282         }
283         return TRUE;
284 }
285
286 static Bool init_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
287 {
288         CARD8 repeats = *((CARD8 *) (&bios->data[offset + 1]));
289         CARD8 i;
290
291         if (iexec->execute) {
292                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REPEATING FOLLOWING SEGMENT %d TIMES.\n", 
293                                 offset, repeats);
294
295                 iexec->repeat = TRUE;
296
297                 for (i = 0; i < repeats - 1; i++)
298                         parse_init_table(pScrn, bios, offset + 2, iexec);
299
300                 iexec->repeat = FALSE;
301         }
302         return TRUE;
303 }
304
305 static Bool init_end_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
306 {
307         if (iexec->repeat)
308                 return FALSE;
309
310         return TRUE;
311 }
312
313 static Bool init_copy(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
314 {
315         /* XXX: double check this... */
316         NVPtr pNv = NVPTR(pScrn);
317         volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
318         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
319         CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
320         CARD8 and1 = *((CARD8 *) (&bios->data[offset + 6]));
321         CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 7]));
322         CARD8 index = *((CARD8 *) (&bios->data[offset + 9]));
323         CARD8 and2 = *((CARD8 *) (&bios->data[offset + 10]));
324         CARD32 data;
325         CARD8 crtcdata;
326
327         if (iexec->execute) {
328                 if (nv32_rd(pScrn, reg, &data)) {
329                         if (shift < 0x80) 
330                                 data >>= shift;
331                         else
332                                 data <<= (0x100 - shift);
333
334                         data &= and1;
335                         VGA_WR08(ptr,crtcreg, index);
336                         crtcdata = (VGA_RD08(ptr, crtcreg + 1) & and2) | (CARD8) data;
337
338                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
339                                         "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n"
340                                         , offset, crtcreg, index, crtcdata);
341
342                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
343                                         VGA_RD08(ptr, crtcreg + 1));
344 #ifdef PERFORM_WRITE 
345                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "init_copy crtcreg 0x%X value 0x%X\n",crtcreg+1,crtcdata);
346                         still_alive();
347                         printf("WRITE IS PERFORMED\n");
348                         VGA_WR08(ptr,crtcreg + 1, crtcdata);
349 #endif
350                 }
351         }
352         return TRUE;
353 }
354
355 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
356 {
357         if (iexec->execute) { 
358                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n",
359                         offset);
360         } else {
361                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",
362                         offset);
363         }
364
365         iexec->execute = !iexec->execute;
366         return TRUE;
367 }
368
369 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
370 {
371         NVPtr pNv = NVPTR(pScrn);
372         volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
373         CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
374         CARD16 crtcreg = *((CARD16 *) 
375                 (&bios->data[bios->io_flag_condition_offset + 
376                 cond * IO_FLAG_CONDITION_SIZE]));
377         CARD8 index = *((CARD8 *) 
378                 (&bios->data[bios->io_flag_condition_offset + 
379                 cond * IO_FLAG_CONDITION_SIZE + 2]));
380         CARD8 and1 = *((CARD8 *) 
381                 (&bios->data[bios->io_flag_condition_offset + 
382                 cond * IO_FLAG_CONDITION_SIZE + 3]));
383         CARD8 shift = *((CARD8 *) 
384                 (&bios->data[bios->io_flag_condition_offset + 
385                 cond * IO_FLAG_CONDITION_SIZE + 4]));
386         CARD16 offs = *((CARD16 *) 
387                 (&bios->data[bios->io_flag_condition_offset + 
388                 cond * IO_FLAG_CONDITION_SIZE + 5]));
389         CARD8 and2 = *((CARD8 *) 
390                 (&bios->data[bios->io_flag_condition_offset + 
391                 cond * IO_FLAG_CONDITION_SIZE + 7]));
392         CARD8 cmpval = *((CARD8 *) 
393                 (&bios->data[bios->io_flag_condition_offset + 
394                 cond * IO_FLAG_CONDITION_SIZE + 8]));
395
396         CARD8 data;
397
398         if (iexec->execute) {
399                 VGA_WR08(ptr,crtcreg, index);
400                 data = VGA_RD08(ptr, crtcreg + 1);
401                 data &= and1;
402                 offs += (data >> shift);
403                 data = *((CARD8 *) (&bios->data[offs]));
404                 data &= and2;
405
406                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
407                                 "0x%04X: CHECKING IF DATA: %02X equals COND: %02X\n", offset, 
408                                 data, cmpval);
409
410                 if (data == cmpval) {
411                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
412                                         "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n", 
413                                         offset);
414                 } else {
415                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
416                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
417                                         "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
418                         iexec->execute = FALSE;     
419                 }
420         }
421         return TRUE;
422 }
423
424 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
425 {
426         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
427         /* XXX: this needs to be confirmed... NOT CORRECT */
428         /*init_io_restrict_prog(bios, offset, iexec);*/
429
430         CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
431         CARD8  index = *((CARD8 *) (&bios->data[offset + 3]));
432         CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
433         CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
434         CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
435         CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
436         CARD8 configuration;
437         CARD32 configval, tmp;
438 #if 0
439         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset, 
440                 crtcreg, index, reg);
441
442         VGA_WR08(ptr,crtcreg, index);
443         configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
444
445         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONFIGURATION TO USE: 0x%02X\n", 
446                 offset, configuration);
447
448         if (configuration <= nr) {
449
450                 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &configval)) 
451                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", 
452                                 offset, configval);
453
454                 configval = 
455                         *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
456
457                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, 
458                         reg, configval);
459         }
460 #endif
461
462 #if 0
463         if (iexec->execute) {    
464                 switch (reg) {
465                 case 0x00004004:
466                         configval = 0x01014E07;
467                         break;
468                 case 0x00004024:
469                         configval = 0x13030E02;
470                         break;
471                 }
472
473                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, 
474                                 reg, configval);
475
476                 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
477                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", 
478                                         offset, tmp);
479
480                 nv32_wr(pScrn, reg, configval);
481         }
482 #endif
483         return TRUE;
484 }
485
486 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
487 {
488         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
489         CARD32 val = *((CARD32 *) (&bios->data[offset + 5]));
490         CARD32 configval, tmp;
491 #if 0
492         if (iexec->execute) {
493                 switch (reg) {
494                 case 0x00680508:
495                         configval = 0x00011F05;
496                         break;
497                 }
498
499                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
500                                 configval);
501
502                 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp)) 
503                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", 
504                                         offset, tmp);
505
506                 nv32_wr(pScrn, reg, configval);
507
508                 /*xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);*/
509         }
510 #endif
511         return TRUE;
512 }
513
514 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
515 {
516         CARD8 crtcindex = *((CARD8 *) (&bios->data[offset + 1]));
517         CARD8 crtcdata = *((CARD8 *) (&bios->data[offset + 2]));
518         CARD8 initial_index = *((CARD8 *) (&bios->data[offset + 3]));
519         CARD8 entries = *((CARD8 *) (&bios->data[offset + 4]));
520         CARD8 data;
521         int i;
522
523         if (iexec->execute) {
524                 for (i = 0; i < entries; i++) {
525                         nv_set_crtc_index(pScrn, crtcindex);
526
527                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CRTC INDEX: %02X    DATA: %02X\n", offset,
528                                         crtcindex, initial_index + i);
529
530                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
531                                         nv_rd_crtc_data(pScrn));
532
533                         nv_wr_crtc_data(pScrn, initial_index + i);
534
535                         nv_set_crtc_index(pScrn, crtcdata);
536
537                         data = *((CARD8 *) (&bios->data[offset + 5 + i]));
538
539                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CRTC INDEX: %02X    DATA: %02X\n", offset,
540                                         crtcdata, data);
541
542                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
543                                         nv_rd_crtc_data(pScrn));
544
545                         nv_wr_crtc_data(pScrn, data);
546                 }
547         }
548         return TRUE;
549 }
550
551 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
552 {
553         /* XXX: IS THIS CORRECT? check the typecast .. probably wrong */
554
555         NVPtr pNv = NVPTR(pScrn);
556         CARD8 index = *((CARD32 *) (&bios->data[offset + 1])); 
557         CARD8 and = *((CARD8 *) (&bios->data[offset + 2]));
558         CARD8 or = *((CARD8 *) (&bios->data[offset + 3]));
559         CARD8 data;
560
561         if (iexec->execute) {
562                 nv_set_crtc_index(pScrn, index);
563                 data = (nv_rd_crtc_data(pScrn) & and) | or;
564                 /*printf("and: 0x%02x    or: 0x%02x\n", and, or);*/
565                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset, 
566                                 index, data);
567
568                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
569                                 nv_rd_crtc_data(pScrn));
570
571                 nv_wr_crtc_data(pScrn, data);
572         }
573         return TRUE;
574 }
575
576 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
577 {
578         /* INIT_ZM_CR   opcode: 0x53
579          * 
580          * offset      (8  bit): opcode
581          * offset + 1  (8  bit): CRTC index
582          * offset + 2  (8  bit): value
583          * 
584          * Assign "value" to CRTC register with index "CRTC index".
585          */
586
587         NVPtr pNv = NVPTR(pScrn);
588         CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
589         CARD8 value = *((CARD8 *) (&bios->data[offset + 2]));
590
591         if (iexec->execute) {
592                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset, 
593                                 index, value);
594
595                 nv_set_crtc_index(pScrn, index);
596
597                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
598                                 nv_rd_crtc_data(pScrn));
599
600                 nv_wr_crtc_data(pScrn, value);
601         }
602         return TRUE;
603 }
604
605 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
606 {
607         /* INIT_ZM_CR   opcode: 0x54
608          * 
609          * offset      (8  bit): opcode
610          * offset + 1  (8  bit): number of groups (index, value)
611          * offset + 2  (8  bit): index 1
612          * offset + 3  (8  bit): value 1
613          * ...
614          * 
615          * Assign "value n" to CRTC register with index "index n".
616          */
617     
618         CARD8 nr = *((CARD8 *) (&bios->data[offset + 1]));
619         CARD8 index, value;
620         int i;
621         
622         if (iexec->execute) {
623                 for (i = 0; i < nr; i++) {
624                         index = *((CARD8 *) (&bios->data[offset + 2 + 2 * i]));
625                         value = *((CARD8 *) (&bios->data[offset + 2 + 2 * i + 1]));
626
627                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
628                                         index, value);
629
630                         nv_set_crtc_index(pScrn, index);
631
632                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
633                                         nv_rd_crtc_data(pScrn));
634                         nv_wr_crtc_data(pScrn, value);
635                 }
636         }
637         return TRUE;
638 }
639
640 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
641 {
642         /* My BIOS does not use this command. */
643         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
644
645         return FALSE;
646 }
647
648 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
649 {
650         /* INIT_ZM_REG_SEQUENCE   opcode: 0x58
651          * 
652          * offset      (8  bit): opcode
653          * offset + 1  (32 bit): register base
654          * offset + 5  (8  bit): nr
655          * offset + 6  (32 bit): value to assign "register base" + 4
656          * ...
657          * 
658          * Initialzies a sequence of "nr" registers starting at "register base".
659          */
660
661         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
662         CARD32 nr = *((CARD8 *) (&bios->data[offset + 5]));
663         CARD32 data;
664         CARD32 tmp;
665         int i;
666
667         if (iexec->execute) { 
668                 for (i = 0; i < nr; i++) {
669                         data = *((CARD32 *) (&bios->data[offset + 6 + i * 4]));
670                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
671                                         reg + i * 4, data);
672
673                         if (nv32_rd(pScrn, reg + i * 4, &tmp)) { 
674                                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", 
675                                                 offset, tmp);
676                         }
677
678                         nv32_wr(pScrn, reg + i * 4, data);
679                 }
680         }
681         return TRUE;
682 }
683
684 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
685 {
686         /* INIT_INDIRECT_REG opcode: 0x5A
687          * 
688          * offset      (8  bit): opcode
689          * offset + 1  (32 bit): register
690          * offset + 5  (16 bit): adress offset (in bios)
691          *
692          * Lookup value at offset data in the bios and write it to reg
693          */
694         NVPtr pNv = NVPTR(pScrn);
695         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
696         CARD32 data = *((CARD16 *) (&bios->data[offset + 5]));
697         CARD32 data2 = bios->data[data];
698
699         if (iexec->execute) {
700                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
701                                 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n", 
702                                 offset, reg, data, data2);
703
704                 if (DEBUGLEVEL >= 6) {
705                         CARD32 tmpval;
706                         nv32_rd(pScrn, reg, &tmpval);
707                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
708                 }
709
710                 nv32_wr(pScrn, reg, data2);
711         }
712         return TRUE;
713 }
714
715 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
716 {
717         /* INIT_SUB_DIRECT   opcode: 0x5B
718          * 
719          * offset      (8  bit): opcode
720          * offset + 1  (16 bit): subroutine offset (in bios)
721          *
722          * Calls a subroutine that will execute commands until INIT_DONE
723          * is found. 
724          */
725
726         CARD16 sub_offset = *((CARD16 *) (&bios->data[offset + 1]));
727
728         if (iexec->execute) {
729                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: EXECUTING SUB-ROUTINE AT: 0x%04X\n", 
730                                 offset, sub_offset);
731
732                 parse_init_table(pScrn, bios, sub_offset, iexec);
733
734                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: END OF SUB-ROUTINE\n", offset);
735         }
736         return TRUE;
737 }
738
739 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
740 {   
741         CARD32 srcreg = *((CARD32 *) (&bios->data[offset + 1]));
742         CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
743         CARD32 and1 = *((CARD32 *) (&bios->data[offset + 6]));
744         CARD32 xor = *((CARD32 *) (&bios->data[offset + 10]));
745         CARD32 dstreg = *((CARD32 *) (&bios->data[offset + 14]));
746         CARD32 and2 = *((CARD32 *) (&bios->data[offset + 18]));
747         CARD32 srcdata;
748         CARD32 dstdata;
749         
750         if (iexec->execute) {
751                 nv32_rd(pScrn, srcreg, &srcdata);
752                 
753                 if (shift > 0)
754                         srcdata >>= shift;
755                 else
756                         srcdata <<= shift;
757
758                 srcdata = (srcdata & and1) ^ xor;
759
760                 nv32_rd(pScrn, dstreg, &dstdata);
761                 dstdata &= and2;
762
763                 dstdata |= srcdata;
764
765                 CARD32 tmp;             
766                 nv32_rd(pScrn, dstreg, &tmp);
767
768                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, dstreg, 
769                                 dstdata);
770
771                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmp);
772
773                 nv32_wr(pScrn, dstreg, dstdata);
774         }
775         return TRUE;
776 }
777
778 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
779 {
780         NVPtr pNv = NVPTR(pScrn);
781         volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
782         CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
783         CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
784         CARD8 value = *((CARD8 *) (&bios->data[offset + 4]));
785
786         if (iexec->execute) {
787                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
788                                 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n", 
789                                 offset, crtcreg, index, value);
790
791                 VGA_WR08(ptr,crtcreg, index);
792
793                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
794                                 VGA_RD08(ptr, crtcreg + 1));
795         
796 #ifdef PERFORM_WRITE
797                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "init_zm_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,value);
798                 still_alive();
799                 VGA_WR08(ptr,crtcreg + 1, value);
800 #endif
801         }
802         return TRUE;
803 }
804
805 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
806 {
807         // FIXME replace with a suitable implementation
808 #if 0
809         CARD16 ramcfg = *((CARD16 *) (&bios->data[bios->ram_table_offset]));
810         CARD32 pfb_debug;
811         CARD32 strapinfo;
812         CARD32 ramcfg2;
813
814         if (iexec->execute) {
815                 nv32_rd(pScrn, 0x00101000, &strapinfo);
816                 nv32_rd(pScrn, 0x00100080, &pfb_debug);
817
818                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "STRAPINFO: 0x%08X\n", strapinfo);
819                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "PFB_DEBUG: 0x%08X\n", pfb_debug);
820                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "RAM CFG: 0x%04X\n", ramcfg);
821
822                 pfb_debug &= 0xffffffef;
823                 strapinfo >>= 2;
824                 strapinfo &= 0x0000000f;
825                 ramcfg2 = *((CARD16 *) 
826                                 (&bios->data[bios->ram_table_offset + (2 * strapinfo)])); 
827
828                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "AFTER MANIPULATION\n");
829                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "STRAPINFO: 0x%08X\n", strapinfo);
830                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "PFB_DEBUG: 0x%08X\n", pfb_debug);
831                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "RAM CFG2: 0x%08X\n", ramcfg2);
832
833                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
834
835                 CARD32 reg1;
836                 CARD32 reg2;
837
838                 nv32_rd(pScrn, 0x00100200, &reg1);
839                 nv32_rd(pScrn, 0x0010020C, &reg2);
840
841                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x00100200: 0x%08X\n", reg1);
842                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x0010020C: 0x%08X\n", reg2);
843         }
844 #endif
845         return TRUE;
846 }
847
848 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
849 {
850         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
851         CARD32 value1 = *((CARD32 *) (&bios->data[offset + 5]));
852         CARD32 value2 = *((CARD32 *) (&bios->data[offset + 9]));
853
854         if (iexec->execute) {
855                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", 
856                                 offset, reg, value1);
857                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", 
858                                 offset, reg, value2);
859
860                 if (DEBUGLEVEL >= 6) {
861                         CARD32 tmpval;
862                         nv32_rd(pScrn, reg, &tmpval);
863                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
864 #if 0
865                         nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), &tmpval);
866                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: PCICFG_ROMSHADOW: 0x%02X\n", offset, tmpval);
867 #endif
868                 }
869                 nv32_wr(pScrn, reg, value1);
870                 nv32_wr(pScrn, reg, value2);
871         }
872         /* PCI Config space init needs to be added here. */
873         /* if (nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), value1)) */
874         /*     nv32_wr(pScrn, PCICFG(PCICFG_ROMSHADOW), value1 & 0xfffffffe) */
875
876         return TRUE;
877 }
878
879 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
880 {
881         /* INIT_INDEX_IO8   opcode: 0x69
882          * 
883          * offset      (8  bit): opcode
884          * offset + 1  (16 bit): CRTC reg
885          * offset + 3  (8  bit): and mask
886          * offset + 4  (8  bit): or with
887          * 
888          * 
889          */
890
891         NVPtr pNv = NVPTR(pScrn);
892         volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
893         CARD16 reg = *((CARD16 *) (&bios->data[offset + 1]));
894         CARD8 and  = *((CARD8 *) (&bios->data[offset + 3]));
895         CARD8 or = *((CARD8 *) (&bios->data[offset + 4]));
896         CARD8 data;
897
898         if (iexec->execute) {
899                 data = (VGA_RD08(ptr, reg) & and) | or;
900
901                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
902                                 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n", 
903                                 offset, reg, data);
904                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
905                                 VGA_RD08(ptr, reg));
906
907 #ifdef PERFORM_WRITE
908                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
909                 still_alive();
910                 VGA_WR08(ptr, reg, data);
911 #endif
912         }
913         return TRUE;
914 }
915
916 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
917 {
918         CARD8 sub = *((CARD8 *) (&bios->data[offset + 1]));
919
920         if (iexec->execute) {
921                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: EXECUTING SUB-SCRIPT: %d\n", offset, sub);
922
923                 parse_init_table(pScrn, bios, 
924                                 *((CARD16 *) (&bios->data[bios->init_tbls_offset + sub * 2])),
925                                 iexec);
926
927                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: END OF SUB-SCRIPT\n", offset);
928         }
929         return TRUE;
930 }
931
932 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
933 {
934         /* INIT_RAM_CONDITION   opcode: 0x6D
935          * 
936          * offset      (8  bit): opcode
937          * offset + 1  (8  bit): and mask
938          * offset + 2  (8  bit): cmpval
939          *
940          * Test if (NV_PFB_BOOT & and mask) matches cmpval
941          */
942         NVPtr pNv = NVPTR(pScrn);
943         CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
944         CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
945         CARD32 data;
946
947         if (iexec->execute) {
948                 data=(pNv->PFB[NV_PFB_BOOT/4])&and;
949
950                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
951                                 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
952                                 offset, data, cmpval);
953
954                 if (data == cmpval) {
955                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
956                                         "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
957                                         offset);
958                 } else {
959                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
960                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
961                                         "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
962                         iexec->execute = FALSE;     
963                 }
964         }
965         return TRUE;
966 }
967
968 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
969 {
970         /* INIT_NV_REG   opcode: 0x6E
971          * 
972          * offset      (8  bit): opcode
973          * offset + 1  (32 bit): register
974          * offset + 5  (32 bit): and mask
975          * offset + 9  (32 bit): or with
976          *
977          * Assign "register" to (REGVAL(register) & "and mask") | "or with";
978          */
979
980         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
981         CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
982         CARD32 or = *((CARD32 *) (&bios->data[offset + 9]));
983         CARD32 data;
984         unsigned int status;
985
986         if (iexec->execute) {
987                 /* end temp test */
988                 if ((status = nv32_rd(pScrn, reg, &data))) {
989                         data = (data & and) | or;
990                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, 
991                                         reg, data);
992
993                         if (DEBUGLEVEL >= 6 && status) {
994                                 CARD32 tmpval;
995                                 nv32_rd(pScrn, reg, &tmpval);
996                                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n",
997                                                 offset, tmpval);
998                         }
999
1000                         nv32_wr(pScrn, reg, data);
1001                         /* Assign: reg = data */
1002                 }
1003         }
1004         return TRUE;
1005 }
1006
1007 #if 0
1008 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1009 {
1010         // FIXME replace with the haiku version
1011         /* XXX: Not sure this is correct... */
1012
1013         CARD8 macro = *((CARD8 *) (&bios->data[offset + 1]));
1014         CARD32 reg = 
1015                 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE]));
1016         CARD32 value =
1017                 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE + 4]));
1018
1019         if (iexec->execute) {
1020                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: EXECUTING MACRO: 0x%02X\n", offset, macro);
1021                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
1022                                 value);
1023
1024                 if (DEBUGLEVEL >= 6) {
1025                         CARD32 tmpval;
1026                         nv32_rd(pScrn, reg, &tmpval);
1027                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1028                                         offset, tmpval);
1029                 }
1030
1031                 nv32_wr(pScrn, reg, value);
1032         }
1033         return TRUE;
1034 }
1035 #endif
1036
1037 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1038 {
1039         CARD8 index = *((CARD8 *) (&bios->data[offset + 1]));
1040         CARD32 tmp = bios->macro_index_offset + (index << 1);
1041         CARD32 offs =  *((CARD8 *) (&bios->data[tmp]))  << 3;
1042         CARD32 nr = *((CARD8 *) (&bios->data[tmp + 1]));
1043         CARD32 reg, data;
1044
1045         int i;
1046         
1047     if (iexec->execute) {
1048             offs += bios->macro_offset;
1049             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: WRITE %d 32-BIT REGS:\n", offset, nr);
1050
1051             for (i = 0; i < nr; i++) {
1052                     reg = *((CARD32 *) (&bios->data[offs + (i << 3)]));
1053                     data = *((CARD32 *) (&bios->data[offs + (i << 3) + 4]));
1054                     
1055                     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1056                         reg, data);
1057
1058                     if (DEBUGLEVEL >= 6) {
1059                             CARD32 tmpval;
1060                             nv32_rd(pScrn, reg, &tmpval);
1061                             xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1062                                 offset, tmpval);
1063                     }
1064
1065                     nv32_wr(pScrn, reg, data);
1066             }
1067     }
1068     return TRUE;
1069 }
1070
1071 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1072 {
1073         return TRUE;
1074 }
1075
1076 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1077 {
1078         if (!iexec->execute) {
1079                 iexec->execute = TRUE;;
1080                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n",
1081                                 offset);
1082         }
1083         return TRUE;
1084 }
1085
1086 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1087 {
1088         /* INIT_RAM_CONDITION2   opcode: 0x73
1089          * 
1090          * offset      (8  bit): opcode
1091          * offset + 1  (8  bit): and mask
1092          * offset + 2  (8  bit): cmpval
1093          *
1094          * Test if (NV_EXTDEV_BOOT & and mask) matches cmpval
1095          */
1096         NVPtr pNv = NVPTR(pScrn);
1097         CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
1098         CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
1099         CARD32 data;
1100
1101         if (iexec->execute) {
1102                 data=(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT))&and;
1103                 
1104                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1105                                 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1106                                 offset, data, cmpval);
1107
1108                 if (data == cmpval) {
1109                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1110                                         "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1111                                         offset);
1112                 } else {
1113                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1114                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1115                                         "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
1116                         iexec->execute = FALSE;     
1117                 }
1118         }
1119         return TRUE;
1120 }
1121
1122 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1123 {
1124         /* INIT_TIME   opcode: 0x74
1125          * 
1126          * offset      (8  bit): opcode
1127          * offset + 1  (16 bit): time
1128          * 
1129          * Sleep for "time" microseconds.
1130          */
1131
1132         CARD16 time = *((CARD16 *) (&bios->data[offset + 1]));
1133
1134         if (iexec->execute) {
1135                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: Sleeping for 0x%04X microseconds.\n", 
1136                                 offset, time);
1137
1138                 usleep(time);
1139         }
1140         return TRUE;
1141 }
1142
1143 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1144 {
1145         CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
1146         CARD32 reg = 
1147                 *((CARD32 *) 
1148                                 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE]));
1149         CARD32 and = 
1150                 *((CARD32 *) 
1151                                 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 4]));
1152         CARD32 cmpval = 
1153                 *((CARD32 *) 
1154                                 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 8]));
1155         CARD32 data;
1156
1157         if (iexec->execute) {
1158                 if (nv32_rd(pScrn, reg, &data)) {
1159                         data &= and;
1160
1161                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1162                                         "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1163                                         offset, data, cmpval);
1164
1165                         if (data == cmpval) {
1166                                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1167                                                 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1168                                                 offset);
1169                         } else {
1170                                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1171                                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1172                                                 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
1173                                 iexec->execute = FALSE;     
1174                         }
1175                 }
1176         }
1177         return TRUE;
1178 }
1179
1180 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1181 {
1182         /* INIT_INDEX_IO   opcode: 0x78
1183          * 
1184          * offset      (8  bit): opcode
1185          * offset + 1  (16 bit): CRTC reg
1186          * offset + 3  (8  bit): CRTC index
1187          * offset + 4  (8  bit): and mask
1188          * offset + 5  (8  bit): or with
1189          * 
1190          * 
1191          */
1192
1193         NVPtr pNv = NVPTR(pScrn);
1194         volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
1195         CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
1196         CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
1197         CARD8 and  = *((CARD8 *) (&bios->data[offset + 4]));
1198         CARD8 or = *((CARD8 *) (&bios->data[offset + 5]));
1199         CARD8 data;
1200         
1201         if (iexec->execute) {
1202                 VGA_WR08(ptr,crtcreg, index);
1203                 /* data at reg + 1 */
1204                 data = (VGA_RD08(ptr, crtcreg + 1) & and) | or;
1205
1206                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1207                                 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n", 
1208                                 offset, crtcreg, index, data);
1209                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
1210                                 VGA_RD08(ptr, crtcreg + 1));
1211
1212 #ifdef PERFORM_WRITE
1213                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "init_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,data);
1214                 still_alive();
1215                 VGA_WR08(ptr,crtcreg + 1, data);
1216 #endif
1217         }
1218         return TRUE;
1219 }
1220
1221 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1222 {
1223         /* INIT_ZM_REG   opcode: 0x7A
1224          * 
1225          * offset      (8  bit): opcode
1226          * offset + 1  (32 bit): register
1227          * offset + 5  (32 bit): value
1228          * 
1229          * Assign "register" to "value";
1230          */
1231
1232         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1233         CARD32 value = *((CARD32 *) (&bios->data[offset + 5]));
1234
1235         if (iexec->execute) {
1236                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", 
1237                                 offset, reg, value);
1238
1239                 if (DEBUGLEVEL >= 6) {
1240                         CARD32 tmpval;
1241                         nv32_rd(pScrn, reg, &tmpval);
1242                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1243                 }
1244
1245                 nv32_wr(pScrn, reg, value);
1246
1247                 /* Assign: reg = value */
1248         }
1249         return TRUE;
1250 }
1251
1252 static init_tbl_entry_t itbl_entry[] = {
1253         /* command name                       , id  , length  , offset  , mult    , command handler                 */
1254         { "INIT_PROG"                         , 0x31, 15      , 10      , 4       , init_prog                       },
1255         { "INIT_IO_RESTRICT_PROG"             , 0x32, 11      , 6       , 4       , init_io_restrict_prog           },
1256         { "INIT_REPEAT"                       , 0x33, 2       , 0       , 0       , init_repeat                     },
1257         { "INIT_END_REPEAT"                   , 0x36, 1       , 0       , 0       , init_end_repeat                 },
1258         { "INIT_COPY"                         , 0x37, 11      , 0       , 0       , init_copy                       },
1259         { "INIT_NOT"                          , 0x38, 1       , 0       , 0       , init_not                        },
1260         { "INIT_IO_FLAG_CONDITION"            , 0x39, 2       , 0       , 0       , init_io_flag_condition          },
1261 /*      { "INIT_INDEX_ADDRESS_LATCHED"        , 0x49, x       , x       , x,      , init_idx_addr_latched           }, */       
1262         { "INIT_IO_RESTRICT_PLL"              , 0x4A, 43      , 0       , 0       , init_io_restrict_pll            },
1263         { "INIT_PLL"                          , 0x4B, 9       , 0       , 0       , init_pll                        },
1264 /*      { "INIT_I2C_BYTE"                     , 0x4C, x       , x       , x       , init_i2c_byte                   }, */
1265 /*      { "INIT_ZM_I2C_BYTE"                  , 0x4D, x       , x       , x       , init_zm_i2c_byte                }, */
1266 /*      { "INIT_ZM_I2C"                       , 0x4E, x       , x       , x       , init_zm_i2c                     }, */
1267         { "INIT_CR_INDEX_ADDRESS_LATCHED"     , 0x51, 5       , 4       , 1       , init_cr_idx_adr_latch           },
1268         { "INIT_CR"                           , 0x52, 4       , 0       , 0       , init_cr                         },
1269         { "INIT_ZM_CR"                        , 0x53, 3       , 0       , 0       , init_zm_cr                      },
1270         { "INIT_ZM_CR_GROUP"                  , 0x54, 2       , 1       , 2       , init_zm_cr_group                },
1271         { "INIT_CONDITION_TIME"               , 0x56, 3       , 0       , 0       , init_condition_time             },
1272         { "INIT_ZM_REG_SEQUENCE"              , 0x58, 6       , 5       , 4       , init_zm_reg_sequence            },
1273         { "INIT_INDIRECT_REG"                 , 0x5A, 7       , 0       , 0       , init_indirect_reg               },
1274         { "INIT_SUB_DIRECT"                   , 0x5B, 3       , 0       , 0       , init_sub_direct                 },
1275         { "INIT_COPY_NV_REG"                  , 0x5F, 22      , 0       , 0       , init_copy_nv_reg                },
1276         { "INIT_ZM_INDEX_IO"                  , 0x62, 5       , 0       , 0       , init_zm_index_io                },
1277         { "INIT_COMPUTE_MEM"                  , 0x63, 1       , 0       , 0       , init_compute_mem                },
1278         { "INIT_RESET"                        , 0x65, 13      , 0       , 0       , init_reset                      },
1279 /*      { "INIT_NEXT"                         , 0x66, x       , x       , x       , init_next                       }, */       
1280 /*      { "INIT_NEXT"                         , 0x67, x       , x       , x       , init_next                       }, */       
1281 /*      { "INIT_NEXT"                         , 0x68, x       , x       , x       , init_next                       }, */       
1282         { "INIT_INDEX_IO8"                    , 0x69, 5       , 0       , 0       , init_index_io8                  },
1283         { "INIT_SUB"                          , 0x6B, 2       , 0       , 0       , init_sub                        },
1284         { "INIT_RAM_CONDITION"                , 0x6D, 3       , 0       , 0       , init_ram_condition              },
1285         { "INIT_NV_REG"                       , 0x6E, 13      , 0       , 0       , init_nv_reg                     },
1286         { "INIT_MACRO"                        , 0x6F, 2       , 0       , 0       , init_macro                      },
1287         { "INIT_DONE"                         , 0x71, 1       , 0       , 0       , init_done                       },
1288         { "INIT_RESUME"                       , 0x72, 1       , 0       , 0       , init_resume                     },
1289         { "INIT_RAM_CONDITION2"               , 0x73, 9       , 0       , 0       , init_ram_condition2             },
1290         { "INIT_TIME"                         , 0x74, 3       , 0       , 0       , init_time                       },
1291         { "INIT_CONDITION"                    , 0x75, 2       , 0       , 0       , init_condition                  },
1292 /*      { "INIT_IO_CONDITION",                , 0x76, x       , x,      , x       , init_io_condition               }, */
1293         { "INIT_INDEX_IO"                     , 0x78, 6       , 0       , 0       , init_index_io                   },
1294 /*      { "INIT_PLL2"                         , 0x79, x       , x       , x       , init_pll2                       }, */
1295         { "INIT_ZM_REG"                       , 0x7A, 9       , 0       , 0       , init_zm_reg                     },
1296 /*      { "INIT_RAM_RESTRICT_ZM_REG_GROUP"    , 0x8F, x       , x       , x       , init_ram_restrict_zm_reg_group  }, */
1297 /*      { "INIT_COPY_ZM_REG"                  , 0x90, x       , x       , x       , init_copy_zm_reg                }, */
1298 /*      { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, x       , x       , x       , init_zm_reg_group_addr_latched  }, */
1299 /*      { "INIT_RESERVED"                     , 0x92, x       , x       , x       , init_reserved                   }, */
1300         { 0                                   , 0   , 0       , 0       , 0       , 0                               }
1301 };
1302
1303 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
1304 {
1305         /* Calculates the length of a given init table entry. */
1306         return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
1307 }
1308
1309 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
1310 {
1311         /* Parses all commands in a init table. */
1312
1313         /* We start out executing all commands found in the
1314          * init table. Some op codes may change the status
1315          * of this variable to SKIP, which will cause
1316          * the following op codes to perform no operation until
1317          * the value is changed back to EXECUTE.
1318          */
1319         unsigned char id;
1320         int i;
1321
1322         int count=0;
1323         /* Loop as long as INIT_DONE (command id 0x71) has not been found
1324          * (and offset < bios length just in case... )
1325          * (and no more than 10000 iterations just in case... ) */
1326         while (((id = bios->data[offset]) != 0x71) && (offset < bios->length) && (count++<10000)) {
1327                 /* Find matching id in itbl_entry */
1328                 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
1329                         ;
1330
1331                 if (itbl_entry[i].name) {
1332                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X:  [ (0x%02X) -  %s ]\n", offset, 
1333                                 itbl_entry[i].id, itbl_entry[i].name);
1334
1335                         /* execute eventual command handler */
1336                         if (itbl_entry[i].handler)
1337                                 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
1338                                         break;
1339                 } else {
1340                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: Init table command not found: 0x%02X\n", 
1341                                 offset, id);
1342                 }
1343
1344                 /* Add the offset of the current command including all data
1345                  * of that command. The offset will then be pointing on the
1346                  * next op code.
1347                  */
1348                 offset += get_init_table_entry_length(bios, offset, i);
1349         }
1350 }
1351
1352 void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios)
1353 {
1354         /* Loops and calls parse_init_table() for each present table. */
1355
1356         int i = 0;
1357         CARD16 table;
1358         init_exec_t iexec = {TRUE, FALSE};
1359
1360         while (table = *((CARD16 *) (&bios->data[bios->init_tbls_offset + i]))) {
1361         
1362                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: Parsing init table %d\n", 
1363                         table, i / 2);
1364
1365                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",table);
1366                 still_alive();
1367                 parse_init_table(pScrn, bios, table, &iexec);         
1368                 i += 2;
1369         }
1370 }
1371
1372 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
1373 {
1374         /* Parses the init table segment that the bit entry points to.
1375          * Starting at bitentry->offset: 
1376          * 
1377          * offset + 0  (16 bits): offset of init tables
1378          * offset + 2  (16 bits): macro index table offset
1379          * offset + 4  (16 bits): macro offset
1380          * offset + 6  (16 bits): condition offset
1381          * offset + 8  (16 bits): io flag condition offset (?)
1382          * offset + 10 (16 bits): io flag condition offset (?)
1383          * offset + 12 (16 bits): unknown
1384          *
1385          * offset + 8 and offset + 10 seems to contain the same
1386          * offsets on all bioses i have checked. Don't know which
1387          * one is the correct, therefore this code will bail out
1388          * if the two values are not the same.
1389          *
1390          * TODO:
1391          * * In addition to "conditions" and "io flag conditions" there seems to be
1392          *   "io conditions". These are probably located at offset + (8, 10 or 12).
1393          *    We need more BIOS dumps to figure this out...
1394          * 
1395          * * Are 'I' bit entries always of length 0xE?
1396          * 
1397          */
1398
1399         if (bitentry->length < 12) {
1400                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "Unable to regocnize BIT init table entry.\n");
1401                 return 0;
1402         }
1403
1404         bios->init_tbls_offset = *((CARD16 *) (&bios->data[bitentry->offset]));
1405         bios->macro_index_offset = *((CARD16 *) (&bios->data[bitentry->offset + 2]));
1406         bios->macro_offset = *((CARD16 *) (&bios->data[bitentry->offset + 4]));
1407         bios->condition_offset = 
1408                 *((CARD16 *) (&bios->data[bitentry->offset + 6]));
1409         if (*((CARD16 *) (&bios->data[bitentry->offset + 8])) != 
1410                 *((CARD16 *) (&bios->data[bitentry->offset + 10]))) {
1411                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "Unable to find IO flag condition offset.\n");
1412                 return 0;
1413         }
1414
1415         bios->io_flag_condition_offset =
1416                 *((CARD16 *) (&bios->data[bitentry->offset + 8]));
1417
1418         parse_init_tables(pScrn, bios);
1419
1420         return 1;
1421 }
1422
1423 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1424 {
1425         bit_entry_t *bitentry;
1426         char done = 0;
1427
1428         while (!done) {
1429                 bitentry = (bit_entry_t *) &bios->data[offset];
1430
1431                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: Found BIT command with id 0x%02X\n", 
1432                                 offset, bitentry->id[0]); 
1433
1434                 switch (bitentry->id[0]) {
1435                 case 0:
1436                         /* id[0] = 0 and id[1] = 0  ==> end of BIT struture */
1437                         if (bitentry->id[1] == 0)
1438                                 done = 1;
1439                         break;
1440                 case 'I':
1441                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1442                                 "0x%04X: Found init table entry in BIT structure.\n", 
1443                                 offset);
1444
1445                         parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1446                         /*parse_init_tables(pScrn, bios);*/
1447                         break;
1448                         
1449                         /* TODO: What kind of information does the other BIT entrys point to?
1450                          *       'P' entry is probably performance tables, but there are
1451                          *       quite a few others...
1452                          */
1453                 }
1454
1455                 offset += sizeof(bit_entry_t);
1456         }
1457 }
1458
1459 static unsigned short brs(unsigned char *data, int offset)
1460 {
1461   unsigned short ret;
1462
1463   ret = (data[offset]) | ((data[offset+1]) << 8);
1464   return ret;
1465 }
1466
1467 static void parse_pins_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1468 {
1469         int pins_version_major=bios->data[offset+5];
1470         int pins_version_minor=bios->data[offset+6];
1471         int init1 = bios->data[offset + 18] + (bios->data[offset + 19] * 256);     
1472         int init2 = bios->data[offset + 20] + (bios->data[offset + 21] * 256);     
1473         int init_size = bios->data[offset + 22] + (bios->data[offset + 23] * 256) + 1;                                                    
1474         int ram_tab;
1475         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "PINS version %d.%d\n",pins_version_major,pins_version_minor);
1476
1477 #if 0
1478         if (pins_version_major==2)
1479                 ram_tab = init1-0x0010;
1480         else
1481                 ram_tab = bios->data[offset + 24] + (bios->data[offset + 25] * 256);
1482
1483         if ((pins_version_major==5)&&(pins_version_minor>=6))
1484         {
1485                 /* VCO range info */
1486         }
1487
1488         if ((pins_version_major==5)&&(pins_version_minor>=16))
1489         {
1490
1491         }
1492
1493         parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1494
1495 #endif
1496 }
1497
1498 static unsigned int findstr(bios_t* bios, unsigned char *str, int len)
1499 {
1500         int i;
1501
1502         for (i = 2; i < bios->length; i++)
1503                 if (strncmp(&bios->data[i], str, len) == 0)
1504                         return i;
1505
1506         return 0;
1507 }
1508
1509 #define G5_FIXED_LOC 0xe2f8
1510
1511
1512 static unsigned int nv_find_dcb_table(ScrnInfoPtr pScrn, bios_t *bios)
1513 {
1514         NVPtr pNv = NVPTR(pScrn);
1515         CARD16 bufloc;
1516         int is_g5 = 0;
1517         CARD32 sig;
1518         char *table2;
1519         unsigned char headerSize, entries;
1520         CARD32 header_word;
1521         int i;
1522         int sig_offsets[2] = { 0x4, 0x6 };
1523         int offset = -1;
1524
1525         /* get the offset from 0x36 */
1526         
1527         bufloc = *(CARD16 *)&bios->data[0x36];
1528
1529         if (bufloc == 0x0) {
1530                 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV43) {
1531                         is_g5 = 1;
1532                         bufloc = G5_FIXED_LOC;
1533                 } else {
1534                         return 0;
1535                 }
1536         }
1537         
1538         table2 = &bios->data[bufloc];
1539
1540         /* lets play hunt the signature */
1541         for (i = 0; i < sizeof(sig_offsets) / sizeof(int); i++) {
1542           sig = *(uint32_t*)(table2 + sig_offsets[i]);
1543           if ((sig == 0x4edcbdcb) || (sig == 0xcbbddc4e)) {
1544             offset = sig_offsets[i];
1545             break;
1546           }
1547         }
1548         if (offset == -1)
1549           return 0;
1550
1551         if (offset == 6) {
1552           header_word = *(uint32_t *)table2;
1553           if (is_g5) {
1554             headerSize = 0x3c;
1555             entries = 0xa;
1556           } else {
1557             headerSize = (header_word >> 8) & 0xff;
1558             entries = (header_word >> 16) & 0xff;
1559           }
1560         } else {
1561           entries = 0xa;
1562           headerSize = 0x8;
1563         }
1564
1565         ErrorF("DCB size is %02X, entries is %02X\n", headerSize, entries);
1566         if (entries >= NV40_NUM_DCB_ENTRIES)
1567                 entries = NV40_NUM_DCB_ENTRIES;
1568
1569         for (i = 0; i < entries; i++) {
1570                 if (is_g5)
1571                         pNv->dcb_table[i] = __bswap_32(*(uint32_t *)&table2[headerSize + 8 * i]);
1572                 else
1573                         pNv->dcb_table[i] = *(uint32_t *)&table2[headerSize + 8 * i];
1574         }
1575
1576         return entries;
1577 }
1578
1579
1580 unsigned int NVParseBios(ScrnInfoPtr pScrn)
1581 {
1582         unsigned int bit_offset;
1583         bios_t bios;
1584         bios.data=NULL;
1585         bios.length=NV_PROM_SIZE;
1586         unsigned char nv_signature[]={0xff,0x7f,'N','V',0x0};
1587         unsigned char bit_signature[]={'B','I','T'};
1588         NVPtr pNv;
1589         int i, ret;
1590         pNv = NVPTR(pScrn);
1591
1592         bios.data=xalloc(NV_PROM_SIZE);
1593
1594         /* enable ROM access */
1595         nvWriteMC(pNv, 0x1850, 0x0);
1596         for(i=0;i<NV_PROM_SIZE;i++)
1597         {
1598                 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
1599                 bios.data[i]=pNv->PROM[i];
1600                 bios.data[i]=pNv->PROM[i];
1601                 bios.data[i]=pNv->PROM[i];
1602                 bios.data[i]=pNv->PROM[i];
1603                 bios.data[i]=pNv->PROM[i];
1604         }
1605         /* disable ROM access */
1606         nvWriteMC(pNv, 0x1850, 0x1);
1607
1608         /* check for BIOS signature */
1609         if (!(bios.data[0] == 0x55 && bios.data[1] == 0xAA)) {
1610                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "BIOS signature not found!\n");
1611                 xfree(bios.data);
1612                 return 0;
1613         }
1614
1615         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "BIOS signature found.\n");
1616
1617         /* check for known signatures */
1618         if (bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature))) {
1619                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "BIT signature found.\n");
1620                 parse_bit_structure(pScrn, &bios, bit_offset + 4);
1621         } else if (bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature))) {
1622                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "NV signature found.\n");
1623                 parse_pins_structure(pScrn, &bios, bit_offset);
1624         } else {
1625                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "No known script signature found.\n");
1626         }
1627
1628         /* look for NV40+ DCB table - and make a copy somewhere for output setup code */
1629         ret = nv_find_dcb_table(pScrn, &bios);
1630         if (ret)
1631         {
1632                 pNv->dcb_entries = ret;
1633                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "DCB found %d entries.\n", ret);
1634         }
1635         else
1636                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "No DCB table found\n");
1637         xfree(bios.data);
1638         return 1;
1639 }