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