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