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;
50 static Bool NVValidVBIOS(ScrnInfoPtr pScrn, const unsigned char *data)
52 /* check for BIOS signature */
53 if (!(data[0] == 0x55 && data[1] == 0xAA)) {
54 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
55 "...BIOS signature not found\n");
59 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "...appears to be valid\n");
63 static void NVShadowVBIOS_PROM(ScrnInfoPtr pScrn, unsigned char *data)
65 NVPtr pNv = NVPTR(pScrn);
68 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
69 "Attempting to locate BIOS image in PROM\n");
71 /* enable ROM access */
72 nvWriteMC(pNv, 0x1850, 0x0);
73 for (i=0; i<NV_PROM_SIZE; i++) {
74 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
75 data[i] = pNv->PROM[i];
76 data[i] = pNv->PROM[i];
77 data[i] = pNv->PROM[i];
78 data[i] = pNv->PROM[i];
79 data[i] = pNv->PROM[i];
81 /* disable ROM access */
82 nvWriteMC(pNv, 0x1850, 0x1);
85 static void NVShadowVBIOS_PRAMIN(ScrnInfoPtr pScrn, unsigned char *data)
87 NVPtr pNv = NVPTR(pScrn);
88 const unsigned char *pramin = (void*)&pNv->REGS[0x00700000/4];
89 uint32_t old_bar0_pramin = 0;
91 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
92 "Attempting to locate BIOS image in PRAMIN\n");
94 if (pNv->Architecture >= NV_ARCH_50) {
97 vbios_vram = (pNv->REGS[0x619f04/4] & ~0xff) << 8;
99 vbios_vram = pNv->REGS[0x1700/4] << 16;
100 vbios_vram += 0xf0000;
103 old_bar0_pramin = pNv->REGS[0x1700/4];
104 pNv->REGS[0x1700/4] = vbios_vram >> 16;
107 memcpy(data, pramin, 65536);
109 if (pNv->Architecture >= NV_ARCH_50) {
110 pNv->REGS[0x1700/4] = old_bar0_pramin;
114 static Bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint32_t *data)
116 NVPtr pNv = NVPTR(pScrn);
118 NVShadowVBIOS_PROM(pScrn, data);
119 if (NVValidVBIOS(pScrn, data))
122 NVShadowVBIOS_PRAMIN(pScrn, data);
123 if (NVValidVBIOS(pScrn, data))
134 int length_multiplier;
135 Bool (*handler)(ScrnInfoPtr pScrn, bios_t *, CARD16, init_exec_t *);
140 unsigned short length;
141 unsigned short offset;
144 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec);
146 /* #define MACRO_SIZE 8 */
147 #define CONDITION_SIZE 12
148 #define IO_FLAG_CONDITION_SIZE 9
156 static int nv_valid_reg(CARD32 reg)
158 #define WITHIN(x,y,z) ((x>=y)&&(x<y+z))
159 if (WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
161 if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE))
163 if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE))
165 if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
167 if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
169 if (WITHIN(reg,NV_PGRAPH_OFFSET,NV_PGRAPH_SIZE))
171 if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
173 if (WITHIN(reg,NV_PTIMER_OFFSET,NV_PTIMER_SIZE))
175 if (WITHIN(reg,NV_PVIDEO_OFFSET,NV_PVIDEO_SIZE))
177 if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
179 if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
181 if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
183 if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
185 if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
187 if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
193 static int nv32_rd(ScrnInfoPtr pScrn, CARD32 reg, CARD32 *data)
195 NVPtr pNv = NVPTR(pScrn);
196 *data=pNv->REGS[reg/4];
200 static int nv32_wr(ScrnInfoPtr pScrn, CARD32 reg, CARD32 data)
203 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv32_wr reg 0x%X value 0x%X\n",reg,data);
205 if (!nv_valid_reg(reg))
207 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "========= unknown reg 0x%X ==========\n",reg);
211 NVPtr pNv = NVPTR(pScrn);
212 pNv->REGS[reg/4]=data;
217 void nv_set_crtc_index(ScrnInfoPtr pScrn, CARD8 index)
220 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_set_crtc_index index 0x%X\n",index);
222 NVPtr pNv = NVPTR(pScrn);
223 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
224 VGA_WR08(ptr, 0x3D4, index);
228 CARD8 nv_rd_crtc_data(ScrnInfoPtr pScrn)
230 NVPtr pNv = NVPTR(pScrn);
231 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
232 return VGA_RD08(ptr, 0x3D5);
235 void nv_wr_crtc_data(ScrnInfoPtr pScrn, CARD8 val)
238 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_wr_crtc_data value 0x%X\n",val);
240 NVPtr pNv = NVPTR(pScrn);
241 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
242 VGA_WR08(ptr, 0x3D5, val);
246 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
248 /* INIT_PROG opcode: 0x31
250 * offset (8 bit): opcode
251 * offset + 1 (32 bit): reg
252 * offset + 5 (32 bit): and mask
253 * offset + 9 (8 bit): shift right
254 * offset + 10 (8 bit): number of configurations
255 * offset + 11 (32 bit): register
256 * offset + 15 (32 bit): configuration 1
259 * Starting at offset + 15 there are "number of configurations"
260 * 32 bit values. To find out which configuration value to use
261 * read "CRTC reg" on the CRTC controller with index "CRTC index"
262 * and bitwise AND this value with "and mask" and then bit shift the
263 * result "shift right" bits to the right.
264 * Assign "register" with appropriate configuration value.
267 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
268 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
269 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
270 CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
271 CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
273 CARD32 configval, tmp;
275 if (iexec->execute) {
276 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%04X\n", offset,
279 nv32_rd(pScrn, reg, &tmp);
280 configuration = (tmp & and) >> shiftr;
282 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
283 offset, configuration);
285 if (configuration <= nr) {
288 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
290 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
293 if (nv32_rd(pScrn, reg2, &tmp)) {
294 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
297 nv32_wr(pScrn, reg2, configval);
303 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
305 /* INIT_IO_RESTRICT_PROG opcode: 0x32
307 * offset (8 bit): opcode
308 * offset + 1 (16 bit): CRTC reg
309 * offset + 3 (8 bit): CRTC index
310 * offset + 4 (8 bit): and mask
311 * offset + 5 (8 bit): shift right
312 * offset + 6 (8 bit): number of configurations
313 * offset + 7 (32 bit): register
314 * offset + 11 (32 bit): configuration 1
317 * Starting at offset + 11 there are "number of configurations"
318 * 32 bit values. To find out which configuration value to use
319 * read "CRTC reg" on the CRTC controller with index "CRTC index"
320 * and bitwise AND this value with "and mask" and then bit shift the
321 * result "shift right" bits to the right.
322 * Assign "register" with appropriate configuration value.
325 NVPtr pNv = NVPTR(pScrn);
326 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
327 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
328 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
329 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
330 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
331 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
332 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
334 CARD32 configval, tmp;
336 if (iexec->execute) {
337 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
340 VGA_WR08(ptr,crtcreg, index);
341 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
343 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
344 offset, configuration);
346 if (configuration <= nr) {
348 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
350 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
353 if (nv32_rd(pScrn, reg, &tmp)) {
354 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
357 nv32_wr(pScrn, reg, configval);
363 static Bool init_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
365 CARD8 repeats = *((CARD8 *) (&bios->data[offset + 1]));
368 if (iexec->execute) {
369 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REPEATING FOLLOWING SEGMENT %d TIMES.\n",
372 iexec->repeat = TRUE;
374 for (i = 0; i < repeats - 1; i++)
375 parse_init_table(pScrn, bios, offset + 2, iexec);
377 iexec->repeat = FALSE;
382 static Bool init_end_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
390 static Bool init_copy(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
392 /* XXX: double check this... */
393 NVPtr pNv = NVPTR(pScrn);
394 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
395 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
396 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
397 CARD8 and1 = *((CARD8 *) (&bios->data[offset + 6]));
398 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 7]));
399 CARD8 index = *((CARD8 *) (&bios->data[offset + 9]));
400 CARD8 and2 = *((CARD8 *) (&bios->data[offset + 10]));
404 if (iexec->execute) {
405 if (nv32_rd(pScrn, reg, &data)) {
409 data <<= (0x100 - shift);
412 VGA_WR08(ptr,crtcreg, index);
413 crtcdata = (VGA_RD08(ptr, crtcreg + 1) & and2) | (CARD8) data;
415 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
416 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n"
417 , offset, crtcreg, index, crtcdata);
419 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
420 VGA_RD08(ptr, crtcreg + 1));
422 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_copy crtcreg 0x%X value 0x%X\n",crtcreg+1,crtcdata);
424 printf("WRITE IS PERFORMED\n");
425 VGA_WR08(ptr,crtcreg + 1, crtcdata);
432 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
434 if (iexec->execute) {
435 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n",
438 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",
442 iexec->execute = !iexec->execute;
446 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
448 NVPtr pNv = NVPTR(pScrn);
449 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
450 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
451 CARD16 crtcreg = *((CARD16 *)
452 (&bios->data[bios->io_flag_condition_offset +
453 cond * IO_FLAG_CONDITION_SIZE]));
454 CARD8 index = *((CARD8 *)
455 (&bios->data[bios->io_flag_condition_offset +
456 cond * IO_FLAG_CONDITION_SIZE + 2]));
457 CARD8 and1 = *((CARD8 *)
458 (&bios->data[bios->io_flag_condition_offset +
459 cond * IO_FLAG_CONDITION_SIZE + 3]));
460 CARD8 shift = *((CARD8 *)
461 (&bios->data[bios->io_flag_condition_offset +
462 cond * IO_FLAG_CONDITION_SIZE + 4]));
463 CARD16 offs = *((CARD16 *)
464 (&bios->data[bios->io_flag_condition_offset +
465 cond * IO_FLAG_CONDITION_SIZE + 5]));
466 CARD8 and2 = *((CARD8 *)
467 (&bios->data[bios->io_flag_condition_offset +
468 cond * IO_FLAG_CONDITION_SIZE + 7]));
469 CARD8 cmpval = *((CARD8 *)
470 (&bios->data[bios->io_flag_condition_offset +
471 cond * IO_FLAG_CONDITION_SIZE + 8]));
475 if (iexec->execute) {
476 VGA_WR08(ptr,crtcreg, index);
477 data = VGA_RD08(ptr, crtcreg + 1);
479 offs += (data >> shift);
480 data = *((CARD8 *) (&bios->data[offs]));
483 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
484 "0x%04X: CHECKING IF DATA: %02X equals COND: %02X\n", offset,
487 if (data == cmpval) {
488 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
489 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
492 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
493 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
494 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
495 iexec->execute = FALSE;
501 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
503 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
504 /* XXX: this needs to be confirmed... NOT CORRECT */
505 /*init_io_restrict_prog(bios, offset, iexec);*/
507 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
508 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
509 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
510 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
511 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
512 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
514 CARD32 configval, tmp;
516 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
517 crtcreg, index, reg);
519 VGA_WR08(ptr,crtcreg, index);
520 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
522 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
523 offset, configuration);
525 if (configuration <= nr) {
527 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &configval))
528 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
532 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
534 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
540 if (iexec->execute) {
543 configval = 0x01014E07;
546 configval = 0x13030E02;
550 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
553 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
554 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
557 nv32_wr(pScrn, reg, configval);
563 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
565 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
566 CARD32 val = *((CARD32 *) (&bios->data[offset + 5]));
567 CARD32 configval, tmp;
569 if (iexec->execute) {
572 configval = 0x00011F05;
576 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
579 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
580 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
583 nv32_wr(pScrn, reg, configval);
585 /*xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);*/
591 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
593 CARD8 crtcindex = *((CARD8 *) (&bios->data[offset + 1]));
594 CARD8 crtcdata = *((CARD8 *) (&bios->data[offset + 2]));
595 CARD8 initial_index = *((CARD8 *) (&bios->data[offset + 3]));
596 CARD8 entries = *((CARD8 *) (&bios->data[offset + 4]));
600 if (iexec->execute) {
601 for (i = 0; i < entries; i++) {
602 nv_set_crtc_index(pScrn, crtcindex);
604 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
605 crtcindex, initial_index + i);
607 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
608 nv_rd_crtc_data(pScrn));
610 nv_wr_crtc_data(pScrn, initial_index + i);
612 nv_set_crtc_index(pScrn, crtcdata);
614 data = *((CARD8 *) (&bios->data[offset + 5 + i]));
616 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
619 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
620 nv_rd_crtc_data(pScrn));
622 nv_wr_crtc_data(pScrn, data);
628 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
630 /* XXX: IS THIS CORRECT? check the typecast .. probably wrong */
632 NVPtr pNv = NVPTR(pScrn);
633 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
634 CARD8 and = *((CARD8 *) (&bios->data[offset + 2]));
635 CARD8 or = *((CARD8 *) (&bios->data[offset + 3]));
638 if (iexec->execute) {
639 nv_set_crtc_index(pScrn, index);
640 data = (nv_rd_crtc_data(pScrn) & and) | or;
641 /*printf("and: 0x%02x or: 0x%02x\n", and, or);*/
642 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
645 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
646 nv_rd_crtc_data(pScrn));
648 nv_wr_crtc_data(pScrn, data);
653 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
655 /* INIT_ZM_CR opcode: 0x53
657 * offset (8 bit): opcode
658 * offset + 1 (8 bit): CRTC index
659 * offset + 2 (8 bit): value
661 * Assign "value" to CRTC register with index "CRTC index".
664 NVPtr pNv = NVPTR(pScrn);
665 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
666 CARD8 value = *((CARD8 *) (&bios->data[offset + 2]));
668 if (iexec->execute) {
669 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
672 nv_set_crtc_index(pScrn, index);
674 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
675 nv_rd_crtc_data(pScrn));
677 nv_wr_crtc_data(pScrn, value);
682 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
684 /* INIT_ZM_CR opcode: 0x54
686 * offset (8 bit): opcode
687 * offset + 1 (8 bit): number of groups (index, value)
688 * offset + 2 (8 bit): index 1
689 * offset + 3 (8 bit): value 1
692 * Assign "value n" to CRTC register with index "index n".
695 CARD8 nr = *((CARD8 *) (&bios->data[offset + 1]));
699 if (iexec->execute) {
700 for (i = 0; i < nr; i++) {
701 index = *((CARD8 *) (&bios->data[offset + 2 + 2 * i]));
702 value = *((CARD8 *) (&bios->data[offset + 2 + 2 * i + 1]));
704 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
707 nv_set_crtc_index(pScrn, index);
709 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
710 nv_rd_crtc_data(pScrn));
711 nv_wr_crtc_data(pScrn, value);
717 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
719 /* My BIOS does not use this command. */
720 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
725 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
727 /* INIT_ZM_REG_SEQUENCE opcode: 0x58
729 * offset (8 bit): opcode
730 * offset + 1 (32 bit): register base
731 * offset + 5 (8 bit): nr
732 * offset + 6 (32 bit): value to assign "register base" + 4
735 * Initialzies a sequence of "nr" registers starting at "register base".
738 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
739 CARD32 nr = *((CARD8 *) (&bios->data[offset + 5]));
744 if (iexec->execute) {
745 for (i = 0; i < nr; i++) {
746 data = *((CARD32 *) (&bios->data[offset + 6 + i * 4]));
747 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
750 if (nv32_rd(pScrn, reg + i * 4, &tmp)) {
751 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
755 nv32_wr(pScrn, reg + i * 4, data);
761 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
763 /* INIT_INDIRECT_REG opcode: 0x5A
765 * offset (8 bit): opcode
766 * offset + 1 (32 bit): register
767 * offset + 5 (16 bit): adress offset (in bios)
769 * Lookup value at offset data in the bios and write it to reg
771 NVPtr pNv = NVPTR(pScrn);
772 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
773 CARD32 data = *((CARD16 *) (&bios->data[offset + 5]));
774 CARD32 data2 = bios->data[data];
776 if (iexec->execute) {
777 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
778 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n",
779 offset, reg, data, data2);
781 if (DEBUGLEVEL >= 6) {
783 nv32_rd(pScrn, reg, &tmpval);
784 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
787 nv32_wr(pScrn, reg, data2);
792 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
794 /* INIT_SUB_DIRECT opcode: 0x5B
796 * offset (8 bit): opcode
797 * offset + 1 (16 bit): subroutine offset (in bios)
799 * Calls a subroutine that will execute commands until INIT_DONE
803 CARD16 sub_offset = *((CARD16 *) (&bios->data[offset + 1]));
805 if (iexec->execute) {
806 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-ROUTINE AT: 0x%04X\n",
809 parse_init_table(pScrn, bios, sub_offset, iexec);
811 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-ROUTINE\n", offset);
816 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
818 CARD32 srcreg = *((CARD32 *) (&bios->data[offset + 1]));
819 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
820 CARD32 and1 = *((CARD32 *) (&bios->data[offset + 6]));
821 CARD32 xor = *((CARD32 *) (&bios->data[offset + 10]));
822 CARD32 dstreg = *((CARD32 *) (&bios->data[offset + 14]));
823 CARD32 and2 = *((CARD32 *) (&bios->data[offset + 18]));
827 if (iexec->execute) {
828 nv32_rd(pScrn, srcreg, &srcdata);
835 srcdata = (srcdata & and1) ^ xor;
837 nv32_rd(pScrn, dstreg, &dstdata);
843 nv32_rd(pScrn, dstreg, &tmp);
845 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, dstreg,
848 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmp);
850 nv32_wr(pScrn, dstreg, dstdata);
855 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
857 NVPtr pNv = NVPTR(pScrn);
858 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
859 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
860 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
861 CARD8 value = *((CARD8 *) (&bios->data[offset + 4]));
863 if (iexec->execute) {
864 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
865 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
866 offset, crtcreg, index, value);
868 VGA_WR08(ptr,crtcreg, index);
870 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
871 VGA_RD08(ptr, crtcreg + 1));
874 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_zm_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,value);
876 VGA_WR08(ptr,crtcreg + 1, value);
882 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
884 // FIXME replace with a suitable implementation
886 CARD16 ramcfg = *((CARD16 *) (&bios->data[bios->ram_table_offset]));
891 if (iexec->execute) {
892 nv32_rd(pScrn, 0x00101000, &strapinfo);
893 nv32_rd(pScrn, 0x00100080, &pfb_debug);
895 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
896 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
897 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG: 0x%04X\n", ramcfg);
899 pfb_debug &= 0xffffffef;
901 strapinfo &= 0x0000000f;
902 ramcfg2 = *((CARD16 *)
903 (&bios->data[bios->ram_table_offset + (2 * strapinfo)]));
905 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AFTER MANIPULATION\n");
906 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
907 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
908 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG2: 0x%08X\n", ramcfg2);
910 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
915 nv32_rd(pScrn, 0x00100200, ®1);
916 nv32_rd(pScrn, 0x0010020C, ®2);
918 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x00100200: 0x%08X\n", reg1);
919 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x0010020C: 0x%08X\n", reg2);
925 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
927 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
928 CARD32 value1 = *((CARD32 *) (&bios->data[offset + 5]));
929 CARD32 value2 = *((CARD32 *) (&bios->data[offset + 9]));
931 if (iexec->execute) {
932 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
933 offset, reg, value1);
934 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
935 offset, reg, value2);
937 if (DEBUGLEVEL >= 6) {
939 nv32_rd(pScrn, reg, &tmpval);
940 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
942 nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), &tmpval);
943 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: PCICFG_ROMSHADOW: 0x%02X\n", offset, tmpval);
946 nv32_wr(pScrn, reg, value1);
947 nv32_wr(pScrn, reg, value2);
949 /* PCI Config space init needs to be added here. */
950 /* if (nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), value1)) */
951 /* nv32_wr(pScrn, PCICFG(PCICFG_ROMSHADOW), value1 & 0xfffffffe) */
956 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
958 /* INIT_INDEX_IO8 opcode: 0x69
960 * offset (8 bit): opcode
961 * offset + 1 (16 bit): CRTC reg
962 * offset + 3 (8 bit): and mask
963 * offset + 4 (8 bit): or with
968 NVPtr pNv = NVPTR(pScrn);
969 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
970 CARD16 reg = *((CARD16 *) (&bios->data[offset + 1]));
971 CARD8 and = *((CARD8 *) (&bios->data[offset + 3]));
972 CARD8 or = *((CARD8 *) (&bios->data[offset + 4]));
975 if (iexec->execute) {
976 data = (VGA_RD08(ptr, reg) & and) | or;
978 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
979 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n",
981 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
985 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
987 VGA_WR08(ptr, reg, data);
993 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
995 CARD8 sub = *((CARD8 *) (&bios->data[offset + 1]));
997 if (iexec->execute) {
998 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-SCRIPT: %d\n", offset, sub);
1000 parse_init_table(pScrn, bios,
1001 *((CARD16 *) (&bios->data[bios->init_tbls_offset + sub * 2])),
1004 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-SCRIPT\n", offset);
1009 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1011 /* INIT_RAM_CONDITION opcode: 0x6D
1013 * offset (8 bit): opcode
1014 * offset + 1 (8 bit): and mask
1015 * offset + 2 (8 bit): cmpval
1017 * Test if (NV_PFB_BOOT & and mask) matches cmpval
1019 NVPtr pNv = NVPTR(pScrn);
1020 CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
1021 CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
1024 if (iexec->execute) {
1025 data=(pNv->PFB[NV_PFB_BOOT/4])∧
1027 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1028 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1029 offset, data, cmpval);
1031 if (data == cmpval) {
1032 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1033 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1036 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1037 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1038 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1039 iexec->execute = FALSE;
1045 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1047 /* INIT_NV_REG opcode: 0x6E
1049 * offset (8 bit): opcode
1050 * offset + 1 (32 bit): register
1051 * offset + 5 (32 bit): and mask
1052 * offset + 9 (32 bit): or with
1054 * Assign "register" to (REGVAL(register) & "and mask") | "or with";
1057 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1058 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
1059 CARD32 or = *((CARD32 *) (&bios->data[offset + 9]));
1061 unsigned int status;
1063 if (iexec->execute) {
1065 if ((status = nv32_rd(pScrn, reg, &data))) {
1066 data = (data & and) | or;
1067 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1070 if (DEBUGLEVEL >= 6 && status) {
1072 nv32_rd(pScrn, reg, &tmpval);
1073 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1077 nv32_wr(pScrn, reg, data);
1078 /* Assign: reg = data */
1085 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1087 // FIXME replace with the haiku version
1088 /* XXX: Not sure this is correct... */
1090 CARD8 macro = *((CARD8 *) (&bios->data[offset + 1]));
1092 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE]));
1094 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE + 4]));
1096 if (iexec->execute) {
1097 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING MACRO: 0x%02X\n", offset, macro);
1098 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
1101 if (DEBUGLEVEL >= 6) {
1103 nv32_rd(pScrn, reg, &tmpval);
1104 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1108 nv32_wr(pScrn, reg, value);
1114 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1116 CARD8 index = *((CARD8 *) (&bios->data[offset + 1]));
1117 CARD32 tmp = bios->macro_index_offset + (index << 1);
1118 CARD32 offs = *((CARD8 *) (&bios->data[tmp])) << 3;
1119 CARD32 nr = *((CARD8 *) (&bios->data[tmp + 1]));
1124 if (iexec->execute) {
1125 offs += bios->macro_offset;
1126 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: WRITE %d 32-BIT REGS:\n", offset, nr);
1128 for (i = 0; i < nr; i++) {
1129 reg = *((CARD32 *) (&bios->data[offs + (i << 3)]));
1130 data = *((CARD32 *) (&bios->data[offs + (i << 3) + 4]));
1132 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1135 if (DEBUGLEVEL >= 6) {
1137 nv32_rd(pScrn, reg, &tmpval);
1138 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1142 nv32_wr(pScrn, reg, data);
1148 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1153 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1155 if (!iexec->execute) {
1156 iexec->execute = TRUE;;
1157 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n",
1163 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1165 /* INIT_RAM_CONDITION2 opcode: 0x73
1167 * offset (8 bit): opcode
1168 * offset + 1 (8 bit): and mask
1169 * offset + 2 (8 bit): cmpval
1171 * Test if (NV_EXTDEV_BOOT & and mask) matches cmpval
1173 NVPtr pNv = NVPTR(pScrn);
1174 CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
1175 CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
1178 if (iexec->execute) {
1179 data=(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT))∧
1181 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1182 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1183 offset, data, cmpval);
1185 if (data == cmpval) {
1186 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1187 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1190 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1191 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1192 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1193 iexec->execute = FALSE;
1199 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1201 /* INIT_TIME opcode: 0x74
1203 * offset (8 bit): opcode
1204 * offset + 1 (16 bit): time
1206 * Sleep for "time" microseconds.
1209 CARD16 time = *((CARD16 *) (&bios->data[offset + 1]));
1211 if (iexec->execute) {
1212 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Sleeping for 0x%04X microseconds.\n",
1220 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1222 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
1225 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE]));
1228 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 4]));
1231 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 8]));
1234 if (iexec->execute) {
1235 if (nv32_rd(pScrn, reg, &data)) {
1238 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1239 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1240 offset, data, cmpval);
1242 if (data == cmpval) {
1243 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1244 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1247 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1248 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1249 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1250 iexec->execute = FALSE;
1257 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1259 /* INIT_INDEX_IO opcode: 0x78
1261 * offset (8 bit): opcode
1262 * offset + 1 (16 bit): CRTC reg
1263 * offset + 3 (8 bit): CRTC index
1264 * offset + 4 (8 bit): and mask
1265 * offset + 5 (8 bit): or with
1270 NVPtr pNv = NVPTR(pScrn);
1271 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
1272 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
1273 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
1274 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
1275 CARD8 or = *((CARD8 *) (&bios->data[offset + 5]));
1278 if (iexec->execute) {
1279 VGA_WR08(ptr,crtcreg, index);
1280 /* data at reg + 1 */
1281 data = (VGA_RD08(ptr, crtcreg + 1) & and) | or;
1283 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1284 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
1285 offset, crtcreg, index, data);
1286 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
1287 VGA_RD08(ptr, crtcreg + 1));
1289 #ifdef PERFORM_WRITE
1290 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,data);
1292 VGA_WR08(ptr,crtcreg + 1, data);
1298 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1300 /* INIT_ZM_REG opcode: 0x7A
1302 * offset (8 bit): opcode
1303 * offset + 1 (32 bit): register
1304 * offset + 5 (32 bit): value
1306 * Assign "register" to "value";
1309 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1310 CARD32 value = *((CARD32 *) (&bios->data[offset + 5]));
1312 if (iexec->execute) {
1313 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
1314 offset, reg, value);
1316 if (DEBUGLEVEL >= 6) {
1318 nv32_rd(pScrn, reg, &tmpval);
1319 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1322 nv32_wr(pScrn, reg, value);
1324 /* Assign: reg = value */
1329 static init_tbl_entry_t itbl_entry[] = {
1330 /* command name , id , length , offset , mult , command handler */
1331 { "INIT_PROG" , 0x31, 15 , 10 , 4 , init_prog },
1332 { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog },
1333 { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat },
1334 { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat },
1335 { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy },
1336 { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not },
1337 { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition },
1338 /* { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, x , x , x, , init_idx_addr_latched }, */
1339 { "INIT_IO_RESTRICT_PLL" , 0x4A, 43 , 0 , 0 , init_io_restrict_pll },
1340 { "INIT_PLL" , 0x4B, 9 , 0 , 0 , init_pll },
1341 /* { "INIT_I2C_BYTE" , 0x4C, x , x , x , init_i2c_byte }, */
1342 /* { "INIT_ZM_I2C_BYTE" , 0x4D, x , x , x , init_zm_i2c_byte }, */
1343 /* { "INIT_ZM_I2C" , 0x4E, x , x , x , init_zm_i2c }, */
1344 { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch },
1345 { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr },
1346 { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr },
1347 { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group },
1348 { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time },
1349 { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence },
1350 { "INIT_INDIRECT_REG" , 0x5A, 7 , 0 , 0 , init_indirect_reg },
1351 { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct },
1352 { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg },
1353 { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io },
1354 { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem },
1355 { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset },
1356 /* { "INIT_NEXT" , 0x66, x , x , x , init_next }, */
1357 /* { "INIT_NEXT" , 0x67, x , x , x , init_next }, */
1358 /* { "INIT_NEXT" , 0x68, x , x , x , init_next }, */
1359 { "INIT_INDEX_IO8" , 0x69, 5 , 0 , 0 , init_index_io8 },
1360 { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub },
1361 { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition },
1362 { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg },
1363 { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro },
1364 { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done },
1365 { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume },
1366 { "INIT_RAM_CONDITION2" , 0x73, 9 , 0 , 0 , init_ram_condition2 },
1367 { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time },
1368 { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition },
1369 /* { "INIT_IO_CONDITION", , 0x76, x , x, , x , init_io_condition }, */
1370 { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io },
1371 /* { "INIT_PLL2" , 0x79, x , x , x , init_pll2 }, */
1372 { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg },
1373 /* { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, x , x , x , init_ram_restrict_zm_reg_group }, */
1374 /* { "INIT_COPY_ZM_REG" , 0x90, x , x , x , init_copy_zm_reg }, */
1375 /* { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, x , x , x , init_zm_reg_group_addr_latched }, */
1376 /* { "INIT_RESERVED" , 0x92, x , x , x , init_reserved }, */
1377 { 0 , 0 , 0 , 0 , 0 , 0 }
1380 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
1382 /* Calculates the length of a given init table entry. */
1383 return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
1386 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
1388 /* Parses all commands in a init table. */
1390 /* We start out executing all commands found in the
1391 * init table. Some op codes may change the status
1392 * of this variable to SKIP, which will cause
1393 * the following op codes to perform no operation until
1394 * the value is changed back to EXECUTE.
1400 /* Loop as long as INIT_DONE (command id 0x71) has not been found
1401 * (and offset < bios length just in case... )
1402 * (and no more than 10000 iterations just in case... ) */
1403 while (((id = bios->data[offset]) != 0x71) && (offset < bios->length) && (count++<10000)) {
1404 /* Find matching id in itbl_entry */
1405 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
1408 if (itbl_entry[i].name) {
1409 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ (0x%02X) - %s ]\n", offset,
1410 itbl_entry[i].id, itbl_entry[i].name);
1412 /* execute eventual command handler */
1413 if (itbl_entry[i].handler)
1414 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
1417 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Init table command not found: 0x%02X\n",
1421 /* Add the offset of the current command including all data
1422 * of that command. The offset will then be pointing on the
1425 offset += get_init_table_entry_length(bios, offset, i);
1429 void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios)
1431 /* Loops and calls parse_init_table() for each present table. */
1435 init_exec_t iexec = {TRUE, FALSE};
1437 while (table = *((CARD16 *) (&bios->data[bios->init_tbls_offset + i]))) {
1439 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing init table %d\n",
1442 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",table);
1444 parse_init_table(pScrn, bios, table, &iexec);
1449 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
1451 /* Parses the init table segment that the bit entry points to.
1452 * Starting at bitentry->offset:
1454 * offset + 0 (16 bits): offset of init tables
1455 * offset + 2 (16 bits): macro index table offset
1456 * offset + 4 (16 bits): macro offset
1457 * offset + 6 (16 bits): condition offset
1458 * offset + 8 (16 bits): io flag condition offset (?)
1459 * offset + 10 (16 bits): io flag condition offset (?)
1460 * offset + 12 (16 bits): unknown
1462 * offset + 8 and offset + 10 seems to contain the same
1463 * offsets on all bioses i have checked. Don't know which
1464 * one is the correct, therefore this code will bail out
1465 * if the two values are not the same.
1468 * * In addition to "conditions" and "io flag conditions" there seems to be
1469 * "io conditions". These are probably located at offset + (8, 10 or 12).
1470 * We need more BIOS dumps to figure this out...
1472 * * Are 'I' bit entries always of length 0xE?
1476 if (bitentry->length < 12) {
1477 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to regocnize BIT init table entry.\n");
1481 bios->init_tbls_offset = *((CARD16 *) (&bios->data[bitentry->offset]));
1482 bios->macro_index_offset = *((CARD16 *) (&bios->data[bitentry->offset + 2]));
1483 bios->macro_offset = *((CARD16 *) (&bios->data[bitentry->offset + 4]));
1484 bios->condition_offset =
1485 *((CARD16 *) (&bios->data[bitentry->offset + 6]));
1486 if (*((CARD16 *) (&bios->data[bitentry->offset + 8])) !=
1487 *((CARD16 *) (&bios->data[bitentry->offset + 10]))) {
1488 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to find IO flag condition offset.\n");
1492 bios->io_flag_condition_offset =
1493 *((CARD16 *) (&bios->data[bitentry->offset + 8]));
1495 parse_init_tables(pScrn, bios);
1500 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1502 bit_entry_t *bitentry;
1506 bitentry = (bit_entry_t *) &bios->data[offset];
1508 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Found BIT command with id 0x%02X\n",
1509 offset, bitentry->id[0]);
1511 switch (bitentry->id[0]) {
1513 /* id[0] = 0 and id[1] = 0 ==> end of BIT struture */
1514 if (bitentry->id[1] == 0)
1518 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1519 "0x%04X: Found init table entry in BIT structure.\n",
1522 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1523 /*parse_init_tables(pScrn, bios);*/
1526 /* TODO: What kind of information does the other BIT entrys point to?
1527 * 'P' entry is probably performance tables, but there are
1528 * quite a few others...
1532 offset += sizeof(bit_entry_t);
1536 static void parse_pins_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1538 int pins_version_major=bios->data[offset+5];
1539 int pins_version_minor=bios->data[offset+6];
1540 int init1 = bios->data[offset + 18] + (bios->data[offset + 19] * 256);
1541 int init2 = bios->data[offset + 20] + (bios->data[offset + 21] * 256);
1542 int init_size = bios->data[offset + 22] + (bios->data[offset + 23] * 256) + 1;
1545 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PINS version %d.%d\n",pins_version_major,pins_version_minor);
1548 if (pins_version_major==2)
1549 ram_tab = init1-0x0010;
1551 ram_tab = bios->data[offset + 24] + (bios->data[offset + 25] * 256);
1553 if ((pins_version_major==5)&&(pins_version_minor>=6))
1555 /* VCO range info */
1558 if ((pins_version_major==5)&&(pins_version_minor>=16))
1563 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1568 static unsigned int findstr(bios_t* bios, unsigned char *str, int len)
1572 for (i = 2; i < bios->length; i++)
1573 if (strncmp(&bios->data[i], str, len) == 0)
1580 #define G5_FIXED_LOC 0xe2f8
1582 static unsigned int nv_find_dcb_table(ScrnInfoPtr pScrn, bios_t *bios)
1584 NVPtr pNv = NVPTR(pScrn);
1589 unsigned char headerSize, entries;
1592 int sig_offsets[2] = { 0x4, 0x6 };
1594 CARD32 tmp_dcb_table[NV40_NUM_DCB_ENTRIES];
1595 uint32_t counter, port;
1597 /* get the offset from 0x36 */
1599 bufloc = *(CARD16 *)&bios->data[0x36];
1601 if (bufloc == 0x0) {
1602 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV43) {
1604 bufloc = G5_FIXED_LOC;
1610 table2 = &bios->data[bufloc];
1612 /* lets play hunt the signature */
1613 for (i = 0; i < sizeof(sig_offsets) / sizeof(int); i++) {
1614 sig = *(uint32_t*)(table2 + sig_offsets[i]);
1615 if ((sig == 0x4edcbdcb) || (sig == 0xcbbddc4e)) {
1616 offset = sig_offsets[i];
1624 header_word = *(uint32_t *)table2;
1629 headerSize = (header_word >> 8) & 0xff;
1630 entries = (header_word >> 16) & 0xff;
1637 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1638 "DCB size is %02X, entries is %02X\n", headerSize, entries);
1639 if (entries >= NV40_NUM_DCB_ENTRIES)
1640 entries = NV40_NUM_DCB_ENTRIES;
1642 for (i = 0; i < entries; i++) {
1644 tmp_dcb_table[i] = __bswap_32(*(uint32_t *)&table2[headerSize + 8 * i]);
1646 tmp_dcb_table[i] = *(uint32_t *)&table2[headerSize + 8 * i];
1650 /* There is an issue with NV4x cards, that the ordering of i2c buses and other things is strange */
1651 /* Fixing the table to look like earlier cards, with port 1 first is the best solution */
1652 if (pNv->Architecture == NV_ARCH_40) {
1653 for (i = 0; i < entries; i++) {
1654 port = (tmp_dcb_table[i] >> 4) & 0xf;
1655 /* We want port 0 first */
1657 /* We want to label this as port 1 */
1658 pNv->dcb_table[counter] = (tmp_dcb_table[i] & ~(0xf << 4)) | (1 << 4);
1662 for (i = 0; i < entries; i++) {
1663 port = (tmp_dcb_table[i] >> 4) & 0xf;
1666 /* We want to label this as port 0 */
1667 pNv->dcb_table[counter] = (tmp_dcb_table[i] & ~(0xf << 4)) | (0 << 4);
1671 for (i = 0; i < entries; i++) {
1672 port = (tmp_dcb_table[i] >> 4) & 0xf;
1673 /* Are there more ports than 2? */
1675 pNv->dcb_table[counter] = tmp_dcb_table[i];
1680 for (i = 0; i < entries; i++) {
1681 pNv->dcb_table[i] = tmp_dcb_table[i];
1688 unsigned int NVParseBios(ScrnInfoPtr pScrn)
1690 unsigned int bit_offset;
1693 bios.length=NV_PROM_SIZE;
1694 unsigned char nv_signature[]={0xff,0x7f,'N','V',0x0};
1695 unsigned char bit_signature[]={'B','I','T'};
1700 pNv->VBIOS = xalloc(64 * 1024);
1701 if (!NVShadowVBIOS(pScrn, pNv->VBIOS)) {
1702 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1703 "No valid BIOS image found.\n");
1707 bios.data = (unsigned char *)pNv->VBIOS;
1709 /* check for known signatures */
1710 if ((bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature)))) {
1711 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT signature found.\n");
1712 parse_bit_structure(pScrn, &bios, bit_offset + 4);
1713 } else if ((bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature)))) {
1714 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV signature found.\n");
1715 parse_pins_structure(pScrn, &bios, bit_offset);
1717 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No known script signature found.\n");
1720 /* look for NV40+ DCB table - and make a copy somewhere for
1723 ret = nv_find_dcb_table(pScrn, &bios);
1725 pNv->dcb_entries = ret;
1726 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1727 "DCB found %d entries.\n", ret);
1729 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DCB table found\n");