📄 et4000.c
字号:
switch (info->colors) { case 1 << 15: /* All HiColor dacs handle 15 bit */ if ((et4000_dac & 1) == 0) return 0; break; case 1 << 16: /* Unfortunately, we can't tell the difference between a Sierra Mark 2 */ /* and a Mark 3, and the mark 2 is only 15 bit. If this gives you trouble */ /* change it to (8|16) rather than (2|8|16) */ /* Currently allow Sierra Mark2/3, AT&T, STG-170x and AcuMos */ if ((et4000_dac & (2 | 8 | 16 | 32 | 64)) == 0) return 0; break; case 1 << 24: /* Don't know how to set dac command register for Diamond SS2410 Dac */ /* Only allow AT&T, STG-170x and AcuMos */ if ((et4000_dac & (8 | 16 | 32 | 64)) == 0) return 0; break; } return SVGADRV;}/* Check if mode is interlaced */static int et4000_interlaced(int mode){ const unsigned char *regs; if (et4000_modeavailable(mode) != SVGADRV) return 0; regs = LOOKUPMODE(et4000_modes, mode); if (regs == NULL || regs == DISABLE_MODE) return 0; return (regs[EXT + 5] & 0x80) != 0; /* CRTC 35H */}/* Set a mode */static int et4000_setmode(int mode, int prv_mode){ const unsigned char *regs; unsigned char i; if (et4000_dac) /* Standard dac behaviour */ __svgalib_hicolor(et4000_dac, STD_DAC); switch (et4000_modeavailable(mode)) { case STDVGADRV: /* Reset extended register that is set to non-VGA */ /* compatible value for 132-column textmodes (at */ /* least on some cards). */ et4000_unlock(); outb(__svgalib_CRT_I, 0x34); i = inb(__svgalib_CRT_D); if ((i & 0x02) == 0x02) outb(__svgalib_CRT_D, (i & 0xfd)); /* DS */ return __svgalib_vga_driverspecs.setmode(mode, prv_mode); case SVGADRV: regs = LOOKUPMODE(et4000_modes, mode); if (regs != NULL) break; default: return 1; /* mode not available */ } if (et4000_dac && !et4000_extdac) switch (vga_getmodeinfo(mode)->colors) { case 1 << 15: __svgalib_hicolor(et4000_dac, HI15_DAC); break; case 1 << 16: __svgalib_hicolor(et4000_dac, HI16_DAC); break; case 1 << 24: __svgalib_hicolor(et4000_dac, TC24_DAC); break; } __svgalib_setregs(regs); et4000_setregs(regs, mode); return 0;}/* Unlock chipset-specific registers */static void et4000_unlock(void){ /* get access to extended registers */ port_out(3, 0x3bf); if (port_in(0x3cc) & 1) port_out(0xa0, 0x3d8); else port_out(0xa0, 0x3b8);}/* Relock chipset-specific registers */static void et4000_lock(void){}/* Enable linear mode at a particular 4M page (0 to turn off) */static void et4000_setlinear(int addr){ et4000_unlock(); outb(CRT_IC, 0x36); if (addr) outb(CRT_DC, inb(CRT_DC) | 16); /* enable linear mode */ else outb(CRT_DC, inb(CRT_DC) & ~16); /* disable linear mode */ outb(CRT_IC, 0x30); outb(CRT_DC, addr); et4000_lock();}/* Indentify chipset; return non-zero if detected */static int et4000_test(void){ unsigned char new, old, val; int base; et4000_unlock(); /* test for Tseng clues */ old = port_in(0x3cd); port_out(0x55, 0x3cd); new = port_in(0x3cd); port_out(old, 0x3cd); /* return false if not Tseng */ if (new != 0x55) return 0; /* test for ET4000 clues */ if (port_in(0x3cc) & 1) base = CRT_IC; else base = 0x3b4; port_out(0x33, base); old = port_in(base + 1); new = old ^ 0xf; port_out(new, base + 1); val = port_in(base + 1); port_out(old, base + 1); /* return true if ET4000 */ if (val == new) { et4000_init(0, 0, 0); return 1; } return 0;}static unsigned char last_page = 0;/* Bank switching function - set 64K bank number */static void et4000_setpage(int page){ /* Set both read and write bank. */ port_out(last_page = (page | ((page & 15) << 4)), SEG_SELECT); if (et4000_chiptype >= CHIP_ET4000W32i) { /* Write page4-5 to bits 0-1 of ext. bank register, */ /* and to bits 4-5. */ outb(0x3cb, (inb(0x3cb) & ~0x33) | (page >> 4) | (page & 0x30)); }}/* Bank switching function - set 64K read bank number */static void et4000_setrdpage(int page){ last_page &= 0x0F; last_page |= (page << 4); port_out(last_page, SEG_SELECT); if (et4000_chiptype >= CHIP_ET4000W32i) { /* Write page4-5 to bits 4-5 of ext. bank register. */ outb(0x3cb, (inb(0x3cb) & ~0x30) | (page & 0x30)); }}/* Bank switching function - set 64K write bank number */static void et4000_setwrpage(int page){ last_page &= 0xF0; last_page |= page; port_out(last_page, SEG_SELECT); if (et4000_chiptype >= CHIP_ET4000W32i) { /* Write page4-5 to bits 0-1 of ext. bank register. */ outb(0x3cb, (inb(0x3cb) & ~0x03) | (page >> 4)); }}/* Set display start address (not for 16 color modes) *//* ET4000 supports any address in video memory (up to 1Mb) *//* ET4000/W32i/p supports up to 4Mb */static void et4000_setdisplaystart(int address){ outw(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */ outw(CRT_IC, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */ inb(0x3da); /* set ATC to addressing mode */ outb(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ outb(ATT_IW, (inb(ATT_R) & 0xf0) | ((address & 3) << 1)); /* write sa0-1 to bits 1-2 */ outb(CRT_IC, 0x33); if (et4000_chiptype >= CHIP_ET4000W32i) /* write sa18-21 to bit 0-3 */ outb(CRT_DC, (inb(CRT_DC) & 0xf0) | ((address & 0x3c0000) >> 18)); else /* write sa18-19 to bit 0-3 */ outb(CRT_DC, (inb(CRT_DC) & 0xfc) | ((address & 0xc0000) >> 18));}/* Set logical scanline length (usually multiple of 8) *//* ET4000 supports multiples of 8 to 4088 */static void et4000_setlogicalwidth(int width){ outw(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ outb(CRT_IC, 0x3f); outb(CRT_DC, (inb(CRT_DC) & 0x7f) | ((width & 0x800) >> 5)); /* write lw12 to bit 7 */}static int et4000_ext_set(unsigned what, va_list params){ int param2, old_values; switch (what) { case VGA_EXT_AVAILABLE: param2 = va_arg(params, int); switch (param2) { case VGA_AVAIL_SET: return VGA_EXT_AVAILABLE | VGA_EXT_SET | VGA_EXT_CLEAR | VGA_EXT_RESET; case VGA_AVAIL_ACCEL: return 0; case VGA_AVAIL_FLAGS: return pos_ext_settings; } return 0; case VGA_EXT_SET: old_values = ext_settings; ext_settings |= (va_arg(params, int)) & pos_ext_settings; params_changed: if (((old_values ^ ext_settings) & pos_ext_settings)) { int cmd; CRITICAL = 1; vga_lockvc(); _ramdac_dactocomm(); cmd = inb(PEL_MSK); _ramdac_dactocomm(); if (ext_settings & VGA_CLUT8) cmd |= 2; else cmd &= ~2; outb(PEL_MSK, cmd); vga_unlockvc(); CRITICAL = 0; } return old_values; case VGA_EXT_CLEAR: old_values = ext_settings; ext_settings &= ~((va_arg(params, int)) & pos_ext_settings); goto params_changed; case VGA_EXT_RESET: old_values = ext_settings; ext_settings = (va_arg(params, int)) & pos_ext_settings; goto params_changed; default: return 0; }}static int et4000_linear(int op, int param){ /* linear mode not supported on original chipset */ if (et4000_chiptype == CHIP_ET4000) return -1; else if (op == LINEAR_QUERY_GRANULARITY) return 4 * 1024 * 1024; else if (op == LINEAR_QUERY_RANGE) return 256; else if (op == LINEAR_ENABLE) { et4000_setlinear(param / (4 * 1024 * 1024)); return 0; } else if (op == LINEAR_DISABLE) { et4000_setlinear(0); return 0; } else return -1;}/* Function table (exported) */DriverSpecs __svgalib_et4000_driverspecs ={ et4000_saveregs, et4000_setregs, et4000_unlock, et4000_lock, et4000_test, et4000_init, et4000_setpage, et4000_setrdpage, et4000_setwrpage, et4000_setmode, et4000_modeavailable, et4000_setdisplaystart, et4000_setlogicalwidth, et4000_getmodeinfo, 0, /* bitblt */ 0, /* imageblt */ 0, /* fillblt */ 0, /* hlinelistblt */ 0, /* bltwait */ et4000_ext_set, 0, et4000_linear, NULL, /* Accelspecs */ NULL, /* Emulation */};/* Hicolor DAC detection derived from vgadoc (looks tricky) */#ifndef DAC_TYPEstatic int testdac(void){ int x, y, z, v, oldcommreg, oldpelreg, retval; /* Use the following return values: * 0: Ordinary DAC * 1: Sierra SC11486 (32k) * 3: Sierra 32k/64k * 5: SS2410 15/24bit DAC * 9: AT&T 20c491/2 * 10: STG-170x */ retval = 0; /* default to no fancy dac */ _ramdac_dactopel(); x = inb(PEL_MSK); do { /* wait for repeat of value */ y = x; x = inb(PEL_MSK); } while (x != y); z = x; inb(PEL_IW); inb(PEL_MSK); inb(PEL_MSK); inb(PEL_MSK); x = inb(PEL_MSK); y = 8; while ((x != 0x8e) && (y > 0)) { x = inb(PEL_MSK); y--; } if (x == 0x8e) { /* We have an SS2410 */ retval = 1 | 4; _ramdac_dactopel(); } else { _ramdac_dactocomm(); oldcommreg = inb(PEL_MSK); _ramdac_dactopel(); oldpelreg = inb(PEL_MSK); x = oldcommreg ^ 0xFF; outb(PEL_MSK, x); _ramdac_dactocomm(); v = inb(PEL_MSK); if (v != x) { v = _ramdac_setcomm(x = oldcommreg ^ 0x60); /* We have a Sierra SC11486 */ retval = 1; if ((x & 0xe0) == (v & 0xe0)) { /* We have a Sierra 32k/64k */ x = inb(PEL_MSK); _ramdac_dactopel(); retval = 1 | 2; if (x == inb(PEL_MSK)) { /* We have an ATT 20c491 or 20c492 */ retval = 1 | 8; if (_ramdac_setcomm(0xFF) != 0xFF) { /* We have a weird dac, AcuMos ADAC1 */ retval = 1 | 16; } else { /* maybe an STG-170x */ /* try to enable ext. registers */ _ramdac_setcomm(oldcommreg | 0x10); outb(PEL_MSK, 0); outb(PEL_MSK, 0); if (inb(PEL_MSK) == 0x44) { /* it's a 170x */ /* Another read from PEL_MSK gets the chiptype, 0x02 == 1702. */ retval = 1 | 64; et4000_extdac = 1; } } } } _ramdac_dactocomm(); outb(PEL_MSK, oldcommreg); } _ramdac_dactopel(); outb(PEL_MSK, oldpelreg); } return retval;}#endif /* !defined(DAC_TYPE) *//* Initialize chipset (called after detection) */static int et4000_init(int force, int par1, int par2){ int value; int old, new, val;#ifdef USE_CLOCKS int i;#endif#ifdef DYNAMIC if (et4000_modes == NULL) { FILE *regs; regs = fopen(ET4000_REGS, "r"); if (regs != 0) { et4000_modes = NULL; __svgalib_readmodes(regs, &et4000_modes, &et4000_dac, &clocks[0]); fclose(regs); } else et4000_modes = &No_Modes; }#endif /* Determine the ET4000 chip type. */ /* Test for ET4000/W32. */ old = inb(0x3cb); outb(0x3cb, 0x33); new = inb(0x3cb); outb(0x3cb, old); if (new != 0x33) et4000_chiptype = CHIP_ET4000; else { /* ET4000/W32. */ if (getenv("IOPERM") == NULL && iopl(3) < 0) /* Can't get further I/O permissions -- */ /* assume ET4000/W32. */ et4000_chiptype = CHIP_ET4000W32; else { outb(0x217a, 0xec); val = inb(0x217b) >> 4; switch (val) { case 0: et4000_chiptype = CHIP_ET4000W32; break; case 1: case 3: et4000_chiptype = CHIP_ET4000W32i; break; case 2: case 5: default: et4000_chiptype = CHIP_ET4000W32p; } /* Do NOT set back iopl if set before, since */ /* caller most likely still needs it! */ if (getenv("IOPERM") == NULL) iopl(0); } } if (force) et4000_memory = par1; else { outb(CRT_IC, 0x37); value = inb(CRT_DC); et4000_memory = (value & 0x08) ? 256 : 64; switch (value & 3) { case 2: et4000_memory *= 2; break; case 3: et4000_memory *= 4; break; } if (value & 0x80) et4000_memory *= 2; outb(CRT_IC, 0x32); if (inb(CRT_DC) & 0x80) { /* Interleaved memory on ET4000/W32i/p: */ /* Multiply by 2. */ et4000_memory *= 2; } }#ifndef DAC_TYPE if (et4000_dac < 0) et4000_dac = testdac();#endif#ifdef USE_CLOCKS /* Measure clock frequencies */ for (i = 0; i < CLOCKS; ++i) get_clock(i);#endif if (__svgalib_driver_report) { char dacname[60]; switch (et4000_dac & ~1) { case 0: strcpy(dacname, ", Hicolor Dac: Sierra SC11486"); break; case 2: strcpy(dacname, ", Hicolor Dac: Sierra 32k/64k"); break; case 4: strcpy(dacname, ", Hicolor Dac: SS2410"); break; case 8: strcpy(dacname, ", Hicolor Dac: ATT20c491/2"); break; case 16: strcpy(dacname, ", Hicolor Dac: ACUMOS ADAC1"); break; case 32: strcpy(dacname, ", Hicolor Dac: Sierra 15025/6 (24-bit)"); break; case 64: strcpy(dacname, ", Hicolor Dac: STG-170x (24-bit)"); break; default: strcpy(dacname, ", Hicolor Dac: Unknown"); break; } printf("Using Tseng ET4000 driver (%s %d%s).", chipname[et4000_chiptype], et4000_memory, et4000_dac & 1 ? dacname : "");#ifdef USE_CLOCKS printf(" Clocks:"); for (i = 0; i < 8; ++i) printf(" %d", (clocks[i] + 500) / 1000);#endif printf("\n"); } __svgalib_driverspecs = &__svgalib_et4000_driverspecs; __svgalib_banked_mem_base=0xa0000; __svgalib_banked_mem_size=0x10000;/* __svgalib_linear_mem_base=LINEARBASE; __svgalib_linear_mem_size=nv3_memory*0x400; */ pos_ext_settings = 0; if (et4000_dac & (8 | 16 | 32 | 64)) pos_ext_settings = VGA_CLUT8; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -