2 * Copyright 2005-2006 Erik Waling
3 * Copyright 2006 Stephane Marchesin
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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
24 #include "nv_include.h"
28 /*#define PERFORM_WRITE*/
43 CARD16 init_tbls_offset;
44 CARD16 macro_index_offset;
46 CARD16 condition_offset;
47 CARD16 io_flag_condition_offset;
49 CARD16 fptablepointer;
50 CARD16 fpxlatetableptr;
51 CARD16 lvdsmanufacturerpointer;
52 CARD16 fpxlatemanufacturertableptr;
53 CARD16 fpxlateflagtableptr;
56 static Bool NVValidVBIOS(ScrnInfoPtr pScrn, const unsigned char *data)
58 /* check for BIOS signature */
59 if (!(data[0] == 0x55 && data[1] == 0xAA)) {
60 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
61 "...BIOS signature not found\n");
65 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "...appears to be valid\n");
69 static void NVShadowVBIOS_PROM(ScrnInfoPtr pScrn, unsigned char *data)
71 NVPtr pNv = NVPTR(pScrn);
74 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
75 "Attempting to locate BIOS image in PROM\n");
77 /* enable ROM access */
78 nvWriteMC(pNv, 0x1850, 0x0);
79 for (i=0; i<NV_PROM_SIZE; i++) {
80 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
81 data[i] = pNv->PROM[i];
82 data[i] = pNv->PROM[i];
83 data[i] = pNv->PROM[i];
84 data[i] = pNv->PROM[i];
85 data[i] = pNv->PROM[i];
87 /* disable ROM access */
88 nvWriteMC(pNv, 0x1850, 0x1);
91 static void NVShadowVBIOS_PRAMIN(ScrnInfoPtr pScrn, unsigned char *data)
93 NVPtr pNv = NVPTR(pScrn);
94 const unsigned char *pramin = (void*)&pNv->REGS[0x00700000/4];
95 uint32_t old_bar0_pramin = 0;
97 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
98 "Attempting to locate BIOS image in PRAMIN\n");
100 if (pNv->Architecture >= NV_ARCH_50) {
103 vbios_vram = (pNv->REGS[0x619f04/4] & ~0xff) << 8;
105 vbios_vram = pNv->REGS[0x1700/4] << 16;
106 vbios_vram += 0xf0000;
109 old_bar0_pramin = pNv->REGS[0x1700/4];
110 pNv->REGS[0x1700/4] = vbios_vram >> 16;
113 memcpy(data, pramin, 65536);
115 if (pNv->Architecture >= NV_ARCH_50) {
116 pNv->REGS[0x1700/4] = old_bar0_pramin;
120 static Bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint32_t *data)
122 NVPtr pNv = NVPTR(pScrn);
124 NVShadowVBIOS_PROM(pScrn, data);
125 if (NVValidVBIOS(pScrn, data))
128 NVShadowVBIOS_PRAMIN(pScrn, data);
129 if (NVValidVBIOS(pScrn, data))
140 int length_multiplier;
141 Bool (*handler)(ScrnInfoPtr pScrn, bios_t *, CARD16, init_exec_t *);
146 unsigned short length;
147 unsigned short offset;
150 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec);
152 /* #define MACRO_SIZE 8 */
153 #define CONDITION_SIZE 12
154 #define IO_FLAG_CONDITION_SIZE 9
162 static int nv_valid_reg(CARD32 reg)
164 #define WITHIN(x,y,z) ((x>=y)&&(x<y+z))
165 if (WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
167 if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE))
169 if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE))
171 if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
173 if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
175 if (WITHIN(reg,NV_PGRAPH_OFFSET,NV_PGRAPH_SIZE))
177 if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
179 if (WITHIN(reg,NV_PTIMER_OFFSET,NV_PTIMER_SIZE))
181 if (WITHIN(reg,NV_PVIDEO_OFFSET,NV_PVIDEO_SIZE))
183 if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
185 if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
187 if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
189 if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
191 if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
193 if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
199 static int nv32_rd(ScrnInfoPtr pScrn, CARD32 reg, CARD32 *data)
201 NVPtr pNv = NVPTR(pScrn);
202 *data=pNv->REGS[reg/4];
206 static int nv32_wr(ScrnInfoPtr pScrn, CARD32 reg, CARD32 data)
209 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv32_wr reg 0x%X value 0x%X\n",reg,data);
211 if (!nv_valid_reg(reg))
213 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "========= unknown reg 0x%X ==========\n",reg);
217 NVPtr pNv = NVPTR(pScrn);
218 pNv->REGS[reg/4]=data;
223 void nv_set_crtc_index(ScrnInfoPtr pScrn, CARD8 index)
226 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_set_crtc_index index 0x%X\n",index);
228 NVPtr pNv = NVPTR(pScrn);
229 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
230 VGA_WR08(ptr, 0x3D4, index);
234 CARD8 nv_rd_crtc_data(ScrnInfoPtr pScrn)
236 NVPtr pNv = NVPTR(pScrn);
237 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
238 return VGA_RD08(ptr, 0x3D5);
241 void nv_wr_crtc_data(ScrnInfoPtr pScrn, CARD8 val)
244 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_wr_crtc_data value 0x%X\n",val);
246 NVPtr pNv = NVPTR(pScrn);
247 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
248 VGA_WR08(ptr, 0x3D5, val);
252 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
254 /* INIT_PROG opcode: 0x31
256 * offset (8 bit): opcode
257 * offset + 1 (32 bit): reg
258 * offset + 5 (32 bit): and mask
259 * offset + 9 (8 bit): shift right
260 * offset + 10 (8 bit): number of configurations
261 * offset + 11 (32 bit): register
262 * offset + 15 (32 bit): configuration 1
265 * Starting at offset + 15 there are "number of configurations"
266 * 32 bit values. To find out which configuration value to use
267 * read "CRTC reg" on the CRTC controller with index "CRTC index"
268 * and bitwise AND this value with "and mask" and then bit shift the
269 * result "shift right" bits to the right.
270 * Assign "register" with appropriate configuration value.
273 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
274 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
275 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
276 CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
277 CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
279 CARD32 configval, tmp;
281 if (iexec->execute) {
282 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%04X\n", offset,
285 nv32_rd(pScrn, reg, &tmp);
286 configuration = (tmp & and) >> shiftr;
288 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
289 offset, configuration);
291 if (configuration <= nr) {
294 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
296 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
299 if (nv32_rd(pScrn, reg2, &tmp)) {
300 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
303 nv32_wr(pScrn, reg2, configval);
309 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
311 /* INIT_IO_RESTRICT_PROG opcode: 0x32
313 * offset (8 bit): opcode
314 * offset + 1 (16 bit): CRTC reg
315 * offset + 3 (8 bit): CRTC index
316 * offset + 4 (8 bit): and mask
317 * offset + 5 (8 bit): shift right
318 * offset + 6 (8 bit): number of configurations
319 * offset + 7 (32 bit): register
320 * offset + 11 (32 bit): configuration 1
323 * Starting at offset + 11 there are "number of configurations"
324 * 32 bit values. To find out which configuration value to use
325 * read "CRTC reg" on the CRTC controller with index "CRTC index"
326 * and bitwise AND this value with "and mask" and then bit shift the
327 * result "shift right" bits to the right.
328 * Assign "register" with appropriate configuration value.
331 NVPtr pNv = NVPTR(pScrn);
332 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
333 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
334 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
335 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
336 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
337 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
338 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
340 CARD32 configval, tmp;
342 if (iexec->execute) {
343 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
346 VGA_WR08(ptr,crtcreg, index);
347 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
349 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
350 offset, configuration);
352 if (configuration <= nr) {
354 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
356 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
359 if (nv32_rd(pScrn, reg, &tmp)) {
360 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
363 nv32_wr(pScrn, reg, configval);
369 static Bool init_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
371 CARD8 repeats = *((CARD8 *) (&bios->data[offset + 1]));
374 if (iexec->execute) {
375 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REPEATING FOLLOWING SEGMENT %d TIMES.\n",
378 iexec->repeat = TRUE;
380 for (i = 0; i < repeats - 1; i++)
381 parse_init_table(pScrn, bios, offset + 2, iexec);
383 iexec->repeat = FALSE;
388 static Bool init_io_restrict_prog2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
390 /* INIT_IO_RESTRICT_PROG opcode: 0x34
392 * offset (8 bit): opcode
393 * offset + 1 (16 bit): CRTC reg
394 * offset + 3 (8 bit): CRTC index
395 * offset + 4 (8 bit): and mask
396 * offset + 5 (8 bit): shift right
397 * offset + 6 (8 bit): condition offset for doubling freq
398 * offset + 7 (8 bit): number of configurations
399 * offset + 8 (32 bit): register
400 * offset + 12 (32 bit): configuration 1
403 * Starting at offset + 11 there are "number of configurations"
404 * 32 bit values. To find out which configuration value to use
405 * read "CRTC reg" on the CRTC controller with index "CRTC index"
406 * and bitwise AND this value with "and mask" and then bit shift the
407 * result "shift right" bits to the right.
408 * Assign "register" with appropriate configuration value.
411 NVPtr pNv = NVPTR(pScrn);
412 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
413 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
414 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
415 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
416 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
417 CARD8 io_flag_condition_offset = *((CARD8 *) (&bios->data[offset + 6]));
418 CARD8 nr = *((CARD8 *) (&bios->data[offset + 7]));
419 CARD32 reg = *((CARD32 *) (&bios->data[offset + 8]));
421 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
425 static Bool init_end_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
433 static Bool init_copy(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
435 /* XXX: double check this... */
436 NVPtr pNv = NVPTR(pScrn);
437 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
438 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
439 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
440 CARD8 and1 = *((CARD8 *) (&bios->data[offset + 6]));
441 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 7]));
442 CARD8 index = *((CARD8 *) (&bios->data[offset + 9]));
443 CARD8 and2 = *((CARD8 *) (&bios->data[offset + 10]));
447 if (iexec->execute) {
448 if (nv32_rd(pScrn, reg, &data)) {
452 data <<= (0x100 - shift);
455 VGA_WR08(ptr,crtcreg, index);
456 crtcdata = (VGA_RD08(ptr, crtcreg + 1) & and2) | (CARD8) data;
458 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
459 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n"
460 , offset, crtcreg, index, crtcdata);
462 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
463 VGA_RD08(ptr, crtcreg + 1));
465 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_copy crtcreg 0x%X value 0x%X\n",crtcreg+1,crtcdata);
467 printf("WRITE IS PERFORMED\n");
468 VGA_WR08(ptr,crtcreg + 1, crtcdata);
475 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
477 if (iexec->execute) {
478 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n",
481 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",
485 iexec->execute = !iexec->execute;
489 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
491 NVPtr pNv = NVPTR(pScrn);
492 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
493 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
494 CARD16 crtcreg = *((CARD16 *)
495 (&bios->data[bios->io_flag_condition_offset +
496 cond * IO_FLAG_CONDITION_SIZE]));
497 CARD8 index = *((CARD8 *)
498 (&bios->data[bios->io_flag_condition_offset +
499 cond * IO_FLAG_CONDITION_SIZE + 2]));
500 CARD8 and1 = *((CARD8 *)
501 (&bios->data[bios->io_flag_condition_offset +
502 cond * IO_FLAG_CONDITION_SIZE + 3]));
503 CARD8 shift = *((CARD8 *)
504 (&bios->data[bios->io_flag_condition_offset +
505 cond * IO_FLAG_CONDITION_SIZE + 4]));
506 CARD16 offs = *((CARD16 *)
507 (&bios->data[bios->io_flag_condition_offset +
508 cond * IO_FLAG_CONDITION_SIZE + 5]));
509 CARD8 and2 = *((CARD8 *)
510 (&bios->data[bios->io_flag_condition_offset +
511 cond * IO_FLAG_CONDITION_SIZE + 7]));
512 CARD8 cmpval = *((CARD8 *)
513 (&bios->data[bios->io_flag_condition_offset +
514 cond * IO_FLAG_CONDITION_SIZE + 8]));
518 if (iexec->execute) {
519 VGA_WR08(ptr,crtcreg, index);
520 data = VGA_RD08(ptr, crtcreg + 1);
522 offs += (data >> shift);
523 data = *((CARD8 *) (&bios->data[offs]));
526 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
527 "0x%04X: CHECKING IF DATA: %02X equals COND: %02X\n", offset,
530 if (data == cmpval) {
531 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
532 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
535 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
536 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
537 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
538 iexec->execute = FALSE;
544 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
546 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
547 /* XXX: this needs to be confirmed... NOT CORRECT */
548 /*init_io_restrict_prog(bios, offset, iexec);*/
550 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
551 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
552 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
553 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
554 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
555 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
557 CARD32 configval, tmp;
559 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
560 crtcreg, index, reg);
562 VGA_WR08(ptr,crtcreg, index);
563 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
565 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
566 offset, configuration);
568 if (configuration <= nr) {
570 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &configval))
571 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
575 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
577 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
583 if (iexec->execute) {
586 configval = 0x01014E07;
589 configval = 0x13030E02;
593 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
596 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
597 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
600 nv32_wr(pScrn, reg, configval);
606 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
608 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
609 CARD32 val = *((CARD32 *) (&bios->data[offset + 5]));
610 CARD32 configval, tmp;
612 if (iexec->execute) {
615 configval = 0x00011F05;
619 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
622 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
623 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
626 nv32_wr(pScrn, reg, configval);
628 /*xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);*/
634 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
636 CARD8 crtcindex = *((CARD8 *) (&bios->data[offset + 1]));
637 CARD8 crtcdata = *((CARD8 *) (&bios->data[offset + 2]));
638 CARD8 initial_index = *((CARD8 *) (&bios->data[offset + 3]));
639 CARD8 entries = *((CARD8 *) (&bios->data[offset + 4]));
643 if (iexec->execute) {
644 for (i = 0; i < entries; i++) {
645 nv_set_crtc_index(pScrn, crtcindex);
647 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
648 crtcindex, initial_index + i);
650 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
651 nv_rd_crtc_data(pScrn));
653 nv_wr_crtc_data(pScrn, initial_index + i);
655 nv_set_crtc_index(pScrn, crtcdata);
657 data = *((CARD8 *) (&bios->data[offset + 5 + i]));
659 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
662 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
663 nv_rd_crtc_data(pScrn));
665 nv_wr_crtc_data(pScrn, data);
671 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
673 /* XXX: IS THIS CORRECT? check the typecast .. probably wrong */
675 NVPtr pNv = NVPTR(pScrn);
676 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
677 CARD8 and = *((CARD8 *) (&bios->data[offset + 2]));
678 CARD8 or = *((CARD8 *) (&bios->data[offset + 3]));
681 if (iexec->execute) {
682 nv_set_crtc_index(pScrn, index);
683 data = (nv_rd_crtc_data(pScrn) & and) | or;
684 /*printf("and: 0x%02x or: 0x%02x\n", and, or);*/
685 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
688 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
689 nv_rd_crtc_data(pScrn));
691 nv_wr_crtc_data(pScrn, data);
696 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
698 /* INIT_ZM_CR opcode: 0x53
700 * offset (8 bit): opcode
701 * offset + 1 (8 bit): CRTC index
702 * offset + 2 (8 bit): value
704 * Assign "value" to CRTC register with index "CRTC index".
707 NVPtr pNv = NVPTR(pScrn);
708 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
709 CARD8 value = *((CARD8 *) (&bios->data[offset + 2]));
711 if (iexec->execute) {
712 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
715 nv_set_crtc_index(pScrn, index);
717 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
718 nv_rd_crtc_data(pScrn));
720 nv_wr_crtc_data(pScrn, value);
725 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
727 /* INIT_ZM_CR opcode: 0x54
729 * offset (8 bit): opcode
730 * offset + 1 (8 bit): number of groups (index, value)
731 * offset + 2 (8 bit): index 1
732 * offset + 3 (8 bit): value 1
735 * Assign "value n" to CRTC register with index "index n".
738 CARD8 nr = *((CARD8 *) (&bios->data[offset + 1]));
742 if (iexec->execute) {
743 for (i = 0; i < nr; i++) {
744 index = *((CARD8 *) (&bios->data[offset + 2 + 2 * i]));
745 value = *((CARD8 *) (&bios->data[offset + 2 + 2 * i + 1]));
747 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
750 nv_set_crtc_index(pScrn, index);
752 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
753 nv_rd_crtc_data(pScrn));
754 nv_wr_crtc_data(pScrn, value);
760 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
762 /* My BIOS does not use this command. */
763 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
768 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
770 /* INIT_ZM_REG_SEQUENCE opcode: 0x58
772 * offset (8 bit): opcode
773 * offset + 1 (32 bit): register base
774 * offset + 5 (8 bit): nr
775 * offset + 6 (32 bit): value to assign "register base" + 4
778 * Initialzies a sequence of "nr" registers starting at "register base".
781 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
782 CARD32 nr = *((CARD8 *) (&bios->data[offset + 5]));
787 if (iexec->execute) {
788 for (i = 0; i < nr; i++) {
789 data = *((CARD32 *) (&bios->data[offset + 6 + i * 4]));
790 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
793 if (nv32_rd(pScrn, reg + i * 4, &tmp)) {
794 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
798 nv32_wr(pScrn, reg + i * 4, data);
804 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
806 /* INIT_INDIRECT_REG opcode: 0x5A
808 * offset (8 bit): opcode
809 * offset + 1 (32 bit): register
810 * offset + 5 (16 bit): adress offset (in bios)
812 * Lookup value at offset data in the bios and write it to reg
814 NVPtr pNv = NVPTR(pScrn);
815 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
816 CARD32 data = *((CARD16 *) (&bios->data[offset + 5]));
817 CARD32 data2 = bios->data[data];
819 if (iexec->execute) {
820 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
821 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n",
822 offset, reg, data, data2);
824 if (DEBUGLEVEL >= 6) {
826 nv32_rd(pScrn, reg, &tmpval);
827 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
830 nv32_wr(pScrn, reg, data2);
835 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
837 /* INIT_SUB_DIRECT opcode: 0x5B
839 * offset (8 bit): opcode
840 * offset + 1 (16 bit): subroutine offset (in bios)
842 * Calls a subroutine that will execute commands until INIT_DONE
846 CARD16 sub_offset = *((CARD16 *) (&bios->data[offset + 1]));
848 if (iexec->execute) {
849 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-ROUTINE AT: 0x%04X\n",
852 parse_init_table(pScrn, bios, sub_offset, iexec);
854 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-ROUTINE\n", offset);
859 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
861 CARD32 srcreg = *((CARD32 *) (&bios->data[offset + 1]));
862 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
863 CARD32 and1 = *((CARD32 *) (&bios->data[offset + 6]));
864 CARD32 xor = *((CARD32 *) (&bios->data[offset + 10]));
865 CARD32 dstreg = *((CARD32 *) (&bios->data[offset + 14]));
866 CARD32 and2 = *((CARD32 *) (&bios->data[offset + 18]));
870 if (iexec->execute) {
871 nv32_rd(pScrn, srcreg, &srcdata);
878 srcdata = (srcdata & and1) ^ xor;
880 nv32_rd(pScrn, dstreg, &dstdata);
886 nv32_rd(pScrn, dstreg, &tmp);
888 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, dstreg,
891 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmp);
893 nv32_wr(pScrn, dstreg, dstdata);
898 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
900 NVPtr pNv = NVPTR(pScrn);
901 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
902 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
903 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
904 CARD8 value = *((CARD8 *) (&bios->data[offset + 4]));
906 if (iexec->execute) {
907 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
908 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
909 offset, crtcreg, index, value);
911 VGA_WR08(ptr,crtcreg, index);
913 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
914 VGA_RD08(ptr, crtcreg + 1));
917 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_zm_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,value);
919 VGA_WR08(ptr,crtcreg + 1, value);
925 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
927 // FIXME replace with a suitable implementation
929 CARD16 ramcfg = *((CARD16 *) (&bios->data[bios->ram_table_offset]));
934 if (iexec->execute) {
935 nv32_rd(pScrn, 0x00101000, &strapinfo);
936 nv32_rd(pScrn, 0x00100080, &pfb_debug);
938 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
939 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
940 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG: 0x%04X\n", ramcfg);
942 pfb_debug &= 0xffffffef;
944 strapinfo &= 0x0000000f;
945 ramcfg2 = *((CARD16 *)
946 (&bios->data[bios->ram_table_offset + (2 * strapinfo)]));
948 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AFTER MANIPULATION\n");
949 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
950 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
951 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG2: 0x%08X\n", ramcfg2);
953 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
958 nv32_rd(pScrn, 0x00100200, ®1);
959 nv32_rd(pScrn, 0x0010020C, ®2);
961 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x00100200: 0x%08X\n", reg1);
962 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x0010020C: 0x%08X\n", reg2);
968 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
970 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
971 CARD32 value1 = *((CARD32 *) (&bios->data[offset + 5]));
972 CARD32 value2 = *((CARD32 *) (&bios->data[offset + 9]));
974 if (iexec->execute) {
975 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
976 offset, reg, value1);
977 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
978 offset, reg, value2);
980 if (DEBUGLEVEL >= 6) {
982 nv32_rd(pScrn, reg, &tmpval);
983 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
985 nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), &tmpval);
986 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: PCICFG_ROMSHADOW: 0x%02X\n", offset, tmpval);
989 nv32_wr(pScrn, reg, value1);
990 nv32_wr(pScrn, reg, value2);
992 /* PCI Config space init needs to be added here. */
993 /* if (nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), value1)) */
994 /* nv32_wr(pScrn, PCICFG(PCICFG_ROMSHADOW), value1 & 0xfffffffe) */
999 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1001 /* INIT_INDEX_IO8 opcode: 0x69
1003 * offset (8 bit): opcode
1004 * offset + 1 (16 bit): CRTC reg
1005 * offset + 3 (8 bit): and mask
1006 * offset + 4 (8 bit): or with
1011 NVPtr pNv = NVPTR(pScrn);
1012 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
1013 CARD16 reg = *((CARD16 *) (&bios->data[offset + 1]));
1014 CARD8 and = *((CARD8 *) (&bios->data[offset + 3]));
1015 CARD8 or = *((CARD8 *) (&bios->data[offset + 4]));
1018 if (iexec->execute) {
1019 data = (VGA_RD08(ptr, reg) & and) | or;
1021 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1022 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n",
1024 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
1025 VGA_RD08(ptr, reg));
1027 #ifdef PERFORM_WRITE
1028 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
1030 VGA_WR08(ptr, reg, data);
1036 static Bool init_pll2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1038 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1039 CARD16 val = *((CARD16 *) (&bios->data[offset + 5]));
1041 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
1043 if (iexec->execute) {
1044 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%04X\n", offset, reg, val);
1049 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1051 CARD8 sub = *((CARD8 *) (&bios->data[offset + 1]));
1053 if (iexec->execute) {
1054 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-SCRIPT: %d\n", offset, sub);
1056 parse_init_table(pScrn, bios,
1057 *((CARD16 *) (&bios->data[bios->init_tbls_offset + sub * 2])),
1060 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-SCRIPT\n", offset);
1065 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1067 /* INIT_RAM_CONDITION opcode: 0x6D
1069 * offset (8 bit): opcode
1070 * offset + 1 (8 bit): and mask
1071 * offset + 2 (8 bit): cmpval
1073 * Test if (NV_PFB_BOOT & and mask) matches cmpval
1075 NVPtr pNv = NVPTR(pScrn);
1076 CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
1077 CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
1080 if (iexec->execute) {
1081 data=(pNv->PFB[NV_PFB_BOOT/4])∧
1083 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1084 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1085 offset, data, cmpval);
1087 if (data == cmpval) {
1088 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1089 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1092 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1093 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1094 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1095 iexec->execute = FALSE;
1101 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1103 /* INIT_NV_REG opcode: 0x6E
1105 * offset (8 bit): opcode
1106 * offset + 1 (32 bit): register
1107 * offset + 5 (32 bit): and mask
1108 * offset + 9 (32 bit): or with
1110 * Assign "register" to (REGVAL(register) & "and mask") | "or with";
1113 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1114 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
1115 CARD32 or = *((CARD32 *) (&bios->data[offset + 9]));
1117 unsigned int status;
1119 if (iexec->execute) {
1121 if ((status = nv32_rd(pScrn, reg, &data))) {
1122 data = (data & and) | or;
1123 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1126 if (DEBUGLEVEL >= 6 && status) {
1128 nv32_rd(pScrn, reg, &tmpval);
1129 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1133 nv32_wr(pScrn, reg, data);
1134 /* Assign: reg = data */
1141 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1143 // FIXME replace with the haiku version
1144 /* XXX: Not sure this is correct... */
1146 CARD8 macro = *((CARD8 *) (&bios->data[offset + 1]));
1148 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE]));
1150 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE + 4]));
1152 if (iexec->execute) {
1153 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING MACRO: 0x%02X\n", offset, macro);
1154 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
1157 if (DEBUGLEVEL >= 6) {
1159 nv32_rd(pScrn, reg, &tmpval);
1160 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1164 nv32_wr(pScrn, reg, value);
1170 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1172 CARD8 index = *((CARD8 *) (&bios->data[offset + 1]));
1173 CARD32 tmp = bios->macro_index_offset + (index << 1);
1174 CARD32 offs = *((CARD8 *) (&bios->data[tmp])) << 3;
1175 CARD32 nr = *((CARD8 *) (&bios->data[tmp + 1]));
1180 if (iexec->execute) {
1181 offs += bios->macro_offset;
1182 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: WRITE %d 32-BIT REGS:\n", offset, nr);
1184 for (i = 0; i < nr; i++) {
1185 reg = *((CARD32 *) (&bios->data[offs + (i << 3)]));
1186 data = *((CARD32 *) (&bios->data[offs + (i << 3) + 4]));
1188 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1191 if (DEBUGLEVEL >= 6) {
1193 nv32_rd(pScrn, reg, &tmpval);
1194 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1198 nv32_wr(pScrn, reg, data);
1204 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1209 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1211 if (!iexec->execute) {
1212 iexec->execute = TRUE;;
1213 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n",
1219 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1221 /* INIT_RAM_CONDITION2 opcode: 0x73
1223 * offset (8 bit): opcode
1224 * offset + 1 (8 bit): and mask
1225 * offset + 2 (8 bit): cmpval
1227 * Test if (NV_EXTDEV_BOOT & and mask) matches cmpval
1229 NVPtr pNv = NVPTR(pScrn);
1230 CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
1231 CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
1234 if (iexec->execute) {
1235 data=(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT))∧
1237 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1238 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1239 offset, data, cmpval);
1241 if (data == cmpval) {
1242 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1243 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1246 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1247 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1248 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1249 iexec->execute = FALSE;
1255 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1257 /* INIT_TIME opcode: 0x74
1259 * offset (8 bit): opcode
1260 * offset + 1 (16 bit): time
1262 * Sleep for "time" microseconds.
1265 CARD16 time = *((CARD16 *) (&bios->data[offset + 1]));
1267 if (iexec->execute) {
1268 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Sleeping for 0x%04X microseconds.\n",
1276 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1278 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
1281 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE]));
1284 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 4]));
1287 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 8]));
1290 if (iexec->execute) {
1291 if (nv32_rd(pScrn, reg, &data)) {
1294 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1295 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1296 offset, data, cmpval);
1298 if (data == cmpval) {
1299 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1300 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1303 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1304 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1305 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1306 iexec->execute = FALSE;
1313 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1315 /* INIT_INDEX_IO opcode: 0x78
1317 * offset (8 bit): opcode
1318 * offset + 1 (16 bit): CRTC reg
1319 * offset + 3 (8 bit): CRTC index
1320 * offset + 4 (8 bit): and mask
1321 * offset + 5 (8 bit): or with
1326 NVPtr pNv = NVPTR(pScrn);
1327 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
1328 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
1329 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
1330 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
1331 CARD8 or = *((CARD8 *) (&bios->data[offset + 5]));
1334 if (iexec->execute) {
1335 VGA_WR08(ptr,crtcreg, index);
1336 /* data at reg + 1 */
1337 data = (VGA_RD08(ptr, crtcreg + 1) & and) | or;
1339 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1340 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
1341 offset, crtcreg, index, data);
1342 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
1343 VGA_RD08(ptr, crtcreg + 1));
1345 #ifdef PERFORM_WRITE
1346 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,data);
1348 VGA_WR08(ptr,crtcreg + 1, data);
1354 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1356 /* INIT_ZM_REG opcode: 0x7A
1358 * offset (8 bit): opcode
1359 * offset + 1 (32 bit): register
1360 * offset + 5 (32 bit): value
1362 * Assign "register" to "value";
1365 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1366 CARD32 value = *((CARD32 *) (&bios->data[offset + 5]));
1368 if (iexec->execute) {
1369 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
1370 offset, reg, value);
1372 if (DEBUGLEVEL >= 6) {
1374 nv32_rd(pScrn, reg, &tmpval);
1375 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1378 nv32_wr(pScrn, reg, value);
1380 /* Assign: reg = value */
1385 static init_tbl_entry_t itbl_entry[] = {
1386 /* command name , id , length , offset , mult , command handler */
1387 { "INIT_PROG" , 0x31, 15 , 10 , 4 , init_prog },
1388 { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog },
1389 { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat },
1390 { "INIT_IO_RESTRICT_PROG2" , 0x34, 12 , 7 , 2 , init_io_restrict_prog2 },
1391 { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat },
1392 { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy },
1393 { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not },
1394 { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition },
1395 /* { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, x , x , x, , init_idx_addr_latched }, */
1396 { "INIT_IO_RESTRICT_PLL" , 0x4A, 43 , 0 , 0 , init_io_restrict_pll },
1397 { "INIT_PLL" , 0x4B, 9 , 0 , 0 , init_pll },
1398 /* { "INIT_I2C_BYTE" , 0x4C, x , x , x , init_i2c_byte }, */
1399 /* { "INIT_ZM_I2C_BYTE" , 0x4D, x , x , x , init_zm_i2c_byte }, */
1400 /* { "INIT_ZM_I2C" , 0x4E, x , x , x , init_zm_i2c }, */
1401 { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch },
1402 { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr },
1403 { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr },
1404 { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group },
1405 { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time },
1406 { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence },
1407 { "INIT_INDIRECT_REG" , 0x5A, 7 , 0 , 0 , init_indirect_reg },
1408 { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct },
1409 { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg },
1410 { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io },
1411 { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem },
1412 { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset },
1413 /* { "INIT_NEXT" , 0x66, x , x , x , init_next }, */
1414 /* { "INIT_NEXT" , 0x67, x , x , x , init_next }, */
1415 /* { "INIT_NEXT" , 0x68, x , x , x , init_next }, */
1416 { "INIT_INDEX_IO8" , 0x69, 5 , 0 , 0 , init_index_io8 },
1417 { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub },
1418 { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition },
1419 { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg },
1420 { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro },
1421 { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done },
1422 { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume },
1423 { "INIT_RAM_CONDITION2" , 0x73, 9 , 0 , 0 , init_ram_condition2 },
1424 { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time },
1425 { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition },
1426 /* { "INIT_IO_CONDITION", , 0x76, x , x, , x , init_io_condition }, */
1427 { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io },
1428 { "INIT_PLL2" , 0x79, 7 , 0 , 0 , init_pll2 },
1429 { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg },
1430 /* { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, x , x , x , init_ram_restrict_zm_reg_group }, */
1431 /* { "INIT_COPY_ZM_REG" , 0x90, x , x , x , init_copy_zm_reg }, */
1432 /* { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, x , x , x , init_zm_reg_group_addr_latched }, */
1433 /* { "INIT_RESERVED" , 0x92, x , x , x , init_reserved }, */
1434 { 0 , 0 , 0 , 0 , 0 , 0 }
1437 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
1439 /* Calculates the length of a given init table entry. */
1440 return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
1443 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
1445 /* Parses all commands in a init table. */
1447 /* We start out executing all commands found in the
1448 * init table. Some op codes may change the status
1449 * of this variable to SKIP, which will cause
1450 * the following op codes to perform no operation until
1451 * the value is changed back to EXECUTE.
1457 /* Loop as long as INIT_DONE (command id 0x71) has not been found
1458 * (and offset < bios length just in case... )
1459 * (and no more than 10000 iterations just in case... ) */
1460 while (((id = bios->data[offset]) != 0x71) && (offset < bios->length) && (count++<10000)) {
1461 /* Find matching id in itbl_entry */
1462 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
1465 if (itbl_entry[i].name) {
1466 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ (0x%02X) - %s ]\n", offset,
1467 itbl_entry[i].id, itbl_entry[i].name);
1469 /* execute eventual command handler */
1470 if (itbl_entry[i].handler)
1471 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
1474 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Init table command not found: 0x%02X\n",
1479 /* Add the offset of the current command including all data
1480 * of that command. The offset will then be pointing on the
1483 offset += get_init_table_entry_length(bios, offset, i);
1487 void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios)
1489 /* Loops and calls parse_init_table() for each present table. */
1493 init_exec_t iexec = {TRUE, FALSE};
1495 while (table = *((CARD16 *) (&bios->data[bios->init_tbls_offset + i]))) {
1497 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing init table %d\n",
1500 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",table);
1502 parse_init_table(pScrn, bios, table, &iexec);
1507 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
1509 /* Parses the init table segment that the bit entry points to.
1510 * Starting at bitentry->offset:
1512 * offset + 0 (16 bits): offset of init tables
1513 * offset + 2 (16 bits): macro index table offset
1514 * offset + 4 (16 bits): macro offset
1515 * offset + 6 (16 bits): condition offset
1516 * offset + 8 (16 bits): io flag condition offset (?)
1517 * offset + 10 (16 bits): io flag condition offset (?)
1518 * offset + 12 (16 bits): unknown
1520 * offset + 8 and offset + 10 seems to contain the same
1521 * offsets on all bioses i have checked. Don't know which
1522 * one is the correct, therefore this code will bail out
1523 * if the two values are not the same.
1526 * * In addition to "conditions" and "io flag conditions" there seems to be
1527 * "io conditions". These are probably located at offset + (8, 10 or 12).
1528 * We need more BIOS dumps to figure this out...
1530 * * Are 'I' bit entries always of length 0xE?
1534 if (bitentry->length < 12) {
1535 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to regocnize BIT init table entry.\n");
1539 bios->init_tbls_offset = *((CARD16 *) (&bios->data[bitentry->offset]));
1540 bios->macro_index_offset = *((CARD16 *) (&bios->data[bitentry->offset + 2]));
1541 bios->macro_offset = *((CARD16 *) (&bios->data[bitentry->offset + 4]));
1542 bios->condition_offset =
1543 *((CARD16 *) (&bios->data[bitentry->offset + 6]));
1544 if (*((CARD16 *) (&bios->data[bitentry->offset + 8])) !=
1545 *((CARD16 *) (&bios->data[bitentry->offset + 10]))) {
1546 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to find IO flag condition offset.\n");
1550 bios->io_flag_condition_offset =
1551 *((CARD16 *) (&bios->data[bitentry->offset + 8]));
1553 bios->fptablepointer = *((CARD16 *)(&bios->data[bitentry->offset + 30]));
1554 bios->fpxlatetableptr = *((CARD16 *)(&bios->data[bitentry->offset + 32]));
1555 bios->lvdsmanufacturerpointer = *((CARD16 *)(&bios->data[bitentry->offset + 42]));
1556 bios->fpxlatemanufacturertableptr = *((CARD16 *)(&bios->data[bitentry->offset + 44]));
1557 bios->fpxlateflagtableptr = *((CARD16 *)(&bios->data[bitentry->offset + 46]));
1559 parse_init_tables(pScrn, bios);
1564 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1566 bit_entry_t *bitentry;
1570 bitentry = (bit_entry_t *) &bios->data[offset];
1572 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Found BIT command with id 0x%02X\n",
1573 offset, bitentry->id[0]);
1575 switch (bitentry->id[0]) {
1577 /* id[0] = 0 and id[1] = 0 ==> end of BIT struture */
1578 if (bitentry->id[1] == 0)
1582 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1583 "0x%04X: Found init table entry in BIT structure.\n",
1586 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1587 /*parse_init_tables(pScrn, bios);*/
1590 /* TODO: What kind of information does the other BIT entrys point to?
1591 * 'P' entry is probably performance tables, but there are
1592 * quite a few others...
1596 offset += sizeof(bit_entry_t);
1600 static void parse_pins_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1602 int pins_version_major=bios->data[offset+5];
1603 int pins_version_minor=bios->data[offset+6];
1604 int init1 = bios->data[offset + 18] + (bios->data[offset + 19] * 256);
1605 int init2 = bios->data[offset + 20] + (bios->data[offset + 21] * 256);
1606 int init_size = bios->data[offset + 22] + (bios->data[offset + 23] * 256) + 1;
1611 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PINS version %d.%d\n",pins_version_major,pins_version_minor);
1614 for (i=0; i < 8; i++)
1615 chksum += bios->data[offset+i];
1617 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "bad PINS checksum\n");
1621 switch(pins_version_major) {
1623 ram_tab = init1-0x0010;
1628 ram_tab = bios->data[offset + 24] + (bios->data[offset + 25] * 256);
1634 if ((pins_version_major==5)&&(pins_version_minor>=6))
1636 /* VCO range info */
1639 if ((pins_version_major==5)&&(pins_version_minor>=16))
1641 bit_entry_t bitentry;
1642 bitentry.offset = offset + 75;
1643 parse_bit_init_tbl_entry(pScrn, bios, &bitentry);
1646 /* TODO type1 script */
1651 static unsigned int findstr(bios_t* bios, unsigned char *str, int len)
1655 for (i = 2; i < bios->length; i++)
1656 if (strncmp(&bios->data[i], str, len) == 0)
1663 nv_read_dcb_i2c_table(ScrnInfoPtr pScrn, bios_t *bios, uint16_t i2ctabptr)
1665 NVPtr pNv = NVPTR(pScrn);
1666 unsigned char *i2ctable;
1667 unsigned char dcb_version, headerlen = 0;
1668 int recordoffset = 0, rdofs = 1, wrofs = 0;
1671 pNv->dcb_table.i2c_entries = MAX_NUM_DCB_ENTRIES;
1672 memset(pNv->dcb_table.i2c_read, 0, sizeof(pNv->dcb_table.i2c_read));
1673 memset(pNv->dcb_table.i2c_write, 0, sizeof(pNv->dcb_table.i2c_write));
1675 i2ctable = &bios->data[i2ctabptr];
1676 dcb_version = pNv->dcb_table.version;
1678 if (dcb_version >= 0x30) {
1679 if (i2ctable[0] != dcb_version) { /* necessary? */
1680 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1681 "DCB I2C table version mismatch (%02X vs %02X)\n",
1682 i2ctable[0], dcb_version);
1685 headerlen = i2ctable[1];
1686 pNv->dcb_table.i2c_entries = i2ctable[2];
1687 if (i2ctable[0] >= 0x40) {
1688 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1689 "G80 DCB I2C table detected, arrgh\n"); /* they're plain weird */
1693 /* it's your own fault if you call this function on a DCB 1.1 BIOS */
1694 if (dcb_version < 0x14) {
1700 for (i = 0; i < pNv->dcb_table.i2c_entries; i++) {
1701 if (i2ctable[headerlen + 4 * i + 3] != 0xff) {
1702 pNv->dcb_table.i2c_read[i] = i2ctable[headerlen + recordoffset + rdofs + 4 * i];
1703 pNv->dcb_table.i2c_write[i] = i2ctable[headerlen + recordoffset + wrofs + 4 * i];
1708 #define G5_FIXED_LOC 0xe2f8
1710 static unsigned int nv_read_dcb_table(ScrnInfoPtr pScrn, bios_t *bios)
1712 NVPtr pNv = NVPTR(pScrn);
1713 uint16_t dcbptr, i2ctabptr = 0;
1715 unsigned char *dcbtable;
1716 unsigned char dcb_version, headerlen = 0x4, entries = MAX_NUM_DCB_ENTRIES;
1717 Bool configblock = FALSE;
1718 int recordlength = 8;
1721 pNv->dcb_table.entries = 0;
1722 pNv->dcb_table.i2c_entries = 0;
1724 /* get the offset from 0x36 */
1725 dcbptr = *(uint16_t *)&bios->data[0x36];
1727 if (dcbptr == 0x0) {
1728 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV43) {
1730 dcbtable = &bios->data[G5_FIXED_LOC];
1731 dcb_version = 0x5; // magic G5 value
1738 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1739 "No Display Configuration Block pointer found\n");
1744 dcbtable = &bios->data[dcbptr];
1746 /* get DCB version */
1747 dcb_version = dcbtable[0];
1748 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1749 "Display Configuration Block version %d.%d found\n",
1750 dcb_version >> 4, dcb_version & 0xf);
1752 if (dcb_version >= 0x20) { /* NV17+ */
1755 if (dcb_version >= 0x30) { /* NV40+ */
1756 headerlen = dcbtable[1];
1757 entries = dcbtable[2];
1758 i2ctabptr = *(uint16_t *)&dcbtable[4];
1759 sig = *(uint32_t *)&dcbtable[6];
1761 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1762 "DCB header length %02X, with %02X possible entries\n",
1763 headerlen, entries);
1765 /* dcb_block_count = *(dcbtable[1]); */
1766 i2ctabptr = *(uint16_t *)&dcbtable[2];
1767 sig = *(uint32_t *)&dcbtable[4];
1772 if ((sig != 0x4edcbdcb) && (sig != 0xcbbddc4e)) {
1773 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1774 "Bad Display Configuration Block signature (%08X)\n", sig);
1777 } else if (dcb_version >= 0x14) { /* some NV15/16, and NV11+ */
1781 strncpy(sig, &dcbtable[-7], 7);
1782 /* dcb_block_count = *(dcbtable[1]); */
1783 i2ctabptr = *(uint16_t *)&dcbtable[2];
1786 if (strcmp(sig, "DEV_REC")) {
1787 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1788 "Bad Display Configuration Block signature (%s)\n", sig);
1791 } else if (dcb_version >= 0x12) { /* some NV6/10, and NV15+ */
1792 /* dcb_block_count = *(dcbtable[1]); */
1793 i2ctabptr = *(uint16_t *)&dcbtable[2];
1794 } else { /* NV5+, maybe NV4 */
1795 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1796 "Structure of Display Configuration Blocks prior to version 1.2 unknown\n");
1801 pNv->dcb_table.version = dcb_version;
1803 if (entries >= MAX_NUM_DCB_ENTRIES)
1804 entries = MAX_NUM_DCB_ENTRIES;
1806 for (i = 0; i < entries; i++) {
1807 uint32_t connection, config = 0;
1810 connection = __bswap_32(*(uint32_t *)&dcbtable[headerlen + recordlength * i]);
1812 config = __bswap_32(*(uint32_t *)&dcbtable[headerlen + 4 + recordlength * i]);
1814 connection = *(uint32_t *)&dcbtable[headerlen + recordlength * i];
1816 config = *(uint32_t *)&dcbtable[headerlen + 4 + recordlength * i];
1819 /* I think this is a good descriminator, but I don't understand
1820 * pre v2.0 DCBs so well, so maybe those need testing against
1822 /* Should we allow discontinuous DCBs? Certainly DCB I2C tables
1823 * can be discontinuous */
1824 if ((connection & 0x0f000000) == 0x0f000000) /* end of records */
1827 pNv->dcb_table.connection[i] = connection;
1828 pNv->dcb_table.config[i] = config;
1830 pNv->dcb_table.entries = i;
1832 nv_read_dcb_i2c_table(pScrn, bios, i2ctabptr);
1834 return pNv->dcb_table.entries;
1837 static void nv_read_fp_tables(ScrnInfoPtr pScrn, bios_t *bios)
1839 #ifdef ENABLE_RANDR12
1840 NVPtr pNv = NVPTR(pScrn);
1841 unsigned int fpstrapping;
1842 unsigned char *fptable, *fpxlatetable;
1843 unsigned char *lvdsmanufacturertable, *fpxlatemanufacturertable;
1844 unsigned char *fpxlateflagtable;
1845 unsigned int fpindex, lvdsmanufacturerindex;
1846 DisplayModePtr mode;
1848 fpstrapping = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT) >> 16) & 0xf;
1850 if (bios->fptablepointer == 0x0 || bios->fpxlatetableptr == 0x0) {
1851 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1852 "Pointer to flat panel table invalid\n");
1856 fptable = &bios->data[bios->fptablepointer];
1857 fpxlatetable = &bios->data[bios->fpxlatetableptr];
1859 lvdsmanufacturertable = &bios->data[bios->lvdsmanufacturerpointer];
1860 fpxlatemanufacturertable = &bios->data[bios->fpxlatemanufacturertableptr];
1861 fpxlateflagtable = &bios->data[bios->fpxlateflagtableptr]; */
1863 fpindex = fpxlatetable[fpstrapping];
1865 lvdsmanufacturerindex = fpxlatemanufacturertable[fpstrapping]; */
1867 if (fpindex > 0xf) {
1868 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1869 "Bad flat panel table index\n");
1873 /* FIXME: try to understand go6800 dump... */
1874 if (fptable[44 * fpindex] != 0x10) {
1875 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1876 "FP Table revisions other than 0x10 not currently supported\n");
1880 if (!(mode = xcalloc(1, sizeof(DisplayModeRec))))
1883 /* bytes 1-2 are "panel type", including bits on whether Colour/mono, single/dual link, and type (TFT etc.) */
1884 /* bytes 3-5 are bits per colour in RGB */
1885 /* byte 6 is empty */
1886 mode->Clock = *(uint16_t *)&fptable[44 * fpindex + 7] * 10;
1888 mode->HDisplay = *(uint16_t *)&fptable[44 * fpindex + 9];
1889 /* 11-12 is HDispEnd */
1890 /* 13-14 is HValid Start */
1891 /* 15-16 is HValid End */
1892 mode->HSyncStart = *(uint16_t *)&fptable[44 * fpindex + 17] + 1;
1893 mode->HSyncEnd = *(uint16_t *)&fptable[44 * fpindex + 19] + 1;
1894 mode->HTotal = *(uint16_t *)&fptable[44 * fpindex + 21] + 1;
1896 mode->VDisplay = *(uint16_t *)&fptable[44 * fpindex + 23];
1897 mode->VSyncStart = *(uint16_t *)&fptable[44 * fpindex + 31] + 1;
1898 mode->VSyncEnd = *(uint16_t *)&fptable[44 * fpindex + 33] + 1;
1899 mode->VTotal = *(uint16_t *)&fptable[44 * fpindex + 35] + 1;
1901 mode->Flags |= (fptable[44 * fpindex + 37] & 0x10) ? V_PHSYNC : V_NHSYNC;
1902 mode->Flags |= (fptable[44 * fpindex + 37] & 0x1) ? V_PVSYNC : V_NVSYNC;
1904 /* bytes 38-39 relate to spread spectrum settings */
1905 /* bytes 40-43 are something to do with PWM */
1907 mode->prev = mode->next = NULL;
1908 mode->status = MODE_OK;
1909 mode->type = M_T_DRIVER | M_T_PREFERRED;
1910 xf86SetModeDefaultName(mode);
1912 // if (pNv->debug_modes) { this should exist
1913 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1914 "Found flat panel mode in BIOS tables:\n");
1915 xf86PrintModeline(pScrn->scrnIndex, mode);
1918 pNv->fp_native_mode = mode;
1920 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1921 "Reading flat panel tables disabled\n");
1925 unsigned int NVParseBios(ScrnInfoPtr pScrn)
1927 unsigned int bit_offset;
1930 bios.length=NV_PROM_SIZE;
1931 unsigned char nv_signature[]={0xff,0x7f,'N','V',0x0};
1932 unsigned char bit_signature[]={'B','I','T'};
1937 pNv->dcb_table.entries = 0;
1938 pNv->dcb_table.i2c_entries = 0;
1940 pNv->VBIOS = xalloc(64 * 1024);
1941 if (!NVShadowVBIOS(pScrn, pNv->VBIOS)) {
1942 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1943 "No valid BIOS image found.\n");
1947 bios.data = (unsigned char *)pNv->VBIOS;
1949 /* check for known signatures */
1950 if ((bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature)))) {
1951 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT signature found.\n");
1952 parse_bit_structure(pScrn, &bios, bit_offset + 4);
1953 } else if ((bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature)))) {
1954 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV signature found.\n");
1955 parse_pins_structure(pScrn, &bios, bit_offset);
1957 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No known script signature found.\n");
1960 /* read Display Configuration Block (DCB) table */
1961 ret = nv_read_dcb_table(pScrn, &bios);
1963 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1964 "Found %d entries in DCB.\n", ret);
1966 pNv->fp_native_mode = NULL;
1967 /* FIXME: can we detect mobile BIOS? */
1969 nv_read_fp_tables(pScrn, &bios);