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