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