Rehabilitate BMP parsing
[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
28 /* FIXME: put these somewhere */
29 #define CRTC_INDEX_COLOR VGA_IOBASE_COLOR + VGA_CRTC_INDEX_OFFSET
30 #define NV_VGA_CRTCX_OWNER_HEADA 0x0
31 #define NV_VGA_CRTCX_OWNER_HEADB 0x3
32 #define NV_PBUS_PCI_NV_19 0x0000184C
33 #define NV_PBUS_PCI_NV_20 0x00001850
34 #define NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED 0x00000000
35 #define NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED 0x00000001
36 #define NV_PRAMIN_ROM_OFFSET 0x00700000
37
38 #define DEBUGLEVEL 6
39
40 /* TODO: 
41  *       * PLL algorithms.
42  */
43
44 static int crtchead = 0;
45
46 typedef struct {
47         Bool execute;
48         Bool repeat;
49 } init_exec_t;
50
51 static uint16_t le16_to_cpu(const uint16_t x)
52 {
53 #if X_BYTE_ORDER == X_BIG_ENDIAN
54         return bswap_16(x);
55 #else
56         return x;
57 #endif
58 }
59
60 static uint32_t le32_to_cpu(const uint32_t x)
61 {
62 #if X_BYTE_ORDER == X_BIG_ENDIAN
63         return bswap_32(x);
64 #else
65         return x;
66 #endif
67 }
68
69 static Bool nv_cksum(const uint8_t *data, unsigned int length)
70 {
71         /* there's a few checksums in the BIOS, so here's a generic checking function */
72         int i;
73         uint8_t sum = 0;
74
75         for (i = 0; i < length; i++)
76                 sum += data[i];
77
78         if (sum)
79                 return TRUE;
80
81         return FALSE;
82 }
83
84 static int NVValidVBIOS(ScrnInfoPtr pScrn, const uint8_t *data)
85 {
86         /* check for BIOS signature */
87         if (!(data[0] == 0x55 && data[1] == 0xAA)) {
88                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
89                            "... BIOS signature not found\n");
90                 return 0;
91         }
92
93         if (nv_cksum(data, data[2] * 512)) {
94                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
95                            "... BIOS checksum invalid\n");
96                 /* probably ought to set a do_not_execute flag for table parsing here,
97                  * assuming most BIOSen are valid */
98                 return 1;
99         } else
100                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "... appears to be valid\n");
101
102         return 2;
103 }
104
105 static void NVShadowVBIOS_PROM(ScrnInfoPtr pScrn, uint8_t *data)
106 {
107         NVPtr pNv = NVPTR(pScrn);
108         int i;
109
110         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
111                    "Attempting to locate BIOS image in PROM\n");
112
113         /* enable ROM access */
114         nvWriteMC(pNv, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED);
115         for (i = 0; i < NV_PROM_SIZE; i++) {
116                 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
117                 data[i] = pNv->PROM[i];
118                 data[i] = pNv->PROM[i];
119                 data[i] = pNv->PROM[i];
120                 data[i] = pNv->PROM[i];
121                 data[i] = pNv->PROM[i];
122         }
123         /* disable ROM access */
124         nvWriteMC(pNv, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
125 }
126
127 static void NVShadowVBIOS_PRAMIN(ScrnInfoPtr pScrn, uint32_t *data)
128 {
129         NVPtr pNv = NVPTR(pScrn);
130         const uint32_t *pramin = (uint32_t *)&pNv->REGS[NV_PRAMIN_ROM_OFFSET/4];
131         uint32_t old_bar0_pramin = 0;
132
133         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
134                    "Attempting to locate BIOS image in PRAMIN\n");
135
136         if (pNv->Architecture >= NV_ARCH_50) {
137                 uint32_t vbios_vram;
138
139                 vbios_vram = (pNv->REGS[0x619f04/4] & ~0xff) << 8;
140                 if (!vbios_vram) {
141                         vbios_vram = pNv->REGS[0x1700/4] << 16;
142                         vbios_vram += 0xf0000;
143                 }
144
145                 old_bar0_pramin = pNv->REGS[0x1700/4];
146                 pNv->REGS[0x1700/4] = vbios_vram >> 16;
147         }
148
149         memcpy(data, pramin, NV_PROM_SIZE);
150
151         if (pNv->Architecture >= NV_ARCH_50) {
152                 pNv->REGS[0x1700/4] = old_bar0_pramin;
153         }
154 }
155
156 static Bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint8_t *data)
157 {
158         NVShadowVBIOS_PROM(pScrn, data);
159         if (NVValidVBIOS(pScrn, data) == 2)
160                 return TRUE;
161
162         NVShadowVBIOS_PRAMIN(pScrn, (uint32_t *)data);
163         if (NVValidVBIOS(pScrn, data))
164                 return TRUE;
165
166         return FALSE;
167 }
168
169 typedef struct {
170         char* name;
171         uint8_t id;
172         int length;
173         int length_offset;
174         int length_multiplier;
175         Bool (*handler)(ScrnInfoPtr pScrn, bios_t *, uint16_t, init_exec_t *);
176 } init_tbl_entry_t;
177
178 typedef struct {
179         uint8_t id[2];
180         uint16_t length;
181         uint16_t offset;
182 } bit_entry_t;
183
184 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec);
185
186 #define MACRO_INDEX_SIZE        2
187 #define MACRO_SIZE              8
188 #define CONDITION_SIZE          12
189 #define IO_FLAG_CONDITION_SIZE  9 
190
191 void still_alive()
192 {
193         sync();
194 //      usleep(200000);
195 }
196
197 static int nv_valid_reg(uint32_t reg)
198 {
199         #define WITHIN(x,y,z) ((x>=y)&&(x<y+z))
200         if (WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
201                 return 1;
202         if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE))
203                 return 1;
204         if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE))
205                 return 1;
206         if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
207                 return 1;
208         if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
209                 return 1;
210         if (WITHIN(reg,NV_PGRAPH_OFFSET,NV_PGRAPH_SIZE))
211                 return 1;
212         if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
213                 return 1;
214         if (WITHIN(reg,NV_PTIMER_OFFSET,NV_PTIMER_SIZE))
215                 return 1;
216         if (WITHIN(reg,NV_PVIDEO_OFFSET,NV_PVIDEO_SIZE))
217                 return 1;
218         if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
219                 return 1;
220         if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
221                 return 1;
222         if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
223                 return 1;
224         if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
225                 return 1;
226         if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
227                 return 1;
228         if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
229                 return 1;
230         if (WITHIN(reg,NV_PRAMIN_ROM_OFFSET,NV_PROM_SIZE))
231                 return 1;
232         /* A new PBUS? */
233         if (WITHIN(reg,0x88000,0x1000))
234                 return 1;
235         #undef WITHIN
236         return 0;
237 }
238
239 static void nv32_rd(ScrnInfoPtr pScrn, uint32_t reg, uint32_t *data)
240 {
241         NVPtr pNv = NVPTR(pScrn);
242
243         if (!nv_valid_reg(reg)) {
244                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
245                            "========= unknown reg 0x%08X ==========\n", reg);
246                 return;
247         }
248         *data = pNv->REGS[reg/4];
249         if (DEBUGLEVEL >= 6)
250                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
251                            "    Read:  Reg: 0x%08X, Data: 0x%08X\n", reg, *data);
252 }
253
254 static int nv32_wr(ScrnInfoPtr pScrn, uint32_t reg, uint32_t data)
255 {
256         NVPtr pNv = NVPTR(pScrn);
257         int specialcase = 0;
258         uint8_t saved1 = 0, saved2 = 0;
259         volatile uint8_t *crtcptr = crtchead ? pNv->PCIO1 : pNv->PCIO0;
260
261         if (DEBUGLEVEL >= 8) {
262                 uint32_t tmp;
263                 nv32_rd(pScrn, reg, &tmp);
264         }
265         if (DEBUGLEVEL >= 6)
266                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
267                            "    Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data);
268         if (!nv_valid_reg(reg)) {
269                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
270                            "========= unknown reg 0x%08X ==========\n", reg);
271                 return 0;
272         }
273
274         if (pNv->VBIOS.execute) {
275                 still_alive();
276
277                 if ((reg & 0xffc) == 0x3c0) {
278                         specialcase = 1;
279                         saved1 = VGA_RD08(crtcptr, VGA_MISC_OUT_R);
280                         saved2 = VGA_RD08(crtcptr, VGA_ENABLE);
281                 }
282                 if ((reg & 0xffc) == 0x3cc) {
283                         specialcase = 2;
284                         saved1 = VGA_RD08(crtcptr, VGA_GRAPH_INDEX);
285                         VGA_WR08(crtcptr, VGA_GRAPH_INDEX, 0x06);
286                         saved2 = VGA_RD08(crtcptr, VGA_GRAPH_DATA);
287                 }
288
289                 pNv->REGS[reg/4] = data;
290
291                 if (specialcase == 1) {
292                         VGA_WR08(crtcptr, VGA_ENABLE, saved2);
293                         VGA_WR08(crtcptr, VGA_MISC_OUT_W, saved1);
294                 }
295                 if (specialcase == 2) {
296                         VGA_WR08(crtcptr, VGA_GRAPH_INDEX, 0x06);
297                         VGA_WR08(crtcptr, VGA_GRAPH_DATA, saved2);
298                         VGA_WR08(crtcptr, VGA_GRAPH_INDEX, saved1);
299                 }
300         }
301
302         return 1;
303 }
304
305 static void nv_idx_port_rd(ScrnInfoPtr pScrn, uint16_t port, uint8_t index, uint8_t *data)
306 {
307         NVPtr pNv = NVPTR(pScrn);
308         volatile uint8_t *ptr = crtchead ? pNv->PCIO1 : pNv->PCIO0;
309
310         VGA_WR08(ptr, port, index);
311         *data = VGA_RD08(ptr, port + 1);
312
313         if (DEBUGLEVEL >= 6)
314                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
315                            "    Indexed read:  Port: 0x%04X, Index: 0x%02X, Head: 0x%02X, Data: 0x%02X\n",
316                            port, index, crtchead, *data);
317 }
318
319 static void nv_idx_port_wr(ScrnInfoPtr pScrn, uint16_t port, uint8_t index, uint8_t data)
320 {
321         NVPtr pNv = NVPTR(pScrn);
322         volatile uint8_t *ptr;
323
324         /* The current head is maintained in a file scope variable crtchead.
325          * We trap changes to CRTCX_OWNER and update the head variable
326          * and hence the register set written.
327          * As CRTCX_OWNER only exists on CRTC0, we update crtchead to head0
328          * in advance of the write, and to head1 after the write
329          */
330         if (port == CRTC_INDEX_COLOR && index == NV_VGA_CRTCX_OWNER && data != NV_VGA_CRTCX_OWNER_HEADB)
331                 crtchead = 0;
332         ptr = crtchead ? pNv->PCIO1 : pNv->PCIO0;
333
334         if (DEBUGLEVEL >= 8) {
335                 uint8_t tmp;
336                 nv_idx_port_rd(pScrn, port, index, &tmp);
337         }
338         if (DEBUGLEVEL >= 6)
339                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
340                            "    Indexed write: Port: 0x%04X, Index: 0x%02X, Head: 0x%02X, Data: 0x%02X\n",
341                            port, index, crtchead, data);
342
343         if (pNv->VBIOS.execute) {
344                 still_alive();
345                 VGA_WR08(ptr, port, index);
346                 VGA_WR08(ptr, port + 1, data);
347         }
348
349         if (port == CRTC_INDEX_COLOR && index == NV_VGA_CRTCX_OWNER && data == NV_VGA_CRTCX_OWNER_HEADB)
350                 crtchead = 1;
351 }
352
353 static Bool io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, uint8_t cond)
354 {
355         /* The IO flag condition entry has 2 bytes for the CRTC port; 1 byte
356          * for the CRTC index; 1 byte for the mask to apply to the value
357          * retrieved from the CRTC; 1 byte for the shift right to apply to the
358          * masked CRTC value; 2 bytes for the offset to the flag array, to
359          * which the shifted value is added; 1 byte for the mask applied to the
360          * value read from the flag array; and 1 byte for the value to compare
361          * against the masked byte from the flag table.
362          */
363
364         uint16_t condptr = bios->io_flag_condition_tbl_ptr + cond * IO_FLAG_CONDITION_SIZE;
365         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[condptr])));
366         uint8_t crtcindex = bios->data[condptr + 2];
367         uint8_t mask = bios->data[condptr + 3];
368         uint8_t shift = bios->data[condptr + 4];
369         uint16_t flagarray = le16_to_cpu(*((uint16_t *)(&bios->data[condptr + 5])));
370         uint8_t flagarraymask = bios->data[condptr + 7];
371         uint8_t cmpval = bios->data[condptr + 8];
372         uint8_t data;
373
374         if (DEBUGLEVEL >= 6)
375                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
376                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, FlagArray: 0x%04X, FAMask: 0x%02X, Cmpval: 0x%02X\n",
377                            offset, crtcport, crtcindex, mask, shift, flagarray, flagarraymask, cmpval);
378
379         nv_idx_port_rd(pScrn, crtcport, crtcindex, &data);
380
381         data = bios->data[flagarray + ((data & mask) >> shift)];
382         data &= flagarraymask;
383
384         if (DEBUGLEVEL >= 6)
385                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
386                            "0x%04X: Checking if 0x%02X equals 0x%02X\n",
387                            offset, data, cmpval);
388
389         if (data == cmpval)
390                 return TRUE;
391
392         return FALSE;
393 }
394
395 uint32_t getMNP_single(NVPtr pNv, uint32_t clk, int *bestNM, int *bestlog2P)
396 {
397         /* Find M, N and P for a single stage PLL
398          *
399          * Note that some bioses (NV3x) have lookup tables of precomputed MNP values,
400          * but we're too lazy to use those atm
401          *
402          * "clk" parameter in kHz
403          * returns calculated clock
404          */
405
406         bios_t *bios = &pNv->VBIOS;
407         int maxM = 0, M, N;
408         int maxlog2P, log2P, P;
409         int crystal = 0;
410         uint32_t minvco = bios->fminvco;
411         uint32_t maxvco = bios->fmaxvco;
412         int clkP;
413         int calcclk, delta;
414         unsigned int bestdelta = UINT_MAX;
415         uint32_t bestclk = 0;
416
417         switch (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT) & (1 << 22 | 1 << 6)) {
418         case 0:
419                 maxM = 13;
420                 crystal = 13500;
421                 break;
422         case (1 << 6):
423                 maxM = 14;
424                 crystal = 14318;
425                 break;
426         case (1 << 22):
427         case (1 << 22 | 1 << 6):
428                 maxM = 14;
429                 crystal = 27000;
430                 break;
431         }
432
433         /* this division verified for nv20, nv28 (Haiku), nv34 -- nv17 is guessed */
434         /* possibly correlated with introduction of 27MHz crystal */
435         if (bios->chip_version <= 0x16 || bios->chip_version == 0x20) {
436                 if (clk > 250000)
437                         maxM = 6;
438                 if (clk > 340000)
439                         maxM = 2;
440                 maxlog2P = 4;
441         } else {
442                 if (clk > 150000)
443                         maxM = 6;
444                 if (clk > 200000)
445                         maxM = 4;
446                 if (clk > 340000)
447                         maxM = 2;
448                 maxlog2P = 5;
449         }
450
451         if ((clk << maxlog2P) < minvco) {
452                 minvco = clk << maxlog2P;
453                 maxvco = minvco * 2;
454         }
455         if (clk + clk/200 > maxvco)     /* +0.5% */
456                 maxvco = clk + clk/200;
457
458         /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */
459         for (log2P = 0; log2P <= maxlog2P; log2P++) {
460                 P = 1 << log2P;
461                 clkP = clk * P;
462                 if (clkP < minvco)
463                         continue;
464                 if (clkP > maxvco)
465                         return bestclk;
466
467                 /* nv_hw.c in nv driver uses 7 and 8 for minM */
468                 for (M = 1; M <= maxM; M++) {
469                         /* add crystal/2 to round better */
470                         N = (clkP * M + crystal/2) / crystal;
471                         if (N > 256)    /* we lost */
472                                 goto nextP;
473
474                         /* more rounding additions */
475                         calcclk = ((N * crystal + P/2) / P + M/2) / M;
476                         delta = abs(calcclk - clk);
477                         /* we do an exhaustive search rather than terminating
478                          * on an optimality condition...
479                          */
480                         if (delta < bestdelta) {
481                                 bestdelta = delta;
482                                 bestclk = calcclk;
483                                 *bestNM = N << 8 | M;
484                                 *bestlog2P = log2P;
485                                 if (delta == 0) /* except this one */
486                                         return bestclk;
487                         }
488                 }
489 nextP:
490                 continue;
491         }
492
493         return bestclk;
494 }
495
496 uint32_t getMNP_double(NVPtr pNv, struct pll_lims *pll_lim, uint32_t clk, int *bestNM1, int *bestNM2, int *bestlog2P)
497 {
498         /* Find M, N and P for a two stage PLL
499          *
500          * Note that some bioses (NV30+) have lookup tables of precomputed MNP values,
501          * but we're too lazy to use those atm
502          *
503          * "clk" parameter in kHz
504          * returns calculated clock
505          */
506
507         int crystal = 0;
508         uint32_t minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq;
509         uint32_t minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq, vco2;
510         int maxM1 = 13, M1, N1;
511         int maxM2 = 4, M2, N2;
512         uint32_t minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq;
513         int log2P;
514         int clkP;
515         int calcclk1, calcclk2, calcclkout, delta;
516         unsigned int bestdelta = UINT_MAX;
517         uint32_t bestclk = 0;
518
519         /* some defaults */
520         *bestNM1 = 0xff << 8 | 13;
521         *bestNM2 = 0xff << 8 | 5;
522         *bestlog2P = 6;
523
524         switch (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT) & (1 << 22 | 1 << 6)) {
525         case 0:
526                 crystal = 13500;
527                 break;
528         case (1 << 6):
529                 crystal = 14318;
530                 break;
531         case (1 << 22):
532         case (1 << 22 | 1 << 6):
533                 crystal = 27000;
534                 break;
535         }
536
537         if (maxvco2 < clk + clk/200)    /* +0.5% */
538                 maxvco2 = clk + clk/200;
539         vco2 = (maxvco2 - maxvco2/200) / 2;
540
541         for (log2P = 0; log2P < 6 && clk <= (vco2 >> log2P); log2P++) /* log2P is maximum of 6 */
542                 ;
543         clkP = clk << log2P;
544
545         for (M1 = 1; M1 <= maxM1; M1++) {
546                 if (crystal/M1 < minU1)
547                         return bestclk;
548
549                 for (N1 = 1; N1 <= 0xff; N1++) {
550                         calcclk1 = crystal * N1 / M1;
551                         if (calcclk1 < minvco1)
552                                 continue;
553                         if (calcclk1 > maxvco1)
554                                 break;
555
556                         for (M2 = 1; M2 <= maxM2; M2++) {
557                                 if (calcclk1/M2 < minU2)
558                                         break;
559
560                                 /* add calcclk1/2 to round better */
561                                 N2 = (clkP * M2 + calcclk1/2) / calcclk1;
562                                 /* this N2 > maxM2 test is a bit weird, but it's correct for nv31 */
563                                 if (N2 < 4 || N2 > 0x46 || N2 > maxM2)
564                                         continue;
565                                 if (N2/M2 < 4 || N2/M2 > 10)
566                                         continue;
567
568                                 calcclk2 = calcclk1 * N2 / M2;
569                                 if (calcclk2 < minvco2 || calcclk2 > maxvco2)
570                                         continue;
571
572                                 calcclkout = calcclk2 >> log2P;
573                                 delta = abs(calcclkout - clk);
574                                 /* we do an exhaustive search rather than terminating
575                                  * on an optimality condition...
576                                  */
577                                 if (delta < bestdelta) {
578                                         bestdelta = delta;
579                                         bestclk = calcclkout;
580                                         *bestNM1 = N1 << 8 | M1;
581                                         *bestNM2 = N2 << 8 | M2;
582                                         *bestlog2P = log2P;
583                                         if (delta == 0) /* except this one */
584                                                 return bestclk;
585                                 }
586                         }
587                 }
588         }
589
590         return bestclk;
591 }
592
593 static void setPLL_single(ScrnInfoPtr pScrn, uint32_t reg, int NM, int log2P)
594 {
595         uint32_t pll;
596
597         nv32_rd(pScrn, reg, &pll);
598         if (pll == (log2P << 16 | NM))
599                 return; /* already set */
600
601 #if 0
602         //this stuff is present on my nv34 and something similar on the nv31
603         //it is not on nv20, and I don't know how useful or necessary it is
604
605         uint32_t saved_1584, 1584shift;
606         Bool frob1584 = FALSE;
607         switch (reg) {
608         case 0x680500:
609                 1584shift = 0;
610                 frob1584 = TRUE;
611                 break;
612         case 0x680504:
613                 1584shift = 4;
614                 frob1584 = TRUE;
615                 break;
616         case 0x680508:
617                 1584shift = 8;
618                 frob1584 = TRUE;
619                 break;
620         case 0x680520:
621                 1584shift = 12;
622                 frob1584 = TRUE;
623                 break;
624         }
625
626         if (frob1584) {
627                 nv32_rd(pScrn, 0x00001584, &saved_1584);
628                 nv32_wr(pScrn, 0x00001584, saved_1584 & ~(0xf << 1584shift) | 1 << 1584shift);
629         }
630 #endif
631
632         /* write NM first */
633         nv32_wr(pScrn, reg, (pll & 0xffff0000) | NM);
634
635         /* wait a bit */
636         usleep(64000);
637         nv32_rd(pScrn, reg, &pll);
638
639         /* then write P as well */
640         nv32_wr(pScrn, reg, (pll & 0xfff8ffff) | log2P << 16);
641
642 #if 0
643         if (frob1584)
644                 nv32_wr(pScrn, 0x00001584, saved_1584);
645 #endif
646 }
647
648 static void setPLL_double(ScrnInfoPtr pScrn, uint32_t reg1, int NM1, int NM2, int log2P)
649 {
650         uint32_t reg2, pll1, pll2;
651
652         reg2 = reg1 + 0x70;
653         if (reg2 == 0x680590)
654                 reg2 = NV_RAMDAC_VPLL2_B;
655
656         nv32_rd(pScrn, reg1, &pll1);
657         nv32_rd(pScrn, reg2, &pll2);
658         if (pll1 == (log2P << 16 | NM1) && pll2 == (1 << 31 | NM2))
659                 return; /* already set */
660
661 #if 0
662         //this stuff is present on my nv31
663         //I don't know how useful or necessary it is
664
665         uint32_t saved_1584, 1584shift;
666         Bool frob1584 = FALSE;
667         switch (reg) {
668         case 0x680500:
669                 1584shift = 0;
670                 frob1584 = TRUE;
671                 break;
672         case 0x680504:
673                 1584shift = 4;
674                 frob1584 = TRUE;
675                 break;
676         }
677
678         if (frob1584) {
679                 nv32_rd(pScrn, 0x00001584, &saved_1584);
680                 nv32_wr(pScrn, 0x00001584, saved_1584 & ~(0xf << 1584shift) | 1 << 1584shift);
681         }
682 #endif
683
684         nv32_wr(pScrn, reg2, (pll2 & 0x7fff0000) | NM2);
685         nv32_wr(pScrn, reg1, (pll1 & 0xfff80000) | log2P << 16 | NM1);
686
687 #if 0
688         if (frob1584)
689                 nv32_wr(pScrn, 0x00001584, saved_1584);
690 #endif
691 }
692
693 Bool get_pll_limits(ScrnInfoPtr pScrn, enum pll_types plltype, struct pll_lims *pll_lim);
694
695 static void setPLL(ScrnInfoPtr pScrn, bios_t *bios, uint32_t reg, uint32_t clk)
696 {
697         /* clk in kHz */
698         NVPtr pNv = NVPTR(pScrn);
699         int NM1, NM2, log2P;
700
701         // FIXME: both getMNP versions will need some alterations for nv40 type stuff
702         if (bios->chip_version >= 0x40 || bios->chip_version == 0x31 || bios->chip_version == 0x36) {
703                 struct pll_lims pll_lim;
704                 // for NV40, pll_type will need setting
705                 get_pll_limits(pScrn, 0, &pll_lim);
706                 getMNP_double(pNv, &pll_lim, clk, &NM1, &NM2, &log2P);
707                 setPLL_double(pScrn, reg, NM1, NM2, log2P);
708         } else {
709                 getMNP_single(pNv, clk, &NM1, &log2P);
710                 setPLL_single(pScrn, reg, NM1, log2P);
711         }
712 }
713
714 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
715 {
716         /* INIT_PROG   opcode: 0x31
717          * 
718          * offset      (8  bit): opcode
719          * offset + 1  (32 bit): reg
720          * offset + 5  (32 bit): and mask
721          * offset + 9  (8  bit): shift right
722          * offset + 10 (8  bit): number of configurations
723          * offset + 11 (32 bit): register
724          * offset + 15 (32 bit): configuration 1
725          * ...
726          * 
727          * Starting at offset + 15 there are "number of configurations"
728          * 32 bit values. To find out which configuration value to use
729          * read "CRTC reg" on the CRTC controller with index "CRTC index"
730          * and bitwise AND this value with "and mask" and then bit shift the
731          * result "shift right" bits to the right.
732          * Assign "register" with appropriate configuration value.
733          */
734
735         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
736         CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
737         CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
738         CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
739         CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
740         CARD8 configuration;
741         CARD32 configval, tmp;
742
743         if (iexec->execute) {
744                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%04X\n", offset, 
745                                 reg);
746
747                 nv32_rd(pScrn, reg, &tmp);
748                 configuration = (tmp & and) >> shiftr;
749
750                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONFIGURATION TO USE: 0x%02X\n", 
751                                 offset, configuration);
752
753                 if (configuration <= nr) {
754
755                         configval = 
756                                 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
757
758                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, 
759                                         reg2, configval);
760                         
761                         nv32_rd(pScrn, reg2, &tmp);
762                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n",
763                                 offset, tmp);
764                         nv32_wr(pScrn, reg2, configval);
765                 }
766         }
767         return TRUE;
768 }
769
770 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
771 {
772         /* INIT_IO_RESTRICT_PROG   opcode: 0x32 ('2')
773          *
774          * offset      (8  bit): opcode
775          * offset + 1  (16 bit): CRTC port
776          * offset + 3  (8  bit): CRTC index
777          * offset + 4  (8  bit): mask
778          * offset + 5  (8  bit): shift
779          * offset + 6  (8  bit): count
780          * offset + 7  (32 bit): register
781          * offset + 11 (32 bit): configuration 1
782          * ...
783          *
784          * Starting at offset + 11 there are "count" 32 bit values.
785          * To find out which value to use read index "CRTC index" on "CRTC port",
786          * AND this value with "mask" and then bit shift right "shift" bits.
787          * Read the appropriate value using this index and write to "register"
788          */
789
790         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
791         uint8_t crtcindex = bios->data[offset + 3];
792         uint8_t mask = bios->data[offset + 4];
793         uint8_t shift = bios->data[offset + 5];
794         uint8_t count = bios->data[offset + 6];
795         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 7])));
796         uint8_t config;
797         uint32_t configval;
798
799         if (!iexec->execute)
800                 return TRUE;
801
802         if (DEBUGLEVEL >= 6)
803                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
804                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
805                            offset, crtcport, crtcindex, mask, shift, count, reg);
806
807         nv_idx_port_rd(pScrn, crtcport, crtcindex, &config);
808         config = (config & mask) >> shift;
809         if (config > count) {
810                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
811                            "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
812                            offset, config, count);
813                 return FALSE;
814         }
815
816         configval = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 11 + config * 4])));
817
818         if (DEBUGLEVEL >= 6)
819                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
820                            "0x%04X: Writing config %02X\n", offset, config);
821
822         nv32_wr(pScrn, reg, configval);
823
824         return TRUE;
825 }
826
827 static Bool init_repeat(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
828 {
829         /* INIT_REPEAT   opcode: 0x33 ('3')
830          *
831          * offset      (8 bit): opcode
832          * offset + 1  (8 bit): count
833          *
834          * Execute script following this opcode up to INIT_REPEAT_END
835          * "count" times
836          */
837
838         uint8_t count = bios->data[offset + 1];
839         uint8_t i;
840
841         /* no iexec->execute check by design */
842
843         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
844                    "0x%04X: REPEATING FOLLOWING SEGMENT %d TIMES\n",
845                    offset, count);
846
847         iexec->repeat = TRUE;
848
849         /* count - 1, as the script block will execute once when we leave this
850          * opcode -- this is compatible with bios behaviour as:
851          * a) the block is always executed at least once, even if count == 0
852          * b) the bios interpreter skips to the op following INIT_END_REPEAT,
853          * while we don't
854          */
855         for (i = 0; i < count - 1; i++)
856                 parse_init_table(pScrn, bios, offset + 2, iexec);
857
858         iexec->repeat = FALSE;
859
860         return TRUE;
861 }
862
863 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
864 {
865         /* INIT_IO_RESTRICT_PLL   opcode: 0x34 ('4')
866          *
867          * offset      (8  bit): opcode
868          * offset + 1  (16 bit): CRTC port
869          * offset + 3  (8  bit): CRTC index
870          * offset + 4  (8  bit): mask
871          * offset + 5  (8  bit): shift
872          * offset + 6  (8  bit): IO flag condition index
873          * offset + 7  (8  bit): count
874          * offset + 8  (32 bit): register
875          * offset + 12 (16 bit): frequency 1
876          * ...
877          *
878          * Starting at offset + 12 there are "count" 16 bit frequencies (10kHz).
879          * Set PLL register "register" to coefficients for frequency n,
880          * selected by reading index "CRTC index" of "CRTC port" ANDed with
881          * "mask" and shifted right by "shift". If "IO flag condition index" > 0,
882          * and condition met, double frequency before setting it.
883          */
884
885         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
886         uint8_t crtcindex = bios->data[offset + 3];
887         uint8_t mask = bios->data[offset + 4];
888         uint8_t shift = bios->data[offset + 5];
889         int8_t io_flag_condition_idx = bios->data[offset + 6];
890         uint8_t count = bios->data[offset + 7];
891         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 8])));
892         uint8_t config;
893         uint16_t freq;
894
895         if (!iexec->execute)
896                 return TRUE;
897
898         if (DEBUGLEVEL >= 6)
899                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
900                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, IO Flag Condition: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
901                            offset, crtcport, crtcindex, mask, shift, io_flag_condition_idx, count, reg);
902
903         nv_idx_port_rd(pScrn, crtcport, crtcindex, &config);
904         config = (config & mask) >> shift;
905         if (config > count) {
906                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
907                            "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
908                            offset, config, count);
909                 return FALSE;
910         }
911
912         freq = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 12 + config * 2])));
913
914         if (io_flag_condition_idx > 0) {
915                 if (io_flag_condition(pScrn, bios, offset, io_flag_condition_idx)) {
916                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
917                                    "0x%04X: CONDITION FULFILLED - FREQ DOUBLED\n", offset);
918                         freq *= 2;
919                 } else
920                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
921                                    "0x%04X: CONDITION IS NOT FULFILLED. FREQ UNCHANGED\n", offset);
922         }
923
924         if (DEBUGLEVEL >= 6)
925                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
926                            "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n",
927                            offset, reg, config, freq);
928
929         setPLL(pScrn, bios, reg, freq * 10);
930
931         return TRUE;
932 }
933
934 static Bool init_end_repeat(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
935 {
936         /* INIT_END_REPEAT   opcode: 0x36 ('6')
937          *
938          * offset      (8 bit): opcode
939          *
940          * Marks the end of the block for INIT_REPEAT to repeat
941          */
942
943         /* no iexec->execute check by design */
944
945         /* iexec->repeat flag necessary to go past INIT_END_REPEAT opcode when
946          * we're not in repeat mode
947          */
948         if (iexec->repeat)
949                 return FALSE;
950
951         return TRUE;
952 }
953
954 static Bool init_copy(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
955 {
956         /* INIT_COPY   opcode: 0x37 ('7')
957          *
958          * offset      (8  bit): opcode
959          * offset + 1  (32 bit): register
960          * offset + 5  (8  bit): shift
961          * offset + 6  (8  bit): srcmask
962          * offset + 7  (16 bit): CRTC port
963          * offset + 9  (8 bit): CRTC index
964          * offset + 10  (8 bit): mask
965          *
966          * Read index "CRTC index" on "CRTC port", AND with "mask", OR with
967          * (REGVAL("register") >> "shift" & "srcmask") and write-back to CRTC port
968          */
969
970         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
971         uint8_t shift = bios->data[offset + 5];
972         uint8_t srcmask = bios->data[offset + 6];
973         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 7])));
974         uint8_t crtcindex = bios->data[offset + 9];
975         uint8_t mask = bios->data[offset + 10];
976         uint32_t data;
977         uint8_t crtcdata;
978
979         if (!iexec->execute)
980                 return TRUE;
981
982         if (DEBUGLEVEL >= 6)
983                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
984                            "0x%04X: Reg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%02X, Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X\n",
985                            offset, reg, shift, srcmask, crtcport, crtcindex, mask);
986
987         nv32_rd(pScrn, reg, &data);
988
989         if (shift < 0x80)
990                 data >>= shift;
991         else
992                 data <<= (0x100 - shift);
993
994         data &= srcmask;
995
996         nv_idx_port_rd(pScrn, crtcport, crtcindex, &crtcdata);
997         crtcdata = (crtcdata & mask) | (uint8_t)data;
998         nv_idx_port_wr(pScrn, crtcport, crtcindex, crtcdata);
999
1000         return TRUE;
1001 }
1002
1003 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1004 {
1005         /* INIT_NOT   opcode: 0x38 ('8')
1006          *
1007          * offset      (8  bit): opcode
1008          *
1009          * Invert the current execute / no-execute condition (i.e. "else")
1010          */
1011         if (iexec->execute)
1012                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1013                            "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
1014         else
1015                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1016                            "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n", offset);
1017
1018         iexec->execute = !iexec->execute;
1019         return TRUE;
1020 }
1021
1022 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1023 {
1024         /* INIT_IO_FLAG_CONDITION   opcode: 0x39 ('9')
1025          *
1026          * offset      (8 bit): opcode
1027          * offset + 1  (8 bit): condition number
1028          *
1029          * Check condition "condition number" in the IO flag condition table.
1030          * If condition not met skip subsequent opcodes until condition
1031          * is inverted (INIT_NOT), or we hit INIT_RESUME
1032          */
1033
1034         uint8_t cond = bios->data[offset + 1];
1035
1036         if (!iexec->execute)
1037                 return TRUE;
1038
1039         if (io_flag_condition(pScrn, bios, offset, cond))
1040                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1041                            "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n", offset);
1042         else {
1043                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1044                            "0x%04X: CONDITION IS NOT FULFILLED\n", offset);
1045                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1046                            "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
1047                 iexec->execute = FALSE;
1048         }
1049
1050         return TRUE;
1051 }
1052
1053 Bool init_idx_addr_latched(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1054 {
1055         /* INIT_INDEX_ADDRESS_LATCHED   opcode: 0x49 ('I')
1056          *
1057          * offset      (8  bit): opcode
1058          * offset + 1  (32 bit): control register
1059          * offset + 5  (32 bit): data register
1060          * offset + 9  (32 bit): mask
1061          * offset + 13 (32 bit): data
1062          * offset + 17 (8  bit): count
1063          * offset + 18 (8  bit): address 1
1064          * offset + 19 (8  bit): data 1
1065          * ...
1066          *
1067          * For each of "count" address and data pairs, write "data n" to "data register",
1068          * read the current value of "control register", and write it back once ANDed
1069          * with "mask", ORed with "data", and ORed with "address n"
1070          */
1071
1072         uint32_t controlreg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1073         uint32_t datareg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
1074         uint32_t mask = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 9])));
1075         uint32_t data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 13])));
1076         uint8_t count = bios->data[offset + 17];
1077         uint32_t value;
1078         int i;
1079
1080         if (!iexec->execute)
1081                 return TRUE;
1082
1083         if (DEBUGLEVEL >= 6)
1084                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1085                            "0x%04X: ControlReg: 0x%08X, DataReg: 0x%08X, Mask: 0x%08X, Data: 0x%08X, Count: 0x%02X\n",
1086                            offset, controlreg, datareg, mask, data, count);
1087
1088         for (i = 0; i < count; i++) {
1089                 uint8_t instaddress = bios->data[offset + 18 + i * 2];
1090                 uint8_t instdata = bios->data[offset + 19 + i * 2];
1091
1092                 if (DEBUGLEVEL >= 6)
1093                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1094                                    "0x%04X: Address: 0x%02X, Data: 0x%02X\n", offset, instaddress, instdata);
1095
1096                 nv32_wr(pScrn, datareg, instdata);
1097
1098                 nv32_rd(pScrn, controlreg, &value);
1099                 value = (value & mask) | data | instaddress;
1100
1101                 nv32_wr(pScrn, controlreg, value);
1102         }
1103
1104         return TRUE;
1105 }
1106
1107 static Bool init_io_restrict_pll2(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1108 {
1109         /* INIT_IO_RESTRICT_PLL2   opcode: 0x4A ('J')
1110          *
1111          * offset      (8  bit): opcode
1112          * offset + 1  (16 bit): CRTC port
1113          * offset + 3  (8  bit): CRTC index
1114          * offset + 4  (8  bit): mask
1115          * offset + 5  (8  bit): shift
1116          * offset + 6  (8  bit): count
1117          * offset + 7  (32 bit): register
1118          * offset + 11 (32 bit): frequency 1
1119          * ...
1120          *
1121          * Starting at offset + 11 there are "count" 32 bit frequencies (kHz).
1122          * Set PLL register "register" to coefficients for frequency n,
1123          * selected by reading index "CRTC index" of "CRTC port" ANDed with
1124          * "mask" and shifted right by "shift".
1125          */
1126
1127         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
1128         uint8_t crtcindex = bios->data[offset + 3];
1129         uint8_t mask = bios->data[offset + 4];
1130         uint8_t shift = bios->data[offset + 5];
1131         uint8_t count = bios->data[offset + 6];
1132         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 7])));
1133         uint8_t config;
1134         uint32_t freq;
1135
1136         if (!iexec->execute)
1137                 return TRUE;
1138
1139         if (DEBUGLEVEL >= 6)
1140                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1141                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
1142                            offset, crtcport, crtcindex, mask, shift, count, reg);
1143
1144         if (!reg)
1145                 return TRUE;
1146
1147         nv_idx_port_rd(pScrn, crtcport, crtcindex, &config);
1148         config = (config & mask) >> shift;
1149         if (config > count) {
1150                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1151                            "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
1152                            offset, config, count);
1153                 return FALSE;
1154         }
1155
1156         freq = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 11 + config * 4])));
1157
1158         if (DEBUGLEVEL >= 6)
1159                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1160                            "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n",
1161                            offset, reg, config, freq);
1162
1163         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
1164
1165         return TRUE;
1166 }
1167
1168 static Bool init_pll2(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1169 {
1170         /* INIT_PLL2   opcode: 0x4B ('K')
1171          *
1172          * offset      (8  bit): opcode
1173          * offset + 1  (32 bit): register
1174          * offset + 5  (32 bit): freq
1175          *
1176          * Set PLL register "register" to coefficients for frequency "freq"
1177          */
1178
1179         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1180         uint32_t freq = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
1181
1182         if (!iexec->execute)
1183                 return TRUE;
1184
1185         if (DEBUGLEVEL >= 6)
1186                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1187                            "0x%04X: Reg: 0x%04X, Freq: %dkHz\n",
1188                            offset, reg, freq);
1189
1190         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
1191
1192         return TRUE;
1193 }
1194
1195 static uint32_t get_tmds_index_reg(ScrnInfoPtr pScrn, uint8_t mlv)
1196 {
1197         /* For mlv < 0x80, it is an index into a table of TMDS base addresses
1198          * For mlv == 0x80 use the "or" value of the dcb_entry indexed by CR58 for CR57 = 0
1199          * to index a table of offsets to the basic 0x6808b0 address
1200          * For mlv == 0x81 use the "or" value of the dcb_entry indexed by CR58 for CR57 = 0
1201          * to index a table of offsets to the basic 0x6808b0 address, and then flip the offset by 8
1202          */
1203
1204         NVPtr pNv = NVPTR(pScrn);
1205         int pramdac_offset[13] = {0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000};
1206         uint32_t pramdac_table[4] = {0x6808b0, 0x6808b8, 0x6828b0, 0x6828b8};
1207
1208         if (mlv >= 0x80) {
1209                 /* here we assume that the DCB table has already been parsed */
1210                 uint8_t dcb_entry;
1211                 int dacoffset;
1212                 /* This register needs to be written to set index for reading CR58 */
1213                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, 0x57, 0);
1214                 nv_idx_port_rd(pScrn, CRTC_INDEX_COLOR, 0x58, &dcb_entry);
1215                 if (dcb_entry > pNv->dcb_table.entries) {
1216                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1217                                    "CR58 doesn't have a valid DCB entry currently (%02X)\n", dcb_entry);
1218                         return FALSE;
1219                 }
1220                 dacoffset = pramdac_offset[pNv->dcb_table.entry[dcb_entry].or];
1221                 if (mlv == 0x81)
1222                         dacoffset ^= 8;
1223                 return (0x6808b0 + dacoffset);
1224         } else {
1225                 if (mlv > (sizeof(pramdac_table) / sizeof(uint32_t))) {
1226                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1227                                    "Magic Lookup Value too big (%02X)\n", mlv);
1228                         return FALSE;
1229                 }
1230                 return pramdac_table[mlv];
1231         }
1232 }
1233
1234 static Bool init_tmds(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1235 {
1236         /* INIT_TMDS   opcode: 0x4F ('O')       (non-canon name)
1237          *
1238          * offset      (8 bit): opcode
1239          * offset + 1  (8 bit): magic lookup value
1240          * offset + 2  (8 bit): TMDS address
1241          * offset + 3  (8 bit): mask
1242          * offset + 4  (8 bit): data
1243          *
1244          * Read the data reg for TMDS address "TMDS address", AND it with mask
1245          * and OR it with data, then write it back
1246          * "magic lookup value" determines which TMDS base address register is used --
1247          * see get_tmds_index_reg()
1248          */
1249
1250         uint8_t mlv = bios->data[offset + 1];
1251         uint32_t tmdsaddr = bios->data[offset + 2];
1252         uint8_t mask = bios->data[offset + 3];
1253         uint8_t data = bios->data[offset + 4];
1254         uint32_t reg, value;
1255
1256         if (!iexec->execute)
1257                 return TRUE;
1258
1259         if (DEBUGLEVEL >= 6)
1260                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1261                            "0x%04X: MagicLookupValue: 0x%02X, TMDSAddr: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
1262                            offset, mlv, tmdsaddr, mask, data);
1263
1264         reg = get_tmds_index_reg(pScrn, mlv);
1265
1266         nv32_wr(pScrn, reg, tmdsaddr | 0x10000);
1267         nv32_rd(pScrn, reg + 4, &value);
1268         value = (value & mask) | data;
1269         nv32_wr(pScrn, reg + 4, value);
1270         nv32_wr(pScrn, reg, tmdsaddr);
1271
1272         return TRUE;
1273 }
1274
1275 Bool init_zm_tmds_group(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1276 {
1277         /* INIT_ZM_TMDS_GROUP   opcode: 0x50 ('P')      (non-canon name)
1278          *
1279          * offset      (8 bit): opcode
1280          * offset + 1  (8 bit): magic lookup value
1281          * offset + 2  (8 bit): count
1282          * offset + 3  (8 bit): addr 1
1283          * offset + 4  (8 bit): data 1
1284          * ...
1285          *
1286          * For each of "count" TMDS address and data pairs write "data n" to "addr n"
1287          * "magic lookup value" determines which TMDS base address register is used --
1288          * see get_tmds_index_reg()
1289          */
1290
1291         uint8_t mlv = bios->data[offset + 1];
1292         uint8_t count = bios->data[offset + 2];
1293         uint32_t reg;
1294         int i;
1295
1296         if (!iexec->execute)
1297                 return TRUE;
1298
1299         if (DEBUGLEVEL >= 6)
1300                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1301                            "0x%04X: MagicLookupValue: 0x%02X, Count: 0x%02X\n",
1302                            offset, mlv, count);
1303
1304         reg = get_tmds_index_reg(pScrn, mlv);
1305
1306         for (i = 0; i < count; i++) {
1307                 uint8_t tmdsaddr = bios->data[offset + 3 + i * 2];
1308                 uint8_t tmdsdata = bios->data[offset + 4 + i * 2];
1309
1310                 nv32_wr(pScrn, reg + 4, tmdsdata);
1311                 nv32_wr(pScrn, reg, tmdsaddr);
1312         }
1313
1314         return TRUE;
1315 }
1316
1317 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1318 {
1319         /* INIT_CR_INDEX_ADDRESS_LATCHED   opcode: 0x51 ('Q')
1320          *
1321          * offset      (8 bit): opcode
1322          * offset + 1  (8 bit): CRTC index1
1323          * offset + 2  (8 bit): CRTC index2
1324          * offset + 3  (8 bit): baseaddr
1325          * offset + 4  (8 bit): count
1326          * offset + 5  (8 bit): data 1
1327          * ...
1328          *
1329          * For each of "count" address and data pairs, write "baseaddr + n" to
1330          * "CRTC index1" and "data n" to "CRTC index2"
1331          * Once complete, restore initial value read from "CRTC index1"
1332          */
1333         uint8_t crtcindex1 = bios->data[offset + 1];
1334         uint8_t crtcindex2 = bios->data[offset + 2];
1335         uint8_t baseaddr = bios->data[offset + 3];
1336         uint8_t count = bios->data[offset + 4];
1337         uint8_t oldaddr, data;
1338         int i;
1339
1340         if (!iexec->execute)
1341                 return TRUE;
1342
1343         if (DEBUGLEVEL >= 6)
1344                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1345                            "0x%04X: Index1: 0x%02X, Index2: 0x%02X, BaseAddr: 0x%02X, Count: 0x%02X\n",
1346                            offset, crtcindex1, crtcindex2, baseaddr, count);
1347
1348         nv_idx_port_rd(pScrn, CRTC_INDEX_COLOR, crtcindex1, &oldaddr);
1349
1350         for (i = 0; i < count; i++) {
1351                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex1, baseaddr + i);
1352
1353                 data = bios->data[offset + 5 + i];
1354                 nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex2, data);
1355         }
1356
1357         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex1, oldaddr);
1358
1359         return TRUE;
1360 }
1361
1362 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1363 {
1364         /* INIT_CR   opcode: 0x52 ('R')
1365          *
1366          * offset      (8  bit): opcode
1367          * offset + 1  (8  bit): CRTC index
1368          * offset + 2  (8  bit): mask
1369          * offset + 3  (8  bit): data
1370          *
1371          * Assign the value of at "CRTC index" ANDed with mask and ORed with data
1372          * back to "CRTC index"
1373          */
1374
1375         uint8_t crtcindex = bios->data[offset + 1];
1376         uint8_t mask = bios->data[offset + 2];
1377         uint8_t data = bios->data[offset + 3];
1378         uint8_t value;
1379
1380         if (!iexec->execute)
1381                 return TRUE;
1382
1383         if (DEBUGLEVEL >= 6)
1384                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1385                            "0x%04X: Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
1386                            offset, crtcindex, mask, data);
1387
1388         nv_idx_port_rd(pScrn, CRTC_INDEX_COLOR, crtcindex, &value);
1389
1390         value = (value & mask) | data;
1391
1392         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex, value);
1393
1394         return TRUE;
1395 }
1396
1397 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1398 {
1399         /* INIT_ZM_CR   opcode: 0x53 ('S')
1400          *
1401          * offset      (8 bit): opcode
1402          * offset + 1  (8 bit): CRTC index
1403          * offset + 2  (8 bit): value
1404          *
1405          * Assign "value" to CRTC register with index "CRTC index".
1406          */
1407
1408         uint8_t crtcindex = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1409         uint8_t data = bios->data[offset + 2];
1410
1411         if (!iexec->execute)
1412                 return TRUE;
1413
1414         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, crtcindex, data);
1415
1416         return TRUE;
1417 }
1418
1419 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1420 {
1421         /* INIT_ZM_CR_GROUP   opcode: 0x54 ('T')
1422          *
1423          * offset      (8 bit): opcode
1424          * offset + 1  (8 bit): count
1425          * offset + 2  (8 bit): CRTC index 1
1426          * offset + 3  (8 bit): value 1
1427          * ...
1428          *
1429          * For "count", assign "value n" to CRTC register with index "CRTC index n".
1430          */
1431     
1432         uint8_t count = bios->data[offset + 1];
1433         int i;
1434
1435         if (!iexec->execute)
1436                 return TRUE;
1437
1438         for (i = 0; i < count; i++)
1439                 init_zm_cr(pScrn, bios, offset + 2 + 2 * i - 1, iexec);
1440
1441         return TRUE;
1442 }
1443
1444 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1445 {
1446         /* INIT_CONDITION_TIME   opcode: 0x56 ('V')
1447          *
1448          * offset      (8 bit): opcode
1449          * offset + 1  (8 bit): condition number
1450          *
1451          * Check condition "condition number" in the condition table.
1452          * The condition table entry has 4 bytes for the address of the
1453          * register to check, 4 bytes for a mask and 4 for a test value.
1454          * If condition not met sleep for 2ms
1455          */
1456
1457         // this opcode makes no sense. it seems to do some competely useless things
1458         uint8_t cond = bios->data[offset + 1];
1459 //      uint16_t b = bios->data[offset + 2];    // this needs printing
1460         uint16_t condptr = bios->condition_tbl_ptr + cond * CONDITION_SIZE;
1461         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[condptr])));
1462         uint32_t mask = le32_to_cpu(*((uint32_t *)(&bios->data[condptr + 4])));
1463         uint32_t cmpval = le32_to_cpu(*((uint32_t *)(&bios->data[condptr + 8])));
1464         uint32_t data;
1465
1466         if (!iexec->execute)
1467                 return TRUE;
1468
1469         if (DEBUGLEVEL >= 6)
1470                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1471                            "0x%04X: Cond: 0x%02X, Reg: 0x%08X, Mask: 0x%08X, Cmpval: 0x%08X\n",
1472                            offset, cond, reg, mask, cmpval);
1473
1474 //      b *= 50;
1475         reg &= 0xfffffffc;      // FIXME: this not in init_condition() - should it be?
1476
1477         nv32_rd(pScrn, reg, &data);
1478         data &= mask;
1479
1480         if (DEBUGLEVEL >= 6)
1481                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1482                            "0x%04X: Checking if 0x%08X equals 0x%08X\n",
1483                            offset, data, cmpval);
1484
1485         if (data != cmpval) {
1486                 if (DEBUGLEVEL >= 6)
1487                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1488                                    "0x%04X: Condition not met, sleeping for 2ms\n", offset);
1489 //              reg--;
1490                 usleep(2000);
1491         } else
1492                 if (DEBUGLEVEL >= 6)
1493                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1494                                    "0x%04X: Condition met, continuing\n", offset);
1495
1496         return TRUE;
1497 }
1498
1499 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1500 {
1501         /* INIT_ZM_REG_SEQUENCE   opcode: 0x58 ('X')
1502          *
1503          * offset      (8  bit): opcode
1504          * offset + 1  (32 bit): base register
1505          * offset + 5  (8  bit): count
1506          * offset + 6  (32 bit): value 1
1507          * ...
1508          *
1509          * Starting at offset + 6 there are "count" 32 bit values.
1510          * For "count" iterations set "base register" + 4 * current_iteration
1511          * to "value current_iteration"
1512          */
1513
1514         uint32_t basereg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1515         uint32_t count = bios->data[offset + 5];
1516         int i;
1517
1518         if (!iexec->execute)
1519                 return TRUE;
1520
1521         if (DEBUGLEVEL >= 6)
1522                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1523                            "0x%04X: BaseReg: 0x%08X, Count: 0x%02X\n",
1524                            offset, basereg, count);
1525
1526         for (i = 0; i < count; i++) {
1527                 uint32_t reg = basereg + i * 4;
1528                 uint32_t data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 6 + i * 4])));
1529
1530                 nv32_wr(pScrn, reg, data);
1531         }
1532
1533         return TRUE;
1534 }
1535
1536 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1537 {
1538         /* INIT_INDIRECT_REG opcode: 0x5A
1539          *
1540          * offset      (8  bit): opcode
1541          * offset + 1  (32 bit): register
1542          * offset + 5  (16 bit): adress offset (in bios)
1543          *
1544          * Lookup value at offset data in the bios and write it to reg
1545          */
1546         CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1547         CARD16 data = le16_to_cpu(*((CARD16 *) (&bios->data[offset + 5])));
1548         CARD32 data2 = bios->data[data];
1549
1550         if (iexec->execute) {
1551                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1552                                 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n", 
1553                                 offset, reg, data, data2);
1554
1555                 if (DEBUGLEVEL >= 6) {
1556                         CARD32 tmpval;
1557                         nv32_rd(pScrn, reg, &tmpval);
1558                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1559                 }
1560
1561                 nv32_wr(pScrn, reg, data2);
1562         }
1563         return TRUE;
1564 }
1565
1566 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1567 {
1568         /* INIT_SUB_DIRECT   opcode: 0x5B ('[')
1569          *
1570          * offset      (8  bit): opcode
1571          * offset + 1  (16 bit): subroutine offset (in bios)
1572          *
1573          * Calls a subroutine that will execute commands until INIT_DONE
1574          * is found. 
1575          */
1576
1577         uint16_t sub_offset = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
1578
1579         if (!iexec->execute)
1580                 return TRUE;
1581
1582         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: EXECUTING SUB-ROUTINE AT 0x%04X\n",
1583                         offset, sub_offset);
1584
1585         parse_init_table(pScrn, bios, sub_offset, iexec);
1586
1587         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: END OF SUB-ROUTINE AT 0x%04X\n",
1588                         offset, sub_offset);
1589
1590         return TRUE;
1591 }
1592
1593 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1594 {
1595         /* INIT_COPY_NV_REG   opcode: 0x5F ('_')
1596          *
1597          * offset      (8  bit): opcode
1598          * offset + 1  (32 bit): src reg
1599          * offset + 5  (8  bit): shift
1600          * offset + 6  (32 bit): src mask
1601          * offset + 10 (32 bit): xor
1602          * offset + 14 (32 bit): dst reg
1603          * offset + 18 (32 bit): dst mask
1604          *
1605          * Shift REGVAL("src reg") right by (signed) "shift", AND result with
1606          * "src mask", then XOR with "xor". Write this OR'd with
1607          * (REGVAL("dst reg") AND'd with "dst mask") to "dst reg"
1608          */
1609
1610         uint32_t srcreg = *((uint32_t *)(&bios->data[offset + 1]));
1611         uint8_t shift = bios->data[offset + 5];
1612         uint32_t srcmask = *((uint32_t *)(&bios->data[offset + 6]));
1613         uint32_t xor = *((uint32_t *)(&bios->data[offset + 10]));
1614         uint32_t dstreg = *((uint32_t *)(&bios->data[offset + 14]));
1615         uint32_t dstmask = *((uint32_t *)(&bios->data[offset + 18]));
1616         uint32_t srcvalue, dstvalue;
1617
1618         if (!iexec->execute)
1619                 return TRUE;
1620
1621         if (DEBUGLEVEL >= 6)
1622                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1623                            "0x%04X: SrcReg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%08X, Xor: 0x%08X, DstReg: 0x%08X, DstMask: 0x%08X\n",
1624                            offset, srcreg, shift, srcmask, xor, dstreg, dstmask);
1625
1626         nv32_rd(pScrn, srcreg, &srcvalue);
1627
1628         if (shift < 0x80)
1629                 srcvalue >>= shift;
1630         else
1631                 srcvalue <<= (0x100 - shift);
1632
1633         srcvalue = (srcvalue & srcmask) ^ xor;
1634
1635         nv32_rd(pScrn, dstreg, &dstvalue);
1636         dstvalue &= dstmask;
1637
1638         nv32_wr(pScrn, dstreg, dstvalue | srcvalue);
1639
1640         return TRUE;
1641 }
1642
1643 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1644 {
1645         /* INIT_ZM_INDEX_IO   opcode: 0x62 ('b')
1646          *
1647          * offset      (8  bit): opcode
1648          * offset + 1  (16 bit): CRTC port
1649          * offset + 3  (8  bit): CRTC index
1650          * offset + 4  (8  bit): data
1651          *
1652          * Write "data" to index "CRTC index" of "CRTC port"
1653          */
1654         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
1655         uint8_t crtcindex = bios->data[offset + 3];
1656         uint8_t data = bios->data[offset + 4];
1657
1658         if (!iexec->execute)
1659                 return TRUE;
1660
1661         nv_idx_port_wr(pScrn, crtcport, crtcindex, data);
1662
1663         return TRUE;
1664 }
1665
1666 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1667 {
1668         /* INIT_COMPUTE_MEM   opcode: 0x63 ('c')
1669          *
1670          * offset      (8 bit): opcode
1671          *
1672          * FIXME
1673          */
1674
1675         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
1676 #if 0
1677         uint16_t ramcfg = le16_to_cpu(*((uint16_t *)(&bios->data[bios->ram_table_offset])));
1678         uint32_t pfb_debug;
1679         uint32_t strapinfo;
1680         uint32_t ramcfg2;
1681
1682         if (!iexec->execute)
1683                 return TRUE;
1684
1685         nv32_rd(pScrn, 0x00101000, &strapinfo);
1686         nv32_rd(pScrn, 0x00100080, &pfb_debug);
1687
1688         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
1689         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
1690         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG: 0x%04X\n", ramcfg);
1691
1692         pfb_debug &= 0xffffffef;
1693         strapinfo >>= 2;
1694         strapinfo &= 0x0000000f;
1695         ramcfg2 = le16_to_cpu(*((uint16_t *)
1696                         (&bios->data[bios->ram_table_offset + (2 * strapinfo)])));
1697
1698         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AFTER MANIPULATION\n");
1699         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
1700         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
1701         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG2: 0x%08X\n", ramcfg2);
1702
1703
1704         uint32_t reg1;
1705         uint32_t reg2;
1706
1707         nv32_rd(pScrn, 0x00100200, &reg1);
1708         nv32_rd(pScrn, 0x0010020C, &reg2);
1709
1710         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x00100200: 0x%08X\n", reg1);
1711         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x0010020C: 0x%08X\n", reg2);
1712 #endif
1713
1714         return TRUE;
1715 }
1716
1717 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1718 {
1719         /* INIT_RESET   opcode: 0x65 ('e')
1720          *
1721          * offset      (8  bit): opcode
1722          * offset + 1  (32 bit): register
1723          * offset + 5  (32 bit): value1
1724          * offset + 9  (32 bit): value2
1725          *
1726          * Assign "value1" to "register", then assign "value2" to "register"
1727          */
1728
1729         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1730         uint32_t value1 = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
1731         uint32_t value2 = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 9])));
1732         uint32_t pci_nv_19, pci_nv_20;
1733
1734         /* no iexec->execute check by design */
1735
1736         nv32_rd(pScrn, NV_PBUS_PCI_NV_19, &pci_nv_19);
1737         nv32_wr(pScrn, NV_PBUS_PCI_NV_19, 0);
1738         nv32_wr(pScrn, reg, value1);
1739
1740         usleep(10);
1741
1742         nv32_wr(pScrn, reg, value2);
1743         nv32_wr(pScrn, NV_PBUS_PCI_NV_19, pci_nv_19);
1744
1745         nv32_rd(pScrn, NV_PBUS_PCI_NV_20, &pci_nv_20);
1746         pci_nv_20 &= !NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED;     /* 0xfffffffe */
1747         nv32_wr(pScrn, NV_PBUS_PCI_NV_20, pci_nv_20);
1748
1749         return TRUE;
1750 }
1751
1752 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1753 {
1754         /* INIT_INDEX_IO8   opcode: 0x69
1755          * 
1756          * offset      (8  bit): opcode
1757          * offset + 1  (16 bit): CRTC reg
1758          * offset + 3  (8  bit): and mask
1759          * offset + 4  (8  bit): or with
1760          * 
1761          * 
1762          */
1763
1764         NVPtr pNv = NVPTR(pScrn);
1765         volatile CARD8 *ptr = crtchead ? pNv->PCIO1 : pNv->PCIO0;
1766         CARD16 reg = le16_to_cpu(*((CARD16 *)(&bios->data[offset + 1])));
1767         CARD8 and  = *((CARD8 *)(&bios->data[offset + 3]));
1768         CARD8 or = *((CARD8 *)(&bios->data[offset + 4]));
1769         CARD8 data;
1770
1771         if (iexec->execute) {
1772                 data = (VGA_RD08(ptr, reg) & and) | or;
1773
1774                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1775                                 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n", 
1776                                 offset, reg, data);
1777                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset, 
1778                                 VGA_RD08(ptr, reg));
1779
1780 #ifdef PERFORM_WRITE
1781                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
1782                 still_alive();
1783                 VGA_WR08(ptr, reg, data);
1784 #endif
1785         }
1786         return TRUE;
1787 }
1788
1789 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1790 {
1791         /* INIT_SUB   opcode: 0x6B ('k')
1792          *
1793          * offset      (8 bit): opcode
1794          * offset + 1  (8 bit): script number
1795          *
1796          * Execute script number "script number", as a subroutine
1797          */
1798
1799         uint8_t sub = bios->data[offset + 1];
1800
1801         if (!iexec->execute)
1802                 return TRUE;
1803
1804         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1805                    "0x%04X: EXECUTING SUB-SCRIPT %d\n", offset, sub);
1806
1807         parse_init_table(pScrn, bios,
1808                          le16_to_cpu(*((uint16_t *)(&bios->data[bios->init_script_tbls_ptr + sub * 2]))),
1809                          iexec);
1810
1811         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1812                    "0x%04X: END OF SUB-SCRIPT %d\n", offset, sub);
1813
1814         return TRUE;
1815 }
1816
1817 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1818 {
1819         /* INIT_RAM_CONDITION   opcode: 0x6D
1820          * 
1821          * offset      (8  bit): opcode
1822          * offset + 1  (8  bit): and mask
1823          * offset + 2  (8  bit): cmpval
1824          *
1825          * Test if (NV_PFB_BOOT & and mask) matches cmpval
1826          */
1827         NVPtr pNv = NVPTR(pScrn);
1828         CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
1829         CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
1830         CARD32 data;
1831
1832         if (iexec->execute) {
1833                 data=(pNv->PFB[NV_PFB_BOOT/4])&and;
1834
1835                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1836                                 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1837                                 offset, data, cmpval);
1838
1839                 if (data == cmpval) {
1840                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1841                                         "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1842                                         offset);
1843                 } else {
1844                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONDITION IS NOT FULFILLED\n", offset);
1845                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1846                                         "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
1847                         iexec->execute = FALSE;     
1848                 }
1849         }
1850         return TRUE;
1851 }
1852
1853 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1854 {
1855         /* INIT_NV_REG   opcode: 0x6E ('n')
1856          *
1857          * offset      (8  bit): opcode
1858          * offset + 1  (32 bit): register
1859          * offset + 5  (32 bit): mask
1860          * offset + 9  (32 bit): data
1861          *
1862          * Assign ((REGVAL("register") & "mask") | "data") to "register"
1863          */
1864
1865         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
1866         uint32_t mask = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
1867         uint32_t data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 9])));
1868         uint32_t value;
1869
1870         if (!iexec->execute)
1871                 return TRUE;
1872
1873         if (DEBUGLEVEL >= 6)
1874                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1875                            "0x%04X: Reg: 0x%08X, Mask: 0x%08X, Data: 0x%08X\n",
1876                            offset, reg, mask, data);
1877
1878         nv32_rd(pScrn, reg, &value);
1879
1880         value = (value & mask) | data;
1881
1882         nv32_wr(pScrn, reg, value);
1883
1884         return TRUE;
1885 }
1886
1887 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1888 {
1889         /* INIT_MACRO   opcode: 0x6F ('o')
1890          *
1891          * offset      (8 bit): opcode
1892          * offset + 1  (8 bit): macro number
1893          *
1894          * Look up macro index "macro number" in the macro index table.
1895          * The macro index table entry has 1 byte for the index in the macro table,
1896          * and 1 byte for the number of times to repeat the macro.
1897          * The macro table entry has 4 bytes for the register address and
1898          * 4 bytes for the value to write to that register
1899          */
1900
1901         uint8_t macro_index_tbl_idx = bios->data[offset + 1];
1902         uint16_t tmp = bios->macro_index_tbl_ptr + (macro_index_tbl_idx * MACRO_INDEX_SIZE);
1903         uint8_t macro_tbl_idx = bios->data[tmp];
1904         uint8_t count = bios->data[tmp + 1];
1905         uint32_t reg, data;
1906         int i;
1907
1908         if (!iexec->execute)
1909                 return TRUE;
1910
1911         if (DEBUGLEVEL >= 6)
1912                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1913                            "0x%04X: Macro: 0x%02X, MacroTableIndex: 0x%02X, Count: 0x%02X\n",
1914                            offset, macro_index_tbl_idx, macro_tbl_idx, count);
1915
1916         for (i = 0; i < count; i++) {
1917                 uint16_t macroentryptr = bios->macro_tbl_ptr + (macro_tbl_idx + i) * MACRO_SIZE;
1918
1919                 reg = le32_to_cpu(*((uint32_t *)(&bios->data[macroentryptr])));
1920                 data = le32_to_cpu(*((uint32_t *)(&bios->data[macroentryptr + 4])));
1921
1922                 nv32_wr(pScrn, reg, data);
1923         }
1924
1925         return TRUE;
1926 }
1927
1928 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1929 {
1930         /* INIT_DONE   opcode: 0x71 ('q')
1931          *
1932          * offset      (8  bit): opcode
1933          *
1934          * End the current script
1935          */
1936
1937         /* mild retval abuse to stop parsing this table */
1938         return FALSE;
1939 }
1940
1941 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1942 {
1943         /* INIT_RESUME   opcode: 0x72 ('r')
1944          *
1945          * offset      (8  bit): opcode
1946          *
1947          * End the current execute / no-execute condition
1948          */
1949
1950         if (iexec->execute)
1951                 return TRUE;
1952
1953         iexec->execute = TRUE;;
1954         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1955                    "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n", offset);
1956
1957         return TRUE;
1958 }
1959
1960 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1961 {
1962         /* INIT_RAM_CONDITION2   opcode: 0x73
1963          * 
1964          * offset      (8  bit): opcode
1965          * offset + 1  (8  bit): and mask
1966          * offset + 2  (8  bit): cmpval
1967          *
1968          * Test if (NV_EXTDEV_BOOT & and mask) matches cmpval
1969          */
1970         NVPtr pNv = NVPTR(pScrn);
1971         CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
1972         CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
1973         CARD32 data;
1974
1975         if (iexec->execute) {
1976                 data=(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT))&and;
1977                 
1978                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1979                                 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1980                                 offset, data, cmpval);
1981
1982                 if (data == cmpval) {
1983                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1984                                         "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1985                                         offset);
1986                 } else {
1987                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  "0x%04X: CONDITION IS NOT FULFILLED\n", offset);
1988                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,  
1989                                         "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
1990                         iexec->execute = FALSE;     
1991                 }
1992         }
1993         return TRUE;
1994 }
1995
1996 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
1997 {
1998         /* INIT_TIME   opcode: 0x74 ('t')
1999          *
2000          * offset      (8  bit): opcode
2001          * offset + 1  (16 bit): time
2002          *
2003          * Sleep for "time" microseconds.
2004          */
2005
2006         uint16_t time = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
2007
2008         if (!iexec->execute)
2009                 return TRUE;
2010
2011         if (DEBUGLEVEL >= 6)
2012                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2013                            "0x%04X: Sleeping for 0x%04X microseconds\n", offset, time);
2014
2015         usleep(time);
2016
2017         return TRUE;
2018 }
2019
2020 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2021 {
2022         /* INIT_CONDITION   opcode: 0x75 ('u')
2023          *
2024          * offset      (8 bit): opcode
2025          * offset + 1  (8 bit): condition number
2026          *
2027          * Check condition "condition number" in the condition table.
2028          * The condition table entry has 4 bytes for the address of the
2029          * register to check, 4 bytes for a mask and 4 for a test value.
2030          * If condition not met skip subsequent opcodes until condition
2031          * is inverted (INIT_NOT), or we hit INIT_RESUME
2032          */
2033
2034         uint8_t cond = bios->data[offset + 1];
2035         uint16_t condptr = bios->condition_tbl_ptr + cond * CONDITION_SIZE;
2036         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[condptr])));
2037         uint32_t mask = le32_to_cpu(*((uint32_t *)(&bios->data[condptr + 4])));
2038         uint32_t cmpval = le32_to_cpu(*((uint32_t *)(&bios->data[condptr + 8])));
2039         uint32_t data;
2040
2041         if (!iexec->execute)
2042                 return TRUE;
2043
2044         if (DEBUGLEVEL >= 6)
2045                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2046                            "0x%04X: Cond: 0x%02X, Reg: 0x%08X, Mask: 0x%08X, Cmpval: 0x%08X\n",
2047                            offset, cond, reg, mask, cmpval);
2048
2049         nv32_rd(pScrn, reg, &data);
2050         data &= mask;
2051
2052         if (DEBUGLEVEL >= 6)
2053                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2054                            "0x%04X: Checking if 0x%08X equals 0x%08X\n",
2055                            offset, data, cmpval);
2056
2057         if (data == cmpval) {
2058                 if (DEBUGLEVEL >= 6)
2059                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2060                                    "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n", offset);
2061         } else {
2062                 if (DEBUGLEVEL >= 6)
2063                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2064                                    "0x%04X: CONDITION IS NOT FULFILLED\n", offset);
2065                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2066                            "0x%04X: ------ SKIPPING FOLLOWING COMMANDS  ------\n", offset);
2067                 iexec->execute = FALSE;
2068         }
2069
2070         return TRUE;
2071 }
2072
2073 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2074 {
2075         /* INIT_INDEX_IO   opcode: 0x78 ('x')
2076          *
2077          * offset      (8  bit): opcode
2078          * offset + 1  (16 bit): CRTC port
2079          * offset + 3  (8  bit): CRTC index
2080          * offset + 4  (8  bit): mask
2081          * offset + 5  (8  bit): data
2082          *
2083          * Read value at index "CRTC index" on "CRTC port", AND with "mask", OR with "data", write-back
2084          */
2085
2086         uint16_t crtcport = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 1])));
2087         uint8_t crtcindex = bios->data[offset + 3];
2088         uint8_t mask = bios->data[offset + 4];
2089         uint8_t data = bios->data[offset + 5];
2090         uint8_t value;
2091
2092         if (!iexec->execute)
2093                 return TRUE;
2094
2095         if (DEBUGLEVEL >= 6)
2096                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2097                            "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
2098                            offset, crtcport, crtcindex, mask, data);
2099
2100         nv_idx_port_rd(pScrn, crtcport, crtcindex, &value);
2101         value = (value & mask) | data;
2102         nv_idx_port_wr(pScrn, crtcport, crtcindex, value);
2103
2104         return TRUE;
2105 }
2106
2107 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2108 {
2109         /* INIT_PLL   opcode: 0x79 ('y')
2110          *
2111          * offset      (8  bit): opcode
2112          * offset + 1  (32 bit): register
2113          * offset + 5  (16 bit): freq
2114          *
2115          * Set PLL register "register" to coefficients for frequency (10kHz) "freq"
2116          */
2117
2118         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2119         uint16_t freq = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 5])));
2120
2121         if (!iexec->execute)
2122                 return TRUE;
2123
2124         if (DEBUGLEVEL >= 6)
2125                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2126                            "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n",
2127                            offset, reg, freq);
2128
2129         setPLL(pScrn, bios, reg, freq * 10);
2130
2131         return TRUE;
2132 }
2133
2134 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2135 {
2136         /* INIT_ZM_REG   opcode: 0x7A ('z')
2137          *
2138          * offset      (8  bit): opcode
2139          * offset + 1  (32 bit): register
2140          * offset + 5  (32 bit): value
2141          *
2142          * Assign "value" to "register"
2143          */
2144
2145         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2146         uint32_t value = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
2147
2148         if (!iexec->execute)
2149                 return TRUE;
2150
2151         nv32_wr(pScrn, reg, value);
2152
2153         return TRUE;
2154 }
2155
2156 /* hack to avoid moving the itbl_entry array before this function */
2157 int init_ram_restrict_zm_reg_group_blocklen = 0;
2158
2159 static Bool init_ram_restrict_zm_reg_group(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2160 {
2161         /* INIT_RAM_RESTRICT_ZM_REG_GROUP   opcode: 0x8F ('')
2162          *
2163          * offset      (8  bit): opcode
2164          * offset + 1  (32 bit): reg
2165          * offset + 5  (8  bit): regincrement
2166          * offset + 6  (8  bit): count
2167          * offset + 7  (32 bit): value 1,1
2168          * ...
2169          *
2170          * Use the RAMCFG strap of PEXTDEV_BOOT as an index into the table at
2171          * ram_restrict_table_ptr. The value read from here is 'n', and
2172          * "value 1,n" gets written to "reg". This repeats "count" times and on
2173          * each iteration 'm', "reg" increases by "regincrement" and
2174          * "value m,n" is used. The extent of n is limited by a number read
2175          * from the 'M' BIT table, herein called "blocklen"
2176          */
2177
2178         NVPtr pNv = NVPTR(pScrn);
2179         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2180         uint8_t regincrement = bios->data[offset + 5];
2181         uint8_t count = bios->data[offset + 6];
2182         uint32_t strap_ramcfg, data;
2183         uint16_t blocklen;
2184         uint8_t index;
2185         int i;
2186
2187         /* previously set by 'M' BIT table */
2188         blocklen = init_ram_restrict_zm_reg_group_blocklen;
2189
2190         if (!iexec->execute)
2191                 return TRUE;
2192
2193         if (!blocklen) {
2194                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2195                            "0x%04X: Zero block length - has the M table been parsed?\n", offset);
2196                 return FALSE;
2197         }
2198
2199         strap_ramcfg = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT) >> 2) & 0xf;
2200         index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg];
2201
2202         if (DEBUGLEVEL >= 6)
2203                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2204                            "0x%04X: Reg: 0x%08X, RegIncrement: 0x%02X, Count: 0x%02X, StrapRamCfg: 0x%02X, Index: 0x%02X\n",
2205                            offset, reg, regincrement, count, strap_ramcfg, index);
2206
2207         for (i = 0; i < count; i++) {
2208                 data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 7 + index * 4 + blocklen * i])));
2209
2210                 nv32_wr(pScrn, reg, data);
2211
2212                 reg += regincrement;
2213         }
2214
2215         return TRUE;
2216 }
2217
2218 static Bool init_copy_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2219 {
2220         /* INIT_COPY_ZM_REG   opcode: 0x90 ('')
2221          *
2222          * offset      (8  bit): opcode
2223          * offset + 1  (32 bit): src reg
2224          * offset + 5  (32 bit): dst reg
2225          *
2226          * Put contents of "src reg" into "dst reg"
2227          */
2228
2229         uint32_t srcreg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2230         uint32_t dstreg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 5])));
2231         uint32_t data;
2232
2233         if (!iexec->execute)
2234                 return TRUE;
2235
2236         nv32_rd(pScrn, srcreg, &data);
2237         nv32_wr(pScrn, dstreg, data);
2238
2239         return TRUE;
2240 }
2241
2242 static Bool init_zm_reg_group_addr_latched(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2243 {
2244         /* INIT_ZM_REG_GROUP_ADDRESS_LATCHED   opcode: 0x91 ('')
2245          *
2246          * offset      (8  bit): opcode
2247          * offset + 1  (32 bit): src reg
2248          * offset + 5  (8  bit): count
2249          * offset + 6  (32 bit): data 1
2250          * ...
2251          *
2252          * For each of "count" values write "data n" to "src reg"
2253          */
2254
2255         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 1])));
2256         uint8_t count = bios->data[offset + 5];
2257         int i;
2258
2259         if (!iexec->execute)
2260                 return TRUE;
2261
2262         for (i = 0; i < count; i++) {
2263                 uint32_t data = le32_to_cpu(*((uint32_t *)(&bios->data[offset + 6 + 4 * i])));
2264                 nv32_wr(pScrn, reg, data);
2265         }
2266
2267         return TRUE;
2268 }
2269
2270 static Bool init_reserved(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset, init_exec_t *iexec)
2271 {
2272         /* INIT_RESERVED   opcode: 0x92 ('')
2273          *
2274          * offset      (8 bit): opcode
2275          *
2276          * Seemingly does nothing
2277          */
2278
2279         return TRUE;
2280 }
2281
2282 static init_tbl_entry_t itbl_entry[] = {
2283         /* command name                       , id  , length  , offset  , mult    , command handler                 */
2284 //      { "INIT_PROG"                         , 0x31, 15      , 10      , 4       , init_prog                       },
2285         { "INIT_IO_RESTRICT_PROG"             , 0x32, 11      , 6       , 4       , init_io_restrict_prog           },
2286         { "INIT_REPEAT"                       , 0x33, 2       , 0       , 0       , init_repeat                     },
2287         { "INIT_IO_RESTRICT_PLL"              , 0x34, 12      , 7       , 2       , init_io_restrict_pll            },
2288         { "INIT_END_REPEAT"                   , 0x36, 1       , 0       , 0       , init_end_repeat                 },
2289         { "INIT_COPY"                         , 0x37, 11      , 0       , 0       , init_copy                       },
2290         { "INIT_NOT"                          , 0x38, 1       , 0       , 0       , init_not                        },
2291         { "INIT_IO_FLAG_CONDITION"            , 0x39, 2       , 0       , 0       , init_io_flag_condition          },
2292         { "INIT_INDEX_ADDRESS_LATCHED"        , 0x49, 18      , 17      , 2       , init_idx_addr_latched           },
2293         { "INIT_IO_RESTRICT_PLL2"             , 0x4A, 11      , 6       , 4       , init_io_restrict_pll2           },
2294         { "INIT_PLL2"                         , 0x4B, 9       , 0       , 0       , init_pll2                       },
2295 /*      { "INIT_I2C_BYTE"                     , 0x4C, x       , x       , x       , init_i2c_byte                   }, */
2296 /*      { "INIT_ZM_I2C_BYTE"                  , 0x4D, x       , x       , x       , init_zm_i2c_byte                }, */
2297 /*      { "INIT_ZM_I2C"                       , 0x4E, x       , x       , x       , init_zm_i2c                     }, */
2298         { "INIT_TMDS"                         , 0x4F, 5       , 0       , 0       , init_tmds                       },
2299         { "INIT_ZM_TMDS_GROUP"                , 0x50, 3       , 2       , 2       , init_zm_tmds_group              },
2300         { "INIT_CR_INDEX_ADDRESS_LATCHED"     , 0x51, 5       , 4       , 1       , init_cr_idx_adr_latch           },
2301         { "INIT_CR"                           , 0x52, 4       , 0       , 0       , init_cr                         },
2302         { "INIT_ZM_CR"                        , 0x53, 3       , 0       , 0       , init_zm_cr                      },
2303         { "INIT_ZM_CR_GROUP"                  , 0x54, 2       , 1       , 2       , init_zm_cr_group                },
2304         { "INIT_CONDITION_TIME"               , 0x56, 3       , 0       , 0       , init_condition_time             },
2305         { "INIT_ZM_REG_SEQUENCE"              , 0x58, 6       , 5       , 4       , init_zm_reg_sequence            },
2306 //      { "INIT_INDIRECT_REG"                 , 0x5A, 7       , 0       , 0       , init_indirect_reg               },
2307         { "INIT_SUB_DIRECT"                   , 0x5B, 3       , 0       , 0       , init_sub_direct                 },
2308         { "INIT_COPY_NV_REG"                  , 0x5F, 22      , 0       , 0       , init_copy_nv_reg                },
2309         { "INIT_ZM_INDEX_IO"                  , 0x62, 5       , 0       , 0       , init_zm_index_io                },
2310         { "INIT_COMPUTE_MEM"                  , 0x63, 1       , 0       , 0       , init_compute_mem                },
2311         { "INIT_RESET"                        , 0x65, 13      , 0       , 0       , init_reset                      },
2312 /*      { "INIT_NEXT"                         , 0x66, x       , x       , x       , init_next                       }, */       
2313 /*      { "INIT_NEXT"                         , 0x67, x       , x       , x       , init_next                       }, */       
2314 /*      { "INIT_NEXT"                         , 0x68, x       , x       , x       , init_next                       }, */       
2315 //      { "INIT_INDEX_IO8"                    , 0x69, 5       , 0       , 0       , init_index_io8                  },
2316         { "INIT_SUB"                          , 0x6B, 2       , 0       , 0       , init_sub                        },
2317 //      { "INIT_RAM_CONDITION"                , 0x6D, 3       , 0       , 0       , init_ram_condition              },
2318         { "INIT_NV_REG"                       , 0x6E, 13      , 0       , 0       , init_nv_reg                     },
2319         { "INIT_MACRO"                        , 0x6F, 2       , 0       , 0       , init_macro                      },
2320         { "INIT_DONE"                         , 0x71, 1       , 0       , 0       , init_done                       },
2321         { "INIT_RESUME"                       , 0x72, 1       , 0       , 0       , init_resume                     },
2322 //      { "INIT_RAM_CONDITION2"               , 0x73, 9       , 0       , 0       , init_ram_condition2             },
2323         { "INIT_TIME"                         , 0x74, 3       , 0       , 0       , init_time                       },
2324         { "INIT_CONDITION"                    , 0x75, 2       , 0       , 0       , init_condition                  },
2325 /*      { "INIT_IO_CONDITION"                 , 0x76, x       , x       , x       , init_io_condition               }, */
2326         { "INIT_INDEX_IO"                     , 0x78, 6       , 0       , 0       , init_index_io                   },
2327         { "INIT_PLL"                          , 0x79, 7       , 0       , 0       , init_pll                        },
2328         { "INIT_ZM_REG"                       , 0x7A, 9       , 0       , 0       , init_zm_reg                     },
2329         /* INIT_RAM_RESTRICT_ZM_REG_GROUP's mult is loaded by M table in BIT */
2330         { "INIT_RAM_RESTRICT_ZM_REG_GROUP"    , 0x8F, 7       , 6       , 0       , init_ram_restrict_zm_reg_group  },
2331         { "INIT_COPY_ZM_REG"                  , 0x90, 9       , 0       , 0       , init_copy_zm_reg                },
2332         { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, 6       , 5       , 4       , init_zm_reg_group_addr_latched  },
2333         { "INIT_RESERVED"                     , 0x92, 1       , 0       , 0       , init_reserved                   },
2334         { 0                                   , 0   , 0       , 0       , 0       , 0                               }
2335 };
2336
2337 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
2338 {
2339         /* Calculates the length of a given init table entry. */
2340         return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
2341 }
2342
2343 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
2344 {
2345         /* Parses all commands in a init table. */
2346
2347         /* We start out executing all commands found in the
2348          * init table. Some op codes may change the status
2349          * of this variable to SKIP, which will cause
2350          * the following op codes to perform no operation until
2351          * the value is changed back to EXECUTE.
2352          */
2353         unsigned char id;
2354         int i;
2355
2356         int count=0;
2357         /* Loop until INIT_DONE causes us to break out of the loop
2358          * (or until offset > bios length just in case... )
2359          * (and no more than 10000 iterations just in case... ) */
2360         while ((offset < bios->length) && (count++ < 10000)) {
2361                 id = bios->data[offset];
2362
2363                 /* Find matching id in itbl_entry */
2364                 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
2365                         ;
2366
2367                 if (itbl_entry[i].name) {
2368                         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ (0x%02X) - %s ]\n",
2369                                    offset, itbl_entry[i].id, itbl_entry[i].name);
2370
2371                         /* execute eventual command handler */
2372                         if (itbl_entry[i].handler)
2373                                 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
2374                                         break;
2375                 } else {
2376                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2377                                    "0x%04X: Init table command not found: 0x%02X\n", offset, id);
2378                         break;
2379                 }
2380
2381                 /* Add the offset of the current command including all data
2382                  * of that command. The offset will then be pointing on the
2383                  * next op code.
2384                  */
2385                 offset += get_init_table_entry_length(bios, offset, i);
2386         }
2387 }
2388
2389 static void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios)
2390 {
2391         /* Loops and calls parse_init_table() for each present table. */
2392
2393         int i = 0;
2394         uint16_t table;
2395         init_exec_t iexec = {TRUE, FALSE};
2396
2397         while ((table = le16_to_cpu(*((uint16_t *)(&bios->data[bios->init_script_tbls_ptr + i]))))) {
2398
2399                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing init table %d\n",
2400                         table, i / 2);
2401
2402                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2403                            "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n", table);
2404                 still_alive();
2405                 parse_init_table(pScrn, bios, table, &iexec);
2406                 i += 2;
2407         }
2408 }
2409
2410 void link_head_and_output(ScrnInfoPtr pScrn, int head, int dcb_entry, Bool overrideval)
2411 {
2412         /* The BIOS scripts don't do this for us, sadly
2413          * Luckily we do know the values ;-)
2414          *
2415          * head < 0 indicates we wish to force a setting with the overrideval
2416          * (for VT restore etc.)
2417          */
2418
2419         NVPtr pNv = NVPTR(pScrn);
2420         int preferred_output = (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1) >> 1;
2421         uint8_t tmds04 = 0x80;
2422         uint32_t tmds_ctrl, tmds_ctrl2;
2423
2424         /* Bit 3 crosswires output and bus. */
2425         if (head >= 0 && head != preferred_output)
2426                 tmds04 = 0x88;
2427         if (head < 0 && overrideval)
2428                 tmds04 = 0x88;
2429
2430         if (pNv->dcb_table.entry[dcb_entry].type == OUTPUT_LVDS)
2431                 tmds04 |= 0x01;
2432
2433         tmds_ctrl = NV_PRAMDAC0_OFFSET + (preferred_output ? NV_PRAMDAC0_SIZE : 0) + NV_RAMDAC_FP_TMDS_CONTROL;
2434         tmds_ctrl2 = NV_PRAMDAC0_OFFSET + (preferred_output ? NV_PRAMDAC0_SIZE : 0) + NV_RAMDAC_FP_TMDS_CONTROL_2;
2435
2436         Bool oldexecute = pNv->VBIOS.execute;
2437         pNv->VBIOS.execute = TRUE;
2438         nv32_wr(pScrn, tmds_ctrl + 4, tmds04);
2439         nv32_wr(pScrn, tmds_ctrl, 0x04);
2440         if (pNv->dcb_table.entry[dcb_entry].type == OUTPUT_LVDS && pNv->VBIOS.fp.dual_link)
2441                 nv32_wr(pScrn, tmds_ctrl2 + 4, tmds04 ^ 0x08);
2442         else {
2443                 /* I have encountered no dvi (dual-link or not) that sets to anything else. */
2444                 /* Does this change beyond the 165 MHz boundary? */
2445                 nv32_wr(pScrn, tmds_ctrl2 + 4, 0x0);
2446         }
2447         nv32_wr(pScrn, tmds_ctrl2, 0x04);
2448         pNv->VBIOS.execute = oldexecute;
2449 }
2450
2451 static void call_lvds_manufacturer_script(ScrnInfoPtr pScrn, int head, int dcb_entry, enum LVDS_script script)
2452 {
2453         NVPtr pNv = NVPTR(pScrn);
2454         bios_t *bios = &pNv->VBIOS;
2455         init_exec_t iexec = {TRUE, FALSE};
2456
2457         uint8_t sub = bios->data[bios->fp.xlated_entry + script];
2458         uint16_t scriptofs = le16_to_cpu(*((CARD16 *)(&bios->data[bios->init_script_tbls_ptr + sub * 2])));
2459         Bool power_off_for_reset, reset_after_pclk_change;
2460         uint16_t off_on_delay;
2461
2462         if (!bios->fp.xlated_entry || !sub || !scriptofs)
2463                 return;
2464
2465         if (script == LVDS_INIT && bios->data[scriptofs] != 'q') {
2466                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LVDS init script not stubbed\n");
2467                 return;
2468         }
2469
2470         power_off_for_reset = bios->data[bios->fp.xlated_entry] & 1;
2471         reset_after_pclk_change = bios->data[bios->fp.xlated_entry] & 2;
2472         off_on_delay = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.xlated_entry + 7]);
2473
2474         if (script == LVDS_PANEL_ON && reset_after_pclk_change)
2475                 call_lvds_manufacturer_script(pScrn, head, dcb_entry, LVDS_RESET);
2476         if (script == LVDS_RESET && power_off_for_reset)
2477                 call_lvds_manufacturer_script(pScrn, head, dcb_entry, LVDS_PANEL_OFF);
2478
2479         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Calling LVDS script %d:\n", script);
2480         pNv->VBIOS.execute = TRUE;
2481         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_OWNER,
2482                    head ? NV_VGA_CRTCX_OWNER_HEADB : NV_VGA_CRTCX_OWNER_HEADA);
2483         parse_init_table(pScrn, bios, scriptofs, &iexec);
2484         pNv->VBIOS.execute = FALSE;
2485
2486         if (script == LVDS_PANEL_OFF)
2487                 usleep(off_on_delay * 1000);
2488         if (script == LVDS_RESET)
2489                 link_head_and_output(pScrn, head, dcb_entry, FALSE);
2490 }
2491
2492 static uint16_t clkcmptable(bios_t *bios, uint16_t clktable, uint16_t pxclk)
2493 {
2494         int compare_record_len, i = 0;
2495         uint16_t compareclk, scriptptr = 0;
2496
2497         if (bios->major_version < 5) /* pre BIT */
2498                 compare_record_len = 3;
2499         else
2500                 compare_record_len = 4;
2501
2502         do {
2503                 compareclk = le16_to_cpu(*((uint16_t *)&bios->data[clktable + compare_record_len * i]));
2504                 if (pxclk >= compareclk) {
2505                         if (bios->major_version < 5) {
2506                                 uint8_t tmdssub = bios->data[clktable + 2 + compare_record_len * i];
2507                                 scriptptr = le16_to_cpu(*((uint16_t *)(&bios->data[bios->init_script_tbls_ptr + tmdssub * 2])));
2508                         } else
2509                                 scriptptr = le16_to_cpu(*((uint16_t *)&bios->data[clktable + 2 + compare_record_len * i]));
2510                         break;
2511                 }
2512                 i++;
2513         } while (compareclk);
2514
2515         return scriptptr;
2516 }
2517
2518 static void rundigitaloutscript(ScrnInfoPtr pScrn, uint16_t scriptptr, int head, int dcb_entry)
2519 {
2520         NVPtr pNv = NVPTR(pScrn);
2521         bios_t *bios = &pNv->VBIOS;
2522         init_exec_t iexec = {TRUE, FALSE};
2523
2524         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing digital output script table\n", scriptptr);
2525         bios->execute = TRUE;
2526         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, NV_VGA_CRTCX_OWNER,
2527                         head ? NV_VGA_CRTCX_OWNER_HEADB : NV_VGA_CRTCX_OWNER_HEADA);
2528         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, 0x57, 0);
2529         nv_idx_port_wr(pScrn, CRTC_INDEX_COLOR, 0x58, dcb_entry);
2530         parse_init_table(pScrn, bios, scriptptr, &iexec);
2531         bios->execute = FALSE;
2532
2533         link_head_and_output(pScrn, head, dcb_entry, FALSE);
2534 }
2535
2536 static void run_lvds_table(ScrnInfoPtr pScrn, int head, int dcb_entry, enum LVDS_script script, uint16_t pxclk)
2537 {
2538         /* The BIT LVDS table's header has the information to setup the
2539          * necessary registers. Following the standard 4 byte header are:
2540          * A bitmask byte and a dual-link transition pxclk valur for use in
2541          * selecting the init script when not using straps; 4 script pointers
2542          * for panel power, selected by output and on/off; and 8 table pointers
2543          * for panel init, the needed one determined by output, and bits in the
2544          * conf byte. These tables are similar to the TMDS tables, consisting
2545          * of a list of pxclks and script pointers.
2546          */
2547
2548         NVPtr pNv = NVPTR(pScrn);
2549         bios_t *bios = &pNv->VBIOS;
2550         int fpstrapping, outputset = (pNv->dcb_table.entry[dcb_entry].or == 4) ? 1 : 0;
2551         uint16_t scriptptr = 0, clktable;
2552         uint8_t clktableptr = 0;
2553
2554         fpstrapping = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT) >> 16) & 0xf;
2555
2556         /* for now we assume version 3.0 table - g80 support will need some changes */
2557
2558         switch (script) {
2559         case LVDS_INIT:
2560                 return;
2561         case LVDS_BACKLIGHT_ON: // check applicability of the script for this
2562         case LVDS_PANEL_ON:
2563                 scriptptr = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.lvdsmanufacturerpointer + 7 + outputset * 2]);
2564                 break;
2565         case LVDS_BACKLIGHT_OFF:        // check applicability of the script for this
2566         case LVDS_PANEL_OFF:
2567                 scriptptr = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]);
2568                 break;
2569         case LVDS_RESET:
2570                 if (pNv->dcb_table.entry[dcb_entry].lvdsconf.use_straps_for_mode ||
2571                         (fpstrapping != 0x0f && bios->data[bios->fp.xlated_entry + 1] != 0x0f)) {
2572                         if (bios->fp.dual_link)
2573                                 clktableptr += 2;
2574                         if (bios->fp.BITbit1)
2575                                 clktableptr++;
2576                 } else {
2577                         uint8_t fallback = bios->data[bios->fp.lvdsmanufacturerpointer + 4];
2578                         int fallbackcmpval = (pNv->dcb_table.entry[dcb_entry].or == 4) ? 4 : 1;
2579                         uint8_t dltransitionclk = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.lvdsmanufacturerpointer + 5]);
2580                         if (pxclk > dltransitionclk) {  // dual-link
2581                                 clktableptr += 2;
2582                                 fallbackcmpval *= 2;
2583                         }
2584                         if (fallbackcmpval & fallback)
2585                                 clktableptr++;
2586                 }
2587
2588                 /* adding outputset * 8 may not be correct */
2589                 clktable = le16_to_cpu(*(uint16_t *)&bios->data[bios->fp.lvdsmanufacturerpointer + 15 + clktableptr * 2 + outputset * 8]);
2590                 if (!clktable) {
2591                         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Pixel clock comparison table not found\n");
2592                         return;
2593                 }
2594                 scriptptr = clkcmptable(bios, clktable, pxclk);
2595         }
2596
2597         if (!scriptptr) {
2598                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LVDS output init script not found\n");
2599                 return;
2600         }
2601         rundigitaloutscript(pScrn, scriptptr, head, dcb_entry);
2602 }
2603
2604 void call_lvds_script(ScrnInfoPtr pScrn, int head, int dcb_entry, enum LVDS_script script, uint16_t pxclk)
2605 {
2606         /* LVDS operations are multiplexed in an effort to present a single API
2607          * which works with two vastly differing underlying structures.
2608          * This acts as the demux
2609          */
2610
2611         NVPtr pNv = NVPTR(pScrn);
2612         bios_t *bios = &pNv->VBIOS;
2613         uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
2614
2615         if (!lvds_ver)
2616                 return;
2617
2618         if (lvds_ver < 0x30)
2619                 call_lvds_manufacturer_script(pScrn, head, dcb_entry, script);
2620         else
2621                 run_lvds_table(pScrn, head, dcb_entry, script, pxclk);
2622 }
2623
2624 struct fppointers {
2625         uint16_t fptablepointer;
2626         uint16_t fpxlatetableptr;
2627         uint16_t fpxlatemanufacturertableptr;
2628         int xlatwidth;
2629 };
2630
2631 static void parse_fp_mode_table(ScrnInfoPtr pScrn, bios_t *bios, struct fppointers *fpp)
2632 {
2633         NVPtr pNv = NVPTR(pScrn);
2634         unsigned int fpstrapping;
2635         uint8_t *fptable;
2636         uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex;
2637         int ofs;
2638         DisplayModePtr mode;
2639
2640         fpstrapping = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT) >> 16) & 0xf;
2641
2642         if (fpp->fptablepointer == 0x0 || fpp->fpxlatetableptr == 0x0) {
2643                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2644                            "Pointers to flat panel table invalid\n");
2645                 return;
2646         }
2647
2648         fptable = &bios->data[fpp->fptablepointer];
2649
2650         fptable_ver = fptable[0];
2651
2652         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2653                    "Found flat panel mode table revision %d.%d\n",
2654                    fptable_ver >> 4, fptable_ver & 0xf);
2655
2656         switch (fptable_ver) {
2657         /* BMP version 0x5.0x11 BIOSen have version 1 like tables, but no version field,
2658          * and miss one of the spread spectrum/PWM bytes.
2659          * This could affect early GF2Go parts (not seen any appropriate ROMs though).
2660          * Here we assume that a version of 0x05 matches this case (combining with a
2661          * BMP version check would be better), as the common case for the panel type
2662          * field is 0x0005, and that is in fact what we are reading the first byte of. */
2663         case 0x05:      /* some NV10, 11, 15, 16 */
2664                 recordlen = 42;
2665                 ofs = 6;
2666                 break;
2667         case 0x10:      /* some NV15/16, and NV11+ */
2668                 recordlen = 44;
2669                 ofs = 7;
2670                 break;
2671         case 0x20:      /* NV40+ */
2672                 headerlen = fptable[1];
2673                 recordlen = fptable[2];
2674                 fpentries = fptable[3];
2675                 ofs = 0;
2676                 break;
2677         default:
2678                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2679                            "FP Table revision not currently supported\n");
2680                 return;
2681         }
2682
2683         fpindex = bios->data[fpp->fpxlatetableptr + fpstrapping * fpp->xlatwidth];
2684         if (fpindex > fpentries) {
2685                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2686                            "Bad flat panel table index\n");
2687                 return;
2688         }
2689
2690         if (!(mode = xcalloc(1, sizeof(DisplayModeRec))))
2691                 return;
2692
2693         int modeofs = headerlen + recordlen * fpindex + ofs;
2694         mode->Clock = le16_to_cpu(*(uint16_t *)&fptable[modeofs]) * 10;
2695         mode->HDisplay = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 2]);
2696         mode->HSyncStart = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 10] + 1);
2697         mode->HSyncEnd = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 12] + 1);
2698         mode->HTotal = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 14] + 1);
2699         mode->VDisplay = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 16]);
2700         mode->VSyncStart = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 24] + 1);
2701         mode->VSyncEnd = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 26] + 1);
2702         mode->VTotal = le16_to_cpu(*(uint16_t *)&fptable[modeofs + 28] + 1);
2703         mode->Flags |= (fptable[modeofs + 30] & 0x10) ? V_PHSYNC : V_NHSYNC;
2704         mode->Flags |= (fptable[modeofs + 30] & 0x1) ? V_PVSYNC : V_NVSYNC;
2705
2706         /* for version 1.0:
2707          * bytes 1-2 are "panel type", including bits on whether Colour/mono, single/dual link, and type (TFT etc.)
2708          * bytes 3-6 are bits per colour in RGBX
2709          * 11-12 is HDispEnd
2710          * 13-14 is HValid Start
2711          * 15-16 is HValid End
2712          * bytes 38-39 relate to spread spectrum settings
2713          * bytes 40-43 are something to do with PWM */
2714
2715         mode->prev = mode->next = NULL;
2716         mode->status = MODE_OK;
2717         mode->type = M_T_DRIVER | M_T_PREFERRED;
2718         xf86SetModeDefaultName(mode);
2719
2720 //      if (XF86_CRTC_CONFIG_PTR(pScrn)->debug_modes) {
2721                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2722                            "Found flat panel mode in BIOS tables:\n");
2723                 xf86PrintModeline(pScrn->scrnIndex, mode);
2724 //      }
2725
2726         bios->fp.native_mode = mode;
2727 }
2728
2729 static void parse_lvds_manufacturer_table_init(ScrnInfoPtr pScrn, bios_t *bios, struct fppointers *fpp)
2730 {
2731         /* The LVDS table changed considerably with BIT bioses. Previously
2732          * there was a header of version and record length, followed by several
2733          * records, indexed by a seperate xlat table, indexed in turn by the fp
2734          * strap in EXTDEV_BOOT. Each record had a config byte, followed by 6
2735          * script numbers for use by INIT_SUB which controlled panel init and
2736          * power, and finally a dword of ms to sleep between power off and on
2737          * operations.
2738          *
2739          * The BIT LVDS table has the typical BIT table header: version byte,
2740          * header length byte, record length byte, and a byte for the maximum
2741          * number of records that can be held in the table.
2742          *
2743          * The table following the header serves as an integrated config and
2744          * xlat table: the records in the table are indexed by the FP strap
2745          * nibble in EXTDEV_BOOT, and each record has two bytes - the first as
2746          * a config byte, the second for indexing the fp mode table pointed to
2747          * by the BIT 'D' table
2748          */
2749
2750         NVPtr pNv = NVPTR(pScrn);
2751         unsigned int fpstrapping, lvdsmanufacturerindex = 0;
2752         uint8_t lvds_ver, headerlen, recordlen;
2753
2754         fpstrapping = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT) >> 16) & 0xf;
2755
2756         if (bios->fp.lvdsmanufacturerpointer == 0x0) {
2757                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2758                            "Pointer to LVDS manufacturer table invalid\n");
2759                 return;
2760         }
2761
2762         lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
2763
2764         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2765                    "Found LVDS manufacturer table revision %d.%d\n",
2766                    lvds_ver >> 4, lvds_ver & 0xf);
2767
2768         switch (lvds_ver) {
2769         case 0x0a:      /* pre NV40 */
2770                 lvdsmanufacturerindex = bios->data[fpp->fpxlatemanufacturertableptr + fpstrapping];
2771
2772                 headerlen = 2;
2773                 recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
2774
2775                 break;
2776         case 0x30:      /* NV4x */
2777                 lvdsmanufacturerindex = fpstrapping;
2778                 headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
2779                 if (headerlen < 0x1f) {
2780                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2781                                    "LVDS table header not understood\n");
2782                         return;
2783                 }
2784                 recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2];
2785                 break;
2786         case 0x40:      /* It changed again with gf8 :o( */
2787         default:
2788                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2789                            "LVDS table revision not currently supported\n");
2790                 return;
2791         }
2792
2793         uint16_t lvdsofs = bios->fp.xlated_entry = bios->fp.lvdsmanufacturerpointer + headerlen + recordlen * lvdsmanufacturerindex;
2794         switch (lvds_ver) {
2795         case 0x0a:
2796                 bios->fp.dual_link = bios->data[lvdsofs] & 4;
2797                 bios->fp.if_is_18bit = !(bios->data[lvdsofs] & 16);
2798                 break;
2799         case 0x30:
2800                 bios->fp.dual_link = bios->data[lvdsofs] & 1;
2801                 bios->fp.BITbit1 = bios->data[lvdsofs] & 2;
2802                 fpp->fpxlatetableptr = bios->fp.lvdsmanufacturerpointer + headerlen + 1;
2803                 fpp->xlatwidth = recordlen;
2804                 break;
2805         }
2806 }
2807
2808 void run_tmds_table(ScrnInfoPtr pScrn, int dcb_entry, int head, uint16_t pxclk)
2809 {
2810         /* the dcb_entry parameter is the index of the appropriate DCB entry
2811          * the pxclk parameter is in 10s of kHz (eg. 108Mhz is 10800, or 0x2a30)
2812          *
2813          * This runs the TMDS regs setting code found on BIT bios cards
2814          *
2815          * For ffs(or) == 1 use the first table, for ffs(or) == 2 and
2816          * ffs(or) == 3, use the second.
2817          */
2818
2819         NVPtr pNv = NVPTR(pScrn);
2820         bios_t *bios = &pNv->VBIOS;
2821         uint16_t clktable = 0, scriptptr;
2822
2823         if (pNv->dcb_table.entry[dcb_entry].location) /* off chip */
2824                 return;
2825
2826         switch (ffs(pNv->dcb_table.entry[dcb_entry].or)) {
2827         case 1:
2828                 clktable = bios->tmds.output0_script_ptr;
2829                 break;
2830         case 2:
2831         case 3:
2832                 clktable = bios->tmds.output1_script_ptr;
2833                 break;
2834         }
2835
2836         if (!clktable) {
2837                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Pixel clock comparison table not found\n");
2838                 return;
2839         }
2840
2841         scriptptr = clkcmptable(bios, clktable, pxclk);
2842
2843         if (!scriptptr) {
2844                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TMDS output init script not found\n");
2845                 return;
2846         }
2847
2848         rundigitaloutscript(pScrn, scriptptr, head, dcb_entry);
2849 }
2850
2851 static void parse_bios_version(ScrnInfoPtr pScrn, bios_t *bios, uint16_t offset)
2852 {
2853         /* offset + 0  (8 bits): Micro version
2854          * offset + 1  (8 bits): Minor version
2855          * offset + 2  (8 bits): Chip version
2856          * offset + 3  (8 bits): Major version
2857          */
2858
2859         bios->major_version = bios->data[offset + 3];
2860         bios->chip_version = bios->data[offset + 2];
2861         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios version %02x.%02x.%02x.%02x\n",
2862                    bios->data[offset + 3], bios->data[offset + 2],
2863                    bios->data[offset + 1], bios->data[offset]);
2864 }
2865
2866 Bool get_pll_limits(ScrnInfoPtr pScrn, enum pll_types plltype, struct pll_lims *pll_lim)
2867 {
2868         /* PLL limits table
2869          *
2870          * Version 0x10: NV31
2871          * One byte header (version), one record of 24 bytes
2872          * Version 0x11: NV36 - Not implemented
2873          * Seems to have same record style as 0x10, but 3 records rather than 1
2874          * Version 0x20: Found on Geforce 6 cards
2875          * Trivial 4 byte BIT header. 31 (0x1f) byte record length
2876          * Version 0x21: Found on Geforce 7, 8 and some Geforce 6 cards
2877          * 5 byte header, fifth byte of unknown purpose. 35 (0x23) byte record length
2878          */
2879
2880         NVPtr pNv = NVPTR(pScrn);
2881         bios_t *bios = &pNv->VBIOS;
2882         uint8_t pll_lim_ver, headerlen, recordlen, entries;
2883         int pllindex = 0, i;
2884
2885         if (!bios->pll_limit_tbl_ptr) {
2886                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Pointer to PLL limits table invalid\n");
2887                 return FALSE;
2888         }
2889
2890         pll_lim_ver = bios->data[bios->pll_limit_tbl_ptr + 0];
2891
2892         if (DEBUGLEVEL >= 6)
2893                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2894                            "Found BIT PLL limits table version 0x%X\n", pll_lim_ver);
2895
2896         switch (pll_lim_ver) {
2897         case 0x10:
2898                 headerlen = 1;
2899                 recordlen = 0x18;
2900                 entries = 1;
2901                 pllindex = 0;
2902                 break;
2903         case 0x20:
2904         case 0x21:
2905                 headerlen = bios->data[bios->pll_limit_tbl_ptr + 1];
2906                 recordlen = bios->data[bios->pll_limit_tbl_ptr + 2];
2907                 entries = bios->data[bios->pll_limit_tbl_ptr + 3];
2908                 break;
2909         default:
2910                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2911                            "PLL limits table revision not currently supported\n");
2912                 return FALSE;
2913         }
2914
2915         /* initialize all members to zero */
2916         memset (pll_lim, 0, sizeof(struct pll_lims));
2917
2918         if (pll_lim_ver == 0x10) {
2919                 uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex;
2920
2921                 pll_lim->vco1.minfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs])));
2922                 pll_lim->vco1.maxfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 4])));
2923                 pll_lim->vco2.minfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 8])));
2924                 pll_lim->vco2.maxfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 12])));
2925                 pll_lim->vco1.min_inputfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 16])));
2926                 pll_lim->vco2.min_inputfreq = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + 20])));
2927         } else {        /* ver 0x20, 0x21 */
2928                 uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen;
2929
2930                 for (i = 0; i < entries; i++) {
2931                         uint32_t reg = le32_to_cpu(*((uint32_t *)(&bios->data[plloffs + recordlen * i])));
2932
2933                         if (plltype == VPLL1 && (reg == 0x680508 || reg == 0x4010)) {
2934                                 pllindex = i;
2935                                 break;
2936                         }
2937                         if (plltype == VPLL2 && (reg == 0x680520 || reg == 0x4018)) {
2938                                 pllindex = i;
2939                                 break;
2940                         }
2941                         if (reg == 0x0000) /* generic pll settings */
2942                                 pllindex = i;
2943                 }
2944
2945                 plloffs += recordlen * pllindex;
2946
2947                 if (DEBUGLEVEL >= 6)
2948                         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Loading PLL limits for reg 0x%08x\n",
2949                                    le32_to_cpu(*((uint32_t *)(&bios->data[plloffs]))));
2950
2951                 /* What output frequencies can each VCO generate? */
2952                 pll_lim->vco1.minfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 4])));
2953                 pll_lim->vco1.maxfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 6])));
2954                 pll_lim->vco2.minfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 8])));
2955                 pll_lim->vco2.maxfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 10])));
2956
2957                 /* What input frequencies do they accept (past the m-divider)? */
2958                 pll_lim->vco1.min_inputfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 12])));
2959                 pll_lim->vco1.max_inputfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 14])));
2960                 pll_lim->vco2.min_inputfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 16])));
2961                 pll_lim->vco2.max_inputfreq = le16_to_cpu(*((uint16_t *)(&bios->data[plloffs + 18])));
2962
2963                 /* What values are accepted as multiplier and divider? */
2964                 pll_lim->vco1.min_n = bios->data[plloffs + 20];
2965                 pll_lim->vco1.max_n = bios->data[plloffs + 21];
2966                 pll_lim->vco1.min_m = bios->data[plloffs + 22];
2967                 pll_lim->vco1.max_m = bios->data[plloffs + 23];
2968                 pll_lim->vco2.min_n = bios->data[plloffs + 24];
2969                 pll_lim->vco2.max_n = bios->data[plloffs + 25];
2970                 pll_lim->vco2.min_m = bios->data[plloffs + 26];
2971                 pll_lim->vco2.max_m = bios->data[plloffs + 27];
2972
2973                 pll_lim->unk1c = bios->data[plloffs + 28];
2974                 pll_lim->unk1d = bios->data[plloffs + 29];
2975                 pll_lim->unk1e = bios->data[plloffs + 30];
2976         }
2977
2978 #if 1 /* for easy debugging */
2979         ErrorF("pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq);
2980         ErrorF("pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq);
2981         ErrorF("pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq);
2982         ErrorF("pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq);
2983
2984         ErrorF("pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq);
2985         ErrorF("pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq);
2986         ErrorF("pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq);
2987         ErrorF("pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq);
2988
2989         ErrorF("pll.vco1.min_n: %d\n", pll_lim->vco1.min_n);
2990         ErrorF("pll.vco1.max_n: %d\n", pll_lim->vco1.max_n);
2991         ErrorF("pll.vco1.min_m: %d\n", pll_lim->vco1.min_m);
2992         ErrorF("pll.vco1.max_m: %d\n", pll_lim->vco1.max_m);
2993         ErrorF("pll.vco2.min_n: %d\n", pll_lim->vco2.min_n);
2994         ErrorF("pll.vco2.max_n: %d\n", pll_lim->vco2.max_n);
2995         ErrorF("pll.vco2.min_m: %d\n", pll_lim->vco2.min_m);
2996         ErrorF("pll.vco2.max_m: %d\n", pll_lim->vco2.max_m);
2997
2998         ErrorF("pll.unk1c: %d\n", pll_lim->unk1c);
2999         ErrorF("pll.unk1d: %d\n", pll_lim->unk1d);
3000         ErrorF("pll.unk1e: %d\n", pll_lim->unk1e);
3001 #endif
3002
3003         return TRUE;
3004 }
3005
3006 static int parse_bit_B_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3007 {
3008         /* offset + 0  (32 bits): BIOS version dword
3009          *
3010          * There's a bunch of bits in this table other than the bios version
3011          * that we don't use - their use currently unknown
3012          */
3013
3014         if (bitentry->length < 0x4) {
3015                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3016                            "Do not understand B table entry\n");
3017                 return 0;
3018         }
3019
3020         parse_bios_version(pScrn, bios, bitentry->offset);
3021
3022         return 1;
3023 }
3024
3025 static int parse_bit_C_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3026 {
3027         /* offset + 8  (16 bits): PLL limits table pointer
3028          *
3029          * There's more in here, but that's unknown.
3030          */
3031
3032         if (bitentry->length < 10) {
3033                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Do not understand C table entry\n");
3034                 return 0;
3035         }
3036
3037         bios->pll_limit_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 8])));
3038
3039         return 1;
3040 }
3041
3042 static int parse_bit_display_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry, struct fppointers *fpp)
3043 {
3044         /* Parses the flat panel table segment that the bit entry points to.
3045          * Starting at bitentry->offset:
3046          *
3047          * offset + 0  (16 bits): FIXME table pointer
3048          * offset + 2  (16 bits): mode table pointer
3049          */
3050
3051         if (bitentry->length != 4) {
3052                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3053                            "Do not understand BIT display table entry\n");
3054                 return 0;
3055         }
3056
3057         fpp->fptablepointer = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 2])));
3058
3059         return 1;
3060 }
3061
3062 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3063 {
3064         /* Parses the init table segment that the bit entry points to.
3065          * Starting at bitentry->offset: 
3066          * 
3067          * offset + 0  (16 bits): init script tables pointer
3068          * offset + 2  (16 bits): macro index table pointer
3069          * offset + 4  (16 bits): macro table pointer
3070          * offset + 6  (16 bits): condition table pointer
3071          * offset + 8  (16 bits): io condition table pointer
3072          * offset + 10 (16 bits): io flag condition table pointer
3073          * offset + 12 (16 bits): init function table pointer
3074          *
3075          * TODO:
3076          * * Are 'I' bit entries always of length 0xE?
3077          * 
3078          */
3079
3080         if (bitentry->length < 14) {
3081                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3082                            "Unable to recognize BIT init table entry\n");
3083                 return 0;
3084         }
3085
3086         bios->init_script_tbls_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset])));
3087         bios->macro_index_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 2])));
3088         bios->macro_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 4])));
3089         bios->condition_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 6])));
3090         bios->io_condition_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 8])));
3091         bios->io_flag_condition_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 10])));
3092         bios->init_function_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 12])));
3093
3094         return 1;
3095 }
3096
3097 static int parse_bit_lvds_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry, struct fppointers *fpp)
3098 {
3099         /* Parses the LVDS table segment that the bit entry points to.
3100          * Starting at bitentry->offset:
3101          *
3102          * offset + 0  (16 bits): LVDS strap xlate table pointer
3103          */
3104
3105         if (bitentry->length != 2) {
3106                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3107                            "Do not understand BIT LVDS table entry\n");
3108                 return 0;
3109         }
3110
3111         /* no idea if it's still called the LVDS manufacturer table, but the concept's close enough */
3112         bios->fp.lvdsmanufacturerpointer = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset])));
3113
3114         parse_lvds_manufacturer_table_init(pScrn, bios, fpp);
3115
3116         return 1;
3117 }
3118
3119 static int parse_bit_M_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3120 {
3121         /* offset + 2  (8  bits): number of options in an INIT_RAM_RESTRICT_ZM_REG_GROUP opcode option set
3122          * offset + 3  (16 bits): pointer to strap xlate table for RAM restrict option selection
3123          *
3124          * There's a bunch of bits in this table other than the RAM restrict
3125          * stuff that we don't use - their use currently unknown
3126          */
3127
3128         int i;
3129
3130         /* Older bios versions don't have a sufficiently long table for what we want */
3131         if (bitentry->length < 0x5)
3132                 return 1;
3133
3134         /* set up multiplier for INIT_RAM_RESTRICT_ZM_REG_GROUP */
3135         for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != 0x8f); i++)
3136                 ;
3137         itbl_entry[i].length_multiplier = bios->data[bitentry->offset + 2] * 4;
3138         init_ram_restrict_zm_reg_group_blocklen = itbl_entry[i].length_multiplier;
3139
3140         bios->ram_restrict_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset + 3])));
3141
3142         return 1;
3143 }
3144
3145 static int parse_bit_tmds_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
3146 {
3147         /* Parses the pointer to the TMDS table
3148          *
3149          * Starting at bitentry->offset:
3150          *
3151          * offset + 0  (16 bits): TMDS table pointer
3152          *
3153          * The TMDS table is typically found just before the DCB table, with a
3154          * characteristic signature of 0x11,0x13 (1.1 being version, 0x13 being
3155          * length?)
3156          *
3157          * At offset +7 is a pointer to a script, which I don't know how to run yet
3158          * At offset +9 is a pointer to another script, likewise
3159          * Offset +11 has a pointer to a table where the first word is a pxclk
3160          * frequency and the second word a pointer to a script, which should be
3161          * run if the comparison pxclk frequency is less than the pxclk desired.
3162          * This repeats for decreasing comparison frequencies
3163          * Offset +13 has a pointer to a similar table
3164          * The selection of table (and possibly +7/+9 script) is dictated by
3165          * "or" from the DCB.
3166          */
3167
3168         uint16_t tmdstableptr, script1, script2;
3169
3170         if (bitentry->length != 2) {
3171                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3172                            "Do not understand BIT TMDS table entry\n");
3173                 return 0;
3174         }
3175
3176         tmdstableptr = le16_to_cpu(*((uint16_t *)(&bios->data[bitentry->offset])));
3177
3178         if (tmdstableptr == 0x0) {
3179                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Pointer to TMDS table invalid\n");
3180                 return 0;
3181         }
3182
3183         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found TMDS table revision %d.%d\n",
3184                    bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
3185
3186         /* These two scripts are odd: they don't seem to get run even when they are not stubbed */
3187         script1 = le16_to_cpu(*((uint16_t *)&bios->data[tmdstableptr + 7]));
3188         script2 = le16_to_cpu(*((uint16_t *)&bios->data[tmdstableptr + 9]));
3189         if (bios->data[script1] != 'q' || bios->data[script2] != 'q')
3190                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TMDS table script pointers not stubbed\n");
3191
3192         bios->tmds.output0_script_ptr = le16_to_cpu(*((uint16_t *)&bios->data[tmdstableptr + 11]));
3193         bios->tmds.output1_script_ptr = le16_to_cpu(*((uint16_t *)&bios->data[tmdstableptr + 13]));
3194
3195         return 1;
3196 }
3197
3198 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
3199 {
3200         bit_entry_t bitentry;
3201         char done = 0;
3202         struct fppointers fpp;
3203         NVPtr pNv = NVPTR(pScrn);
3204
3205         memset(&fpp, 0, sizeof(struct fppointers));
3206
3207         while (!done) {
3208                 bitentry.id[0] = bios->data[offset];
3209                 bitentry.id[1] = bios->data[offset + 1];
3210                 bitentry.length = le16_to_cpu(*((uint16_t *)&bios->data[offset + 2]));
3211                 bitentry.offset = le16_to_cpu(*((uint16_t *)&bios->data[offset + 4]));
3212
3213                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3214                            "0x%04X: Found BIT command with id 0x%02X (%c)\n",
3215                            offset, bitentry.id[0], bitentry.id[0]);
3216
3217                 switch (bitentry.id[0]) {
3218                 case 0:
3219                         /* id[0] = 0 and id[1] = 0 ==> end of BIT struture */
3220                         if (bitentry.id[1] == 0)
3221                                 done = 1;
3222                         break;
3223                 case 'B':
3224                         parse_bit_B_tbl_entry(pScrn, bios, &bitentry);
3225                         break;
3226                 case 'C':
3227                         parse_bit_C_tbl_entry(pScrn, bios, &bitentry);
3228                         break;
3229                 case 'D':
3230                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3231                                    "0x%04X: Found flat panel display table entry in BIT structure\n", offset);
3232                         parse_bit_display_tbl_entry(pScrn, bios, &bitentry, &fpp);
3233                         break;
3234                 case 'I':
3235                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3236                                    "0x%04X: Found init table entry in BIT structure\n", offset);
3237                         parse_bit_init_tbl_entry(pScrn, bios, &bitentry);
3238                         break;
3239                 case 'L':
3240                         parse_bit_lvds_tbl_entry(pScrn, bios, &bitentry, &fpp);
3241                         break;
3242                 case 'M': /* memory? */
3243                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3244                                    "0x%04X: Found M table entry in BIT structure\n", offset);
3245                         parse_bit_M_tbl_entry(pScrn, bios, &bitentry);
3246                         break;
3247                 case 'T':
3248                         parse_bit_tmds_tbl_entry(pScrn, bios, &bitentry);
3249                         break;
3250
3251                         /* TODO: What kind of information does the other BIT entrys point to?
3252                          *       'P' entry is probably performance tables, but there are
3253                          *       quite a few others...
3254                          */
3255                 }
3256
3257                 offset += sizeof(bit_entry_t);
3258         }
3259
3260         /* C and M tables have to be parsed before init can run */
3261         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3262                    "Parsing previously deferred init table entry\n");
3263         parse_init_tables(pScrn, bios);
3264
3265         /* If it's not a laptop, you probably don't care about LVDS */
3266         /* FIXME: detect mobile BIOS? */
3267         if (!pNv->Mobile)
3268                 return;
3269
3270         /* Need D and L tables parsed before doing this */
3271         parse_fp_mode_table(pScrn, bios, &fpp);
3272 }
3273
3274 static void parse_bmp_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
3275 {
3276         /* Parse the BMP structure for useful things
3277          *
3278          * offset +  10: BCD encoded BIOS version
3279          *
3280          * offset +  67: maximum internal PLL frequency (single stage PLL)
3281          * offset +  71: minimum internal PLL frequency (single stage PLL)
3282          *
3283          * offset +  75: script table pointers, as for parse_bit_init_tbl_entry
3284          *
3285          * offset +  89: TMDS single link output A table pointer
3286          * offset +  91: TMDS single link output B table pointer
3287          * offset + 105: flat panel timings table pointer
3288          * offset + 107: flat panel strapping translation table pointer
3289          * offset + 117: LVDS manufacturer panel config table pointer
3290          * offset + 119: LVDS manufacturer strapping translation table pointer
3291          */
3292
3293         NVPtr pNv = NVPTR(pScrn);
3294         uint16_t bmplength = 67;
3295         struct fppointers fpp;
3296         memset(&fpp, 0, sizeof(struct fppointers));
3297
3298         uint8_t bmp_version_major=bios->data[offset + 5];
3299         uint8_t bmp_version_minor=bios->data[offset + 6];
3300
3301         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BMP version %d.%d\n",
3302                    bmp_version_major, bmp_version_minor);
3303
3304         if (bmp_version_major < 5) {
3305                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BMP versions prior to 5.0 not supported\n");
3306                 return;
3307         }
3308
3309         /* don't know if 5.0 exists... if it does, adding support ought to be fairly easy */
3310         if (bmp_version_minor < 0x1) {
3311                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BMP versions prior to 5.01 not yet supported\n");
3312                 return;
3313         }
3314
3315         if (bmp_version_minor < 0x10)
3316                 bmplength = 67; /* exact for 5.01 */
3317         else if (bmp_version_minor < 0x11)
3318                 bmplength = 89; /* exact for 5.10h */
3319         else if (bmp_version_minor < 0x14)
3320                 bmplength = 118; /* exact for 5.11h */
3321         else if (bmp_version_minor < 0x24) /* not sure of version where pll limits came in;
3322                                             * certainly exist by 0x24 though */
3323                 /* length not exact: this is long enough to get lvds members */
3324                 bmplength = 123;
3325         else
3326                 /* length not exact: this is long enough to get pll limit member */
3327                 bmplength = 144;
3328
3329         /* checksum */
3330         if (nv_cksum(bios->data + offset, 8)) {
3331                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bad BMP checksum\n");
3332                 return;
3333         }
3334
3335         parse_bios_version(pScrn, bios, offset + 10);
3336
3337         uint16_t inittbl = le16_to_cpu(*(uint16_t *)&bios->data[offset + 18]);
3338         uint16_t extrainittbl = le16_to_cpu(*(uint16_t *)&bios->data[offset + 20]);
3339         uint16_t inittbl_size = le16_to_cpu(*(uint16_t *)&bios->data[offset + 22]);
3340         uint16_t meminittbl = le16_to_cpu(*(uint16_t *)&bios->data[offset + 24]);
3341         uint16_t sdrmemseqtbl = le16_to_cpu(*(uint16_t *)&bios->data[offset + 26]);
3342         uint16_t ddrmemseqtbl = le16_to_cpu(*(uint16_t *)&bios->data[offset + 28]);
3343
3344         uint8_t crt_i2cport = bios->data[offset + 54];
3345         uint8_t tv_i2cport = bios->data[offset + 55];
3346         uint8_t panel_i2cport = bios->data[offset + 56];
3347         uint8_t i2cport0_crtcport_w = bios->data[offset + 58];
3348         uint8_t i2cport0_crtcport_r = bios->data[offset + 59];
3349         uint8_t i2cport1_crtcport_w = bios->data[offset + 60];
3350         uint8_t i2cport1_crtcport_r = bios->data[offset + 61];
3351
3352         if (bmplength > 73) {
3353                 bios->fmaxvco = le32_to_cpu(*((uint32_t *)&bios->data[offset + 67]));
3354                 bios->fminvco = le32_to_cpu(*((uint32_t *)&bios->data[offset + 71]));
3355         }
3356         if (bmplength > 75) {
3357                 bit_entry_t initbitentry;
3358                 initbitentry.length = bmplength - 75;
3359                 initbitentry.offset = offset + 75;
3360                 parse_bit_init_tbl_entry(pScrn, bios, &initbitentry);
3361         }
3362         if (bmplength > 92) {
3363                 bios->tmds.output0_script_ptr = le16_to_cpu(*((uint16_t *)&bios->data[offset + 89]));
3364                 bios->tmds.output1_script_ptr = le16_to_cpu(*((uint16_t *)&bios->data[offset + 91]));
3365         }
3366         if (bmplength > 108) {
3367                 fpp.fptablepointer = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 105])));
3368                 fpp.fpxlatetableptr = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 107])));
3369                 fpp.xlatwidth = 1;
3370         }
3371         if (bmplength > 120) {
3372                 bios->fp.lvdsmanufacturerpointer = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 117])));
3373                 fpp.fpxlatemanufacturertableptr = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 119])));
3374         }
3375         if (bmplength > 143)
3376                 bios->pll_limit_tbl_ptr = le16_to_cpu(*((uint16_t *)(&bios->data[offset + 142])));
3377
3378         /* want pll_limit_tbl_ptr set (if available) before init is run */
3379         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3380                    "Parsing previously deferred init tables\n");
3381         if (bmp_version_minor < 0x10) {
3382                 /* TODO type1 script */
3383         } else
3384                 parse_init_tables(pScrn, bios);
3385
3386         /* If it's not a laptop, you probably don't care about fptables */
3387         /* FIXME: detect mobile BIOS? */
3388         if (!pNv->Mobile)
3389                 return;
3390
3391         parse_fp_mode_table(pScrn, bios, &fpp);
3392         parse_lvds_manufacturer_table_init(pScrn, bios, &fpp);
3393         /* I've never seen a valid LVDS_INIT script, so we'll do a test for it here */
3394         call_lvds_script(pScrn, 0, 0, LVDS_INIT, 0);
3395 }
3396
3397 static unsigned int findstr(bios_t* bios, unsigned char *str, int len)
3398 {
3399         int i;
3400
3401         for (i = 2; i <= (bios->length - len); i++)
3402                 if (strncmp((char *)&bios->data[i], (char *)str, len) == 0)
3403                         return i;
3404
3405         return 0;
3406 }
3407
3408 static Bool parse_dcb_entry(uint8_t dcb_version, uint32_t conn, uint32_t conf, struct dcb_entry *entry)
3409 {
3410         memset(entry, 0, sizeof (struct dcb_entry));
3411
3412         if (dcb_version >= 0x20) {
3413                 entry->type = conn & 0xf;
3414                 entry->i2c_index = (conn >> 4) & 0xf;
3415                 entry->heads = (conn >> 8) & 0xf;
3416                 entry->bus = (conn >> 16) & 0xf;
3417                 entry->location = (conn >> 20) & 0xf;
3418                 entry->or = (conn >> 24) & 0xf;
3419                 if ((1 << ffs(entry->or)) * 3 == entry->or)
3420                         entry->duallink_possible = TRUE;
3421                 else
3422                         entry->duallink_possible = FALSE;
3423
3424                 switch (entry->type) {
3425                 case OUTPUT_LVDS:
3426                         if (conf & 0xfffffffa)
3427                                 ErrorF("Unknown LVDS configuration bits, please report\n");
3428                         if (conf & 0x1)
3429                                 entry->lvdsconf.use_straps_for_mode = TRUE;
3430                         if (conf & 0x4)
3431                                 entry->lvdsconf.use_power_scripts = TRUE;
3432                         break;
3433                 }
3434         } else if (dcb_version >= 0x14 ) {
3435                 if (conn != 0xf0003f00) {
3436                         ErrorF("Unknown DCB 1.4 entry, please report\n");
3437                         return FALSE;
3438                 }
3439                 /* safe defaults for a crt */
3440                 entry->type = 0;
3441                 entry->i2c_index = 0;
3442                 entry->heads = 1;
3443                 entry->bus = 0;
3444                 entry->location = 0;
3445                 entry->or = 1;
3446                 entry->duallink_possible = FALSE;
3447         } else {
3448                 // 1.2 needs more loving
3449                 return FALSE;
3450                 entry->type = 0;
3451                 entry->i2c_index = 0;
3452                 entry->heads = 0;
3453                 entry->bus = 0;
3454                 entry->location = 0;
3455                 entry->or = 0;
3456                 entry->duallink_possible = FALSE;
3457         }
3458
3459         return TRUE;
3460 }
3461
3462 static void
3463 read_dcb_i2c_table(ScrnInfoPtr pScrn, bios_t *bios, uint8_t dcb_version, uint16_t i2ctabptr)
3464 {
3465         NVPtr pNv = NVPTR(pScrn);
3466         uint8_t *i2ctable;
3467         uint8_t headerlen = 0;
3468         int i2c_entries;
3469         int recordoffset = 0, rdofs = 1, wrofs = 0;
3470         int i;
3471
3472         i2c_entries = MAX_NUM_DCB_ENTRIES;
3473         memset(pNv->dcb_table.i2c_read, 0, sizeof(pNv->dcb_table.i2c_read));
3474         memset(pNv->dcb_table.i2c_write, 0, sizeof(pNv->dcb_table.i2c_write));
3475
3476         i2ctable = &bios->data[i2ctabptr];
3477
3478         if (dcb_version >= 0x30) {
3479                 if (i2ctable[0] != dcb_version) { /* necessary? */
3480                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3481                                    "DCB I2C table version mismatch (%02X vs %02X)\n",
3482                                    i2ctable[0], dcb_version);
3483                         return;
3484                 }
3485                 headerlen = i2ctable[1];
3486                 i2c_entries = i2ctable[2];
3487                 if (i2ctable[0] >= 0x40) {
3488                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3489                                    "G80 DCB I2C table detected, arrgh\n"); /* they're plain weird */
3490                         return;
3491                 }
3492         }
3493         /* it's your own fault if you call this function on a DCB 1.1 BIOS */
3494         if (dcb_version < 0x14) {
3495                 recordoffset = 2;
3496                 rdofs = 0;
3497                 wrofs = 1;
3498         }
3499
3500         for (i = 0; i < i2c_entries; i++) {
3501                 if (i2ctable[headerlen + 4 * i + 3] != 0xff) {
3502                         pNv->dcb_table.i2c_read[i] = i2ctable[headerlen + recordoffset + rdofs + 4 * i];
3503                         pNv->dcb_table.i2c_write[i] = i2ctable[headerlen + recordoffset + wrofs + 4 * i];
3504                 }
3505         }
3506 }
3507
3508 static unsigned int parse_dcb_table(ScrnInfoPtr pScrn, bios_t *bios)
3509 {
3510         NVPtr pNv = NVPTR(pScrn);
3511         uint16_t dcbptr, i2ctabptr = 0;
3512         uint8_t *dcbtable;
3513         uint8_t dcb_version, headerlen = 0x4, entries = MAX_NUM_DCB_ENTRIES;
3514         Bool configblock = TRUE;
3515         int recordlength = 8, confofs = 4;
3516         int i;
3517
3518         pNv->dcb_table.entries = 0;
3519
3520         /* get the offset from 0x36 */
3521         dcbptr = le16_to_cpu(*(uint16_t *)&bios->data[0x36]);
3522
3523         if (dcbptr == 0x0) {
3524                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3525                            "No Display Configuration Block pointer found\n");
3526                 return 0;
3527         }
3528
3529         dcbtable = &bios->data[dcbptr];
3530
3531         /* get DCB version */
3532         dcb_version = dcbtable[0];
3533         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3534                    "Display Configuration Block version %d.%d found\n",
3535                    dcb_version >> 4, dcb_version & 0xf);
3536
3537         if (dcb_version >= 0x20) { /* NV17+ */
3538                 uint32_t sig;
3539
3540                 if (dcb_version >= 0x30) { /* NV40+ */
3541                         headerlen = dcbtable[1];
3542                         entries = dcbtable[2];
3543                         i2ctabptr = le16_to_cpu(*(uint16_t *)&dcbtable[4]);
3544                         sig = le32_to_cpu(*(uint32_t *)&dcbtable[6]);
3545
3546                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3547                                    "DCB header length %02X, with %02X possible entries\n",
3548                                    headerlen, entries);
3549                 } else {
3550                         /* dcb_block_count = *(dcbtable[1]); */
3551                         i2ctabptr = le16_to_cpu(*(uint16_t *)&dcbtable[2]);
3552                         sig = le32_to_cpu(*(uint32_t *)&dcbtable[4]);
3553                         headerlen = 8;
3554                 }
3555
3556                 if (sig != 0x4edcbdcb) {
3557                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3558                                    "Bad Display Configuration Block signature (%08X)\n", sig);
3559                         return 0;
3560                 }
3561         } else if (dcb_version >= 0x14) { /* some NV15/16, and NV11+ */
3562                 char sig[8];
3563
3564                 memset(sig, 0, 8);
3565                 strncpy(sig, (char *)&dcbtable[-7], 7);
3566                 /* dcb_block_count = *(dcbtable[1]); */
3567                 i2ctabptr = le16_to_cpu(*(uint16_t *)&dcbtable[2]);
3568                 recordlength = 10;
3569                 confofs = 6;
3570
3571                 if (strcmp(sig, "DEV_REC")) {
3572                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3573                                    "Bad Display Configuration Block signature (%s)\n", sig);
3574                         return 0;
3575                 }
3576         } else if (dcb_version >= 0x12) { /* some NV6/10, and NV15+ */
3577                 /* dcb_block_count = *(dcbtable[1]); */
3578                 i2ctabptr = le16_to_cpu(*(uint16_t *)&dcbtable[2]);
3579                 configblock = FALSE;
3580         } else {        /* NV5+, maybe NV4 */
3581                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3582                            "Structure of Display Configuration Blocks prior to version 1.2 unknown\n");
3583                 return 0;
3584         }
3585
3586         if (entries >= MAX_NUM_DCB_ENTRIES)
3587                 entries = MAX_NUM_DCB_ENTRIES;
3588
3589         for (i = 0; i < entries; i++) {
3590                 uint32_t connection, config = 0;
3591
3592                 connection = le32_to_cpu(*(uint32_t *)&dcbtable[headerlen + recordlength * i]);
3593                 if (configblock)
3594                         config = le32_to_cpu(*(uint32_t *)&dcbtable[headerlen + confofs + recordlength * i]);
3595
3596                 /* Should we allow discontinuous DCBs? Certainly DCB I2C tables
3597                  * can be discontinuous */
3598                 if ((connection & 0x0000000f) == 0x0000000f) /* end of records */
3599                         break;
3600
3601                 ErrorF("Raw DCB entry %d: %08x %08x\n", i, connection, config);
3602                 if (!parse_dcb_entry(dcb_version, connection, config, &pNv->dcb_table.entry[i]))
3603                         break;
3604         }
3605         pNv->dcb_table.entries = i;
3606
3607         read_dcb_i2c_table(pScrn, bios, dcb_version, i2ctabptr);
3608
3609         /* This is needed for DCB version 2.0 */
3610         /* Otherwise you end up with multiple outputs that are trying to be activated */
3611         for ( i = 0; i < pNv->dcb_table.entries; i ++) {
3612                 int j;
3613                 int cur_i2c = pNv->dcb_table.entry[i].i2c_index;
3614                 int cur_type = pNv->dcb_table.entry[i].type;
3615                 for ( j = 0; j < pNv->dcb_table.entries; j ++ ) {
3616                         if ( i == j ) continue;
3617                         if ( pNv->dcb_table.entry[j].type == 100) continue; /* merged entry */
3618                         if (( pNv->dcb_table.entry[j].i2c_index == cur_i2c )  && ( pNv->dcb_table.entry[j].type == cur_type ))  {
3619                                 /* We can only merge entries with the same allowed crtc's. */
3620                                 /* This has not occured so far and needs some logic (to merge dual link properly). */ 
3621                                 /* So this remains TODO for the moment. */
3622
3623                                 /* We also merge entries with the same allowed output routes */
3624                                 if (pNv->dcb_table.entry[i].or == pNv->dcb_table.entry[j].or) {
3625                                         xf86DrvMsg(0, X_INFO, "Merging DCB entries %d and %d!\n", i, j);
3626                                         pNv->dcb_table.entry[i].heads |= pNv->dcb_table.entry[j].heads;
3627
3628                                         pNv->dcb_table.entry[j].type = 100; /* dummy value */
3629                                 }
3630                         }
3631                 }
3632         }
3633
3634         /* Remove "disabled" entries (merged) */
3635         int valid_entries[pNv->dcb_table.entries];
3636         int cent = 0;
3637         for ( i = 0; i < pNv->dcb_table.entries; i ++) valid_entries[i] = -1;
3638         for ( i = 0; i < pNv->dcb_table.entries; i ++)
3639                 if ( pNv->dcb_table.entry[i].type != 100 ) {
3640                         valid_entries[cent] = i;
3641                         cent++;
3642                 }
3643         for ( i = 0; i < cent; i++) {
3644                 memmove(&pNv->dcb_table.entry[i], &pNv->dcb_table.entry[valid_entries[i]], sizeof(pNv->dcb_table.entry[i]));
3645                 memmove(&pNv->dcb_table.i2c_read[i], &pNv->dcb_table.i2c_read[valid_entries[i]], sizeof(pNv->dcb_table.i2c_read[i]));
3646                 memmove(&pNv->dcb_table.i2c_write[i], &pNv->dcb_table.i2c_write[valid_entries[i]], sizeof(pNv->dcb_table.i2c_write[i]));
3647         }
3648
3649         pNv->dcb_table.entries = cent;
3650
3651         return pNv->dcb_table.entries;
3652 }
3653
3654 unsigned int NVParseBios(ScrnInfoPtr pScrn)
3655 {
3656         unsigned int bit_offset;
3657         uint8_t nv_signature[]={0xff,0x7f,'N','V',0x0};
3658         uint8_t bit_signature[]={'B','I','T'};
3659         NVPtr pNv;
3660         pNv = NVPTR(pScrn);
3661
3662         pNv->dcb_table.entries = 0;
3663
3664         memset(&pNv->VBIOS, 0, sizeof(bios_t));
3665         pNv->VBIOS.execute = FALSE;
3666         pNv->VBIOS.data = xalloc(64 * 1024);
3667         if (!NVShadowVBIOS(pScrn, pNv->VBIOS.data)) {
3668                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3669                            "No valid BIOS image found\n");
3670                 xfree(pNv->VBIOS.data);
3671                 return 0;
3672         }
3673         pNv->VBIOS.length = pNv->VBIOS.data[2] * 512;
3674         if (pNv->VBIOS.length > NV_PROM_SIZE)
3675                 pNv->VBIOS.length = NV_PROM_SIZE;
3676
3677         /* parse Display Configuration Block (DCB) table */
3678         if (parse_dcb_table(pScrn, &pNv->VBIOS))
3679                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3680                            "Found %d entries in DCB\n", pNv->dcb_table.entries);
3681
3682         /* check for known signatures */
3683         if ((bit_offset = findstr(&pNv->VBIOS, bit_signature, sizeof(bit_signature)))) {
3684                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT signature found\n");
3685                 parse_bit_structure(pScrn, &pNv->VBIOS, bit_offset + 4);
3686         } else if ((bit_offset = findstr(&pNv->VBIOS, nv_signature, sizeof(nv_signature)))) {
3687                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV signature found\n");
3688                 parse_bmp_structure(pScrn, &pNv->VBIOS, bit_offset);
3689         } else
3690                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3691                            "No known script signature found\n");
3692
3693         return 1;
3694 }