2 * Copyright 2005-2006 Erik Waling
3 * Copyright 2006 Stephane Marchesin
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #include "nv_include.h"
28 /*#define PERFORM_WRITE*/
43 CARD16 init_tbls_offset;
44 CARD16 macro_index_offset;
46 CARD16 condition_offset;
47 CARD16 io_flag_condition_offset;
50 static Bool NVValidVBIOS(ScrnInfoPtr pScrn, const unsigned char *data)
52 /* check for BIOS signature */
53 if (!(data[0] == 0x55 && data[1] == 0xAA)) {
54 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
55 "...BIOS signature not found\n");
59 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "...appears to be valid\n");
63 static void NVShadowVBIOS_PROM(ScrnInfoPtr pScrn, unsigned char *data)
65 NVPtr pNv = NVPTR(pScrn);
68 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
69 "Attempting to locate BIOS image in PROM\n");
71 /* enable ROM access */
72 nvWriteMC(pNv, 0x1850, 0x0);
73 for (i=0; i<NV_PROM_SIZE; i++) {
74 /* according to nvclock, we need that to work around a 6600GT/6800LE bug */
75 data[i] = pNv->PROM[i];
76 data[i] = pNv->PROM[i];
77 data[i] = pNv->PROM[i];
78 data[i] = pNv->PROM[i];
79 data[i] = pNv->PROM[i];
81 /* disable ROM access */
82 nvWriteMC(pNv, 0x1850, 0x1);
85 static void NVShadowVBIOS_PRAMIN(ScrnInfoPtr pScrn, unsigned char *data)
87 NVPtr pNv = NVPTR(pScrn);
88 const unsigned char *pramin = (void*)&pNv->REGS[0x00700000/4];
89 uint32_t old_bar0_pramin = 0;
91 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
92 "Attempting to locate BIOS image in PRAMIN\n");
94 if (pNv->Architecture >= NV_ARCH_50) {
97 vbios_vram = (pNv->REGS[0x619f04/4] & ~0xff) << 8;
99 vbios_vram = pNv->REGS[0x1700/4] << 16;
100 vbios_vram += 0xf0000;
103 old_bar0_pramin = pNv->REGS[0x1700/4];
104 pNv->REGS[0x1700/4] = vbios_vram >> 16;
107 memcpy(data, pramin, 65536);
109 if (pNv->Architecture >= NV_ARCH_50) {
110 pNv->REGS[0x1700/4] = old_bar0_pramin;
114 static Bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint32_t *data)
116 NVPtr pNv = NVPTR(pScrn);
118 NVShadowVBIOS_PROM(pScrn, data);
119 if (NVValidVBIOS(pScrn, data))
122 NVShadowVBIOS_PRAMIN(pScrn, data);
123 if (NVValidVBIOS(pScrn, data))
134 int length_multiplier;
135 Bool (*handler)(ScrnInfoPtr pScrn, bios_t *, CARD16, init_exec_t *);
140 unsigned short length;
141 unsigned short offset;
144 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec);
146 /* #define MACRO_SIZE 8 */
147 #define CONDITION_SIZE 12
148 #define IO_FLAG_CONDITION_SIZE 9
156 static int nv_valid_reg(CARD32 reg)
158 #define WITHIN(x,y,z) ((x>=y)&&(x<y+z))
159 if (WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
161 if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE))
163 if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE))
165 if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
167 if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
169 if (WITHIN(reg,NV_PGRAPH_OFFSET,NV_PGRAPH_SIZE))
171 if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
173 if (WITHIN(reg,NV_PTIMER_OFFSET,NV_PTIMER_SIZE))
175 if (WITHIN(reg,NV_PVIDEO_OFFSET,NV_PVIDEO_SIZE))
177 if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
179 if (WITHIN(reg,NV_FIFO_OFFSET,NV_FIFO_SIZE))
181 if (WITHIN(reg,NV_PCIO0_OFFSET,NV_PCIO0_SIZE))
183 if (WITHIN(reg,NV_PDIO0_OFFSET,NV_PDIO0_SIZE))
185 if (WITHIN(reg,NV_PVIO_OFFSET,NV_PVIO_SIZE))
187 if (WITHIN(reg,NV_PROM_OFFSET,NV_PROM_SIZE))
193 static int nv32_rd(ScrnInfoPtr pScrn, CARD32 reg, CARD32 *data)
195 NVPtr pNv = NVPTR(pScrn);
196 *data=pNv->REGS[reg/4];
200 static int nv32_wr(ScrnInfoPtr pScrn, CARD32 reg, CARD32 data)
203 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv32_wr reg 0x%X value 0x%X\n",reg,data);
205 if (!nv_valid_reg(reg))
207 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "========= unknown reg 0x%X ==========\n",reg);
211 NVPtr pNv = NVPTR(pScrn);
212 pNv->REGS[reg/4]=data;
217 void nv_set_crtc_index(ScrnInfoPtr pScrn, CARD8 index)
220 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_set_crtc_index index 0x%X\n",index);
222 NVPtr pNv = NVPTR(pScrn);
223 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
224 VGA_WR08(ptr, 0x3D4, index);
228 CARD8 nv_rd_crtc_data(ScrnInfoPtr pScrn)
230 NVPtr pNv = NVPTR(pScrn);
231 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
232 return VGA_RD08(ptr, 0x3D5);
235 void nv_wr_crtc_data(ScrnInfoPtr pScrn, CARD8 val)
238 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_wr_crtc_data value 0x%X\n",val);
240 NVPtr pNv = NVPTR(pScrn);
241 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
242 VGA_WR08(ptr, 0x3D5, val);
246 static Bool init_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
248 /* INIT_PROG opcode: 0x31
250 * offset (8 bit): opcode
251 * offset + 1 (32 bit): reg
252 * offset + 5 (32 bit): and mask
253 * offset + 9 (8 bit): shift right
254 * offset + 10 (8 bit): number of configurations
255 * offset + 11 (32 bit): register
256 * offset + 15 (32 bit): configuration 1
259 * Starting at offset + 15 there are "number of configurations"
260 * 32 bit values. To find out which configuration value to use
261 * read "CRTC reg" on the CRTC controller with index "CRTC index"
262 * and bitwise AND this value with "and mask" and then bit shift the
263 * result "shift right" bits to the right.
264 * Assign "register" with appropriate configuration value.
267 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
268 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
269 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 9]));
270 CARD8 nr = *((CARD8 *) (&bios->data[offset + 10]));
271 CARD32 reg2 = *((CARD32 *) (&bios->data[offset + 11]));
273 CARD32 configval, tmp;
275 if (iexec->execute) {
276 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%04X\n", offset,
279 nv32_rd(pScrn, reg, &tmp);
280 configuration = (tmp & and) >> shiftr;
282 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
283 offset, configuration);
285 if (configuration <= nr) {
288 *((CARD32 *) (&bios->data[offset + 15 + configuration * 4]));
290 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
293 if (nv32_rd(pScrn, reg2, &tmp)) {
294 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
297 nv32_wr(pScrn, reg2, configval);
303 static Bool init_io_restrict_prog(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
305 /* INIT_IO_RESTRICT_PROG opcode: 0x32
307 * offset (8 bit): opcode
308 * offset + 1 (16 bit): CRTC reg
309 * offset + 3 (8 bit): CRTC index
310 * offset + 4 (8 bit): and mask
311 * offset + 5 (8 bit): shift right
312 * offset + 6 (8 bit): number of configurations
313 * offset + 7 (32 bit): register
314 * offset + 11 (32 bit): configuration 1
317 * Starting at offset + 11 there are "number of configurations"
318 * 32 bit values. To find out which configuration value to use
319 * read "CRTC reg" on the CRTC controller with index "CRTC index"
320 * and bitwise AND this value with "and mask" and then bit shift the
321 * result "shift right" bits to the right.
322 * Assign "register" with appropriate configuration value.
325 NVPtr pNv = NVPTR(pScrn);
326 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
327 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
328 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
329 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
330 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
331 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
332 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
334 CARD32 configval, tmp;
336 if (iexec->execute) {
337 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
340 VGA_WR08(ptr,crtcreg, index);
341 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
343 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
344 offset, configuration);
346 if (configuration <= nr) {
348 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
350 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
353 if (nv32_rd(pScrn, reg, &tmp)) {
354 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
357 nv32_wr(pScrn, reg, configval);
363 static Bool init_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
365 CARD8 repeats = *((CARD8 *) (&bios->data[offset + 1]));
368 if (iexec->execute) {
369 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REPEATING FOLLOWING SEGMENT %d TIMES.\n",
372 iexec->repeat = TRUE;
374 for (i = 0; i < repeats - 1; i++)
375 parse_init_table(pScrn, bios, offset + 2, iexec);
377 iexec->repeat = FALSE;
382 static Bool init_io_restrict_prog2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
384 /* INIT_IO_RESTRICT_PROG opcode: 0x34
386 * offset (8 bit): opcode
387 * offset + 1 (16 bit): CRTC reg
388 * offset + 3 (8 bit): CRTC index
389 * offset + 4 (8 bit): and mask
390 * offset + 5 (8 bit): shift right
391 * offset + 6 (8 bit): condition offset for doubling freq
392 * offset + 7 (8 bit): number of configurations
393 * offset + 8 (32 bit): register
394 * offset + 12 (32 bit): configuration 1
397 * Starting at offset + 11 there are "number of configurations"
398 * 32 bit values. To find out which configuration value to use
399 * read "CRTC reg" on the CRTC controller with index "CRTC index"
400 * and bitwise AND this value with "and mask" and then bit shift the
401 * result "shift right" bits to the right.
402 * Assign "register" with appropriate configuration value.
405 NVPtr pNv = NVPTR(pScrn);
406 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
407 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
408 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
409 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
410 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
411 CARD8 io_flag_condition_offset = *((CARD8 *) (&bios->data[offset + 6]));
412 CARD8 nr = *((CARD8 *) (&bios->data[offset + 7]));
413 CARD32 reg = *((CARD32 *) (&bios->data[offset + 8]));
415 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
419 static Bool init_end_repeat(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
427 static Bool init_copy(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
429 /* XXX: double check this... */
430 NVPtr pNv = NVPTR(pScrn);
431 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
432 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
433 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
434 CARD8 and1 = *((CARD8 *) (&bios->data[offset + 6]));
435 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 7]));
436 CARD8 index = *((CARD8 *) (&bios->data[offset + 9]));
437 CARD8 and2 = *((CARD8 *) (&bios->data[offset + 10]));
441 if (iexec->execute) {
442 if (nv32_rd(pScrn, reg, &data)) {
446 data <<= (0x100 - shift);
449 VGA_WR08(ptr,crtcreg, index);
450 crtcdata = (VGA_RD08(ptr, crtcreg + 1) & and2) | (CARD8) data;
452 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
453 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n"
454 , offset, crtcreg, index, crtcdata);
456 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
457 VGA_RD08(ptr, crtcreg + 1));
459 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_copy crtcreg 0x%X value 0x%X\n",crtcreg+1,crtcdata);
461 printf("WRITE IS PERFORMED\n");
462 VGA_WR08(ptr,crtcreg + 1, crtcdata);
469 static Bool init_not(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
471 if (iexec->execute) {
472 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n",
475 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",
479 iexec->execute = !iexec->execute;
483 static Bool init_io_flag_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
485 NVPtr pNv = NVPTR(pScrn);
486 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
487 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
488 CARD16 crtcreg = *((CARD16 *)
489 (&bios->data[bios->io_flag_condition_offset +
490 cond * IO_FLAG_CONDITION_SIZE]));
491 CARD8 index = *((CARD8 *)
492 (&bios->data[bios->io_flag_condition_offset +
493 cond * IO_FLAG_CONDITION_SIZE + 2]));
494 CARD8 and1 = *((CARD8 *)
495 (&bios->data[bios->io_flag_condition_offset +
496 cond * IO_FLAG_CONDITION_SIZE + 3]));
497 CARD8 shift = *((CARD8 *)
498 (&bios->data[bios->io_flag_condition_offset +
499 cond * IO_FLAG_CONDITION_SIZE + 4]));
500 CARD16 offs = *((CARD16 *)
501 (&bios->data[bios->io_flag_condition_offset +
502 cond * IO_FLAG_CONDITION_SIZE + 5]));
503 CARD8 and2 = *((CARD8 *)
504 (&bios->data[bios->io_flag_condition_offset +
505 cond * IO_FLAG_CONDITION_SIZE + 7]));
506 CARD8 cmpval = *((CARD8 *)
507 (&bios->data[bios->io_flag_condition_offset +
508 cond * IO_FLAG_CONDITION_SIZE + 8]));
512 if (iexec->execute) {
513 VGA_WR08(ptr,crtcreg, index);
514 data = VGA_RD08(ptr, crtcreg + 1);
516 offs += (data >> shift);
517 data = *((CARD8 *) (&bios->data[offs]));
520 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
521 "0x%04X: CHECKING IF DATA: %02X equals COND: %02X\n", offset,
524 if (data == cmpval) {
525 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
526 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
529 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
530 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
531 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
532 iexec->execute = FALSE;
538 static Bool init_io_restrict_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
540 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
541 /* XXX: this needs to be confirmed... NOT CORRECT */
542 /*init_io_restrict_prog(bios, offset, iexec);*/
544 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
545 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
546 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
547 CARD8 shiftr = *((CARD8 *) (&bios->data[offset + 5]));
548 CARD8 nr = *((CARD8 *) (&bios->data[offset + 6]));
549 CARD32 reg = *((CARD32 *) (&bios->data[offset + 7]));
551 CARD32 configval, tmp;
553 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%02X\n", offset,
554 crtcreg, index, reg);
556 VGA_WR08(ptr,crtcreg, index);
557 configuration = (VGA_RD08(ptr, crtcreg + 1) & and) >> shiftr;
559 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONFIGURATION TO USE: 0x%02X\n",
560 offset, configuration);
562 if (configuration <= nr) {
564 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &configval))
565 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
569 *((CARD32 *) (&bios->data[offset + 11 + configuration * 4]));
571 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
577 if (iexec->execute) {
580 configval = 0x01014E07;
583 configval = 0x13030E02;
587 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
590 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
591 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
594 nv32_wr(pScrn, reg, configval);
600 static Bool init_pll(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
602 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
603 CARD32 val = *((CARD32 *) (&bios->data[offset + 5]));
604 CARD32 configval, tmp;
606 if (iexec->execute) {
609 configval = 0x00011F05;
613 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
616 if (DEBUGLEVEL >= 6 && nv32_rd(pScrn, reg, &tmp))
617 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
620 nv32_wr(pScrn, reg, configval);
622 /*xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);*/
628 Bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
630 CARD8 crtcindex = *((CARD8 *) (&bios->data[offset + 1]));
631 CARD8 crtcdata = *((CARD8 *) (&bios->data[offset + 2]));
632 CARD8 initial_index = *((CARD8 *) (&bios->data[offset + 3]));
633 CARD8 entries = *((CARD8 *) (&bios->data[offset + 4]));
637 if (iexec->execute) {
638 for (i = 0; i < entries; i++) {
639 nv_set_crtc_index(pScrn, crtcindex);
641 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
642 crtcindex, initial_index + i);
644 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
645 nv_rd_crtc_data(pScrn));
647 nv_wr_crtc_data(pScrn, initial_index + i);
649 nv_set_crtc_index(pScrn, crtcdata);
651 data = *((CARD8 *) (&bios->data[offset + 5 + i]));
653 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: %02X DATA: %02X\n", offset,
656 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
657 nv_rd_crtc_data(pScrn));
659 nv_wr_crtc_data(pScrn, data);
665 Bool init_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
667 /* XXX: IS THIS CORRECT? check the typecast .. probably wrong */
669 NVPtr pNv = NVPTR(pScrn);
670 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
671 CARD8 and = *((CARD8 *) (&bios->data[offset + 2]));
672 CARD8 or = *((CARD8 *) (&bios->data[offset + 3]));
675 if (iexec->execute) {
676 nv_set_crtc_index(pScrn, index);
677 data = (nv_rd_crtc_data(pScrn) & and) | or;
678 /*printf("and: 0x%02x or: 0x%02x\n", and, or);*/
679 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
682 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
683 nv_rd_crtc_data(pScrn));
685 nv_wr_crtc_data(pScrn, data);
690 static Bool init_zm_cr(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
692 /* INIT_ZM_CR opcode: 0x53
694 * offset (8 bit): opcode
695 * offset + 1 (8 bit): CRTC index
696 * offset + 2 (8 bit): value
698 * Assign "value" to CRTC register with index "CRTC index".
701 NVPtr pNv = NVPTR(pScrn);
702 CARD8 index = *((CARD32 *) (&bios->data[offset + 1]));
703 CARD8 value = *((CARD8 *) (&bios->data[offset + 2]));
705 if (iexec->execute) {
706 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
709 nv_set_crtc_index(pScrn, index);
711 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
712 nv_rd_crtc_data(pScrn));
714 nv_wr_crtc_data(pScrn, value);
719 static Bool init_zm_cr_group(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
721 /* INIT_ZM_CR opcode: 0x54
723 * offset (8 bit): opcode
724 * offset + 1 (8 bit): number of groups (index, value)
725 * offset + 2 (8 bit): index 1
726 * offset + 3 (8 bit): value 1
729 * Assign "value n" to CRTC register with index "index n".
732 CARD8 nr = *((CARD8 *) (&bios->data[offset + 1]));
736 if (iexec->execute) {
737 for (i = 0; i < nr; i++) {
738 index = *((CARD8 *) (&bios->data[offset + 2 + 2 * i]));
739 value = *((CARD8 *) (&bios->data[offset + 2 + 2 * i + 1]));
741 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CRTC INDEX: 0x%02X, VALUE: 0x%02X\n", offset,
744 nv_set_crtc_index(pScrn, index);
746 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
747 nv_rd_crtc_data(pScrn));
748 nv_wr_crtc_data(pScrn, value);
754 static Bool init_condition_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
756 /* My BIOS does not use this command. */
757 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
762 static Bool init_zm_reg_sequence(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
764 /* INIT_ZM_REG_SEQUENCE opcode: 0x58
766 * offset (8 bit): opcode
767 * offset + 1 (32 bit): register base
768 * offset + 5 (8 bit): nr
769 * offset + 6 (32 bit): value to assign "register base" + 4
772 * Initialzies a sequence of "nr" registers starting at "register base".
775 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
776 CARD32 nr = *((CARD8 *) (&bios->data[offset + 5]));
781 if (iexec->execute) {
782 for (i = 0; i < nr; i++) {
783 data = *((CARD32 *) (&bios->data[offset + 6 + i * 4]));
784 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
787 if (nv32_rd(pScrn, reg + i * 4, &tmp)) {
788 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
792 nv32_wr(pScrn, reg + i * 4, data);
798 static Bool init_indirect_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
800 /* INIT_INDIRECT_REG opcode: 0x5A
802 * offset (8 bit): opcode
803 * offset + 1 (32 bit): register
804 * offset + 5 (16 bit): adress offset (in bios)
806 * Lookup value at offset data in the bios and write it to reg
808 NVPtr pNv = NVPTR(pScrn);
809 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
810 CARD32 data = *((CARD16 *) (&bios->data[offset + 5]));
811 CARD32 data2 = bios->data[data];
813 if (iexec->execute) {
814 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
815 "0x%04X: REG: 0x%04X, DATA AT: 0x%04X, VALUE IS: 0x%08X\n",
816 offset, reg, data, data2);
818 if (DEBUGLEVEL >= 6) {
820 nv32_rd(pScrn, reg, &tmpval);
821 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
824 nv32_wr(pScrn, reg, data2);
829 static Bool init_sub_direct(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
831 /* INIT_SUB_DIRECT opcode: 0x5B
833 * offset (8 bit): opcode
834 * offset + 1 (16 bit): subroutine offset (in bios)
836 * Calls a subroutine that will execute commands until INIT_DONE
840 CARD16 sub_offset = *((CARD16 *) (&bios->data[offset + 1]));
842 if (iexec->execute) {
843 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-ROUTINE AT: 0x%04X\n",
846 parse_init_table(pScrn, bios, sub_offset, iexec);
848 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-ROUTINE\n", offset);
853 static Bool init_copy_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
855 CARD32 srcreg = *((CARD32 *) (&bios->data[offset + 1]));
856 CARD8 shift = *((CARD8 *) (&bios->data[offset + 5]));
857 CARD32 and1 = *((CARD32 *) (&bios->data[offset + 6]));
858 CARD32 xor = *((CARD32 *) (&bios->data[offset + 10]));
859 CARD32 dstreg = *((CARD32 *) (&bios->data[offset + 14]));
860 CARD32 and2 = *((CARD32 *) (&bios->data[offset + 18]));
864 if (iexec->execute) {
865 nv32_rd(pScrn, srcreg, &srcdata);
872 srcdata = (srcdata & and1) ^ xor;
874 nv32_rd(pScrn, dstreg, &dstdata);
880 nv32_rd(pScrn, dstreg, &tmp);
882 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, dstreg,
885 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmp);
887 nv32_wr(pScrn, dstreg, dstdata);
892 static Bool init_zm_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
894 NVPtr pNv = NVPTR(pScrn);
895 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
896 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
897 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
898 CARD8 value = *((CARD8 *) (&bios->data[offset + 4]));
900 if (iexec->execute) {
901 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
902 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
903 offset, crtcreg, index, value);
905 VGA_WR08(ptr,crtcreg, index);
907 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
908 VGA_RD08(ptr, crtcreg + 1));
911 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_zm_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,value);
913 VGA_WR08(ptr,crtcreg + 1, value);
919 static Bool init_compute_mem(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
921 // FIXME replace with a suitable implementation
923 CARD16 ramcfg = *((CARD16 *) (&bios->data[bios->ram_table_offset]));
928 if (iexec->execute) {
929 nv32_rd(pScrn, 0x00101000, &strapinfo);
930 nv32_rd(pScrn, 0x00100080, &pfb_debug);
932 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
933 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
934 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG: 0x%04X\n", ramcfg);
936 pfb_debug &= 0xffffffef;
938 strapinfo &= 0x0000000f;
939 ramcfg2 = *((CARD16 *)
940 (&bios->data[bios->ram_table_offset + (2 * strapinfo)]));
942 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AFTER MANIPULATION\n");
943 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STRAPINFO: 0x%08X\n", strapinfo);
944 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PFB_DEBUG: 0x%08X\n", pfb_debug);
945 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RAM CFG2: 0x%08X\n", ramcfg2);
947 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
952 nv32_rd(pScrn, 0x00100200, ®1);
953 nv32_rd(pScrn, 0x0010020C, ®2);
955 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x00100200: 0x%08X\n", reg1);
956 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x0010020C: 0x%08X\n", reg2);
962 static Bool init_reset(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
964 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
965 CARD32 value1 = *((CARD32 *) (&bios->data[offset + 5]));
966 CARD32 value2 = *((CARD32 *) (&bios->data[offset + 9]));
968 if (iexec->execute) {
969 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
970 offset, reg, value1);
971 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
972 offset, reg, value2);
974 if (DEBUGLEVEL >= 6) {
976 nv32_rd(pScrn, reg, &tmpval);
977 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
979 nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), &tmpval);
980 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: PCICFG_ROMSHADOW: 0x%02X\n", offset, tmpval);
983 nv32_wr(pScrn, reg, value1);
984 nv32_wr(pScrn, reg, value2);
986 /* PCI Config space init needs to be added here. */
987 /* if (nv32_rd(pScrn, PCICFG(PCICFG_ROMSHADOW), value1)) */
988 /* nv32_wr(pScrn, PCICFG(PCICFG_ROMSHADOW), value1 & 0xfffffffe) */
993 static Bool init_index_io8(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
995 /* INIT_INDEX_IO8 opcode: 0x69
997 * offset (8 bit): opcode
998 * offset + 1 (16 bit): CRTC reg
999 * offset + 3 (8 bit): and mask
1000 * offset + 4 (8 bit): or with
1005 NVPtr pNv = NVPTR(pScrn);
1006 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
1007 CARD16 reg = *((CARD16 *) (&bios->data[offset + 1]));
1008 CARD8 and = *((CARD8 *) (&bios->data[offset + 3]));
1009 CARD8 or = *((CARD8 *) (&bios->data[offset + 4]));
1012 if (iexec->execute) {
1013 data = (VGA_RD08(ptr, reg) & and) | or;
1015 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1016 "0x%04X: CRTC REG: 0x%04X, VALUE: 0x%02X\n",
1018 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
1019 VGA_RD08(ptr, reg));
1021 #ifdef PERFORM_WRITE
1022 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io8 crtcreg 0x%X value 0x%X\n",reg,data);
1024 VGA_WR08(ptr, reg, data);
1030 static Bool init_pll2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1032 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1033 CARD16 val = *((CARD16 *) (&bios->data[offset + 5]));
1035 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ NOT YET IMPLEMENTED ]\n", offset);
1037 if (iexec->execute) {
1038 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%04X\n", offset, reg, val);
1043 static Bool init_sub(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1045 CARD8 sub = *((CARD8 *) (&bios->data[offset + 1]));
1047 if (iexec->execute) {
1048 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING SUB-SCRIPT: %d\n", offset, sub);
1050 parse_init_table(pScrn, bios,
1051 *((CARD16 *) (&bios->data[bios->init_tbls_offset + sub * 2])),
1054 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: END OF SUB-SCRIPT\n", offset);
1059 static Bool init_ram_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1061 /* INIT_RAM_CONDITION opcode: 0x6D
1063 * offset (8 bit): opcode
1064 * offset + 1 (8 bit): and mask
1065 * offset + 2 (8 bit): cmpval
1067 * Test if (NV_PFB_BOOT & and mask) matches cmpval
1069 NVPtr pNv = NVPTR(pScrn);
1070 CARD8 and = *((CARD8 *) (&bios->data[offset + 1]));
1071 CARD8 cmpval = *((CARD8 *) (&bios->data[offset + 2]));
1074 if (iexec->execute) {
1075 data=(pNv->PFB[NV_PFB_BOOT/4])∧
1077 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1078 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1079 offset, data, cmpval);
1081 if (data == cmpval) {
1082 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1083 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1086 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1087 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1088 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1089 iexec->execute = FALSE;
1095 static Bool init_nv_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1097 /* INIT_NV_REG opcode: 0x6E
1099 * offset (8 bit): opcode
1100 * offset + 1 (32 bit): register
1101 * offset + 5 (32 bit): and mask
1102 * offset + 9 (32 bit): or with
1104 * Assign "register" to (REGVAL(register) & "and mask") | "or with";
1107 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1108 CARD32 and = *((CARD32 *) (&bios->data[offset + 5]));
1109 CARD32 or = *((CARD32 *) (&bios->data[offset + 9]));
1111 unsigned int status;
1113 if (iexec->execute) {
1115 if ((status = nv32_rd(pScrn, reg, &data))) {
1116 data = (data & and) | or;
1117 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1120 if (DEBUGLEVEL >= 6 && status) {
1122 nv32_rd(pScrn, reg, &tmpval);
1123 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1127 nv32_wr(pScrn, reg, data);
1128 /* Assign: reg = data */
1135 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1137 // FIXME replace with the haiku version
1138 /* XXX: Not sure this is correct... */
1140 CARD8 macro = *((CARD8 *) (&bios->data[offset + 1]));
1142 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE]));
1144 *((CARD32 *) (&bios->data[bios->macro_offset + macro * MACRO_SIZE + 4]));
1146 if (iexec->execute) {
1147 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: EXECUTING MACRO: 0x%02X\n", offset, macro);
1148 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset, reg,
1151 if (DEBUGLEVEL >= 6) {
1153 nv32_rd(pScrn, reg, &tmpval);
1154 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1158 nv32_wr(pScrn, reg, value);
1164 static Bool init_macro(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1166 CARD8 index = *((CARD8 *) (&bios->data[offset + 1]));
1167 CARD32 tmp = bios->macro_index_offset + (index << 1);
1168 CARD32 offs = *((CARD8 *) (&bios->data[tmp])) << 3;
1169 CARD32 nr = *((CARD8 *) (&bios->data[tmp + 1]));
1174 if (iexec->execute) {
1175 offs += bios->macro_offset;
1176 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: WRITE %d 32-BIT REGS:\n", offset, nr);
1178 for (i = 0; i < nr; i++) {
1179 reg = *((CARD32 *) (&bios->data[offs + (i << 3)]));
1180 data = *((CARD32 *) (&bios->data[offs + (i << 3) + 4]));
1182 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n", offset,
1185 if (DEBUGLEVEL >= 6) {
1187 nv32_rd(pScrn, reg, &tmpval);
1188 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n",
1192 nv32_wr(pScrn, reg, data);
1198 static Bool init_done(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1203 static Bool init_resume(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1205 if (!iexec->execute) {
1206 iexec->execute = TRUE;;
1207 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ---- EXECUTING FOLLOWING COMMANDS ----\n",
1213 static Bool init_ram_condition2(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1215 /* INIT_RAM_CONDITION2 opcode: 0x73
1217 * offset (8 bit): opcode
1218 * offset + 1 (8 bit): and mask
1219 * offset + 2 (8 bit): cmpval
1221 * Test if (NV_EXTDEV_BOOT & and mask) matches cmpval
1223 NVPtr pNv = NVPTR(pScrn);
1224 CARD32 and = *((CARD32 *) (&bios->data[offset + 1]));
1225 CARD32 cmpval = *((CARD32 *) (&bios->data[offset + 5]));
1228 if (iexec->execute) {
1229 data=(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT))∧
1231 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1232 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1233 offset, data, cmpval);
1235 if (data == cmpval) {
1236 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1237 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1240 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1241 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1242 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1243 iexec->execute = FALSE;
1249 static Bool init_time(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1251 /* INIT_TIME opcode: 0x74
1253 * offset (8 bit): opcode
1254 * offset + 1 (16 bit): time
1256 * Sleep for "time" microseconds.
1259 CARD16 time = *((CARD16 *) (&bios->data[offset + 1]));
1261 if (iexec->execute) {
1262 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Sleeping for 0x%04X microseconds.\n",
1270 static Bool init_condition(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1272 CARD8 cond = *((CARD8 *) (&bios->data[offset + 1]));
1275 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE]));
1278 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 4]));
1281 (&bios->data[bios->condition_offset + cond * CONDITION_SIZE + 8]));
1284 if (iexec->execute) {
1285 if (nv32_rd(pScrn, reg, &data)) {
1288 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1289 "0x%04X: CHECKING IF REGVAL: 0x%08X equals COND: 0x%08X\n",
1290 offset, data, cmpval);
1292 if (data == cmpval) {
1293 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1294 "0x%04X: CONDITION FULFILLED - CONTINUING TO EXECUTE\n",
1297 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CONDITION IS NOT FULFILLED.\n", offset);
1298 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1299 "0x%04X: ------ SKIPPING FOLLOWING COMMANDS ------\n", offset);
1300 iexec->execute = FALSE;
1307 static Bool init_index_io(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1309 /* INIT_INDEX_IO opcode: 0x78
1311 * offset (8 bit): opcode
1312 * offset + 1 (16 bit): CRTC reg
1313 * offset + 3 (8 bit): CRTC index
1314 * offset + 4 (8 bit): and mask
1315 * offset + 5 (8 bit): or with
1320 NVPtr pNv = NVPTR(pScrn);
1321 volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
1322 CARD16 crtcreg = *((CARD16 *) (&bios->data[offset + 1]));
1323 CARD8 index = *((CARD8 *) (&bios->data[offset + 3]));
1324 CARD8 and = *((CARD8 *) (&bios->data[offset + 4]));
1325 CARD8 or = *((CARD8 *) (&bios->data[offset + 5]));
1328 if (iexec->execute) {
1329 VGA_WR08(ptr,crtcreg, index);
1330 /* data at reg + 1 */
1331 data = (VGA_RD08(ptr, crtcreg + 1) & and) | or;
1333 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1334 "0x%04X: CRTC REG: 0x%04X, INDEX: 0x%04X, VALUE: 0x%02X\n",
1335 offset, crtcreg, index, data);
1336 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%02X\n", offset,
1337 VGA_RD08(ptr, crtcreg + 1));
1339 #ifdef PERFORM_WRITE
1340 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "init_index_io crtcreg 0x%X value 0x%X\n",crtcreg+1,data);
1342 VGA_WR08(ptr,crtcreg + 1, data);
1348 static Bool init_zm_reg(ScrnInfoPtr pScrn, bios_t *bios, CARD16 offset, init_exec_t *iexec)
1350 /* INIT_ZM_REG opcode: 0x7A
1352 * offset (8 bit): opcode
1353 * offset + 1 (32 bit): register
1354 * offset + 5 (32 bit): value
1356 * Assign "register" to "value";
1359 CARD32 reg = *((CARD32 *) (&bios->data[offset + 1]));
1360 CARD32 value = *((CARD32 *) (&bios->data[offset + 5]));
1362 if (iexec->execute) {
1363 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: REG: 0x%08X, VALUE: 0x%08X\n",
1364 offset, reg, value);
1366 if (DEBUGLEVEL >= 6) {
1368 nv32_rd(pScrn, reg, &tmpval);
1369 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: CURRENT VALUE IS: 0x%08X\n", offset, tmpval);
1372 nv32_wr(pScrn, reg, value);
1374 /* Assign: reg = value */
1379 static init_tbl_entry_t itbl_entry[] = {
1380 /* command name , id , length , offset , mult , command handler */
1381 { "INIT_PROG" , 0x31, 15 , 10 , 4 , init_prog },
1382 { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog },
1383 { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat },
1384 { "INIT_IO_RESTRICT_PROG2" , 0x34, 12 , 7 , 2 , init_io_restrict_prog2 },
1385 { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat },
1386 { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy },
1387 { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not },
1388 { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition },
1389 /* { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, x , x , x, , init_idx_addr_latched }, */
1390 { "INIT_IO_RESTRICT_PLL" , 0x4A, 43 , 0 , 0 , init_io_restrict_pll },
1391 { "INIT_PLL" , 0x4B, 9 , 0 , 0 , init_pll },
1392 /* { "INIT_I2C_BYTE" , 0x4C, x , x , x , init_i2c_byte }, */
1393 /* { "INIT_ZM_I2C_BYTE" , 0x4D, x , x , x , init_zm_i2c_byte }, */
1394 /* { "INIT_ZM_I2C" , 0x4E, x , x , x , init_zm_i2c }, */
1395 { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch },
1396 { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr },
1397 { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr },
1398 { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group },
1399 { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time },
1400 { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence },
1401 { "INIT_INDIRECT_REG" , 0x5A, 7 , 0 , 0 , init_indirect_reg },
1402 { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct },
1403 { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg },
1404 { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io },
1405 { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem },
1406 { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset },
1407 /* { "INIT_NEXT" , 0x66, x , x , x , init_next }, */
1408 /* { "INIT_NEXT" , 0x67, x , x , x , init_next }, */
1409 /* { "INIT_NEXT" , 0x68, x , x , x , init_next }, */
1410 { "INIT_INDEX_IO8" , 0x69, 5 , 0 , 0 , init_index_io8 },
1411 { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub },
1412 { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition },
1413 { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg },
1414 { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro },
1415 { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done },
1416 { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume },
1417 { "INIT_RAM_CONDITION2" , 0x73, 9 , 0 , 0 , init_ram_condition2 },
1418 { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time },
1419 { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition },
1420 /* { "INIT_IO_CONDITION", , 0x76, x , x, , x , init_io_condition }, */
1421 { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io },
1422 { "INIT_PLL2" , 0x79, 7 , 0 , 0 , init_pll2 },
1423 { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg },
1424 /* { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, x , x , x , init_ram_restrict_zm_reg_group }, */
1425 /* { "INIT_COPY_ZM_REG" , 0x90, x , x , x , init_copy_zm_reg }, */
1426 /* { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, x , x , x , init_zm_reg_group_addr_latched }, */
1427 /* { "INIT_RESERVED" , 0x92, x , x , x , init_reserved }, */
1428 { 0 , 0 , 0 , 0 , 0 , 0 }
1431 static unsigned int get_init_table_entry_length(bios_t *bios, unsigned int offset, int i)
1433 /* Calculates the length of a given init table entry. */
1434 return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
1437 static void parse_init_table(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset, init_exec_t *iexec)
1439 /* Parses all commands in a init table. */
1441 /* We start out executing all commands found in the
1442 * init table. Some op codes may change the status
1443 * of this variable to SKIP, which will cause
1444 * the following op codes to perform no operation until
1445 * the value is changed back to EXECUTE.
1451 /* Loop as long as INIT_DONE (command id 0x71) has not been found
1452 * (and offset < bios length just in case... )
1453 * (and no more than 10000 iterations just in case... ) */
1454 while (((id = bios->data[offset]) != 0x71) && (offset < bios->length) && (count++<10000)) {
1455 /* Find matching id in itbl_entry */
1456 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
1459 if (itbl_entry[i].name) {
1460 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: [ (0x%02X) - %s ]\n", offset,
1461 itbl_entry[i].id, itbl_entry[i].name);
1463 /* execute eventual command handler */
1464 if (itbl_entry[i].handler)
1465 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
1468 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Init table command not found: 0x%02X\n",
1473 /* Add the offset of the current command including all data
1474 * of that command. The offset will then be pointing on the
1477 offset += get_init_table_entry_length(bios, offset, i);
1481 void parse_init_tables(ScrnInfoPtr pScrn, bios_t *bios)
1483 /* Loops and calls parse_init_table() for each present table. */
1487 init_exec_t iexec = {TRUE, FALSE};
1489 while (table = *((CARD16 *) (&bios->data[bios->init_tbls_offset + i]))) {
1491 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Parsing init table %d\n",
1494 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: ------ EXECUTING FOLLOWING COMMANDS ------\n",table);
1496 parse_init_table(pScrn, bios, table, &iexec);
1501 static unsigned int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, bios_t *bios, bit_entry_t *bitentry)
1503 /* Parses the init table segment that the bit entry points to.
1504 * Starting at bitentry->offset:
1506 * offset + 0 (16 bits): offset of init tables
1507 * offset + 2 (16 bits): macro index table offset
1508 * offset + 4 (16 bits): macro offset
1509 * offset + 6 (16 bits): condition offset
1510 * offset + 8 (16 bits): io flag condition offset (?)
1511 * offset + 10 (16 bits): io flag condition offset (?)
1512 * offset + 12 (16 bits): unknown
1514 * offset + 8 and offset + 10 seems to contain the same
1515 * offsets on all bioses i have checked. Don't know which
1516 * one is the correct, therefore this code will bail out
1517 * if the two values are not the same.
1520 * * In addition to "conditions" and "io flag conditions" there seems to be
1521 * "io conditions". These are probably located at offset + (8, 10 or 12).
1522 * We need more BIOS dumps to figure this out...
1524 * * Are 'I' bit entries always of length 0xE?
1528 if (bitentry->length < 12) {
1529 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to regocnize BIT init table entry.\n");
1533 bios->init_tbls_offset = *((CARD16 *) (&bios->data[bitentry->offset]));
1534 bios->macro_index_offset = *((CARD16 *) (&bios->data[bitentry->offset + 2]));
1535 bios->macro_offset = *((CARD16 *) (&bios->data[bitentry->offset + 4]));
1536 bios->condition_offset =
1537 *((CARD16 *) (&bios->data[bitentry->offset + 6]));
1538 if (*((CARD16 *) (&bios->data[bitentry->offset + 8])) !=
1539 *((CARD16 *) (&bios->data[bitentry->offset + 10]))) {
1540 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to find IO flag condition offset.\n");
1544 bios->io_flag_condition_offset =
1545 *((CARD16 *) (&bios->data[bitentry->offset + 8]));
1547 parse_init_tables(pScrn, bios);
1552 static void parse_bit_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1554 bit_entry_t *bitentry;
1558 bitentry = (bit_entry_t *) &bios->data[offset];
1560 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%04X: Found BIT command with id 0x%02X\n",
1561 offset, bitentry->id[0]);
1563 switch (bitentry->id[0]) {
1565 /* id[0] = 0 and id[1] = 0 ==> end of BIT struture */
1566 if (bitentry->id[1] == 0)
1570 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1571 "0x%04X: Found init table entry in BIT structure.\n",
1574 parse_bit_init_tbl_entry(pScrn, bios, bitentry);
1575 /*parse_init_tables(pScrn, bios);*/
1578 /* TODO: What kind of information does the other BIT entrys point to?
1579 * 'P' entry is probably performance tables, but there are
1580 * quite a few others...
1584 offset += sizeof(bit_entry_t);
1588 static void parse_pins_structure(ScrnInfoPtr pScrn, bios_t *bios, unsigned int offset)
1590 int pins_version_major=bios->data[offset+5];
1591 int pins_version_minor=bios->data[offset+6];
1592 int init1 = bios->data[offset + 18] + (bios->data[offset + 19] * 256);
1593 int init2 = bios->data[offset + 20] + (bios->data[offset + 21] * 256);
1594 int init_size = bios->data[offset + 22] + (bios->data[offset + 23] * 256) + 1;
1599 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PINS version %d.%d\n",pins_version_major,pins_version_minor);
1602 for (i=0; i < 8; i++)
1603 chksum += bios->data[offset+i];
1605 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "bad PINS checksum\n");
1609 switch(pins_version_major) {
1611 ram_tab = init1-0x0010;
1616 ram_tab = bios->data[offset + 24] + (bios->data[offset + 25] * 256);
1622 if ((pins_version_major==5)&&(pins_version_minor>=6))
1624 /* VCO range info */
1627 if ((pins_version_major==5)&&(pins_version_minor>=16))
1629 bit_entry_t bitentry;
1630 bitentry.offset = offset + 75;
1631 parse_bit_init_tbl_entry(pScrn, bios, &bitentry);
1634 /* TODO type1 script */
1639 static unsigned int findstr(bios_t* bios, unsigned char *str, int len)
1643 for (i = 2; i < bios->length; i++)
1644 if (strncmp(&bios->data[i], str, len) == 0)
1651 #define G5_FIXED_LOC 0xe2f8
1653 static unsigned int nv_find_dcb_table(ScrnInfoPtr pScrn, bios_t *bios)
1655 NVPtr pNv = NVPTR(pScrn);
1660 unsigned char headerSize, entries;
1663 int sig_offsets[2] = { 0x4, 0x6 };
1665 CARD32 tmp_dcb_table[NV40_NUM_DCB_ENTRIES];
1666 uint32_t counter, port;
1668 /* get the offset from 0x36 */
1670 bufloc = *(CARD16 *)&bios->data[0x36];
1672 if (bufloc == 0x0) {
1673 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV43) {
1675 bufloc = G5_FIXED_LOC;
1681 table2 = &bios->data[bufloc];
1683 /* lets play hunt the signature */
1684 for (i = 0; i < sizeof(sig_offsets) / sizeof(int); i++) {
1685 sig = *(uint32_t*)(table2 + sig_offsets[i]);
1686 if ((sig == 0x4edcbdcb) || (sig == 0xcbbddc4e)) {
1687 offset = sig_offsets[i];
1695 header_word = *(uint32_t *)table2;
1700 headerSize = (header_word >> 8) & 0xff;
1701 entries = (header_word >> 16) & 0xff;
1708 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1709 "DCB size is %02X, entries is %02X\n", headerSize, entries);
1710 if (entries >= NV40_NUM_DCB_ENTRIES)
1711 entries = NV40_NUM_DCB_ENTRIES;
1713 for (i = 0; i < entries; i++) {
1715 pNv->dcb_table[i] = __bswap_32(*(uint32_t *)&table2[headerSize + 8 * i]);
1717 pNv->dcb_table[i] = *(uint32_t *)&table2[headerSize + 8 * i];
1723 unsigned int NVParseBios(ScrnInfoPtr pScrn)
1725 unsigned int bit_offset;
1728 bios.length=NV_PROM_SIZE;
1729 unsigned char nv_signature[]={0xff,0x7f,'N','V',0x0};
1730 unsigned char bit_signature[]={'B','I','T'};
1735 pNv->VBIOS = xalloc(64 * 1024);
1736 if (!NVShadowVBIOS(pScrn, pNv->VBIOS)) {
1737 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1738 "No valid BIOS image found.\n");
1742 bios.data = (unsigned char *)pNv->VBIOS;
1744 /* check for known signatures */
1745 if ((bit_offset = findstr(&bios, bit_signature, sizeof(bit_signature)))) {
1746 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIT signature found.\n");
1747 parse_bit_structure(pScrn, &bios, bit_offset + 4);
1748 } else if ((bit_offset = findstr(&bios, nv_signature, sizeof(nv_signature)))) {
1749 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV signature found.\n");
1750 parse_pins_structure(pScrn, &bios, bit_offset);
1752 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No known script signature found.\n");
1755 /* look for NV40+ DCB table - and make a copy somewhere for
1758 ret = nv_find_dcb_table(pScrn, &bios);
1760 pNv->dcb_entries = ret;
1761 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1762 "DCB found %d entries.\n", ret);
1764 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No DCB table found\n");