📄 mach32.c
字号:
outb(DAC2, 0x08); mach32_dacmode |= DAC_SEMICLK; if (xres <= 640) mach32_blankadj(2);#ifdef DEBUG puts("DAC2: 0x01 0x08 0x0d (16/24bpp)");#endif } outb(DAC3, 0x0d); act_ge_conf |= 0x4000; if (dac_mode == DAC_MODE32B) mach32_blankadj(3); break; } if (bladj >= 0) mach32_blankadj(bladj); break; case MACH32_BT481: dac_reg = mach32_dac4;#ifdef DEBUG fputs("DAC4: ", stdout);#endif dac1_4: if (dac_mode <= DAC_MODERGB) { clean_clocks(); outw(EXT_GE_CONF, 0x101a);#ifdef DEBUG printf("%02x\n", dac_reg[dac_mode]);#endif outb(DAC2, dac_reg[dac_mode]); } break; case MACH32_ATI68860: clean_clocks(); outw(EXT_GE_CONF, 0x301a);#ifdef DEBUG printf("DAC5: %02x\n", mach32_dac5[dac_mode]);#endif outb(DAC0, mach32_dac5[dac_mode]); break; }/*Dac RS2,3 to 0 */ act_ge_conf &= 0x8fff; if ((dac_mode == DAC_MODE8) || (dac_mode == DAC_MODEMUX)) if (ext_settings & VGA_CLUT8) act_ge_conf |= 0x4000; outw(EXT_GE_CONF, act_ge_conf);/*Set appropriate DAC_MASK: */ switch (dac_mode) { case DAC_MODE8: case DAC_MODEMUX:#ifdef DEBUG puts("DAC-Mask to 0xff");#endif outb(DAC_MASK, 0xff); break; default: switch (mach32_dac) { case MACH32_ATI6871: case MACH32_BT481:#ifdef DEBUG puts("DAC-Mask to 0x00");#endif outb(DAC_MASK, 0x00); break; }#ifdef DEBUG puts("VGA-DAC-Mask to 0x0f");#endif outb(VGA_DAC_MASK, 0x0f); break; } return clock_intended;}static int mach32_saveregs(unsigned char regs[]){ int i, retval; unsigned short tmp; mach32_bltwait(); /* Ensure noone draws in the screen */ for (i = 0; i < sizeof(mach32_eregs); i++) { outb(ATIPORT, ATISEL(mach32_eregs[i])); regs[EXT + i] = inb(ATIPORT + 1); } regs[EXT + i] = mach32_disp_shadow; /* This is for DISP_CNTL */ retval = i + EXT + 1; for (i = 0; i < (sizeof(mach32_acc_regs) / sizeof(unsigned short)); i += 2) { tmp = inw(mach32_acc_regs[i]); regs[retval++] = tmp; regs[retval++] = (tmp >> 8); } retval = mach32_sav_dac(retval, regs);#ifdef DEBUG printf("mach32_saveregs: retval=%d\n", retval);#endif return retval - EXT;}static void mach32_setregs(const unsigned char regs[], int mode){ int i, offset, retval, clock_intended = 0; unsigned short tmp; mach32_bltwait(); /* Ensure noone draws in the screen */ mach32_accelstate = R_UNKNOWN; /* Accel registers need to be reset */ offset = EXT + sizeof(mach32_eregs) + (sizeof(mach32_acc_regs) / sizeof(unsigned short)) + 1;/*Find out which clock we want to use: */ for (i = (sizeof(mach32_acc_regs) / sizeof(unsigned short)) - 1, retval = offset; i >= 0; i -= 2, retval -= 2) if (mach32_acc_regs[i] == CLOCK_SEL) { clock_intended = ((unsigned short) regs[--retval]) << 8; clock_intended |= regs[--retval]; break; }#ifdef DEBUG printf("mach32_setregs: offset=%d, clock_intended=%d\n", offset, clock_intended);#endif retval = offset + 1; mach32_set_dac(regs[offset], clock_intended, 0); /*We can savely call with a fake xres coz blank adjust will be restored afterwards anyways... */ for (i = (sizeof(mach32_acc_regs) / sizeof(unsigned short)) - 1; i >= 0; i -= 2) { tmp = ((unsigned short) regs[--offset]) << 8; tmp |= regs[--offset]; /* restore only appage in MEM_CFG... otherwise badly interaction with X that may change MEM_CFG and does not only not restore it's original value but also insist on it not being changed on VC change... =:-o */ if (mach32_acc_regs[i] == MEM_CFG) tmp = (inw(MEM_CFG) & ~0xc) | (tmp & 0xc); if (mach32_ast && (mach32_acc_regs[i] == MISC_CTL)) continue; if (mach32_acc_regs[i] == H_DISP) { /* H_TOTAL (alt) in H_DISP broken for some chipsets... */ outb(H_TOTAL, tmp >> 8); outb(H_DISP, tmp); } else { outw(mach32_acc_regs[i], tmp); } } mach32_disp_shadow = regs[--offset] & ~0x60; outb(DISP_CNTL, mach32_disp_shadow | 0x40); /* Mach32 CRT reset */ if (inw(CLOCK_SEL) & 1) /* If in non VGA mode */ outw(DISP_CNTL, mach32_disp_shadow | 0x20); /* Mach32 CRT enabled */ for (i = sizeof(mach32_eregs) - 1; i >= 0; i--) { outb(ATIPORT, ATISEL(mach32_eregs[i])); outb(ATIPORT + 1, regs[--offset]); }}static void mach32_unlock(void){ unsigned short oldval;#ifdef DEBUG puts("mach32_unlock");#endif /* DEBUG */ outb(ATIPORT, ATISEL(0x2e)); oldval = inb(ATIPORT + 1) & ~0x10; /* Unlock CPUCLK Select */ outw(ATIPORT, ATISEL(0x2e) | (oldval << 8)); outb(ATIPORT, ATISEL(0x2b)); oldval = inb(ATIPORT + 1) & ~0x18; /* Unlock DAC, Dbl Scan. */ outw(ATIPORT, ATISEL(0x2b) | (oldval << 8)); outb(ATIPORT, ATISEL(0x34)); oldval = inb(ATIPORT + 1) & ~0xfc; /* Unlock Crt9[0:4,7], Vtiming, Cursr start/end, CRT0-7,8[0-6],CRT14[0-4]. but disable ignore of CRT11[7] */ outw(ATIPORT, ATISEL(0x34) | (oldval << 8)); outb(ATIPORT, ATISEL(0x38)); /* Unlock ATTR00-0f, ATTR11, whole vga, port 3c2 */ oldval = inb(ATIPORT + 1) & ~0x0f; outw(ATIPORT, ATISEL(0x38) | (oldval << 8));/* Unlock vga-memory too: */ outw(MEM_BNDRY, 0);/* Unlock Mach32 CRT Shadowregisters... this one made me crazy... Thanx to the Xfree sources I finally figured it out.... */ outw(SHADOW_SET, 1); outw(SHADOW_CTL, 0); outw(SHADOW_SET, 2); outw(SHADOW_CTL, 0); outw(SHADOW_SET, 0);}static void mach32_lock(void){ unsigned short oldval;#ifdef DEBUG puts("mach32_lock");#endif /* DEBUG *//* I'm really not sure if calling this function would be a good idea *//* Actually it is not called in svgalib */ outb(ATIPORT, ATISEL(0x2b)); oldval = inb(ATIPORT + 1) | 0x18; /* Lock DAC, Dbl Scan. */ outw(ATIPORT, ATISEL(0x2b) | (oldval << 8)); outb(ATIPORT, ATISEL(0x34)); oldval = inb(ATIPORT + 1) | 0xfc; /* Lock Crt9[0:4,7], Vtiming, Cursr start/end, CRT0-7,8[0-6],CRT14[0-4]. but disable ignore of CRT11[7] */ outw(ATIPORT, ATISEL(0x34) | (oldval << 8)); outb(ATIPORT, ATISEL(0x38)); /* Lock ATTR00-0f, ATTR11, whole vga, port 3c2 */ oldval = inb(ATIPORT + 1) | 0x0f; outw(ATIPORT, ATISEL(0x38) | (oldval << 8)); outw(SHADOW_SET, 1); outw(SHADOW_CTL, 0x7f); outw(SHADOW_SET, 2); outw(SHADOW_CTL, 0x7f); outw(SHADOW_SET, 0);}static void mach32_experm(void){ printf("svgalib(mach32): Cannot get I/O permissions.\n"); exit(-1);}static void mach32_bltwait(void){ int i = BUSYWAIT; clock_t clk_time; checkqueue(16); /* Ensure nothing in the queue */ while (i--) if (!(inw(GE_STAT) & (GE_BUSY | 1))) { done: /* Check additional stats */ if (inw(SUBSYS_STAT) & 4) goto failure; CRITICAL = 0; /* Obviously we're idle */ return; } clk_time = clock(); do { if (!(inw(GE_STAT) & (GE_BUSY | 1))) goto done; } while ((clock() - clk_time) < (CLOCKS_PER_SEC * ADDIWAIT)); failure: mach32_ge_reset();}static void mach32_i_bltwait(void){ int i; for (i = 0; i < 100000; i++) if (!(inw(GE_STAT) & (GE_BUSY | 1))) break;}static int mach32_test(void){ int result = 0; short tmp;/* If IOPERM is set, assume permissions have already been set by Olaf Titz' *//* ioperm(1). */ if (getenv("IOPERM") == NULL) if (iopl(3) < 0) mach32_experm();/* Har, har.. now we can switch off interrupts to crash the system... ;-)=) *//* (But actually we need only access to extended io-ports...) */ tmp = inw(SCRATCH_PAD_0); outw(SCRATCH_PAD_0, 0x5555); mach32_i_bltwait(); if (inw(SCRATCH_PAD_0) == 0x5555) { outw(SCRATCH_PAD_0, 0x2a2a); mach32_i_bltwait(); if (inw(SCRATCH_PAD_0) == 0x2a2a) { /* Aha.. 8514/a detected.. */ result = 1; } } outw(SCRATCH_PAD_0, tmp); if (!result) goto quit;/* Now ensure it is not a plain 8514/a: */ result = 0; outw(DESTX_DIASTP, 0xaaaa); mach32_i_bltwait(); if (inw(R_SRC_X) == 0x02aa) { outw(DESTX_DIASTP, 0x5555); mach32_i_bltwait(); if (inw(R_SRC_X) == 0x0555) result = 1; } if (!result) goto quit; result = 0;/* Ok, now we have a Mach32. Unfortunately we need also the VGA to be enabled: */ if (inw(CONF_STAT1) & ONLY_8514) { if (__svgalib_driver_report) puts("Mach32 detected, but unusable with VGA disabled.\nSorry.\n"); goto quit; /*VGA circuitry disabled. */ } result = 1; quit: if (getenv("IOPERM") == NULL) iopl(0); /* safety, mach32_init reenables it */ if (result) mach32_init(0, 0, 0);#ifdef DEBUG printf("mach32_test: returning %d.\n", result);#endif /* DEBUG */ return result;}static void mach32_wait(void){/* Wait for at least 22 us.. (got that out of a BIOS disassemble on my 486/50 ;-) ) ... */ register int i; for (i = 0; i < 16; i++) dummy++; /*Dummy is volatile.. */}static int mach32_eeclock(register int ati33){ outw(ATIPORT, ati33 |= 0x200); /* clock on */ mach32_wait(); outw(ATIPORT, ati33 &= ~0x200); /* clock off */ mach32_wait(); return ati33;}static void mach32_eekeyout(register int ati33, register int offset, register int mask){ do { if (mask & offset) ati33 |= 0x100; else ati33 &= ~0x100; outw(ATIPORT, ati33); mach32_eeclock(ati33); } while (mask >>= 1);}static int mach32_eeget(int offset){ register int ati33; register int result, i;/* get current ATI33 */ outb(ATIPORT, ATISEL(0x33)); ati33 = ((int) inw(ATIPORT + 1)) << 8; ati33 |= ATISEL(0x33);/* prepare offset.. cut and add header and trailer */ offset = (0x600 | (offset & 0x7f)) << 1;/* enable eeprom sequence */ ati33 = mach32_eeclock(ati33);/*input to zero.. */ outw(ATIPORT, ati33 &= ~0x100);/*enable to one */ outw(ATIPORT, ati33 |= 0x400); mach32_eeclock(ati33);/*select to one */ outw(ATIPORT, ati33 |= 0x800); mach32_eeclock(ati33); mach32_eekeyout(ati33, offset, 0x800); for (i = 0, result = 0; i < 16; i++) { result <<= 1; outb(ATIPORT, ATISEL(0x37)); if (inb(ATIPORT + 1) & 0x8) result |= 1; mach32_eeclock(ati33); }/*deselect... */ outw(ATIPORT, ati33 &= ~0x800); mach32_eeclock(ati33);/*disable... */ outw(ATIPORT, ati33 &= ~0x400); mach32_eeclock(ati33); return result;}static int mach32_max_mask(int x){ if (x <= 0x4f) return dacmo640[mach32_dac]; if (x <= 0x63) return dacmo800[mach32_dac]; if (x <= 0x7f) return dacmo1024[mach32_dac]; return dacmo1280[mach32_dac];}static int mach32_max_vfifo16(int x){ int retval; if (x <= 0x63) retval = vfifo16; else if (x <= 0x7f) retval = vfifo16 + 4; else retval = vfifo16 + 5; return (retval < 15) ? retval : 15;}/* Shameless ripped out of Xfree2.1 (with slight changes) : */static void mach32_scan_clocks(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -