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