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*/
44 CARD16 init_tbls_offset;
45 CARD16 macro_index_offset;
47 CARD16 condition_offset;
48 CARD16 io_flag_condition_offset;
57 int length_multiplier;
58 Bool (*handler)(ScrnInfoPtr pScrn, bios_t *, CARD16, init_exec_t *);
63 unsigned short length;
64 unsigned short offset;
67 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec);
69 /* #define MACRO_SIZE 8 */
70 #define CONDITION_SIZE 12
71 #define IO_FLAG_CONDITION_SIZE 9
79 static int nv_valid_reg(CARD32 reg)
81 #define WITHIN(x,y,z) ((x>=y)&&(x<y+z))
82 if (WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
84 if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE))
86 if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE))
88 if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
90 if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
92 if (WITHIN(reg,NV_PGRAPH_OFFSET,NV_PGRAPH_SIZE))
94 if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
96 if (WITHIN(reg,NV_PTIMER_OFFSET,NV_PTIMER_SIZE))
98 if (WITHIN(reg,NV_PVIDEO_OFFSET,NV_PVIDEO_SIZE))
100 if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
102 if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
104 if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
106 if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
108 if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
110 if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
116 static int nv32_rd(ScrnInfoPtr pScrn, CARD32 reg, CARD32 *data)
118 NVPtr pNv = NVPTR(pScrn);
119 *data=pNv->REGS[reg/4];
123 static int nv32_wr(ScrnInfoPtr pScrn, CARD32 reg, CARD32 data)
126 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv32_wr reg 0x%X value 0x%X\n",reg,data);
128 if (!nv_valid_reg(reg))
130 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "========= unknown reg 0x%X ==========\n",reg);
134 NVPtr pNv = NVPTR(pScrn);
135 pNv->REGS[reg/4]=data;
140 void nv_set_crtc_index(ScrnInfoPtr pScrn, CARD8 index)
143 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_set_crtc_index index 0x%X\n",index);
145 NVPtr pNv = NVPTR(pScrn);
146 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
147 VGA_WR08(ptr, 0x3D4, index);
151 CARD8 nv_rd_crtc_data(ScrnInfoPtr pScrn)
153 NVPtr pNv = NVPTR(pScrn);
154 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
155 return VGA_RD08(ptr, 0x3D5);
158 void nv_wr_crtc_data(ScrnInfoPtr pScrn, CARD8 val)
161 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_wr_crtc_data value 0x%X\n",val);
163 NVPtr pNv = NVPTR(pScrn);
164 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
165 VGA_WR08(ptr, 0x3D5, val);
169 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
171 /* INIT_PROG opcode: 0x31
173 * offset (8 bit): opcode
174 * offset + 1 (32 bit): reg
175 * offset + 5 (32 bit): and mask
176 * offset + 9 (8 bit): shift right
177 * offset + 10 (8 bit): number of configurations
178 * offset + 11 (32 bit): register
179 * offset + 15 (32 bit): configuration 1
182 * Starting at offset + 15 there are "number of configurations"
183 * 32 bit values. To find out which configuration value to use
184 * read "CRTC reg" on the CRTC controller with index "CRTC index"
185 * and bitwise AND this value with "and mask" and then bit shift the
186 * result "shift right" bits to the right.
187 * Assign "register" with appropriate configuration value.
190 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
191 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
192 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
193 CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
194 CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
196 CARD32 configval, tmp;
198 if (iexec->execute) {
199 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%04X\n", offset,
202 nv32_rd(pScrn, reg, &tmp);
203 configuration = (tmp & and) >> shiftr;
205 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
206 offset, configuration);
208 if (configuration <= nr) {
211 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
213 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
216 if (nv32_rd(pScrn, reg2, &tmp)) {
217 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
220 nv32_wr(pScrn, reg2, configval);
226 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
228 /* INIT_IO_RESTRICT_PROG opcode: 0x32
230 * offset (8 bit): opcode
231 * offset + 1 (16 bit): CRTC reg
232 * offset + 3 (8 bit): CRTC index
233 * offset + 4 (8 bit): and mask
234 * offset + 5 (8 bit): shift right
235 * offset + 6 (8 bit): number of configurations
236 * offset + 7 (32 bit): register
237 * offset + 11 (32 bit): configuration 1
240 * Starting at offset + 11 there are "number of configurations"
241 * 32 bit values. To find out which configuration value to use
242 * read "CRTC reg" on the CRTC controller with index "CRTC index"
243 * and bitwise AND this value with "and mask" and then bit shift the
244 * result "shift right" bits to the right.
245 * Assign "register" with appropriate configuration value.
248 NVPtr pNv = NVPTR(pScrn);
249 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
250 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
251 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
252 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
253 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
254 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
255 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
257 CARD32 configval, tmp;
259 if (iexec->execute) {
260 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
263 VGA_WR08(ptr,crtcreg, index);
264 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
266 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
267 offset, configuration);
269 if (configuration <= nr) {
271 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
273 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
276 if (nv32_rd(pScrn, reg, &tmp)) {
277 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
280 nv32_wr(pScrn, reg, configval);
286 static Bool init_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
288 CARD8 repeats = *((CARD8 *) (&bios->data[offset + 1]));
291 if (iexec->execute) {
292 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REPEATING FOLLOWING SEGMENT %d TIMES.\n",
295 iexec->repeat = TRUE;
297 for (i = 0; i < repeats - 1; i++)
298 parse_init_table(pScrn, bios, offset + 2, iexec);
300 iexec->repeat = FALSE;
305 static Bool init_end_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
313 static Bool init_copy(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
315 /* XXX: double check this... */
316 NVPtr pNv = NVPTR(pScrn);
317 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
318 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
319 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
320 CARD8 and1 = *((CARD8 *) (&bios->data[offset + 6]));
321 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 7]));
322 CARD8 index = *((CARD8 *) (&bios->data[offset + 9]));
323 CARD8 and2 = *((CARD8 *) (&bios->data[offset + 10]));
327 if (iexec->execute) {
328 if (nv32_rd(pScrn, reg, &data)) {
332 data <<= (0x100 - shift);
335 VGA_WR08(ptr,crtcreg, index);
336 crtcdata = (VGA_RD08(ptr, crtcreg + 1) & and2) | (CARD8) data;
338 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
339 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n"
340 , offset, crtcreg, index, crtcdata);
342 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
343 VGA_RD08(ptr, crtcreg + 1));
345 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_copy crtcreg 0x%X value 0x%X\n",crtcreg+1,crtcdata);
347 printf("WRITE IS PERFORMED\n");
348 VGA_WR08(ptr,crtcreg + 1, crtcdata);
355 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
357 if (iexec->execute) {
358 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n",
361 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",
365 iexec->execute = !iexec->execute;
369 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
371 NVPtr pNv = NVPTR(pScrn);
372 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
373 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
374 CARD16 crtcreg = *((CARD16 *)
375 (&bios->data[bios->io_flag_condition_offset +
376 cond * IO_FLAG_CONDITION_SIZE]));
377 CARD8 index = *((CARD8 *)
378 (&bios->data[bios->io_flag_condition_offset +
379 cond * IO_FLAG_CONDITION_SIZE + 2]));
380 CARD8 and1 = *((CARD8 *)
381 (&bios->data[bios->io_flag_condition_offset +
382 cond * IO_FLAG_CONDITION_SIZE + 3]));
383 CARD8 shift = *((CARD8 *)
384 (&bios->data[bios->io_flag_condition_offset +
385 cond * IO_FLAG_CONDITION_SIZE + 4]));
386 CARD16 offs = *((CARD16 *)
387 (&bios->data[bios->io_flag_condition_offset +
388 cond * IO_FLAG_CONDITION_SIZE + 5]));
389 CARD8 and2 = *((CARD8 *)
390 (&bios->data[bios->io_flag_condition_offset +
391 cond * IO_FLAG_CONDITION_SIZE + 7]));
392 CARD8 cmpval = *((CARD8 *)
393 (&bios->data[bios->io_flag_condition_offset +
394 cond * IO_FLAG_CONDITION_SIZE + 8]));
398 if (iexec->execute) {
399 VGA_WR08(ptr,crtcreg, index);
400 data = VGA_RD08(ptr, crtcreg + 1);
402 offs += (data >> shift);
403 data = *((CARD8 *) (&bios->data[offs]));
406 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
407 "0x%04X: CHECKING IF DATA: %02X equals COND: %02X\n", offset,
410 if (data == cmpval) {
411 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
412 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
415 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
416 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
417 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
418 iexec->execute = FALSE;
424 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
426 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
427 /* XXX: this needs to be confirmed... NOT CORRECT */
428 /*init_io_restrict_prog(bios, offset, iexec);*/
430 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
431 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
432 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
433 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
434 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
435 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
437 CARD32 configval, tmp;
439 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
440 crtcreg, index, reg);
442 VGA_WR08(ptr,crtcreg, index);
443 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
445 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
446 offset, configuration);
448 if (configuration <= nr) {
450 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &configval))
451 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
455 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
457 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
463 if (iexec->execute) {
466 configval = 0x01014E07;
469 configval = 0x13030E02;
473 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
476 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
477 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
480 nv32_wr(pScrn, reg, configval);
486 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
488 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
489 CARD32 val = *((CARD32 *) (&bios->data[offset + 5]));
490 CARD32 configval, tmp;
492 if (iexec->execute) {
495 configval = 0x00011F05;
499 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
502 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
503 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
506 nv32_wr(pScrn, reg, configval);
508 /*xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);*/
514 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
516 CARD8 crtcindex = *((CARD8 *) (&bios->data[offset + 1]));
517 CARD8 crtcdata = *((CARD8 *) (&bios->data[offset + 2]));
518 CARD8 initial_index = *((CARD8 *) (&bios->data[offset + 3]));
519 CARD8 entries = *((CARD8 *) (&bios->data[offset + 4]));
523 if (iexec->execute) {
524 for (i = 0; i < entries; i++) {
525 nv_set_crtc_index(pScrn, crtcindex);
527 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
528 crtcindex, initial_index + i);
530 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
531 nv_rd_crtc_data(pScrn));
533 nv_wr_crtc_data(pScrn, initial_index + i);
535 nv_set_crtc_index(pScrn, crtcdata);
537 data = *((CARD8 *) (&bios->data[offset + 5 + i]));
539 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
542 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
543 nv_rd_crtc_data(pScrn));
545 nv_wr_crtc_data(pScrn, data);
551 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
553 /* XXX: IS THIS CORRECT? check the typecast .. probably wrong */
555 NVPtr pNv = NVPTR(pScrn);
556 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
557 CARD8 and = *((CARD8 *) (&bios->data[offset + 2]));
558 CARD8 or = *((CARD8 *) (&bios->data[offset + 3]));
561 if (iexec->execute) {
562 nv_set_crtc_index(pScrn, index);
563 data = (nv_rd_crtc_data(pScrn) & and) | or;
564 /*printf("and: 0x%02x or: 0x%02x\n", and, or);*/
565 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
568 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
569 nv_rd_crtc_data(pScrn));
571 nv_wr_crtc_data(pScrn, data);
576 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
578 /* INIT_ZM_CR opcode: 0x53
580 * offset (8 bit): opcode
581 * offset + 1 (8 bit): CRTC index
582 * offset + 2 (8 bit): value
584 * Assign "value" to CRTC register with index "CRTC index".
587 NVPtr pNv = NVPTR(pScrn);
588 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
589 CARD8 value = *((CARD8 *) (&bios->data[offset + 2]));
591 if (iexec->execute) {
592 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
595 nv_set_crtc_index(pScrn, index);
597 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
598 nv_rd_crtc_data(pScrn));
600 nv_wr_crtc_data(pScrn, value);
605 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
607 /* INIT_ZM_CR opcode: 0x54
609 * offset (8 bit): opcode
610 * offset + 1 (8 bit): number of groups (index, value)
611 * offset + 2 (8 bit): index 1
612 * offset + 3 (8 bit): value 1
615 * Assign "value n" to CRTC register with index "index n".
618 CARD8 nr = *((CARD8 *) (&bios->data[offset + 1]));
622 if (iexec->execute) {
623 for (i = 0; i < nr; i++) {
624 index = *((CARD8 *) (&bios->data[offset + 2 + 2 * i]));
625 value = *((CARD8 *) (&bios->data[offset + 2 + 2 * i + 1]));
627 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
630 nv_set_crtc_index(pScrn, index);
632 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
633 nv_rd_crtc_data(pScrn));
634 nv_wr_crtc_data(pScrn, value);
640 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
642 /* My BIOS does not use this command. */
643 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
648 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
650 /* INIT_ZM_REG_SEQUENCE opcode: 0x58
652 * offset (8 bit): opcode
653 * offset + 1 (32 bit): register base
654 * offset + 5 (8 bit): nr
655 * offset + 6 (32 bit): value to assign "register base" + 4
658 * Initialzies a sequence of "nr" registers starting at "register base".
661 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
662 CARD32 nr = *((CARD8 *) (&bios->data[offset + 5]));
667 if (iexec->execute) {
668 for (i = 0; i < nr; i++) {
669 data = *((CARD32 *) (&bios->data[offset + 6 + i * 4]));
670 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
673 if (nv32_rd(pScrn, reg + i * 4, &tmp)) {
674 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
678 nv32_wr(pScrn, reg + i * 4, data);
684 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
686 /* INIT_INDIRECT_REG opcode: 0x5A
688 * offset (8 bit): opcode
689 * offset + 1 (32 bit): register
690 * offset + 5 (16 bit): adress offset (in bios)
692 * Lookup value at offset data in the bios and write it to reg
694 NVPtr pNv = NVPTR(pScrn);
695 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
696 CARD32 data = *((CARD16 *) (&bios->data[offset + 5]));
697 CARD32 data2 = bios->data[data];
699 if (iexec->execute) {
700 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
701 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n",
702 offset, reg, data, data2);
704 if (DEBUGLEVEL >= 6) {
706 nv32_rd(pScrn, reg, &tmpval);
707 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
710 nv32_wr(pScrn, reg, data2);
715 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
717 /* INIT_SUB_DIRECT opcode: 0x5B
719 * offset (8 bit): opcode
720 * offset + 1 (16 bit): subroutine offset (in bios)
722 * Calls a subroutine that will execute commands until INIT_DONE
726 CARD16 sub_offset = *((CARD16 *) (&bios->data[offset + 1]));
728 if (iexec->execute) {
729 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-ROUTINE AT: 0x%04X\n",
732 parse_init_table(pScrn, bios, sub_offset, iexec);
734 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-ROUTINE\n", offset);
739 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
741 CARD32 srcreg = *((CARD32 *) (&bios->data[offset + 1]));
742 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
743 CARD32 and1 = *((CARD32 *) (&bios->data[offset + 6]));
744 CARD32 xor = *((CARD32 *) (&bios->data[offset + 10]));
745 CARD32 dstreg = *((CARD32 *) (&bios->data[offset + 14]));
746 CARD32 and2 = *((CARD32 *) (&bios->data[offset + 18]));
750 if (iexec->execute) {
751 nv32_rd(pScrn, srcreg, &srcdata);
758 srcdata = (srcdata & and1) ^ xor;
760 nv32_rd(pScrn, dstreg, &dstdata);
766 nv32_rd(pScrn, dstreg, &tmp);
768 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, dstreg,
771 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmp);
773 nv32_wr(pScrn, dstreg, dstdata);
778 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
780 NVPtr pNv = NVPTR(pScrn);
781 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
782 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
783 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
784 CARD8 value = *((CARD8 *) (&bios->data[offset + 4]));
786 if (iexec->execute) {
787 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
788 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
789 offset, crtcreg, index, value);
791 VGA_WR08(ptr,crtcreg, index);
793 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
794 VGA_RD08(ptr, crtcreg + 1));
797 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_zm_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,value);
799 VGA_WR08(ptr,crtcreg + 1, value);
805 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
807 // FIXME replace with a suitable implementation
809 CARD16 ramcfg = *((CARD16 *) (&bios->data[bios->ram_table_offset]));
814 if (iexec->execute) {
815 nv32_rd(pScrn, 0x00101000, &strapinfo);
816 nv32_rd(pScrn, 0x00100080, &pfb_debug);
818 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
819 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
820 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG: 0x%04X\n", ramcfg);
822 pfb_debug &= 0xffffffef;
824 strapinfo &= 0x0000000f;
825 ramcfg2 = *((CARD16 *)
826 (&bios->data[bios->ram_table_offset + (2 * strapinfo)]));
828 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AFTER MANIPULATION\n");
829 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
830 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
831 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG2: 0x%08X\n", ramcfg2);
833 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
838 nv32_rd(pScrn, 0x00100200, ®1);
839 nv32_rd(pScrn, 0x0010020C, ®2);
841 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x00100200: 0x%08X\n", reg1);
842 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x0010020C: 0x%08X\n", reg2);
848 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
850 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
851 CARD32 value1 = *((CARD32 *) (&bios->data[offset + 5]));
852 CARD32 value2 = *((CARD32 *) (&bios->data[offset + 9]));
854 if (iexec->execute) {
855 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
856 offset, reg, value1);
857 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
858 offset, reg, value2);
860 if (DEBUGLEVEL >= 6) {
862 nv32_rd(pScrn, reg, &tmpval);
863 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
865 nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), &tmpval);
866 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: PCICFG_ROMSHADOW: 0x%02X\n", offset, tmpval);
869 nv32_wr(pScrn, reg, value1);
870 nv32_wr(pScrn, reg, value2);
872 /* PCI Config space init needs to be added here. */
873 /* if (nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), value1)) */
874 /* nv32_wr(pScrn, PCICFG(PCICFG_ROMSHADOW), value1 & 0xfffffffe) */
879 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
881 /* INIT_INDEX_IO8 opcode: 0x69
883 * offset (8 bit): opcode
884 * offset + 1 (16 bit): CRTC reg
885 * offset + 3 (8 bit): and mask
886 * offset + 4 (8 bit): or with
891 NVPtr pNv = NVPTR(pScrn);
892 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
893 CARD16 reg = *((CARD16 *) (&bios->data[offset + 1]));
894 CARD8 and = *((CARD8 *) (&bios->data[offset + 3]));
895 CARD8 or = *((CARD8 *) (&bios->data[offset + 4]));
898 if (iexec->execute) {
899 data = (VGA_RD08(ptr, reg) & and) | or;
901 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
902 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n",
904 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
908 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
910 VGA_WR08(ptr, reg, data);
916 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
918 CARD8 sub = *((CARD8 *) (&bios->data[offset + 1]));
920 if (iexec->execute) {
921 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-SCRIPT: %d\n", offset, sub);
923 parse_init_table(pScrn, bios,
924 *((CARD16 *) (&bios->data[bios->init_tbls_offset + sub * 2])),
927 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-SCRIPT\n", offset);
932 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
934 /* INIT_RAM_CONDITION opcode: 0x6D
936 * offset (8 bit): opcode
937 * offset + 1 (8 bit): and mask
938 * offset + 2 (8 bit): cmpval
940 * Test if (NV_PFB_BOOT & and mask) matches cmpval
942 NVPtr pNv = NVPTR(pScrn);
943 CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
944 CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
947 if (iexec->execute) {
948 data=(pNv->PFB[NV_PFB_BOOT/4])∧
950 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
951 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
952 offset, data, cmpval);
954 if (data == cmpval) {
955 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
956 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
959 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
960 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
961 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
962 iexec->execute = FALSE;
968 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
970 /* INIT_NV_REG opcode: 0x6E
972 * offset (8 bit): opcode
973 * offset + 1 (32 bit): register
974 * offset + 5 (32 bit): and mask
975 * offset + 9 (32 bit): or with
977 * Assign "register" to (REGVAL(register) & "and mask") | "or with";
980 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
981 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
982 CARD32 or = *((CARD32 *) (&bios->data[offset + 9]));
986 if (iexec->execute) {
988 if ((status = nv32_rd(pScrn, reg, &data))) {
989 data = (data & and) | or;
990 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
993 if (DEBUGLEVEL >= 6 && status) {
995 nv32_rd(pScrn, reg, &tmpval);
996 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1000 nv32_wr(pScrn, reg, data);
1001 /* Assign: reg = data */
1008 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1010 // FIXME replace with the haiku version
1011 /* XXX: Not sure this is correct... */
1013 CARD8 macro = *((CARD8 *) (&bios->data[offset + 1]));
1015 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE]));
1017 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE + 4]));
1019 if (iexec->execute) {
1020 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING MACRO: 0x%02X\n", offset, macro);
1021 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
1024 if (DEBUGLEVEL >= 6) {
1026 nv32_rd(pScrn, reg, &tmpval);
1027 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1031 nv32_wr(pScrn, reg, value);
1037 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1039 CARD8 index = *((CARD8 *) (&bios->data[offset + 1]));
1040 CARD32 tmp = bios->macro_index_offset + (index << 1);
1041 CARD32 offs = *((CARD8 *) (&bios->data[tmp])) << 3;
1042 CARD32 nr = *((CARD8 *) (&bios->data[tmp + 1]));
1047 if (iexec->execute) {
1048 offs += bios->macro_offset;
1049 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: WRITE %d 32-BIT REGS:\n", offset, nr);
1051 for (i = 0; i < nr; i++) {
1052 reg = *((CARD32 *) (&bios->data[offs + (i << 3)]));
1053 data = *((CARD32 *) (&bios->data[offs + (i << 3) + 4]));
1055 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1058 if (DEBUGLEVEL >= 6) {
1060 nv32_rd(pScrn, reg, &tmpval);
1061 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1065 nv32_wr(pScrn, reg, data);
1071 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1076 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1078 if (!iexec->execute) {
1079 iexec->execute = TRUE;;
1080 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n",
1086 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1088 /* INIT_RAM_CONDITION2 opcode: 0x73
1090 * offset (8 bit): opcode
1091 * offset + 1 (8 bit): and mask
1092 * offset + 2 (8 bit): cmpval
1094 * Test if (NV_EXTDEV_BOOT & and mask) matches cmpval
1096 NVPtr pNv = NVPTR(pScrn);
1097 CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
1098 CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
1101 if (iexec->execute) {
1102 data=(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT))∧
1104 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1105 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1106 offset, data, cmpval);
1108 if (data == cmpval) {
1109 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1110 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1113 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1114 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1115 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1116 iexec->execute = FALSE;
1122 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1124 /* INIT_TIME opcode: 0x74
1126 * offset (8 bit): opcode
1127 * offset + 1 (16 bit): time
1129 * Sleep for "time" microseconds.
1132 CARD16 time = *((CARD16 *) (&bios->data[offset + 1]));
1134 if (iexec->execute) {
1135 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Sleeping for 0x%04X microseconds.\n",
1143 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1145 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
1148 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE]));
1151 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 4]));
1154 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 8]));
1157 if (iexec->execute) {
1158 if (nv32_rd(pScrn, reg, &data)) {
1161 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1162 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1163 offset, data, cmpval);
1165 if (data == cmpval) {
1166 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1167 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1170 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1171 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1172 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1173 iexec->execute = FALSE;
1180 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1182 /* INIT_INDEX_IO opcode: 0x78
1184 * offset (8 bit): opcode
1185 * offset + 1 (16 bit): CRTC reg
1186 * offset + 3 (8 bit): CRTC index
1187 * offset + 4 (8 bit): and mask
1188 * offset + 5 (8 bit): or with
1193 NVPtr pNv = NVPTR(pScrn);
1194 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
1195 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
1196 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
1197 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
1198 CARD8 or = *((CARD8 *) (&bios->data[offset + 5]));
1201 if (iexec->execute) {
1202 VGA_WR08(ptr,crtcreg, index);
1203 /* data at reg + 1 */
1204 data = (VGA_RD08(ptr, crtcreg + 1) & and) | or;
1206 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1207 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
1208 offset, crtcreg, index, data);
1209 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
1210 VGA_RD08(ptr, crtcreg + 1));
1212 #ifdef PERFORM_WRITE
1213 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,data);
1215 VGA_WR08(ptr,crtcreg + 1, data);
1221 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1223 /* INIT_ZM_REG opcode: 0x7A
1225 * offset (8 bit): opcode
1226 * offset + 1 (32 bit): register
1227 * offset + 5 (32 bit): value
1229 * Assign "register" to "value";
1232 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1233 CARD32 value = *((CARD32 *) (&bios->data[offset + 5]));
1235 if (iexec->execute) {
1236 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
1237 offset, reg, value);
1239 if (DEBUGLEVEL >= 6) {
1241 nv32_rd(pScrn, reg, &tmpval);
1242 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1245 nv32_wr(pScrn, reg, value);
1247 /* Assign: reg = value */
1252 static init_tbl_entry_t itbl_entry[] = {
1253 /* command name , id , length , offset , mult , command handler */
1254 { "INIT_PROG" , 0x31, 15 , 10 , 4 , init_prog },
1255 { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog },
1256 { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat },
1257 { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat },
1258 { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy },
1259 { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not },
1260 { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition },
1261 /* { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, x , x , x, , init_idx_addr_latched }, */
1262 { "INIT_IO_RESTRICT_PLL" , 0x4A, 43 , 0 , 0 , init_io_restrict_pll },
1263 { "INIT_PLL" , 0x4B, 9 , 0 , 0 , init_pll },
1264 /* { "INIT_I2C_BYTE" , 0x4C, x , x , x , init_i2c_byte }, */
1265 /* { "INIT_ZM_I2C_BYTE" , 0x4D, x , x , x , init_zm_i2c_byte }, */
1266 /* { "INIT_ZM_I2C" , 0x4E, x , x , x , init_zm_i2c }, */
1267 { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch },
1268 { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr },
1269 { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr },
1270 { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group },
1271 { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time },
1272 { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence },
1273 { "INIT_INDIRECT_REG" , 0x5A, 7 , 0 , 0 , init_indirect_reg },
1274 { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct },
1275 { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg },
1276 { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io },
1277 { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem },
1278 { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset },
1279 /* { "INIT_NEXT" , 0x66, x , x , x , init_next }, */
1280 /* { "INIT_NEXT" , 0x67, x , x , x , init_next }, */
1281 /* { "INIT_NEXT" , 0x68, x , x , x , init_next }, */
1282 { "INIT_INDEX_IO8" , 0x69, 5 , 0 , 0 , init_index_io8 },
1283 { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub },
1284 { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition },
1285 { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg },
1286 { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro },
1287 { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done },
1288 { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume },
1289 { "INIT_RAM_CONDITION2" , 0x73, 9 , 0 , 0 , init_ram_condition2 },
1290 { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time },
1291 { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition },
1292 /* { "INIT_IO_CONDITION", , 0x76, x , x, , x , init_io_condition }, */
1293 { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io },
1294 /* { "INIT_PLL2" , 0x79, x , x , x , init_pll2 }, */
1295 { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg },
1296 /* { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, x , x , x , init_ram_restrict_zm_reg_group }, */
1297 /* { "INIT_COPY_ZM_REG" , 0x90, x , x , x , init_copy_zm_reg }, */
1298 /* { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, x , x , x , init_zm_reg_group_addr_latched }, */
1299 /* { "INIT_RESERVED" , 0x92, x , x , x , init_reserved }, */
1300 { 0 , 0 , 0 , 0 , 0 , 0 }
1303 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
1305 /* Calculates the length of a given init table entry. */
1306 return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
1309 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
1311 /* Parses all commands in a init table. */
1313 /* We start out executing all commands found in the
1314 * init table. Some op codes may change the status
1315 * of this variable to SKIP, which will cause
1316 * the following op codes to perform no operation until
1317 * the value is changed back to EXECUTE.
1323 /* Loop as long as INIT_DONE (command id 0x71) has not been found
1324 * (and offset < bios length just in case... )
1325 * (and no more than 10000 iterations just in case... ) */
1326 while (((id = bios->data[offset]) != 0x71) && (offset < bios->length) && (count++<10000)) {
1327 /* Find matching id in itbl_entry */
1328 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
1331 if (itbl_entry[i].name) {
1332 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ (0x%02X) - %s ]\n", offset,
1333 itbl_entry[i].id, itbl_entry[i].name);
1335 /* execute eventual command handler */
1336 if (itbl_entry[i].handler)
1337 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
1340 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Init table command not found: 0x%02X\n",
1344 /* Add the offset of the current command including all data
1345 * of that command. The offset will then be pointing on the
1348 offset += get_init_table_entry_length(bios, offset, i);
1352 void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios)
1354 /* Loops and calls parse_init_table() for each present table. */
1358 init_exec_t iexec = {TRUE, FALSE};
1360 while (table = *((CARD16 *) (&bios->data[bios->init_tbls_offset + i]))) {
1362 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing init table %d\n",
1365 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",table);
1367 parse_init_table(pScrn, bios, table, &iexec);
1372 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
1374 /* Parses the init table segment that the bit entry points to.
1375 * Starting at bitentry->offset:
1377 * offset + 0 (16 bits): offset of init tables
1378 * offset + 2 (16 bits): macro index table offset
1379 * offset + 4 (16 bits): macro offset
1380 * offset + 6 (16 bits): condition offset
1381 * offset + 8 (16 bits): io flag condition offset (?)
1382 * offset + 10 (16 bits): io flag condition offset (?)
1383 * offset + 12 (16 bits): unknown
1385 * offset + 8 and offset + 10 seems to contain the same
1386 * offsets on all bioses i have checked. Don't know which
1387 * one is the correct, therefore this code will bail out
1388 * if the two values are not the same.
1391 * * In addition to "conditions" and "io flag conditions" there seems to be
1392 * "io conditions". These are probably located at offset + (8, 10 or 12).
1393 * We need more BIOS dumps to figure this out...
1395 * * Are 'I' bit entries always of length 0xE?
1399 if (bitentry->length < 12) {
1400 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to regocnize BIT init table entry.\n");
1404 bios->init_tbls_offset = *((CARD16 *) (&bios->data[bitentry->offset]));
1405 bios->macro_index_offset = *((CARD16 *) (&bios->data[bitentry->offset + 2]));
1406 bios->macro_offset = *((CARD16 *) (&bios->data[bitentry->offset + 4]));
1407 bios->condition_offset =
1408 *((CARD16 *) (&bios->data[bitentry->offset + 6]));
1409 if (*((CARD16 *) (&bios->data[bitentry->offset + 8])) !=
1410 *((CARD16 *) (&bios->data[bitentry->offset + 10]))) {
1411 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to find IO flag condition offset.\n");
1415 bios->io_flag_condition_offset =
1416 *((CARD16 *) (&bios->data[bitentry->offset + 8]));
1418 parse_init_tables(pScrn, bios);
1423 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1425 bit_entry_t *bitentry;
1429 bitentry = (bit_entry_t *) &bios->data[offset];
1431 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Found BIT command with id 0x%02X\n",
1432 offset, bitentry->id[0]);
1434 switch (bitentry->id[0]) {
1436 /* id[0] = 0 and id[1] = 0 ==> end of BIT struture */
1437 if (bitentry->id[1] == 0)
1441 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1442 "0x%04X: Found init table entry in BIT structure.\n",
1445 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1446 /*parse_init_tables(pScrn, bios);*/
1449 /* TODO: What kind of information does the other BIT entrys point to?
1450 * 'P' entry is probably performance tables, but there are
1451 * quite a few others...
1455 offset += sizeof(bit_entry_t);
1459 static unsigned short brs(unsigned char *data, int offset)
1463 ret = (data[offset]) | ((data[offset+1]) << 8);
1467 static void parse_pins_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1469 int pins_version_major=bios->data[offset+5];
1470 int pins_version_minor=bios->data[offset+6];
1471 int init1 = bios->data[offset + 18] + (bios->data[offset + 19] * 256);
1472 int init2 = bios->data[offset + 20] + (bios->data[offset + 21] * 256);
1473 int init_size = bios->data[offset + 22] + (bios->data[offset + 23] * 256) + 1;
1475 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PINS version %d.%d\n",pins_version_major,pins_version_minor);
1478 if (pins_version_major==2)
1479 ram_tab = init1-0x0010;
1481 ram_tab = bios->data[offset + 24] + (bios->data[offset + 25] * 256);
1483 if ((pins_version_major==5)&&(pins_version_minor>=6))
1485 /* VCO range info */
1488 if ((pins_version_major==5)&&(pins_version_minor>=16))
1493 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1498 static unsigned int findstr(bios_t* bios, unsigned char *str, int len)
1502 for (i = 2; i < bios->length; i++)
1503 if (strncmp(&bios->data[i], str, len) == 0)
1509 #define G5_FIXED_LOC 0xe2f8
1512 static unsigned int nv_find_dcb_table(ScrnInfoPtr pScrn, bios_t *bios)
1514 NVPtr pNv = NVPTR(pScrn);
1519 unsigned char headerSize, entries;
1522 int sig_offsets[2] = { 0x4, 0x6 };
1525 /* get the offset from 0x36 */
1527 bufloc = *(CARD16 *)&bios->data[0x36];
1529 if (bufloc == 0x0) {
1530 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV43) {
1532 bufloc = G5_FIXED_LOC;
1538 table2 = &bios->data[bufloc];
1540 /* lets play hunt the signature */
1541 for (i = 0; i < sizeof(sig_offsets) / sizeof(int); i++) {
1542 sig = *(uint32_t*)(table2 + sig_offsets[i]);
1543 if ((sig == 0x4edcbdcb) || (sig == 0xcbbddc4e)) {
1544 offset = sig_offsets[i];
1552 header_word = *(uint32_t *)table2;
1557 headerSize = (header_word >> 8) & 0xff;
1558 entries = (header_word >> 16) & 0xff;
1565 ErrorF("DCB size is %02X, entries is %02X\n", headerSize, entries);
1566 if (entries >= NV40_NUM_DCB_ENTRIES)
1567 entries = NV40_NUM_DCB_ENTRIES;
1569 for (i = 0; i < entries; i++) {
1571 pNv->dcb_table[i] = __bswap_32(*(uint32_t *)&table2[headerSize + 8 * i]);
1573 pNv->dcb_table[i] = *(uint32_t *)&table2[headerSize + 8 * i];
1580 unsigned int NVParseBios(ScrnInfoPtr pScrn)
1582 unsigned int bit_offset;
1585 bios.length=NV_PROM_SIZE;
1586 unsigned char nv_signature[]={0xff,0x7f,'N','V',0x0};
1587 unsigned char bit_signature[]={'B','I','T'};
1592 bios.data=xalloc(NV_PROM_SIZE);
1594 /* enable ROM access */
1595 nvWriteMC(pNv, 0x1850, 0x0);
1596 for(i=0;i<NV_PROM_SIZE;i++)
1598 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
1599 bios.data[i]=pNv->PROM[i];
1600 bios.data[i]=pNv->PROM[i];
1601 bios.data[i]=pNv->PROM[i];
1602 bios.data[i]=pNv->PROM[i];
1603 bios.data[i]=pNv->PROM[i];
1605 /* disable ROM access */
1606 nvWriteMC(pNv, 0x1850, 0x1);
1608 /* check for BIOS signature */
1609 if (!(bios.data[0] == 0x55 && bios.data[1] == 0xAA)) {
1610 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS signature not found!\n");
1615 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS signature found.\n");
1617 /* check for known signatures */
1618 if (bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature))) {
1619 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT signature found.\n");
1620 parse_bit_structure(pScrn, &bios, bit_offset + 4);
1621 } else if (bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature))) {
1622 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV signature found.\n");
1623 parse_pins_structure(pScrn, &bios, bit_offset);
1625 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No known script signature found.\n");
1628 /* look for NV40+ DCB table - and make a copy somewhere for output setup code */
1629 ret = nv_find_dcb_table(pScrn, &bios);
1632 pNv->dcb_entries = ret;
1633 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DCB found %d entries.\n", ret);
1636 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DCB table found\n");