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