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;
51 static Bool NVValidBios(ScrnInfoPtr pScrn, const unsigned char *data)
53 /* check for BIOS signature */
54 if (!(data[0] == 0x55 && data[1] == 0xAA)) {
55 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
56 "...BIOS signature not found\n");
60 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "...appears to be valid\n");
64 static void NVDownloadBiosPROM(ScrnInfoPtr pScrn, unsigned char *data)
66 NVPtr pNv = NVPTR(pScrn);
69 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
70 "Attempting to locate BIOS image in PROM\n");
72 /* enable ROM access */
73 nvWriteMC(pNv, 0x1850, 0x0);
74 for (i=0; i<NV_PROM_SIZE; i++) {
75 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
76 data[i] = pNv->PROM[i];
77 data[i] = pNv->PROM[i];
78 data[i] = pNv->PROM[i];
79 data[i] = pNv->PROM[i];
80 data[i] = pNv->PROM[i];
82 /* disable ROM access */
83 nvWriteMC(pNv, 0x1850, 0x1);
86 static void NVDownloadBiosPRAMIN(ScrnInfoPtr pScrn, unsigned char *data)
88 NVPtr pNv = NVPTR(pScrn);
89 const unsigned char *pramin = (void*)&pNv->REGS[0x00700000/4];
91 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
92 "Attempting to locate BIOS image in PRAMIN\n");
93 memcpy(data, pramin, 65536);
96 static Bool NVDownloadBios(ScrnInfoPtr pScrn, bios_t *bios)
98 NVPtr pNv = NVPTR(pScrn);
100 bios->data = xcalloc(1, 65536);
102 NVDownloadBiosPROM(pScrn, bios->data);
103 if (NVValidBios(pScrn, bios->data))
106 NVDownloadBiosPRAMIN(pScrn, bios->data);
107 if (NVValidBios(pScrn, bios->data))
110 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
111 "Failed to locate BIOS image\n");
121 int length_multiplier;
122 Bool (*handler)(ScrnInfoPtr pScrn, bios_t *, CARD16, init_exec_t *);
127 unsigned short length;
128 unsigned short offset;
131 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec);
133 /* #define MACRO_SIZE 8 */
134 #define CONDITION_SIZE 12
135 #define IO_FLAG_CONDITION_SIZE 9
143 static int nv_valid_reg(CARD32 reg)
145 #define WITHIN(x,y,z) ((x>=y)&&(x<y+z))
146 if (WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
148 if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE))
150 if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE))
152 if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
154 if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
156 if (WITHIN(reg,NV_PGRAPH_OFFSET,NV_PGRAPH_SIZE))
158 if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
160 if (WITHIN(reg,NV_PTIMER_OFFSET,NV_PTIMER_SIZE))
162 if (WITHIN(reg,NV_PVIDEO_OFFSET,NV_PVIDEO_SIZE))
164 if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
166 if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
168 if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
170 if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
172 if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
174 if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
180 static int nv32_rd(ScrnInfoPtr pScrn, CARD32 reg, CARD32 *data)
182 NVPtr pNv = NVPTR(pScrn);
183 *data=pNv->REGS[reg/4];
187 static int nv32_wr(ScrnInfoPtr pScrn, CARD32 reg, CARD32 data)
190 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv32_wr reg 0x%X value 0x%X\n",reg,data);
192 if (!nv_valid_reg(reg))
194 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "========= unknown reg 0x%X ==========\n",reg);
198 NVPtr pNv = NVPTR(pScrn);
199 pNv->REGS[reg/4]=data;
204 void nv_set_crtc_index(ScrnInfoPtr pScrn, CARD8 index)
207 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_set_crtc_index index 0x%X\n",index);
209 NVPtr pNv = NVPTR(pScrn);
210 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
211 VGA_WR08(ptr, 0x3D4, index);
215 CARD8 nv_rd_crtc_data(ScrnInfoPtr pScrn)
217 NVPtr pNv = NVPTR(pScrn);
218 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
219 return VGA_RD08(ptr, 0x3D5);
222 void nv_wr_crtc_data(ScrnInfoPtr pScrn, CARD8 val)
225 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_wr_crtc_data value 0x%X\n",val);
227 NVPtr pNv = NVPTR(pScrn);
228 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
229 VGA_WR08(ptr, 0x3D5, val);
233 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
235 /* INIT_PROG opcode: 0x31
237 * offset (8 bit): opcode
238 * offset + 1 (32 bit): reg
239 * offset + 5 (32 bit): and mask
240 * offset + 9 (8 bit): shift right
241 * offset + 10 (8 bit): number of configurations
242 * offset + 11 (32 bit): register
243 * offset + 15 (32 bit): configuration 1
246 * Starting at offset + 15 there are "number of configurations"
247 * 32 bit values. To find out which configuration value to use
248 * read "CRTC reg" on the CRTC controller with index "CRTC index"
249 * and bitwise AND this value with "and mask" and then bit shift the
250 * result "shift right" bits to the right.
251 * Assign "register" with appropriate configuration value.
254 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
255 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
256 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
257 CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
258 CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
260 CARD32 configval, tmp;
262 if (iexec->execute) {
263 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%04X\n", offset,
266 nv32_rd(pScrn, reg, &tmp);
267 configuration = (tmp & and) >> shiftr;
269 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
270 offset, configuration);
272 if (configuration <= nr) {
275 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
277 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
280 if (nv32_rd(pScrn, reg2, &tmp)) {
281 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
284 nv32_wr(pScrn, reg2, configval);
290 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
292 /* INIT_IO_RESTRICT_PROG opcode: 0x32
294 * offset (8 bit): opcode
295 * offset + 1 (16 bit): CRTC reg
296 * offset + 3 (8 bit): CRTC index
297 * offset + 4 (8 bit): and mask
298 * offset + 5 (8 bit): shift right
299 * offset + 6 (8 bit): number of configurations
300 * offset + 7 (32 bit): register
301 * offset + 11 (32 bit): configuration 1
304 * Starting at offset + 11 there are "number of configurations"
305 * 32 bit values. To find out which configuration value to use
306 * read "CRTC reg" on the CRTC controller with index "CRTC index"
307 * and bitwise AND this value with "and mask" and then bit shift the
308 * result "shift right" bits to the right.
309 * Assign "register" with appropriate configuration value.
312 NVPtr pNv = NVPTR(pScrn);
313 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
314 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
315 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
316 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
317 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
318 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
319 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
321 CARD32 configval, tmp;
323 if (iexec->execute) {
324 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
327 VGA_WR08(ptr,crtcreg, index);
328 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
330 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
331 offset, configuration);
333 if (configuration <= nr) {
335 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
337 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
340 if (nv32_rd(pScrn, reg, &tmp)) {
341 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
344 nv32_wr(pScrn, reg, configval);
350 static Bool init_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
352 CARD8 repeats = *((CARD8 *) (&bios->data[offset + 1]));
355 if (iexec->execute) {
356 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REPEATING FOLLOWING SEGMENT %d TIMES.\n",
359 iexec->repeat = TRUE;
361 for (i = 0; i < repeats - 1; i++)
362 parse_init_table(pScrn, bios, offset + 2, iexec);
364 iexec->repeat = FALSE;
369 static Bool init_end_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
377 static Bool init_copy(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
379 /* XXX: double check this... */
380 NVPtr pNv = NVPTR(pScrn);
381 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
382 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
383 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
384 CARD8 and1 = *((CARD8 *) (&bios->data[offset + 6]));
385 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 7]));
386 CARD8 index = *((CARD8 *) (&bios->data[offset + 9]));
387 CARD8 and2 = *((CARD8 *) (&bios->data[offset + 10]));
391 if (iexec->execute) {
392 if (nv32_rd(pScrn, reg, &data)) {
396 data <<= (0x100 - shift);
399 VGA_WR08(ptr,crtcreg, index);
400 crtcdata = (VGA_RD08(ptr, crtcreg + 1) & and2) | (CARD8) data;
402 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
403 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n"
404 , offset, crtcreg, index, crtcdata);
406 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
407 VGA_RD08(ptr, crtcreg + 1));
409 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_copy crtcreg 0x%X value 0x%X\n",crtcreg+1,crtcdata);
411 printf("WRITE IS PERFORMED\n");
412 VGA_WR08(ptr,crtcreg + 1, crtcdata);
419 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
421 if (iexec->execute) {
422 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n",
425 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",
429 iexec->execute = !iexec->execute;
433 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
435 NVPtr pNv = NVPTR(pScrn);
436 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
437 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
438 CARD16 crtcreg = *((CARD16 *)
439 (&bios->data[bios->io_flag_condition_offset +
440 cond * IO_FLAG_CONDITION_SIZE]));
441 CARD8 index = *((CARD8 *)
442 (&bios->data[bios->io_flag_condition_offset +
443 cond * IO_FLAG_CONDITION_SIZE + 2]));
444 CARD8 and1 = *((CARD8 *)
445 (&bios->data[bios->io_flag_condition_offset +
446 cond * IO_FLAG_CONDITION_SIZE + 3]));
447 CARD8 shift = *((CARD8 *)
448 (&bios->data[bios->io_flag_condition_offset +
449 cond * IO_FLAG_CONDITION_SIZE + 4]));
450 CARD16 offs = *((CARD16 *)
451 (&bios->data[bios->io_flag_condition_offset +
452 cond * IO_FLAG_CONDITION_SIZE + 5]));
453 CARD8 and2 = *((CARD8 *)
454 (&bios->data[bios->io_flag_condition_offset +
455 cond * IO_FLAG_CONDITION_SIZE + 7]));
456 CARD8 cmpval = *((CARD8 *)
457 (&bios->data[bios->io_flag_condition_offset +
458 cond * IO_FLAG_CONDITION_SIZE + 8]));
462 if (iexec->execute) {
463 VGA_WR08(ptr,crtcreg, index);
464 data = VGA_RD08(ptr, crtcreg + 1);
466 offs += (data >> shift);
467 data = *((CARD8 *) (&bios->data[offs]));
470 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
471 "0x%04X: CHECKING IF DATA: %02X equals COND: %02X\n", offset,
474 if (data == cmpval) {
475 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
476 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
479 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
480 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
481 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
482 iexec->execute = FALSE;
488 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
490 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
491 /* XXX: this needs to be confirmed... NOT CORRECT */
492 /*init_io_restrict_prog(bios, offset, iexec);*/
494 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
495 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
496 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
497 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
498 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
499 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
501 CARD32 configval, tmp;
503 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
504 crtcreg, index, reg);
506 VGA_WR08(ptr,crtcreg, index);
507 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
509 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
510 offset, configuration);
512 if (configuration <= nr) {
514 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &configval))
515 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
519 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
521 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
527 if (iexec->execute) {
530 configval = 0x01014E07;
533 configval = 0x13030E02;
537 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
540 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
541 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
544 nv32_wr(pScrn, reg, configval);
550 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
552 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
553 CARD32 val = *((CARD32 *) (&bios->data[offset + 5]));
554 CARD32 configval, tmp;
556 if (iexec->execute) {
559 configval = 0x00011F05;
563 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
566 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
567 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
570 nv32_wr(pScrn, reg, configval);
572 /*xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);*/
578 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
580 CARD8 crtcindex = *((CARD8 *) (&bios->data[offset + 1]));
581 CARD8 crtcdata = *((CARD8 *) (&bios->data[offset + 2]));
582 CARD8 initial_index = *((CARD8 *) (&bios->data[offset + 3]));
583 CARD8 entries = *((CARD8 *) (&bios->data[offset + 4]));
587 if (iexec->execute) {
588 for (i = 0; i < entries; i++) {
589 nv_set_crtc_index(pScrn, crtcindex);
591 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
592 crtcindex, initial_index + i);
594 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
595 nv_rd_crtc_data(pScrn));
597 nv_wr_crtc_data(pScrn, initial_index + i);
599 nv_set_crtc_index(pScrn, crtcdata);
601 data = *((CARD8 *) (&bios->data[offset + 5 + i]));
603 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
606 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
607 nv_rd_crtc_data(pScrn));
609 nv_wr_crtc_data(pScrn, data);
615 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
617 /* XXX: IS THIS CORRECT? check the typecast .. probably wrong */
619 NVPtr pNv = NVPTR(pScrn);
620 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
621 CARD8 and = *((CARD8 *) (&bios->data[offset + 2]));
622 CARD8 or = *((CARD8 *) (&bios->data[offset + 3]));
625 if (iexec->execute) {
626 nv_set_crtc_index(pScrn, index);
627 data = (nv_rd_crtc_data(pScrn) & and) | or;
628 /*printf("and: 0x%02x or: 0x%02x\n", and, or);*/
629 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
632 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
633 nv_rd_crtc_data(pScrn));
635 nv_wr_crtc_data(pScrn, data);
640 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
642 /* INIT_ZM_CR opcode: 0x53
644 * offset (8 bit): opcode
645 * offset + 1 (8 bit): CRTC index
646 * offset + 2 (8 bit): value
648 * Assign "value" to CRTC register with index "CRTC index".
651 NVPtr pNv = NVPTR(pScrn);
652 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
653 CARD8 value = *((CARD8 *) (&bios->data[offset + 2]));
655 if (iexec->execute) {
656 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
659 nv_set_crtc_index(pScrn, index);
661 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
662 nv_rd_crtc_data(pScrn));
664 nv_wr_crtc_data(pScrn, value);
669 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
671 /* INIT_ZM_CR opcode: 0x54
673 * offset (8 bit): opcode
674 * offset + 1 (8 bit): number of groups (index, value)
675 * offset + 2 (8 bit): index 1
676 * offset + 3 (8 bit): value 1
679 * Assign "value n" to CRTC register with index "index n".
682 CARD8 nr = *((CARD8 *) (&bios->data[offset + 1]));
686 if (iexec->execute) {
687 for (i = 0; i < nr; i++) {
688 index = *((CARD8 *) (&bios->data[offset + 2 + 2 * i]));
689 value = *((CARD8 *) (&bios->data[offset + 2 + 2 * i + 1]));
691 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
694 nv_set_crtc_index(pScrn, index);
696 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
697 nv_rd_crtc_data(pScrn));
698 nv_wr_crtc_data(pScrn, value);
704 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
706 /* My BIOS does not use this command. */
707 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
712 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
714 /* INIT_ZM_REG_SEQUENCE opcode: 0x58
716 * offset (8 bit): opcode
717 * offset + 1 (32 bit): register base
718 * offset + 5 (8 bit): nr
719 * offset + 6 (32 bit): value to assign "register base" + 4
722 * Initialzies a sequence of "nr" registers starting at "register base".
725 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
726 CARD32 nr = *((CARD8 *) (&bios->data[offset + 5]));
731 if (iexec->execute) {
732 for (i = 0; i < nr; i++) {
733 data = *((CARD32 *) (&bios->data[offset + 6 + i * 4]));
734 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
737 if (nv32_rd(pScrn, reg + i * 4, &tmp)) {
738 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
742 nv32_wr(pScrn, reg + i * 4, data);
748 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
750 /* INIT_INDIRECT_REG opcode: 0x5A
752 * offset (8 bit): opcode
753 * offset + 1 (32 bit): register
754 * offset + 5 (16 bit): adress offset (in bios)
756 * Lookup value at offset data in the bios and write it to reg
758 NVPtr pNv = NVPTR(pScrn);
759 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
760 CARD32 data = *((CARD16 *) (&bios->data[offset + 5]));
761 CARD32 data2 = bios->data[data];
763 if (iexec->execute) {
764 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
765 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n",
766 offset, reg, data, data2);
768 if (DEBUGLEVEL >= 6) {
770 nv32_rd(pScrn, reg, &tmpval);
771 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
774 nv32_wr(pScrn, reg, data2);
779 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
781 /* INIT_SUB_DIRECT opcode: 0x5B
783 * offset (8 bit): opcode
784 * offset + 1 (16 bit): subroutine offset (in bios)
786 * Calls a subroutine that will execute commands until INIT_DONE
790 CARD16 sub_offset = *((CARD16 *) (&bios->data[offset + 1]));
792 if (iexec->execute) {
793 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-ROUTINE AT: 0x%04X\n",
796 parse_init_table(pScrn, bios, sub_offset, iexec);
798 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-ROUTINE\n", offset);
803 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
805 CARD32 srcreg = *((CARD32 *) (&bios->data[offset + 1]));
806 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
807 CARD32 and1 = *((CARD32 *) (&bios->data[offset + 6]));
808 CARD32 xor = *((CARD32 *) (&bios->data[offset + 10]));
809 CARD32 dstreg = *((CARD32 *) (&bios->data[offset + 14]));
810 CARD32 and2 = *((CARD32 *) (&bios->data[offset + 18]));
814 if (iexec->execute) {
815 nv32_rd(pScrn, srcreg, &srcdata);
822 srcdata = (srcdata & and1) ^ xor;
824 nv32_rd(pScrn, dstreg, &dstdata);
830 nv32_rd(pScrn, dstreg, &tmp);
832 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, dstreg,
835 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmp);
837 nv32_wr(pScrn, dstreg, dstdata);
842 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
844 NVPtr pNv = NVPTR(pScrn);
845 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
846 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
847 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
848 CARD8 value = *((CARD8 *) (&bios->data[offset + 4]));
850 if (iexec->execute) {
851 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
852 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
853 offset, crtcreg, index, value);
855 VGA_WR08(ptr,crtcreg, index);
857 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
858 VGA_RD08(ptr, crtcreg + 1));
861 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_zm_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,value);
863 VGA_WR08(ptr,crtcreg + 1, value);
869 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
871 // FIXME replace with a suitable implementation
873 CARD16 ramcfg = *((CARD16 *) (&bios->data[bios->ram_table_offset]));
878 if (iexec->execute) {
879 nv32_rd(pScrn, 0x00101000, &strapinfo);
880 nv32_rd(pScrn, 0x00100080, &pfb_debug);
882 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
883 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
884 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG: 0x%04X\n", ramcfg);
886 pfb_debug &= 0xffffffef;
888 strapinfo &= 0x0000000f;
889 ramcfg2 = *((CARD16 *)
890 (&bios->data[bios->ram_table_offset + (2 * strapinfo)]));
892 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AFTER MANIPULATION\n");
893 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
894 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
895 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG2: 0x%08X\n", ramcfg2);
897 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
902 nv32_rd(pScrn, 0x00100200, ®1);
903 nv32_rd(pScrn, 0x0010020C, ®2);
905 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x00100200: 0x%08X\n", reg1);
906 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x0010020C: 0x%08X\n", reg2);
912 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
914 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
915 CARD32 value1 = *((CARD32 *) (&bios->data[offset + 5]));
916 CARD32 value2 = *((CARD32 *) (&bios->data[offset + 9]));
918 if (iexec->execute) {
919 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
920 offset, reg, value1);
921 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
922 offset, reg, value2);
924 if (DEBUGLEVEL >= 6) {
926 nv32_rd(pScrn, reg, &tmpval);
927 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
929 nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), &tmpval);
930 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: PCICFG_ROMSHADOW: 0x%02X\n", offset, tmpval);
933 nv32_wr(pScrn, reg, value1);
934 nv32_wr(pScrn, reg, value2);
936 /* PCI Config space init needs to be added here. */
937 /* if (nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), value1)) */
938 /* nv32_wr(pScrn, PCICFG(PCICFG_ROMSHADOW), value1 & 0xfffffffe) */
943 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
945 /* INIT_INDEX_IO8 opcode: 0x69
947 * offset (8 bit): opcode
948 * offset + 1 (16 bit): CRTC reg
949 * offset + 3 (8 bit): and mask
950 * offset + 4 (8 bit): or with
955 NVPtr pNv = NVPTR(pScrn);
956 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
957 CARD16 reg = *((CARD16 *) (&bios->data[offset + 1]));
958 CARD8 and = *((CARD8 *) (&bios->data[offset + 3]));
959 CARD8 or = *((CARD8 *) (&bios->data[offset + 4]));
962 if (iexec->execute) {
963 data = (VGA_RD08(ptr, reg) & and) | or;
965 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
966 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n",
968 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
972 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
974 VGA_WR08(ptr, reg, data);
980 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
982 CARD8 sub = *((CARD8 *) (&bios->data[offset + 1]));
984 if (iexec->execute) {
985 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-SCRIPT: %d\n", offset, sub);
987 parse_init_table(pScrn, bios,
988 *((CARD16 *) (&bios->data[bios->init_tbls_offset + sub * 2])),
991 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-SCRIPT\n", offset);
996 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
998 /* INIT_RAM_CONDITION opcode: 0x6D
1000 * offset (8 bit): opcode
1001 * offset + 1 (8 bit): and mask
1002 * offset + 2 (8 bit): cmpval
1004 * Test if (NV_PFB_BOOT & and mask) matches cmpval
1006 NVPtr pNv = NVPTR(pScrn);
1007 CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
1008 CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
1011 if (iexec->execute) {
1012 data=(pNv->PFB[NV_PFB_BOOT/4])∧
1014 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1015 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1016 offset, data, cmpval);
1018 if (data == cmpval) {
1019 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1020 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1023 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1024 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1025 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1026 iexec->execute = FALSE;
1032 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1034 /* INIT_NV_REG opcode: 0x6E
1036 * offset (8 bit): opcode
1037 * offset + 1 (32 bit): register
1038 * offset + 5 (32 bit): and mask
1039 * offset + 9 (32 bit): or with
1041 * Assign "register" to (REGVAL(register) & "and mask") | "or with";
1044 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1045 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
1046 CARD32 or = *((CARD32 *) (&bios->data[offset + 9]));
1048 unsigned int status;
1050 if (iexec->execute) {
1052 if ((status = nv32_rd(pScrn, reg, &data))) {
1053 data = (data & and) | or;
1054 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1057 if (DEBUGLEVEL >= 6 && status) {
1059 nv32_rd(pScrn, reg, &tmpval);
1060 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1064 nv32_wr(pScrn, reg, data);
1065 /* Assign: reg = data */
1072 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1074 // FIXME replace with the haiku version
1075 /* XXX: Not sure this is correct... */
1077 CARD8 macro = *((CARD8 *) (&bios->data[offset + 1]));
1079 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE]));
1081 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE + 4]));
1083 if (iexec->execute) {
1084 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING MACRO: 0x%02X\n", offset, macro);
1085 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
1088 if (DEBUGLEVEL >= 6) {
1090 nv32_rd(pScrn, reg, &tmpval);
1091 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1095 nv32_wr(pScrn, reg, value);
1101 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1103 CARD8 index = *((CARD8 *) (&bios->data[offset + 1]));
1104 CARD32 tmp = bios->macro_index_offset + (index << 1);
1105 CARD32 offs = *((CARD8 *) (&bios->data[tmp])) << 3;
1106 CARD32 nr = *((CARD8 *) (&bios->data[tmp + 1]));
1111 if (iexec->execute) {
1112 offs += bios->macro_offset;
1113 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: WRITE %d 32-BIT REGS:\n", offset, nr);
1115 for (i = 0; i < nr; i++) {
1116 reg = *((CARD32 *) (&bios->data[offs + (i << 3)]));
1117 data = *((CARD32 *) (&bios->data[offs + (i << 3) + 4]));
1119 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1122 if (DEBUGLEVEL >= 6) {
1124 nv32_rd(pScrn, reg, &tmpval);
1125 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1129 nv32_wr(pScrn, reg, data);
1135 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1140 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1142 if (!iexec->execute) {
1143 iexec->execute = TRUE;;
1144 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n",
1150 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1152 /* INIT_RAM_CONDITION2 opcode: 0x73
1154 * offset (8 bit): opcode
1155 * offset + 1 (8 bit): and mask
1156 * offset + 2 (8 bit): cmpval
1158 * Test if (NV_EXTDEV_BOOT & and mask) matches cmpval
1160 NVPtr pNv = NVPTR(pScrn);
1161 CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
1162 CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
1165 if (iexec->execute) {
1166 data=(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT))∧
1168 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1169 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1170 offset, data, cmpval);
1172 if (data == cmpval) {
1173 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1174 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1177 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1178 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1179 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1180 iexec->execute = FALSE;
1186 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1188 /* INIT_TIME opcode: 0x74
1190 * offset (8 bit): opcode
1191 * offset + 1 (16 bit): time
1193 * Sleep for "time" microseconds.
1196 CARD16 time = *((CARD16 *) (&bios->data[offset + 1]));
1198 if (iexec->execute) {
1199 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Sleeping for 0x%04X microseconds.\n",
1207 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1209 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
1212 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE]));
1215 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 4]));
1218 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 8]));
1221 if (iexec->execute) {
1222 if (nv32_rd(pScrn, reg, &data)) {
1225 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1226 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1227 offset, data, cmpval);
1229 if (data == cmpval) {
1230 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1231 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1234 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1235 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1236 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1237 iexec->execute = FALSE;
1244 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1246 /* INIT_INDEX_IO opcode: 0x78
1248 * offset (8 bit): opcode
1249 * offset + 1 (16 bit): CRTC reg
1250 * offset + 3 (8 bit): CRTC index
1251 * offset + 4 (8 bit): and mask
1252 * offset + 5 (8 bit): or with
1257 NVPtr pNv = NVPTR(pScrn);
1258 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
1259 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
1260 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
1261 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
1262 CARD8 or = *((CARD8 *) (&bios->data[offset + 5]));
1265 if (iexec->execute) {
1266 VGA_WR08(ptr,crtcreg, index);
1267 /* data at reg + 1 */
1268 data = (VGA_RD08(ptr, crtcreg + 1) & and) | or;
1270 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1271 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
1272 offset, crtcreg, index, data);
1273 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
1274 VGA_RD08(ptr, crtcreg + 1));
1276 #ifdef PERFORM_WRITE
1277 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,data);
1279 VGA_WR08(ptr,crtcreg + 1, data);
1285 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1287 /* INIT_ZM_REG opcode: 0x7A
1289 * offset (8 bit): opcode
1290 * offset + 1 (32 bit): register
1291 * offset + 5 (32 bit): value
1293 * Assign "register" to "value";
1296 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1297 CARD32 value = *((CARD32 *) (&bios->data[offset + 5]));
1299 if (iexec->execute) {
1300 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
1301 offset, reg, value);
1303 if (DEBUGLEVEL >= 6) {
1305 nv32_rd(pScrn, reg, &tmpval);
1306 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1309 nv32_wr(pScrn, reg, value);
1311 /* Assign: reg = value */
1316 static init_tbl_entry_t itbl_entry[] = {
1317 /* command name , id , length , offset , mult , command handler */
1318 { "INIT_PROG" , 0x31, 15 , 10 , 4 , init_prog },
1319 { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog },
1320 { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat },
1321 { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat },
1322 { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy },
1323 { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not },
1324 { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition },
1325 /* { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, x , x , x, , init_idx_addr_latched }, */
1326 { "INIT_IO_RESTRICT_PLL" , 0x4A, 43 , 0 , 0 , init_io_restrict_pll },
1327 { "INIT_PLL" , 0x4B, 9 , 0 , 0 , init_pll },
1328 /* { "INIT_I2C_BYTE" , 0x4C, x , x , x , init_i2c_byte }, */
1329 /* { "INIT_ZM_I2C_BYTE" , 0x4D, x , x , x , init_zm_i2c_byte }, */
1330 /* { "INIT_ZM_I2C" , 0x4E, x , x , x , init_zm_i2c }, */
1331 { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch },
1332 { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr },
1333 { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr },
1334 { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group },
1335 { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time },
1336 { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence },
1337 { "INIT_INDIRECT_REG" , 0x5A, 7 , 0 , 0 , init_indirect_reg },
1338 { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct },
1339 { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg },
1340 { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io },
1341 { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem },
1342 { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset },
1343 /* { "INIT_NEXT" , 0x66, x , x , x , init_next }, */
1344 /* { "INIT_NEXT" , 0x67, x , x , x , init_next }, */
1345 /* { "INIT_NEXT" , 0x68, x , x , x , init_next }, */
1346 { "INIT_INDEX_IO8" , 0x69, 5 , 0 , 0 , init_index_io8 },
1347 { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub },
1348 { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition },
1349 { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg },
1350 { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro },
1351 { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done },
1352 { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume },
1353 { "INIT_RAM_CONDITION2" , 0x73, 9 , 0 , 0 , init_ram_condition2 },
1354 { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time },
1355 { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition },
1356 /* { "INIT_IO_CONDITION", , 0x76, x , x, , x , init_io_condition }, */
1357 { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io },
1358 /* { "INIT_PLL2" , 0x79, x , x , x , init_pll2 }, */
1359 { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg },
1360 /* { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, x , x , x , init_ram_restrict_zm_reg_group }, */
1361 /* { "INIT_COPY_ZM_REG" , 0x90, x , x , x , init_copy_zm_reg }, */
1362 /* { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, x , x , x , init_zm_reg_group_addr_latched }, */
1363 /* { "INIT_RESERVED" , 0x92, x , x , x , init_reserved }, */
1364 { 0 , 0 , 0 , 0 , 0 , 0 }
1367 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
1369 /* Calculates the length of a given init table entry. */
1370 return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
1373 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
1375 /* Parses all commands in a init table. */
1377 /* We start out executing all commands found in the
1378 * init table. Some op codes may change the status
1379 * of this variable to SKIP, which will cause
1380 * the following op codes to perform no operation until
1381 * the value is changed back to EXECUTE.
1387 /* Loop as long as INIT_DONE (command id 0x71) has not been found
1388 * (and offset < bios length just in case... )
1389 * (and no more than 10000 iterations just in case... ) */
1390 while (((id = bios->data[offset]) != 0x71) && (offset < bios->length) && (count++<10000)) {
1391 /* Find matching id in itbl_entry */
1392 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
1395 if (itbl_entry[i].name) {
1396 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ (0x%02X) - %s ]\n", offset,
1397 itbl_entry[i].id, itbl_entry[i].name);
1399 /* execute eventual command handler */
1400 if (itbl_entry[i].handler)
1401 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
1404 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Init table command not found: 0x%02X\n",
1408 /* Add the offset of the current command including all data
1409 * of that command. The offset will then be pointing on the
1412 offset += get_init_table_entry_length(bios, offset, i);
1416 void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios)
1418 /* Loops and calls parse_init_table() for each present table. */
1422 init_exec_t iexec = {TRUE, FALSE};
1424 while (table = *((CARD16 *) (&bios->data[bios->init_tbls_offset + i]))) {
1426 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing init table %d\n",
1429 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",table);
1431 parse_init_table(pScrn, bios, table, &iexec);
1436 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
1438 /* Parses the init table segment that the bit entry points to.
1439 * Starting at bitentry->offset:
1441 * offset + 0 (16 bits): offset of init tables
1442 * offset + 2 (16 bits): macro index table offset
1443 * offset + 4 (16 bits): macro offset
1444 * offset + 6 (16 bits): condition offset
1445 * offset + 8 (16 bits): io flag condition offset (?)
1446 * offset + 10 (16 bits): io flag condition offset (?)
1447 * offset + 12 (16 bits): unknown
1449 * offset + 8 and offset + 10 seems to contain the same
1450 * offsets on all bioses i have checked. Don't know which
1451 * one is the correct, therefore this code will bail out
1452 * if the two values are not the same.
1455 * * In addition to "conditions" and "io flag conditions" there seems to be
1456 * "io conditions". These are probably located at offset + (8, 10 or 12).
1457 * We need more BIOS dumps to figure this out...
1459 * * Are 'I' bit entries always of length 0xE?
1463 if (bitentry->length < 12) {
1464 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to regocnize BIT init table entry.\n");
1468 bios->init_tbls_offset = *((CARD16 *) (&bios->data[bitentry->offset]));
1469 bios->macro_index_offset = *((CARD16 *) (&bios->data[bitentry->offset + 2]));
1470 bios->macro_offset = *((CARD16 *) (&bios->data[bitentry->offset + 4]));
1471 bios->condition_offset =
1472 *((CARD16 *) (&bios->data[bitentry->offset + 6]));
1473 if (*((CARD16 *) (&bios->data[bitentry->offset + 8])) !=
1474 *((CARD16 *) (&bios->data[bitentry->offset + 10]))) {
1475 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to find IO flag condition offset.\n");
1479 bios->io_flag_condition_offset =
1480 *((CARD16 *) (&bios->data[bitentry->offset + 8]));
1482 parse_init_tables(pScrn, bios);
1487 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1489 bit_entry_t *bitentry;
1493 bitentry = (bit_entry_t *) &bios->data[offset];
1495 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Found BIT command with id 0x%02X\n",
1496 offset, bitentry->id[0]);
1498 switch (bitentry->id[0]) {
1500 /* id[0] = 0 and id[1] = 0 ==> end of BIT struture */
1501 if (bitentry->id[1] == 0)
1505 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1506 "0x%04X: Found init table entry in BIT structure.\n",
1509 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1510 /*parse_init_tables(pScrn, bios);*/
1513 /* TODO: What kind of information does the other BIT entrys point to?
1514 * 'P' entry is probably performance tables, but there are
1515 * quite a few others...
1519 offset += sizeof(bit_entry_t);
1523 static unsigned short brs(unsigned char *data, int offset)
1527 ret = (data[offset]) | ((data[offset+1]) << 8);
1531 static void parse_pins_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1533 int pins_version_major=bios->data[offset+5];
1534 int pins_version_minor=bios->data[offset+6];
1535 int init1 = bios->data[offset + 18] + (bios->data[offset + 19] * 256);
1536 int init2 = bios->data[offset + 20] + (bios->data[offset + 21] * 256);
1537 int init_size = bios->data[offset + 22] + (bios->data[offset + 23] * 256) + 1;
1539 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PINS version %d.%d\n",pins_version_major,pins_version_minor);
1542 if (pins_version_major==2)
1543 ram_tab = init1-0x0010;
1545 ram_tab = bios->data[offset + 24] + (bios->data[offset + 25] * 256);
1547 if ((pins_version_major==5)&&(pins_version_minor>=6))
1549 /* VCO range info */
1552 if ((pins_version_major==5)&&(pins_version_minor>=16))
1557 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1562 static unsigned int findstr(bios_t* bios, unsigned char *str, int len)
1566 for (i = 2; i < bios->length; i++)
1567 if (strncmp(&bios->data[i], str, len) == 0)
1573 #define G5_FIXED_LOC 0xe2f8
1576 static unsigned int nv_find_dcb_table(ScrnInfoPtr pScrn, bios_t *bios)
1578 NVPtr pNv = NVPTR(pScrn);
1583 unsigned char headerSize, entries;
1586 int sig_offsets[2] = { 0x4, 0x6 };
1589 /* get the offset from 0x36 */
1591 bufloc = *(CARD16 *)&bios->data[0x36];
1593 if (bufloc == 0x0) {
1594 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV43) {
1596 bufloc = G5_FIXED_LOC;
1602 table2 = &bios->data[bufloc];
1604 /* lets play hunt the signature */
1605 for (i = 0; i < sizeof(sig_offsets) / sizeof(int); i++) {
1606 sig = *(uint32_t*)(table2 + sig_offsets[i]);
1607 if ((sig == 0x4edcbdcb) || (sig == 0xcbbddc4e)) {
1608 offset = sig_offsets[i];
1616 header_word = *(uint32_t *)table2;
1621 headerSize = (header_word >> 8) & 0xff;
1622 entries = (header_word >> 16) & 0xff;
1629 ErrorF("DCB size is %02X, entries is %02X\n", headerSize, entries);
1630 if (entries >= NV40_NUM_DCB_ENTRIES)
1631 entries = NV40_NUM_DCB_ENTRIES;
1633 for (i = 0; i < entries; i++) {
1635 pNv->dcb_table[i] = __bswap_32(*(uint32_t *)&table2[headerSize + 8 * i]);
1637 pNv->dcb_table[i] = *(uint32_t *)&table2[headerSize + 8 * i];
1644 unsigned int NVParseBios(ScrnInfoPtr pScrn)
1646 unsigned int bit_offset;
1649 bios.length=NV_PROM_SIZE;
1650 unsigned char nv_signature[]={0xff,0x7f,'N','V',0x0};
1651 unsigned char bit_signature[]={'B','I','T'};
1656 if (!NVDownloadBios(pScrn, &bios)) {
1657 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1658 "No valid BIOS image found.\n");
1662 /* check for known signatures */
1663 if ((bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature)))) {
1664 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT signature found.\n");
1665 parse_bit_structure(pScrn, &bios, bit_offset + 4);
1666 } else if ((bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature)))) {
1667 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV signature found.\n");
1668 parse_pins_structure(pScrn, &bios, bit_offset);
1670 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No known script signature found.\n");
1673 /* look for NV40+ DCB table - and make a copy somewhere for output setup code */
1674 ret = nv_find_dcb_table(pScrn, &bios);
1677 pNv->dcb_entries = ret;
1678 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DCB found %d entries.\n", ret);
1681 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DCB table found\n");