2 * Copyright 2005-2006 Erik Waling
3 * Copyright 2006 Stephane Marchesin
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #include "nv_include.h"
28 /*#define PERFORM_WRITE*/
43 CARD16 init_tbls_offset;
44 CARD16 macro_index_offset;
46 CARD16 condition_offset;
47 CARD16 io_flag_condition_offset;
50 static Bool NVValidBios(ScrnInfoPtr pScrn, const unsigned char *data)
52 /* check for BIOS signature */
53 if (!(data[0] == 0x55 && data[1] == 0xAA)) {
54 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
55 "...BIOS signature not found\n");
59 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "...appears to be valid\n");
63 static void NVDownloadBiosPROM(ScrnInfoPtr pScrn, unsigned char *data)
65 NVPtr pNv = NVPTR(pScrn);
68 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
69 "Attempting to locate BIOS image in PROM\n");
71 /* enable ROM access */
72 nvWriteMC(pNv, 0x1850, 0x0);
73 for (i=0; i<NV_PROM_SIZE; i++) {
74 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
75 data[i] = pNv->PROM[i];
76 data[i] = pNv->PROM[i];
77 data[i] = pNv->PROM[i];
78 data[i] = pNv->PROM[i];
79 data[i] = pNv->PROM[i];
81 /* disable ROM access */
82 nvWriteMC(pNv, 0x1850, 0x1);
85 static void NVDownloadBiosPRAMIN(ScrnInfoPtr pScrn, unsigned char *data)
87 NVPtr pNv = NVPTR(pScrn);
88 const unsigned char *pramin = (void*)&pNv->REGS[0x00700000/4];
90 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
91 "Attempting to locate BIOS image in PRAMIN\n");
92 memcpy(data, pramin, 65536);
95 static Bool NVDownloadBios(ScrnInfoPtr pScrn, bios_t *bios)
97 NVPtr pNv = NVPTR(pScrn);
99 bios->data = xcalloc(1, 65536);
101 NVDownloadBiosPROM(pScrn, bios->data);
102 if (NVValidBios(pScrn, bios->data))
105 NVDownloadBiosPRAMIN(pScrn, bios->data);
106 if (NVValidBios(pScrn, bios->data))
109 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
110 "Failed to locate BIOS image\n");
120 int length_multiplier;
121 Bool (*handler)(ScrnInfoPtr pScrn, bios_t *, CARD16, init_exec_t *);
126 unsigned short length;
127 unsigned short offset;
130 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec);
132 /* #define MACRO_SIZE 8 */
133 #define CONDITION_SIZE 12
134 #define IO_FLAG_CONDITION_SIZE 9
142 static int nv_valid_reg(CARD32 reg)
144 #define WITHIN(x,y,z) ((x>=y)&&(x<y+z))
145 if (WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
147 if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE))
149 if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE))
151 if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
153 if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
155 if (WITHIN(reg,NV_PGRAPH_OFFSET,NV_PGRAPH_SIZE))
157 if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
159 if (WITHIN(reg,NV_PTIMER_OFFSET,NV_PTIMER_SIZE))
161 if (WITHIN(reg,NV_PVIDEO_OFFSET,NV_PVIDEO_SIZE))
163 if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
165 if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
167 if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
169 if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
171 if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
173 if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
179 static int nv32_rd(ScrnInfoPtr pScrn, CARD32 reg, CARD32 *data)
181 NVPtr pNv = NVPTR(pScrn);
182 *data=pNv->REGS[reg/4];
186 static int nv32_wr(ScrnInfoPtr pScrn, CARD32 reg, CARD32 data)
189 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv32_wr reg 0x%X value 0x%X\n",reg,data);
191 if (!nv_valid_reg(reg))
193 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "========= unknown reg 0x%X ==========\n",reg);
197 NVPtr pNv = NVPTR(pScrn);
198 pNv->REGS[reg/4]=data;
203 void nv_set_crtc_index(ScrnInfoPtr pScrn, CARD8 index)
206 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_set_crtc_index index 0x%X\n",index);
208 NVPtr pNv = NVPTR(pScrn);
209 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
210 VGA_WR08(ptr, 0x3D4, index);
214 CARD8 nv_rd_crtc_data(ScrnInfoPtr pScrn)
216 NVPtr pNv = NVPTR(pScrn);
217 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
218 return VGA_RD08(ptr, 0x3D5);
221 void nv_wr_crtc_data(ScrnInfoPtr pScrn, CARD8 val)
224 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_wr_crtc_data value 0x%X\n",val);
226 NVPtr pNv = NVPTR(pScrn);
227 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
228 VGA_WR08(ptr, 0x3D5, val);
232 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
234 /* INIT_PROG opcode: 0x31
236 * offset (8 bit): opcode
237 * offset + 1 (32 bit): reg
238 * offset + 5 (32 bit): and mask
239 * offset + 9 (8 bit): shift right
240 * offset + 10 (8 bit): number of configurations
241 * offset + 11 (32 bit): register
242 * offset + 15 (32 bit): configuration 1
245 * Starting at offset + 15 there are "number of configurations"
246 * 32 bit values. To find out which configuration value to use
247 * read "CRTC reg" on the CRTC controller with index "CRTC index"
248 * and bitwise AND this value with "and mask" and then bit shift the
249 * result "shift right" bits to the right.
250 * Assign "register" with appropriate configuration value.
253 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
254 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
255 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
256 CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
257 CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
259 CARD32 configval, tmp;
261 if (iexec->execute) {
262 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%04X\n", offset,
265 nv32_rd(pScrn, reg, &tmp);
266 configuration = (tmp & and) >> shiftr;
268 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
269 offset, configuration);
271 if (configuration <= nr) {
274 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
276 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
279 if (nv32_rd(pScrn, reg2, &tmp)) {
280 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
283 nv32_wr(pScrn, reg2, configval);
289 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
291 /* INIT_IO_RESTRICT_PROG opcode: 0x32
293 * offset (8 bit): opcode
294 * offset + 1 (16 bit): CRTC reg
295 * offset + 3 (8 bit): CRTC index
296 * offset + 4 (8 bit): and mask
297 * offset + 5 (8 bit): shift right
298 * offset + 6 (8 bit): number of configurations
299 * offset + 7 (32 bit): register
300 * offset + 11 (32 bit): configuration 1
303 * Starting at offset + 11 there are "number of configurations"
304 * 32 bit values. To find out which configuration value to use
305 * read "CRTC reg" on the CRTC controller with index "CRTC index"
306 * and bitwise AND this value with "and mask" and then bit shift the
307 * result "shift right" bits to the right.
308 * Assign "register" with appropriate configuration value.
311 NVPtr pNv = NVPTR(pScrn);
312 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
313 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
314 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
315 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
316 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
317 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
318 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
320 CARD32 configval, tmp;
322 if (iexec->execute) {
323 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
326 VGA_WR08(ptr,crtcreg, index);
327 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
329 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
330 offset, configuration);
332 if (configuration <= nr) {
334 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
336 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
339 if (nv32_rd(pScrn, reg, &tmp)) {
340 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
343 nv32_wr(pScrn, reg, configval);
349 static Bool init_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
351 CARD8 repeats = *((CARD8 *) (&bios->data[offset + 1]));
354 if (iexec->execute) {
355 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REPEATING FOLLOWING SEGMENT %d TIMES.\n",
358 iexec->repeat = TRUE;
360 for (i = 0; i < repeats - 1; i++)
361 parse_init_table(pScrn, bios, offset + 2, iexec);
363 iexec->repeat = FALSE;
368 static Bool init_end_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
376 static Bool init_copy(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
378 /* XXX: double check this... */
379 NVPtr pNv = NVPTR(pScrn);
380 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
381 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
382 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
383 CARD8 and1 = *((CARD8 *) (&bios->data[offset + 6]));
384 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 7]));
385 CARD8 index = *((CARD8 *) (&bios->data[offset + 9]));
386 CARD8 and2 = *((CARD8 *) (&bios->data[offset + 10]));
390 if (iexec->execute) {
391 if (nv32_rd(pScrn, reg, &data)) {
395 data <<= (0x100 - shift);
398 VGA_WR08(ptr,crtcreg, index);
399 crtcdata = (VGA_RD08(ptr, crtcreg + 1) & and2) | (CARD8) data;
401 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
402 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n"
403 , offset, crtcreg, index, crtcdata);
405 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
406 VGA_RD08(ptr, crtcreg + 1));
408 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_copy crtcreg 0x%X value 0x%X\n",crtcreg+1,crtcdata);
410 printf("WRITE IS PERFORMED\n");
411 VGA_WR08(ptr,crtcreg + 1, crtcdata);
418 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
420 if (iexec->execute) {
421 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n",
424 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",
428 iexec->execute = !iexec->execute;
432 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
434 NVPtr pNv = NVPTR(pScrn);
435 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
436 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
437 CARD16 crtcreg = *((CARD16 *)
438 (&bios->data[bios->io_flag_condition_offset +
439 cond * IO_FLAG_CONDITION_SIZE]));
440 CARD8 index = *((CARD8 *)
441 (&bios->data[bios->io_flag_condition_offset +
442 cond * IO_FLAG_CONDITION_SIZE + 2]));
443 CARD8 and1 = *((CARD8 *)
444 (&bios->data[bios->io_flag_condition_offset +
445 cond * IO_FLAG_CONDITION_SIZE + 3]));
446 CARD8 shift = *((CARD8 *)
447 (&bios->data[bios->io_flag_condition_offset +
448 cond * IO_FLAG_CONDITION_SIZE + 4]));
449 CARD16 offs = *((CARD16 *)
450 (&bios->data[bios->io_flag_condition_offset +
451 cond * IO_FLAG_CONDITION_SIZE + 5]));
452 CARD8 and2 = *((CARD8 *)
453 (&bios->data[bios->io_flag_condition_offset +
454 cond * IO_FLAG_CONDITION_SIZE + 7]));
455 CARD8 cmpval = *((CARD8 *)
456 (&bios->data[bios->io_flag_condition_offset +
457 cond * IO_FLAG_CONDITION_SIZE + 8]));
461 if (iexec->execute) {
462 VGA_WR08(ptr,crtcreg, index);
463 data = VGA_RD08(ptr, crtcreg + 1);
465 offs += (data >> shift);
466 data = *((CARD8 *) (&bios->data[offs]));
469 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
470 "0x%04X: CHECKING IF DATA: %02X equals COND: %02X\n", offset,
473 if (data == cmpval) {
474 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
475 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
478 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
479 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
480 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
481 iexec->execute = FALSE;
487 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
489 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
490 /* XXX: this needs to be confirmed... NOT CORRECT */
491 /*init_io_restrict_prog(bios, offset, iexec);*/
493 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
494 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
495 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
496 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
497 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
498 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
500 CARD32 configval, tmp;
502 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
503 crtcreg, index, reg);
505 VGA_WR08(ptr,crtcreg, index);
506 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
508 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
509 offset, configuration);
511 if (configuration <= nr) {
513 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &configval))
514 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
518 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
520 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
526 if (iexec->execute) {
529 configval = 0x01014E07;
532 configval = 0x13030E02;
536 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
539 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
540 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
543 nv32_wr(pScrn, reg, configval);
549 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
551 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
552 CARD32 val = *((CARD32 *) (&bios->data[offset + 5]));
553 CARD32 configval, tmp;
555 if (iexec->execute) {
558 configval = 0x00011F05;
562 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
565 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
566 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
569 nv32_wr(pScrn, reg, configval);
571 /*xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);*/
577 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
579 CARD8 crtcindex = *((CARD8 *) (&bios->data[offset + 1]));
580 CARD8 crtcdata = *((CARD8 *) (&bios->data[offset + 2]));
581 CARD8 initial_index = *((CARD8 *) (&bios->data[offset + 3]));
582 CARD8 entries = *((CARD8 *) (&bios->data[offset + 4]));
586 if (iexec->execute) {
587 for (i = 0; i < entries; i++) {
588 nv_set_crtc_index(pScrn, crtcindex);
590 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
591 crtcindex, initial_index + i);
593 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
594 nv_rd_crtc_data(pScrn));
596 nv_wr_crtc_data(pScrn, initial_index + i);
598 nv_set_crtc_index(pScrn, crtcdata);
600 data = *((CARD8 *) (&bios->data[offset + 5 + i]));
602 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
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, data);
614 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
616 /* XXX: IS THIS CORRECT? check the typecast .. probably wrong */
618 NVPtr pNv = NVPTR(pScrn);
619 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
620 CARD8 and = *((CARD8 *) (&bios->data[offset + 2]));
621 CARD8 or = *((CARD8 *) (&bios->data[offset + 3]));
624 if (iexec->execute) {
625 nv_set_crtc_index(pScrn, index);
626 data = (nv_rd_crtc_data(pScrn) & and) | or;
627 /*printf("and: 0x%02x or: 0x%02x\n", and, or);*/
628 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
631 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
632 nv_rd_crtc_data(pScrn));
634 nv_wr_crtc_data(pScrn, data);
639 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
641 /* INIT_ZM_CR opcode: 0x53
643 * offset (8 bit): opcode
644 * offset + 1 (8 bit): CRTC index
645 * offset + 2 (8 bit): value
647 * Assign "value" to CRTC register with index "CRTC index".
650 NVPtr pNv = NVPTR(pScrn);
651 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
652 CARD8 value = *((CARD8 *) (&bios->data[offset + 2]));
654 if (iexec->execute) {
655 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
658 nv_set_crtc_index(pScrn, index);
660 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
661 nv_rd_crtc_data(pScrn));
663 nv_wr_crtc_data(pScrn, value);
668 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
670 /* INIT_ZM_CR opcode: 0x54
672 * offset (8 bit): opcode
673 * offset + 1 (8 bit): number of groups (index, value)
674 * offset + 2 (8 bit): index 1
675 * offset + 3 (8 bit): value 1
678 * Assign "value n" to CRTC register with index "index n".
681 CARD8 nr = *((CARD8 *) (&bios->data[offset + 1]));
685 if (iexec->execute) {
686 for (i = 0; i < nr; i++) {
687 index = *((CARD8 *) (&bios->data[offset + 2 + 2 * i]));
688 value = *((CARD8 *) (&bios->data[offset + 2 + 2 * i + 1]));
690 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
693 nv_set_crtc_index(pScrn, index);
695 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
696 nv_rd_crtc_data(pScrn));
697 nv_wr_crtc_data(pScrn, value);
703 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
705 /* My BIOS does not use this command. */
706 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
711 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
713 /* INIT_ZM_REG_SEQUENCE opcode: 0x58
715 * offset (8 bit): opcode
716 * offset + 1 (32 bit): register base
717 * offset + 5 (8 bit): nr
718 * offset + 6 (32 bit): value to assign "register base" + 4
721 * Initialzies a sequence of "nr" registers starting at "register base".
724 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
725 CARD32 nr = *((CARD8 *) (&bios->data[offset + 5]));
730 if (iexec->execute) {
731 for (i = 0; i < nr; i++) {
732 data = *((CARD32 *) (&bios->data[offset + 6 + i * 4]));
733 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
736 if (nv32_rd(pScrn, reg + i * 4, &tmp)) {
737 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
741 nv32_wr(pScrn, reg + i * 4, data);
747 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
749 /* INIT_INDIRECT_REG opcode: 0x5A
751 * offset (8 bit): opcode
752 * offset + 1 (32 bit): register
753 * offset + 5 (16 bit): adress offset (in bios)
755 * Lookup value at offset data in the bios and write it to reg
757 NVPtr pNv = NVPTR(pScrn);
758 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
759 CARD32 data = *((CARD16 *) (&bios->data[offset + 5]));
760 CARD32 data2 = bios->data[data];
762 if (iexec->execute) {
763 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
764 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n",
765 offset, reg, data, data2);
767 if (DEBUGLEVEL >= 6) {
769 nv32_rd(pScrn, reg, &tmpval);
770 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
773 nv32_wr(pScrn, reg, data2);
778 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
780 /* INIT_SUB_DIRECT opcode: 0x5B
782 * offset (8 bit): opcode
783 * offset + 1 (16 bit): subroutine offset (in bios)
785 * Calls a subroutine that will execute commands until INIT_DONE
789 CARD16 sub_offset = *((CARD16 *) (&bios->data[offset + 1]));
791 if (iexec->execute) {
792 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-ROUTINE AT: 0x%04X\n",
795 parse_init_table(pScrn, bios, sub_offset, iexec);
797 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-ROUTINE\n", offset);
802 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
804 CARD32 srcreg = *((CARD32 *) (&bios->data[offset + 1]));
805 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
806 CARD32 and1 = *((CARD32 *) (&bios->data[offset + 6]));
807 CARD32 xor = *((CARD32 *) (&bios->data[offset + 10]));
808 CARD32 dstreg = *((CARD32 *) (&bios->data[offset + 14]));
809 CARD32 and2 = *((CARD32 *) (&bios->data[offset + 18]));
813 if (iexec->execute) {
814 nv32_rd(pScrn, srcreg, &srcdata);
821 srcdata = (srcdata & and1) ^ xor;
823 nv32_rd(pScrn, dstreg, &dstdata);
829 nv32_rd(pScrn, dstreg, &tmp);
831 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, dstreg,
834 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmp);
836 nv32_wr(pScrn, dstreg, dstdata);
841 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
843 NVPtr pNv = NVPTR(pScrn);
844 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
845 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
846 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
847 CARD8 value = *((CARD8 *) (&bios->data[offset + 4]));
849 if (iexec->execute) {
850 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
851 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
852 offset, crtcreg, index, value);
854 VGA_WR08(ptr,crtcreg, index);
856 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
857 VGA_RD08(ptr, crtcreg + 1));
860 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_zm_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,value);
862 VGA_WR08(ptr,crtcreg + 1, value);
868 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
870 // FIXME replace with a suitable implementation
872 CARD16 ramcfg = *((CARD16 *) (&bios->data[bios->ram_table_offset]));
877 if (iexec->execute) {
878 nv32_rd(pScrn, 0x00101000, &strapinfo);
879 nv32_rd(pScrn, 0x00100080, &pfb_debug);
881 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
882 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
883 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG: 0x%04X\n", ramcfg);
885 pfb_debug &= 0xffffffef;
887 strapinfo &= 0x0000000f;
888 ramcfg2 = *((CARD16 *)
889 (&bios->data[bios->ram_table_offset + (2 * strapinfo)]));
891 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AFTER MANIPULATION\n");
892 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
893 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
894 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG2: 0x%08X\n", ramcfg2);
896 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
901 nv32_rd(pScrn, 0x00100200, ®1);
902 nv32_rd(pScrn, 0x0010020C, ®2);
904 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x00100200: 0x%08X\n", reg1);
905 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x0010020C: 0x%08X\n", reg2);
911 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
913 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
914 CARD32 value1 = *((CARD32 *) (&bios->data[offset + 5]));
915 CARD32 value2 = *((CARD32 *) (&bios->data[offset + 9]));
917 if (iexec->execute) {
918 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
919 offset, reg, value1);
920 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
921 offset, reg, value2);
923 if (DEBUGLEVEL >= 6) {
925 nv32_rd(pScrn, reg, &tmpval);
926 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
928 nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), &tmpval);
929 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: PCICFG_ROMSHADOW: 0x%02X\n", offset, tmpval);
932 nv32_wr(pScrn, reg, value1);
933 nv32_wr(pScrn, reg, value2);
935 /* PCI Config space init needs to be added here. */
936 /* if (nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), value1)) */
937 /* nv32_wr(pScrn, PCICFG(PCICFG_ROMSHADOW), value1 & 0xfffffffe) */
942 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
944 /* INIT_INDEX_IO8 opcode: 0x69
946 * offset (8 bit): opcode
947 * offset + 1 (16 bit): CRTC reg
948 * offset + 3 (8 bit): and mask
949 * offset + 4 (8 bit): or with
954 NVPtr pNv = NVPTR(pScrn);
955 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
956 CARD16 reg = *((CARD16 *) (&bios->data[offset + 1]));
957 CARD8 and = *((CARD8 *) (&bios->data[offset + 3]));
958 CARD8 or = *((CARD8 *) (&bios->data[offset + 4]));
961 if (iexec->execute) {
962 data = (VGA_RD08(ptr, reg) & and) | or;
964 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
965 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n",
967 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
971 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
973 VGA_WR08(ptr, reg, data);
979 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
981 CARD8 sub = *((CARD8 *) (&bios->data[offset + 1]));
983 if (iexec->execute) {
984 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-SCRIPT: %d\n", offset, sub);
986 parse_init_table(pScrn, bios,
987 *((CARD16 *) (&bios->data[bios->init_tbls_offset + sub * 2])),
990 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-SCRIPT\n", offset);
995 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
997 /* INIT_RAM_CONDITION opcode: 0x6D
999 * offset (8 bit): opcode
1000 * offset + 1 (8 bit): and mask
1001 * offset + 2 (8 bit): cmpval
1003 * Test if (NV_PFB_BOOT & and mask) matches cmpval
1005 NVPtr pNv = NVPTR(pScrn);
1006 CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
1007 CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
1010 if (iexec->execute) {
1011 data=(pNv->PFB[NV_PFB_BOOT/4])∧
1013 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1014 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1015 offset, data, cmpval);
1017 if (data == cmpval) {
1018 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1019 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1022 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1023 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1024 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1025 iexec->execute = FALSE;
1031 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1033 /* INIT_NV_REG opcode: 0x6E
1035 * offset (8 bit): opcode
1036 * offset + 1 (32 bit): register
1037 * offset + 5 (32 bit): and mask
1038 * offset + 9 (32 bit): or with
1040 * Assign "register" to (REGVAL(register) & "and mask") | "or with";
1043 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1044 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
1045 CARD32 or = *((CARD32 *) (&bios->data[offset + 9]));
1047 unsigned int status;
1049 if (iexec->execute) {
1051 if ((status = nv32_rd(pScrn, reg, &data))) {
1052 data = (data & and) | or;
1053 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1056 if (DEBUGLEVEL >= 6 && status) {
1058 nv32_rd(pScrn, reg, &tmpval);
1059 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1063 nv32_wr(pScrn, reg, data);
1064 /* Assign: reg = data */
1071 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1073 // FIXME replace with the haiku version
1074 /* XXX: Not sure this is correct... */
1076 CARD8 macro = *((CARD8 *) (&bios->data[offset + 1]));
1078 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE]));
1080 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE + 4]));
1082 if (iexec->execute) {
1083 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING MACRO: 0x%02X\n", offset, macro);
1084 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
1087 if (DEBUGLEVEL >= 6) {
1089 nv32_rd(pScrn, reg, &tmpval);
1090 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1094 nv32_wr(pScrn, reg, value);
1100 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1102 CARD8 index = *((CARD8 *) (&bios->data[offset + 1]));
1103 CARD32 tmp = bios->macro_index_offset + (index << 1);
1104 CARD32 offs = *((CARD8 *) (&bios->data[tmp])) << 3;
1105 CARD32 nr = *((CARD8 *) (&bios->data[tmp + 1]));
1110 if (iexec->execute) {
1111 offs += bios->macro_offset;
1112 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: WRITE %d 32-BIT REGS:\n", offset, nr);
1114 for (i = 0; i < nr; i++) {
1115 reg = *((CARD32 *) (&bios->data[offs + (i << 3)]));
1116 data = *((CARD32 *) (&bios->data[offs + (i << 3) + 4]));
1118 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1121 if (DEBUGLEVEL >= 6) {
1123 nv32_rd(pScrn, reg, &tmpval);
1124 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1128 nv32_wr(pScrn, reg, data);
1134 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1139 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1141 if (!iexec->execute) {
1142 iexec->execute = TRUE;;
1143 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n",
1149 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1151 /* INIT_RAM_CONDITION2 opcode: 0x73
1153 * offset (8 bit): opcode
1154 * offset + 1 (8 bit): and mask
1155 * offset + 2 (8 bit): cmpval
1157 * Test if (NV_EXTDEV_BOOT & and mask) matches cmpval
1159 NVPtr pNv = NVPTR(pScrn);
1160 CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
1161 CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
1164 if (iexec->execute) {
1165 data=(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT))∧
1167 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1168 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1169 offset, data, cmpval);
1171 if (data == cmpval) {
1172 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1173 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1176 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1177 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1178 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1179 iexec->execute = FALSE;
1185 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1187 /* INIT_TIME opcode: 0x74
1189 * offset (8 bit): opcode
1190 * offset + 1 (16 bit): time
1192 * Sleep for "time" microseconds.
1195 CARD16 time = *((CARD16 *) (&bios->data[offset + 1]));
1197 if (iexec->execute) {
1198 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Sleeping for 0x%04X microseconds.\n",
1206 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1208 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
1211 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE]));
1214 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 4]));
1217 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 8]));
1220 if (iexec->execute) {
1221 if (nv32_rd(pScrn, reg, &data)) {
1224 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1225 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1226 offset, data, cmpval);
1228 if (data == cmpval) {
1229 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1230 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1233 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1234 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1235 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1236 iexec->execute = FALSE;
1243 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1245 /* INIT_INDEX_IO opcode: 0x78
1247 * offset (8 bit): opcode
1248 * offset + 1 (16 bit): CRTC reg
1249 * offset + 3 (8 bit): CRTC index
1250 * offset + 4 (8 bit): and mask
1251 * offset + 5 (8 bit): or with
1256 NVPtr pNv = NVPTR(pScrn);
1257 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
1258 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
1259 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
1260 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
1261 CARD8 or = *((CARD8 *) (&bios->data[offset + 5]));
1264 if (iexec->execute) {
1265 VGA_WR08(ptr,crtcreg, index);
1266 /* data at reg + 1 */
1267 data = (VGA_RD08(ptr, crtcreg + 1) & and) | or;
1269 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1270 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
1271 offset, crtcreg, index, data);
1272 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
1273 VGA_RD08(ptr, crtcreg + 1));
1275 #ifdef PERFORM_WRITE
1276 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,data);
1278 VGA_WR08(ptr,crtcreg + 1, data);
1284 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1286 /* INIT_ZM_REG opcode: 0x7A
1288 * offset (8 bit): opcode
1289 * offset + 1 (32 bit): register
1290 * offset + 5 (32 bit): value
1292 * Assign "register" to "value";
1295 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1296 CARD32 value = *((CARD32 *) (&bios->data[offset + 5]));
1298 if (iexec->execute) {
1299 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
1300 offset, reg, value);
1302 if (DEBUGLEVEL >= 6) {
1304 nv32_rd(pScrn, reg, &tmpval);
1305 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1308 nv32_wr(pScrn, reg, value);
1310 /* Assign: reg = value */
1315 static init_tbl_entry_t itbl_entry[] = {
1316 /* command name , id , length , offset , mult , command handler */
1317 { "INIT_PROG" , 0x31, 15 , 10 , 4 , init_prog },
1318 { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog },
1319 { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat },
1320 { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat },
1321 { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy },
1322 { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not },
1323 { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition },
1324 /* { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, x , x , x, , init_idx_addr_latched }, */
1325 { "INIT_IO_RESTRICT_PLL" , 0x4A, 43 , 0 , 0 , init_io_restrict_pll },
1326 { "INIT_PLL" , 0x4B, 9 , 0 , 0 , init_pll },
1327 /* { "INIT_I2C_BYTE" , 0x4C, x , x , x , init_i2c_byte }, */
1328 /* { "INIT_ZM_I2C_BYTE" , 0x4D, x , x , x , init_zm_i2c_byte }, */
1329 /* { "INIT_ZM_I2C" , 0x4E, x , x , x , init_zm_i2c }, */
1330 { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch },
1331 { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr },
1332 { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr },
1333 { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group },
1334 { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time },
1335 { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence },
1336 { "INIT_INDIRECT_REG" , 0x5A, 7 , 0 , 0 , init_indirect_reg },
1337 { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct },
1338 { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg },
1339 { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io },
1340 { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem },
1341 { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset },
1342 /* { "INIT_NEXT" , 0x66, x , x , x , init_next }, */
1343 /* { "INIT_NEXT" , 0x67, x , x , x , init_next }, */
1344 /* { "INIT_NEXT" , 0x68, x , x , x , init_next }, */
1345 { "INIT_INDEX_IO8" , 0x69, 5 , 0 , 0 , init_index_io8 },
1346 { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub },
1347 { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition },
1348 { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg },
1349 { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro },
1350 { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done },
1351 { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume },
1352 { "INIT_RAM_CONDITION2" , 0x73, 9 , 0 , 0 , init_ram_condition2 },
1353 { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time },
1354 { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition },
1355 /* { "INIT_IO_CONDITION", , 0x76, x , x, , x , init_io_condition }, */
1356 { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io },
1357 /* { "INIT_PLL2" , 0x79, x , x , x , init_pll2 }, */
1358 { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg },
1359 /* { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, x , x , x , init_ram_restrict_zm_reg_group }, */
1360 /* { "INIT_COPY_ZM_REG" , 0x90, x , x , x , init_copy_zm_reg }, */
1361 /* { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, x , x , x , init_zm_reg_group_addr_latched }, */
1362 /* { "INIT_RESERVED" , 0x92, x , x , x , init_reserved }, */
1363 { 0 , 0 , 0 , 0 , 0 , 0 }
1366 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
1368 /* Calculates the length of a given init table entry. */
1369 return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
1372 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
1374 /* Parses all commands in a init table. */
1376 /* We start out executing all commands found in the
1377 * init table. Some op codes may change the status
1378 * of this variable to SKIP, which will cause
1379 * the following op codes to perform no operation until
1380 * the value is changed back to EXECUTE.
1386 /* Loop as long as INIT_DONE (command id 0x71) has not been found
1387 * (and offset < bios length just in case... )
1388 * (and no more than 10000 iterations just in case... ) */
1389 while (((id = bios->data[offset]) != 0x71) && (offset < bios->length) && (count++<10000)) {
1390 /* Find matching id in itbl_entry */
1391 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
1394 if (itbl_entry[i].name) {
1395 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ (0x%02X) - %s ]\n", offset,
1396 itbl_entry[i].id, itbl_entry[i].name);
1398 /* execute eventual command handler */
1399 if (itbl_entry[i].handler)
1400 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
1403 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Init table command not found: 0x%02X\n",
1407 /* Add the offset of the current command including all data
1408 * of that command. The offset will then be pointing on the
1411 offset += get_init_table_entry_length(bios, offset, i);
1415 void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios)
1417 /* Loops and calls parse_init_table() for each present table. */
1421 init_exec_t iexec = {TRUE, FALSE};
1423 while (table = *((CARD16 *) (&bios->data[bios->init_tbls_offset + i]))) {
1425 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing init table %d\n",
1428 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",table);
1430 parse_init_table(pScrn, bios, table, &iexec);
1435 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
1437 /* Parses the init table segment that the bit entry points to.
1438 * Starting at bitentry->offset:
1440 * offset + 0 (16 bits): offset of init tables
1441 * offset + 2 (16 bits): macro index table offset
1442 * offset + 4 (16 bits): macro offset
1443 * offset + 6 (16 bits): condition offset
1444 * offset + 8 (16 bits): io flag condition offset (?)
1445 * offset + 10 (16 bits): io flag condition offset (?)
1446 * offset + 12 (16 bits): unknown
1448 * offset + 8 and offset + 10 seems to contain the same
1449 * offsets on all bioses i have checked. Don't know which
1450 * one is the correct, therefore this code will bail out
1451 * if the two values are not the same.
1454 * * In addition to "conditions" and "io flag conditions" there seems to be
1455 * "io conditions". These are probably located at offset + (8, 10 or 12).
1456 * We need more BIOS dumps to figure this out...
1458 * * Are 'I' bit entries always of length 0xE?
1462 if (bitentry->length < 12) {
1463 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to regocnize BIT init table entry.\n");
1467 bios->init_tbls_offset = *((CARD16 *) (&bios->data[bitentry->offset]));
1468 bios->macro_index_offset = *((CARD16 *) (&bios->data[bitentry->offset + 2]));
1469 bios->macro_offset = *((CARD16 *) (&bios->data[bitentry->offset + 4]));
1470 bios->condition_offset =
1471 *((CARD16 *) (&bios->data[bitentry->offset + 6]));
1472 if (*((CARD16 *) (&bios->data[bitentry->offset + 8])) !=
1473 *((CARD16 *) (&bios->data[bitentry->offset + 10]))) {
1474 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to find IO flag condition offset.\n");
1478 bios->io_flag_condition_offset =
1479 *((CARD16 *) (&bios->data[bitentry->offset + 8]));
1481 parse_init_tables(pScrn, bios);
1486 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1488 bit_entry_t *bitentry;
1492 bitentry = (bit_entry_t *) &bios->data[offset];
1494 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Found BIT command with id 0x%02X\n",
1495 offset, bitentry->id[0]);
1497 switch (bitentry->id[0]) {
1499 /* id[0] = 0 and id[1] = 0 ==> end of BIT struture */
1500 if (bitentry->id[1] == 0)
1504 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1505 "0x%04X: Found init table entry in BIT structure.\n",
1508 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1509 /*parse_init_tables(pScrn, bios);*/
1512 /* TODO: What kind of information does the other BIT entrys point to?
1513 * 'P' entry is probably performance tables, but there are
1514 * quite a few others...
1518 offset += sizeof(bit_entry_t);
1522 static void parse_pins_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1524 int pins_version_major=bios->data[offset+5];
1525 int pins_version_minor=bios->data[offset+6];
1526 int init1 = bios->data[offset + 18] + (bios->data[offset + 19] * 256);
1527 int init2 = bios->data[offset + 20] + (bios->data[offset + 21] * 256);
1528 int init_size = bios->data[offset + 22] + (bios->data[offset + 23] * 256) + 1;
1531 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PINS version %d.%d\n",pins_version_major,pins_version_minor);
1534 if (pins_version_major==2)
1535 ram_tab = init1-0x0010;
1537 ram_tab = bios->data[offset + 24] + (bios->data[offset + 25] * 256);
1539 if ((pins_version_major==5)&&(pins_version_minor>=6))
1541 /* VCO range info */
1544 if ((pins_version_major==5)&&(pins_version_minor>=16))
1549 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1554 static unsigned int findstr(bios_t* bios, unsigned char *str, int len)
1558 for (i = 2; i < bios->length; i++)
1559 if (strncmp(&bios->data[i], str, len) == 0)
1566 #define G5_FIXED_LOC 0xe2f8
1568 static unsigned int nv_find_dcb_table(ScrnInfoPtr pScrn, bios_t *bios)
1570 NVPtr pNv = NVPTR(pScrn);
1575 unsigned char headerSize, entries;
1578 int sig_offsets[2] = { 0x4, 0x6 };
1581 /* get the offset from 0x36 */
1583 bufloc = *(CARD16 *)&bios->data[0x36];
1585 if (bufloc == 0x0) {
1586 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV43) {
1588 bufloc = G5_FIXED_LOC;
1594 table2 = &bios->data[bufloc];
1596 /* lets play hunt the signature */
1597 for (i = 0; i < sizeof(sig_offsets) / sizeof(int); i++) {
1598 sig = *(uint32_t*)(table2 + sig_offsets[i]);
1599 if ((sig == 0x4edcbdcb) || (sig == 0xcbbddc4e)) {
1600 offset = sig_offsets[i];
1608 header_word = *(uint32_t *)table2;
1613 headerSize = (header_word >> 8) & 0xff;
1614 entries = (header_word >> 16) & 0xff;
1621 ErrorF("DCB size is %02X, entries is %02X\n", headerSize, entries);
1622 if (entries >= NV40_NUM_DCB_ENTRIES)
1623 entries = NV40_NUM_DCB_ENTRIES;
1625 for (i = 0; i < entries; i++) {
1627 pNv->dcb_table[i] = __bswap_32(*(uint32_t *)&table2[headerSize + 8 * i]);
1629 pNv->dcb_table[i] = *(uint32_t *)&table2[headerSize + 8 * i];
1635 unsigned int NVParseBios(ScrnInfoPtr pScrn)
1637 unsigned int bit_offset;
1640 bios.length=NV_PROM_SIZE;
1641 unsigned char nv_signature[]={0xff,0x7f,'N','V',0x0};
1642 unsigned char bit_signature[]={'B','I','T'};
1647 if (!NVDownloadBios(pScrn, &bios)) {
1648 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1649 "No valid BIOS image found.\n");
1653 /* check for known signatures */
1654 if ((bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature)))) {
1655 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT signature found.\n");
1656 parse_bit_structure(pScrn, &bios, bit_offset + 4);
1657 } else if ((bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature)))) {
1658 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV signature found.\n");
1659 parse_pins_structure(pScrn, &bios, bit_offset);
1661 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No known script signature found.\n");
1664 /* look for NV40+ DCB table - and make a copy somewhere for
1667 ret = nv_find_dcb_table(pScrn, &bios);
1669 pNv->dcb_entries = ret;
1670 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1671 "DCB found %d entries.\n", ret);
1673 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DCB table found\n");