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*/
31 * * Fix indentation. Currently a mix between spaces and tabs.
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_PMC_OFFSET,NV_PMC_SIZE))
100 if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
102 if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
104 if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
106 if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
108 if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
114 static int nv32_rd(ScrnInfoPtr pScrn, CARD32 reg, CARD32 *data)
116 NVPtr pNv = NVPTR(pScrn);
117 *data=pNv->REGS[reg/4];
121 static int nv32_wr(ScrnInfoPtr pScrn, CARD32 reg, CARD32 data)
124 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv32_wr reg 0x%X value 0x%X\n",reg,data);
126 if (!nv_valid_reg(reg))
128 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "========= unknown reg 0x%X ==========\n",reg);
132 NVPtr pNv = NVPTR(pScrn);
133 pNv->REGS[reg/4]=data;
138 void nv_set_crtc_index(ScrnInfoPtr pScrn, CARD8 index)
141 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_set_crtc_index index 0x%X\n",index);
143 NVPtr pNv = NVPTR(pScrn);
144 VGA_WR08(pNv->PCIO, 0x3D4, index);
148 CARD8 nv_rd_crtc_data(ScrnInfoPtr pScrn)
150 NVPtr pNv = NVPTR(pScrn);
151 return VGA_RD08(pNv->PCIO, 0x3D5);
154 void nv_wr_crtc_data(ScrnInfoPtr pScrn, CARD8 val)
157 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_wr_crtc_data value 0x%X\n",val);
159 NVPtr pNv = NVPTR(pScrn);
160 VGA_WR08(pNv->PCIO, 0x3D5, val);
165 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
167 /* INIT_PROG opcode: 0x31
169 * offset (8 bit): opcode
170 * offset + 1 (32 bit): reg
171 * offset + 5 (32 bit): and mask
172 * offset + 9 (8 bit): shift right
173 * offset + 10 (8 bit): number of configurations
174 * offset + 11 (32 bit): register
175 * offset + 15 (32 bit): configuration 1
178 * Starting at offset + 15 there are "number of configurations"
179 * 32 bit values. To find out which configuration value to use
180 * read "CRTC reg" on the CRTC controller with index "CRTC index"
181 * and bitwise AND this value with "and mask" and then bit shift the
182 * result "shift right" bits to the right.
183 * Assign "register" with appropriate configuration value.
186 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
187 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
188 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
189 CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
190 CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
192 CARD32 configval, tmp;
194 if (iexec->execute) {
195 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%04X\n", offset,
198 nv32_rd(pScrn, reg, &tmp);
199 configuration = (tmp & and) >> shiftr;
201 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
202 offset, configuration);
204 if (configuration <= nr) {
208 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
210 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
213 if (nv32_rd(pScrn, reg2, &tmp)) {
214 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
217 nv32_wr(pScrn, reg2, configval);
223 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
225 /* INIT_IO_RESTRICT_PROG opcode: 0x32
227 * offset (8 bit): opcode
228 * offset + 1 (16 bit): CRTC reg
229 * offset + 3 (8 bit): CRTC index
230 * offset + 4 (8 bit): and mask
231 * offset + 5 (8 bit): shift right
232 * offset + 6 (8 bit): number of configurations
233 * offset + 7 (32 bit): register
234 * offset + 11 (32 bit): configuration 1
237 * Starting at offset + 11 there are "number of configurations"
238 * 32 bit values. To find out which configuration value to use
239 * read "CRTC reg" on the CRTC controller with index "CRTC index"
240 * and bitwise AND this value with "and mask" and then bit shift the
241 * result "shift right" bits to the right.
242 * Assign "register" with appropriate configuration value.
245 NVPtr pNv = NVPTR(pScrn);
246 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
247 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
248 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
249 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
250 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
251 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
253 CARD32 configval, tmp;
255 if (iexec->execute) {
256 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
259 VGA_WR08(pNv->PCIO,crtcreg, index);
260 configuration = (VGA_RD08(pNv->PCIO, crtcreg + 1) & and) >> shiftr;
262 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
263 offset, configuration);
265 if (configuration <= nr) {
269 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
271 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
274 if (nv32_rd(pScrn, reg, &tmp)) {
275 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
278 nv32_wr(pScrn, reg, configval);
284 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 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
318 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
319 CARD8 and1 = *((CARD8 *) (&bios->data[offset + 6]));
320 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 7]));
321 CARD8 index = *((CARD8 *) (&bios->data[offset + 9]));
322 CARD8 and2 = *((CARD8 *) (&bios->data[offset + 10]));
326 if (iexec->execute) {
327 if (nv32_rd(pScrn, reg, &data)) {
331 data <<= (0x100 - shift);
334 VGA_WR08(pNv->PCIO,crtcreg, index);
335 crtcdata = (VGA_RD08(pNv->PCIO, crtcreg + 1) & and2) | (CARD8) data;
337 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
338 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n"
339 , offset, crtcreg, index, crtcdata);
341 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
342 VGA_RD08(pNv->PCIO, crtcreg + 1));
344 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_copy crtcreg 0x%X value 0x%X\n",crtcreg+1,crtcdata);
346 printf("WRITE IS PERFORMED\n");
347 VGA_WR08(pNv->PCIO,crtcreg + 1, crtcdata);
354 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
356 if (iexec->execute) {
357 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n",
360 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",
364 iexec->execute = !iexec->execute;
368 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
370 NVPtr pNv = NVPTR(pScrn);
371 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
372 CARD16 crtcreg = *((CARD16 *)
373 (&bios->data[bios->io_flag_condition_offset +
374 cond * IO_FLAG_CONDITION_SIZE]));
375 CARD8 index = *((CARD8 *)
376 (&bios->data[bios->io_flag_condition_offset +
377 cond * IO_FLAG_CONDITION_SIZE + 2]));
378 CARD8 and1 = *((CARD8 *)
379 (&bios->data[bios->io_flag_condition_offset +
380 cond * IO_FLAG_CONDITION_SIZE + 3]));
381 CARD8 shift = *((CARD8 *)
382 (&bios->data[bios->io_flag_condition_offset +
383 cond * IO_FLAG_CONDITION_SIZE + 4]));
384 CARD16 offs = *((CARD16 *)
385 (&bios->data[bios->io_flag_condition_offset +
386 cond * IO_FLAG_CONDITION_SIZE + 5]));
387 CARD8 and2 = *((CARD8 *)
388 (&bios->data[bios->io_flag_condition_offset +
389 cond * IO_FLAG_CONDITION_SIZE + 7]));
390 CARD8 cmpval = *((CARD8 *)
391 (&bios->data[bios->io_flag_condition_offset +
392 cond * IO_FLAG_CONDITION_SIZE + 8]));
396 if (iexec->execute) {
398 VGA_WR08(pNv->PCIO,crtcreg, index);
399 data = VGA_RD08(pNv->PCIO, crtcreg + 1);
401 offs += (data >> shift);
402 data = *((CARD8 *) (&bios->data[offs]));
405 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
406 "0x%04X: CHECKING IF DATA: %02X equals COND: %02X\n", offset,
409 if (data == cmpval) {
410 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
411 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
414 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
415 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
416 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
417 iexec->execute = FALSE;
424 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
427 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
428 /* XXX: this needs to be confirmed... NOT CORRECT */
429 /*init_io_restrict_prog(bios, offset, iexec);*/
432 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
433 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
434 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
435 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
436 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
437 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
439 CARD32 configval, tmp;
441 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
442 crtcreg, index, reg);
444 VGA_WR08(pNv->PCIO,crtcreg, index);
445 configuration = (VGA_RD08(pNv->PCIO, crtcreg + 1) & and) >> shiftr;
447 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
448 offset, configuration);
450 if (configuration <= nr) {
452 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &configval))
453 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
457 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
459 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
464 if (iexec->execute) {
467 configval = 0x01014E07;
470 configval = 0x13030E02;
474 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
477 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
478 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
481 nv32_wr(pScrn, reg, configval);
487 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
490 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
491 CARD32 val = *((CARD32 *) (&bios->data[offset + 5]));
492 CARD32 configval, tmp;
494 if (iexec->execute) {
497 configval = 0x00011F05;
501 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
505 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
506 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
509 nv32_wr(pScrn, reg, configval);
511 /*xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);*/
517 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
520 CARD8 crtcindex = *((CARD8 *) (&bios->data[offset + 1]));
521 CARD8 crtcdata = *((CARD8 *) (&bios->data[offset + 2]));
522 CARD8 initial_index = *((CARD8 *) (&bios->data[offset + 3]));
523 CARD8 entries = *((CARD8 *) (&bios->data[offset + 4]));
527 if (iexec->execute) {
528 for (i = 0; i < entries; i++) {
529 nv_set_crtc_index(pScrn, crtcindex);
531 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
532 crtcindex, initial_index + i);
534 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
535 nv_rd_crtc_data(pScrn));
537 nv_wr_crtc_data(pScrn, initial_index + i);
539 nv_set_crtc_index(pScrn, crtcdata);
541 data = *((CARD8 *) (&bios->data[offset + 5 + i]));
543 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
546 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
547 nv_rd_crtc_data(pScrn));
549 nv_wr_crtc_data(pScrn, data);
557 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
559 /* XXX: IS THIS CORRECT? check the typecast .. probably wrong */
561 NVPtr pNv = NVPTR(pScrn);
562 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
563 CARD8 and = *((CARD8 *) (&bios->data[offset + 2]));
564 CARD8 or = *((CARD8 *) (&bios->data[offset + 3]));
567 if (iexec->execute) {
568 nv_set_crtc_index(pScrn, index);
569 data = (nv_rd_crtc_data(pScrn) & and) | or;
570 /*printf("and: 0x%02x or: 0x%02x\n", and, or);*/
571 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
574 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
575 nv_rd_crtc_data(pScrn));
577 nv_wr_crtc_data(pScrn, data);
584 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
586 /* INIT_ZM_CR opcode: 0x53
588 * offset (8 bit): opcode
589 * offset + 1 (8 bit): CRTC index
590 * offset + 2 (8 bit): value
592 * Assign "value" to CRTC register with index "CRTC index".
595 NVPtr pNv = NVPTR(pScrn);
596 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
597 CARD8 value = *((CARD8 *) (&bios->data[offset + 2]));
599 if (iexec->execute) {
600 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
603 nv_set_crtc_index(pScrn, index);
605 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
606 nv_rd_crtc_data(pScrn));
608 nv_wr_crtc_data(pScrn, value);
613 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
615 /* INIT_ZM_CR opcode: 0x54
617 * offset (8 bit): opcode
618 * offset + 1 (8 bit): number of groups (index, value)
619 * offset + 2 (8 bit): index 1
620 * offset + 3 (8 bit): value 1
623 * Assign "value n" to CRTC register with index "index n".
626 CARD8 nr = *((CARD8 *) (&bios->data[offset + 1]));
630 if (iexec->execute) {
631 for (i = 0; i < nr; i++) {
632 index = *((CARD8 *) (&bios->data[offset + 2 + 2 * i]));
633 value = *((CARD8 *) (&bios->data[offset + 2 + 2 * i + 1]));
635 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
638 nv_set_crtc_index(pScrn, index);
640 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
641 nv_rd_crtc_data(pScrn));
642 nv_wr_crtc_data(pScrn, value);
648 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
650 /* My BIOS does not use this command. */
651 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
656 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
658 /* INIT_ZM_REG_SEQUENCE opcode: 0x58
660 * offset (8 bit): opcode
661 * offset + 1 (32 bit): register base
662 * offset + 5 (8 bit): nr
663 * offset + 6 (32 bit): value to assign "register base" + 4
666 * Initialzies a sequence of "nr" registers starting at "register base".
669 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
670 CARD32 nr = *((CARD8 *) (&bios->data[offset + 5]));
675 if (iexec->execute) {
676 for (i = 0; i < nr; i++) {
677 data = *((CARD32 *) (&bios->data[offset + 6 + i * 4]));
678 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
681 if (nv32_rd(pScrn, reg + i * 4, &tmp)) {
682 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
686 nv32_wr(pScrn, reg + i * 4, data);
693 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
695 /* INIT_INDIRECT_REG opcode: 0x5A
697 * offset (8 bit): opcode
698 * offset + 1 (32 bit): register
699 * offset + 5 (16 bit): adress offset (in bios)
701 * Lookup value at offset data in the bios and write it to reg
703 NVPtr pNv = NVPTR(pScrn);
704 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
705 CARD32 data = *((CARD16 *) (&bios->data[offset + 5]));
706 CARD32 data2 = bios->data[data];
709 if (iexec->execute) {
710 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
711 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n",
712 offset, reg, data, data2);
714 if (DEBUGLEVEL >= 6) {
716 nv32_rd(pScrn, reg, &tmpval);
717 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
720 nv32_wr(pScrn, reg, data2);
726 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
728 /* INIT_SUB_DIRECT opcode: 0x5B
730 * offset (8 bit): opcode
731 * offset + 1 (16 bit): subroutine offset (in bios)
733 * Calls a subroutine that will execute commands until INIT_DONE
737 CARD16 sub_offset = *((CARD16 *) (&bios->data[offset + 1]));
739 if (iexec->execute) {
740 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-ROUTINE AT: 0x%04X\n",
743 parse_init_table(pScrn, bios, sub_offset, iexec);
745 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-ROUTINE\n", offset);
750 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
753 CARD32 srcreg = *((CARD32 *) (&bios->data[offset + 1]));
754 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
755 CARD32 and1 = *((CARD32 *) (&bios->data[offset + 6]));
756 CARD32 xor = *((CARD32 *) (&bios->data[offset + 10]));
757 CARD32 dstreg = *((CARD32 *) (&bios->data[offset + 14]));
758 CARD32 and2 = *((CARD32 *) (&bios->data[offset + 18]));
762 if (iexec->execute) {
763 nv32_rd(pScrn, srcreg, &srcdata);
770 srcdata = (srcdata & and1) ^ xor;
772 nv32_rd(pScrn, dstreg, &dstdata);
778 nv32_rd(pScrn, dstreg, &tmp);
780 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, dstreg,
783 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmp);
785 nv32_wr(pScrn, dstreg, dstdata);
791 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
793 NVPtr pNv = NVPTR(pScrn);
794 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
795 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
796 CARD8 value = *((CARD8 *) (&bios->data[offset + 4]));
799 if (iexec->execute) {
800 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
801 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
802 offset, crtcreg, index, value);
804 VGA_WR08(pNv->PCIO,crtcreg, index);
806 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
807 VGA_RD08(pNv->PCIO, crtcreg + 1));
810 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_zm_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,value);
812 VGA_WR08(pNv->PCIO,crtcreg + 1, value);
818 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
820 // FIXME replace with a suitable implementation
822 CARD16 ramcfg = *((CARD16 *) (&bios->data[bios->ram_table_offset]));
827 if (iexec->execute) {
828 nv32_rd(pScrn, 0x00101000, &strapinfo);
829 nv32_rd(pScrn, 0x00100080, &pfb_debug);
831 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
832 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
833 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG: 0x%04X\n", ramcfg);
835 pfb_debug &= 0xffffffef;
837 strapinfo &= 0x0000000f;
838 ramcfg2 = *((CARD16 *)
839 (&bios->data[bios->ram_table_offset + (2 * strapinfo)]));
841 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AFTER MANIPULATION\n");
842 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
843 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
844 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG2: 0x%08X\n", ramcfg2);
846 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
852 nv32_rd(pScrn, 0x00100200, ®1);
853 nv32_rd(pScrn, 0x0010020C, ®2);
855 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x00100200: 0x%08X\n", reg1);
856 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x0010020C: 0x%08X\n", reg2);
864 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
867 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
868 CARD32 value1 = *((CARD32 *) (&bios->data[offset + 5]));
869 CARD32 value2 = *((CARD32 *) (&bios->data[offset + 9]));
871 if (iexec->execute) {
872 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
873 offset, reg, value1);
874 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
875 offset, reg, value2);
877 if (DEBUGLEVEL >= 6) {
879 nv32_rd(pScrn, reg, &tmpval);
880 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
882 nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), &tmpval);
883 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: PCICFG_ROMSHADOW: 0x%02X\n", offset, tmpval);
886 nv32_wr(pScrn, reg, value1);
887 nv32_wr(pScrn, reg, value2);
890 /* PCI Config space init needs to be added here. */
892 if (nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), value1))
893 nv32_wr(pScrn, PCICFG(PCICFG_ROMSHADOW), value1 & 0xfffffffe)
899 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
901 /* INIT_INDEX_IO8 opcode: 0x69
903 * offset (8 bit): opcode
904 * offset + 1 (16 bit): CRTC reg
905 * offset + 3 (8 bit): and mask
906 * offset + 4 (8 bit): or with
911 NVPtr pNv = NVPTR(pScrn);
912 CARD16 reg = *((CARD16 *) (&bios->data[offset + 1]));
913 CARD8 and = *((CARD8 *) (&bios->data[offset + 3]));
914 CARD8 or = *((CARD8 *) (&bios->data[offset + 4]));
918 if (iexec->execute) {
919 data = (VGA_RD08(pNv->PCIO, reg) & and) | or;
921 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
922 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n",
924 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
925 VGA_RD08(pNv->PCIO, reg));
928 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
930 VGA_WR08(pNv->PCIO, reg, data);
938 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
940 CARD8 sub = *((CARD8 *) (&bios->data[offset + 1]));
942 if (iexec->execute) {
943 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-SCRIPT: %d\n", offset, sub);
945 parse_init_table(pScrn, bios,
946 *((CARD16 *) (&bios->data[bios->init_tbls_offset + sub * 2])),
949 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-SCRIPT\n", offset);
954 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
956 /* INIT_RAM_CONDITION opcode: 0x6D
958 * offset (8 bit): opcode
959 * offset + 1 (8 bit): and mask
960 * offset + 2 (8 bit): cmpval
962 * Test if (NV_PFB_BOOT & and mask) matches cmpval
964 NVPtr pNv = NVPTR(pScrn);
965 CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
966 CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
969 if (iexec->execute) {
970 data=(pNv->PFB[NV_PFB_BOOT/4])∧
972 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
973 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
974 offset, data, cmpval);
976 if (data == cmpval) {
977 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
978 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
981 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
982 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
983 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
984 iexec->execute = FALSE;
990 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
992 /* INIT_NV_REG opcode: 0x6E
994 * offset (8 bit): opcode
995 * offset + 1 (32 bit): register
996 * offset + 5 (32 bit): and mask
997 * offset + 9 (32 bit): or with
999 * Assign "register" to (REGVAL(register) & "and mask") | "or with";
1002 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1003 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
1004 CARD32 or = *((CARD32 *) (&bios->data[offset + 9]));
1006 unsigned int status;
1008 if (iexec->execute) {
1011 if ((status = nv32_rd(pScrn, reg, &data))) {
1012 data = (data & and) | or;
1013 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1016 if (DEBUGLEVEL >= 6 && status) {
1018 nv32_rd(pScrn, reg, &tmpval);
1019 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1023 nv32_wr(pScrn, reg, data);
1024 /* Assign: reg = data */
1030 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1032 // FIXME replace with the haiku version
1033 /* XXX: Not sure this is correct... */
1035 CARD8 macro = *((CARD8 *) (&bios->data[offset + 1]));
1037 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE]));
1039 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE + 4]));
1041 if (iexec->execute) {
1042 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING MACRO: 0x%02X\n", offset, macro);
1043 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
1046 if (DEBUGLEVEL >= 6) {
1048 nv32_rd(pScrn, reg, &tmpval);
1049 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1053 nv32_wr(pScrn, reg, value);
1061 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1063 CARD8 index = *((CARD8 *) (&bios->data[offset + 1]));
1064 CARD32 tmp = bios->macro_index_offset + (index << 1);
1065 CARD32 offs = *((CARD8 *) (&bios->data[tmp])) << 3;
1066 CARD32 nr = *((CARD8 *) (&bios->data[tmp + 1]));
1071 if (iexec->execute) {
1073 offs += bios->macro_offset;
1074 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: WRITE %d 32-BIT REGS:\n", offset, nr);
1076 for (i = 0; i < nr; i++) {
1077 reg = *((CARD32 *) (&bios->data[offs + (i << 3)]));
1078 data = *((CARD32 *) (&bios->data[offs + (i << 3) + 4]));
1080 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1083 if (DEBUGLEVEL >= 6) {
1085 nv32_rd(pScrn, reg, &tmpval);
1086 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1090 nv32_wr(pScrn, reg, data);
1098 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1103 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1105 if (!iexec->execute) {
1106 iexec->execute = TRUE;;
1107 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n",
1113 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1115 /* INIT_RAM_CONDITION2 opcode: 0x73
1117 * offset (8 bit): opcode
1118 * offset + 1 (8 bit): and mask
1119 * offset + 2 (8 bit): cmpval
1121 * Test if (NV_PEXTDEV_BOOT & and mask) matches cmpval
1123 NVPtr pNv = NVPTR(pScrn);
1124 CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
1125 CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
1128 if (iexec->execute) {
1129 data=(pNv->PEXTDEV[NV_PEXTDEV_BOOT/4])∧
1131 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1132 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1133 offset, data, cmpval);
1135 if (data == cmpval) {
1136 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1137 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1140 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1141 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1142 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1143 iexec->execute = FALSE;
1149 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1151 /* INIT_TIME opcode: 0x74
1153 * offset (8 bit): opcode
1154 * offset + 1 (16 bit): time
1156 * Sleep for "time" microseconds.
1159 CARD16 time = *((CARD16 *) (&bios->data[offset + 1]));
1161 if (iexec->execute) {
1162 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Sleeping for 0x%04X microseconds.\n",
1170 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1172 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
1175 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE]));
1178 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 4]));
1181 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 8]));
1184 if (iexec->execute) {
1185 if (nv32_rd(pScrn, reg, &data)) {
1188 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1189 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1190 offset, data, cmpval);
1192 if (data == cmpval) {
1193 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1194 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1197 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1198 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1199 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1200 iexec->execute = FALSE;
1208 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1210 /* INIT_INDEX_IO opcode: 0x78
1212 * offset (8 bit): opcode
1213 * offset + 1 (16 bit): CRTC reg
1214 * offset + 3 (8 bit): CRTC index
1215 * offset + 4 (8 bit): and mask
1216 * offset + 5 (8 bit): or with
1221 NVPtr pNv = NVPTR(pScrn);
1222 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
1223 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
1224 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
1225 CARD8 or = *((CARD8 *) (&bios->data[offset + 5]));
1229 if (iexec->execute) {
1230 VGA_WR08(pNv->PCIO,crtcreg, index);
1231 /* data at reg + 1 */
1232 data = (VGA_RD08(pNv->PCIO, crtcreg + 1) & and) | or;
1234 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1235 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
1236 offset, crtcreg, index, data);
1237 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
1238 VGA_RD08(pNv->PCIO, crtcreg + 1));
1240 #ifdef PERFORM_WRITE
1241 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,data);
1243 VGA_WR08(pNv->PCIO,crtcreg + 1, data);
1251 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1253 /* INIT_ZM_REG opcode: 0x7A
1255 * offset (8 bit): opcode
1256 * offset + 1 (32 bit): register
1257 * offset + 5 (32 bit): value
1259 * Assign "register" to "value";
1262 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1263 CARD32 value = *((CARD32 *) (&bios->data[offset + 5]));
1265 if (iexec->execute) {
1266 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
1267 offset, reg, value);
1269 if (DEBUGLEVEL >= 6) {
1271 nv32_rd(pScrn, reg, &tmpval);
1272 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1275 nv32_wr(pScrn, reg, value);
1277 /* Assign: reg = value */
1282 static init_tbl_entry_t itbl_entry[] = {
1283 /* command name , id , length , offset , mult , command handler */
1284 { "INIT_PROG" , 0x31, 15 , 10 , 4 , init_prog },
1285 { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog },
1286 { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat },
1287 { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat },
1288 { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy },
1289 { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not },
1290 { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition },
1291 /* [ "INIT_INDEX_ADDRESS_LATCHED" , 0x49, x , x , x, , init_idx_addr_latched }, */
1292 { "INIT_IO_RESTRICT_PLL" , 0x4A, 43 , 0 , 0 , init_io_restrict_pll },
1293 { "INIT_PLL" , 0x4B, 9 , 0 , 0 , init_pll },
1294 /* { "INIT_I2C_BYTE" , 0x4C, x , x , x , init_i2c_byte }, */
1295 /* { "INIT_ZM_I2C_BYTE" , 0x4D, x , x , x , init_zm_i2c_byte }, */
1296 /* { "INIT_ZM_I2C" , 0x4E, x , x , x , init_zm_i2c }, */
1297 { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch },
1298 { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr },
1299 { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr },
1300 { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group },
1301 { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time },
1302 { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence },
1303 { "INIT_INDIRECT_REG" , 0x5A, 7 , 0 , 0 , init_indirect_reg },
1304 { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct },
1305 { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg },
1306 { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io },
1307 { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem },
1308 { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset },
1309 /* { "INIT_NEXT" , 0x66, x , x , x , init_next }, */
1310 /* { "INIT_NEXT" , 0x67, x , x , x , init_next }, */
1311 /* { "INIT_NEXT" , 0x68, x , x , x , init_next }, */
1312 { "INIT_INDEX_IO8" , 0x69, 5 , 0 , 0 , init_index_io8 },
1313 { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub },
1314 { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition },
1315 { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg },
1316 { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro },
1317 { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done },
1318 { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume },
1319 { "INIT_RAM_CONDITION2" , 0x73, 9 , 0 , 0 , init_ram_condition2 },
1320 { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time },
1321 { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition },
1322 /* { "INIT_IO_CONDITION", , 0x76, x , x, , x , init_io_condition }, */
1323 { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io },
1324 /* { "INIT_PLL2" , 0x79, x , x , x , init_pll2 }, */
1325 { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg },
1326 /* { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, x , x , x , init_ram_restrict_zm_reg_group }, */
1327 /* { "INIT_COPY_ZM_REG" , 0x90, x , x , x , init_copy_zm_reg }, */
1328 /* { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, x , x , x , init_zm_reg_group_addr_latched }, */
1329 /* { "INIT_RESERVED" , 0x92, x , x , x , init_reserved }, */
1330 { 0 , 0 , 0 , 0 , 0 , 0 }
1334 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
1336 /* Calculates the length of a given init table entry. */
1337 return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
1340 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
1343 /* Parses all commands in a init table. */
1345 /* We start out executing all commands found in the
1346 * init table. Some op codes may change the status
1347 * of this variable to SKIP, which will cause
1348 * the following op codes to perform no operation until
1349 * the value is changed back to EXECUTE.
1356 /* Loop as long as INIT_DONE (command id 0x71) has not been found
1357 * (and offset < bios length just in case... )
1358 * (and no more than 10000 iterations just in case... ) */
1359 while (((id = bios->data[offset]) != 0x71) && (offset < bios->length) && (count++<10000)) {
1360 /* Find matching id in itbl_entry */
1361 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
1364 if (itbl_entry[i].name) {
1366 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ (0x%02X) - %s ]\n", offset,
1367 itbl_entry[i].id, itbl_entry[i].name);
1369 /* execute eventual command handler */
1370 if (itbl_entry[i].handler)
1371 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
1375 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Init table command not found: 0x%02X\n",
1379 /* Add the offset of the current command including all data
1380 * of that command. The offset will then be pointing on the
1383 offset += get_init_table_entry_length(bios, offset, i);
1387 void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios) {
1389 /* Loops and calls parse_init_table() for each present table. */
1393 init_exec_t iexec = {TRUE, FALSE};
1395 while (table = *((CARD16 *) (&bios->data[bios->init_tbls_offset + i]))) {
1397 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing init table %d\n",
1400 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",table);
1402 parse_init_table(pScrn, bios, table, &iexec);
1407 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry) {
1409 /* Parses the init table segment that the bit entry points to.
1410 * Starting at bitentry->offset:
1412 * offset + 0 (16 bits): offset of init tables
1413 * offset + 2 (16 bits): macro index table offset
1414 * offset + 4 (16 bits): macro offset
1415 * offset + 6 (16 bits): condition offset
1416 * offset + 8 (16 bits): io flag condition offset (?)
1417 * offset + 10 (16 bits): io flag condition offset (?)
1418 * offset + 12 (16 bits): unknown
1420 * offset + 8 and offset + 10 seems to contain the same
1421 * offsets on all bioses i have checked. Don't know which
1422 * one is the correct, therefore this code will bail out
1423 * if the two values are not the same.
1426 * * In addition to "conditions" and "io flag conditions" there seems to be
1427 * "io conditions". These are probably located at offset + (8, 10 or 12).
1428 * We need more BIOS dumps to figure this out...
1430 * * Are 'I' bit entries always of length 0xE?
1434 if (bitentry->length < 12) {
1435 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to regocnize BIT init table entry.\n");
1439 bios->init_tbls_offset = *((CARD16 *) (&bios->data[bitentry->offset]));
1440 bios->macro_index_offset = *((CARD16 *) (&bios->data[bitentry->offset + 2]));
1441 bios->macro_offset = *((CARD16 *) (&bios->data[bitentry->offset + 4]));
1442 bios->condition_offset =
1443 *((CARD16 *) (&bios->data[bitentry->offset + 6]));
1445 if (*((CARD16 *) (&bios->data[bitentry->offset + 8])) !=
1446 *((CARD16 *) (&bios->data[bitentry->offset + 10]))) {
1447 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to find IO flag condition offset.\n");
1451 bios->io_flag_condition_offset =
1452 *((CARD16 *) (&bios->data[bitentry->offset + 8]));
1454 parse_init_tables(pScrn, bios);
1459 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset) {
1461 bit_entry_t *bitentry;
1465 bitentry = (bit_entry_t *) &bios->data[offset];
1467 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Found BIT command with id 0x%02X\n",
1468 offset, bitentry->id[0]);
1470 switch (bitentry->id[0]) {
1472 /* id[0] = 0 and id[1] = 0 ==> end of BIT struture */
1473 if (bitentry->id[1] == 0)
1477 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1478 "0x%04X: Found init table entry in BIT structure.\n",
1481 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1482 /*parse_init_tables(pScrn, bios);*/
1485 /* TODO: What kind of information does the other BIT entrys point to?
1486 * 'P' entry is probably performance tables, but there are
1487 * quite a few others...
1491 offset += sizeof(bit_entry_t);
1495 static void parse_pins_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset) {
1496 int pins_version_major=bios->data[offset+5];
1497 int pins_version_minor=bios->data[offset+6];
1498 int init1 = bios->data[offset + 18] + (bios->data[offset + 19] * 256);
1499 int init2 = bios->data[offset + 20] + (bios->data[offset + 21] * 256);
1500 int init_size = bios->data[offset + 22] + (bios->data[offset + 23] * 256) + 1;
1503 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PINS version %d.%d\n",pins_version_major,pins_version_minor);
1506 if (pins_version_major==2)
1507 ram_tab = init1-0x0010;
1509 ram_tab = bios->data[offset + 24] + (bios->data[offset + 25] * 256);
1511 if ((pins_version_major==5)&&(pins_version_minor>=6))
1513 /* VCO range info */
1517 if ((pins_version_major==5)&&(pins_version_minor>=16))
1522 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1528 static unsigned int findstr(bios_t* bios, unsigned char *str, int len) {
1532 for (i = 2; i < bios->length; i++)
1533 if (strncmp(&bios->data[i], str, len) == 0)
1540 unsigned int NVParseBios(ScrnInfoPtr pScrn) {
1542 unsigned int bit_offset;
1545 bios.length=NV_PROM_SIZE;
1546 unsigned char nv_signature[]={0xff,0x7f,'N','V',0x0};
1547 unsigned char bit_signature[]={'B','I','T'};
1552 bios.data=xalloc(NV_PROM_SIZE);
1554 /* enable ROM access */
1555 nvWriteMC(pNv, 0x1850, 0x0);
1556 for(i=0;i<NV_PROM_SIZE;i++)
1558 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
1559 bios.data[i]=pNv->PROM[i];
1560 bios.data[i]=pNv->PROM[i];
1561 bios.data[i]=pNv->PROM[i];
1562 bios.data[i]=pNv->PROM[i];
1563 bios.data[i]=pNv->PROM[i];
1565 /* disable ROM access */
1566 nvWriteMC(pNv, 0x1850, 0x1);
1568 /* check for BIOS signature */
1569 if (!(bios.data[0] == 0x55 && bios.data[1] == 0xAA)) {
1570 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS signature not found!\n");
1575 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS signature found.\n");
1577 /* check for known signatures */
1578 if (bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature))) {
1579 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT signature found.\n");
1580 parse_bit_structure(pScrn, &bios, bit_offset + 4);
1581 } else if (bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature))) {
1582 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV signature found.\n");
1583 parse_pins_structure(pScrn, &bios, bit_offset);
1585 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No known script signature found.\n");