📄 mach32.c
字号:
static volatile char *mach32_aperture = NULL;static volatile int dummy;static signed char mach32_search_clk(int clk);static void mach32_setstate(accelstate which);static void mach32_blankadj(int adj);static void mach32_modfill(const mode_entry * mode, int modemask, int forcein);static int mach32_test(void);static int mach32_init(int force, int chiptype, int memory);static void mach32_i_bltwait(void);static void mach32_bltwait(void);static void mach32_wait(void);static void mach32_experm(void);static int mach32_eeclock(register int ati33);static void mach32_eekeyout(register int ati33, register int offset, register int mask);static int mach32_eeget(int offset);static int mach32_saveregs(unsigned char regs[]);static void mach32_setregs(const unsigned char regs[], int mode);static void mach32_unlock(void);static void mach32_lock(void);static int mach32_sav_dac(int offset, unsigned char regs[]);static int mach32_set_dac(int dac_mode, int clock_intended, int xres);static void mach32_setpage(int page);static void mach32_setrdpage(int page);static void mach32_setwrpage(int page);static void mach32_setappage(int page);static void mach32_setdisplaystart(int address);static void mach32_setlogicalwidth(int width);static int mach32_modeavailable(int mode);static void mach32_getmodeinfo(int mode, vga_modeinfo * modeinfo);static int mach32_setmode(int mode, int previous);static void mach32_bitblt(int srcaddr, int destaddr, int w, int h, int pitch);static void mach32_fillblt(int destaddr, int w, int h, int pitch, int c);static void mach32_imageblt(void *srcaddr, int destaddr, int w, int h, int pitch);static void mach32_memimageblt(void *srcaddr, int destaddr, int w, int h, int pitch);static void mach32_hlinelistblt(int ymin, int n, int *xmin, int *xmax, int pitch, int c);static void mach32_readconfig(void);static void mach32_final_modefixup(void);static int mach32_ext_set(unsigned what, va_list params);static int mach32_accel(unsigned operation, va_list params);static void mach32_ge_reset(void);static void slow_queue(unsigned short mask);static void mach32_savepalette(unsigned char *red, unsigned char *green, unsigned char *blue);static void mach32_restorepalette(const unsigned char *red, const unsigned char *green, const unsigned char *blue);static int mach32_setpalette(int index, int red, int green, int blue);static void mach32_getpalette(int index, int *red, int *green, int *blue);static int mach32_screenon(void);static void mach32_waitretrace(void);DriverSpecs __svgalib_mach32_driverspecs ={ mach32_saveregs, /* saveregs */ mach32_setregs, /* setregs */ mach32_unlock, /* unlock */ mach32_lock, /* lock */ mach32_test, mach32_init, mach32_setpage, /* __svgalib_setpage */ mach32_setrdpage, /* __svgalib_setrdpage */ mach32_setwrpage, /* __svgalib_setwrpage */ mach32_setmode, /* setmode */ mach32_modeavailable, /* modeavailable */ mach32_setdisplaystart, /* setdisplaystart */ mach32_setlogicalwidth, /* setlogicalwidth */ mach32_getmodeinfo, /* getmodeinfo */ mach32_bitblt, /* bitblt */ mach32_imageblt, /* imageblt */ mach32_fillblt, /* fillblt */ mach32_hlinelistblt, /* hlinelistblt */ mach32_bltwait, /* bltwait */ mach32_ext_set, mach32_accel, 0, /* linear -- mach32 driver handles it differently */ NULL, /* Accelspecs */ NULL, /* Emulation */};static Emulation mach32_vgaemul = { mach32_savepalette, mach32_restorepalette, mach32_setpalette, mach32_getpalette, NULL, /* void (*savefont)(void); */ NULL, /* void (*restorefont)(void); */ NULL, /* int (*screenoff)(void); */ mach32_screenon, mach32_waitretrace,};#ifdef FAST_MEMCPY/* This memcpy is immediately derived from memset as given in speedtest.c in this same svgalib package written by Harm Hanemaayer */static inline void * fast_memcpy(void *dest, void *source, size_t count){ __asm__( "cld\n\t" "cmpl $12,%%edx\n\t" "jl 1f\n\t" /* if (count >= 12) */ "movl %%edx,%%ecx\n\t" "negl %%ecx\n\t" "andl $3,%%ecx\n\t" /* (-s % 4) */ "subl %%ecx,%%edx\n\t" /* count -= (-s % 4) */ "rep ; movsb\n\t" /* align to longword boundary */ "movl %%edx,%%ecx\n\t" "shrl $2,%%ecx\n\t" /* Doing any loop unrolling here proved to SLOW!!! down the copy on my system, at least it didn't show any speedup. */ "rep ; movsl\n\t" /* copy remaining longwords */ "andl $3,%%edx\n" /* copy last few bytes */ "1:\tmovl %%edx,%%ecx\n\t" /* <= 12 entry point */ "rep ; movsb\n\t": /* no outputs */ : /* inputs */ /* SI= source address */ "S"(source), /* DI= destination address */ "D"(dest), /* CX= words to transfer */ "d"(count): /* eax, edx, esi, edi, ecx destructed: */ "%eax", "%edx", "%esi", "%edi", "%ecx"); return dest;}#else#define fast_memcpy memcpy#endifstatic inline int max(int a, int b){ return (a > b) ? a : b;}static inline void checkqueue(int n){ /* This checks for at least n free queue positions *//*Prepare mask: */ unsigned short mask = (unsigned short) (0xffff0000 >> n); int i = BUSYWAIT; while (i--) if (!(inw(EXT_FIFO_STATUS) & mask)) return; slow_queue(mask);}static void slow_queue(unsigned short mask){ clock_t clk_time; clk_time = clock(); do { if (!(inw(EXT_FIFO_STATUS) & mask)) return; } while ((clock() - clk_time) < (CLOCKS_PER_SEC * ADDIWAIT)); mach32_ge_reset(); /* Give up */}static void mach32_ge_reset(void){ /* This is intended as a safety bailout if we locked up the card. */ int queue_stat, ioerr, ge_stat; int i = 1000000; volatile int dummy;/* Provide diagnostics: */ ioerr = inw(SUBSYS_STAT); queue_stat = inw(EXT_FIFO_STATUS); ge_stat = inw(GE_STAT); outw(SUBSYS_CNTL, 0x800f); /*Reset GE, disable all IRQ, reset all IRQ state bits */ while (i--) dummy++; outw(SUBSYS_CNTL, 0x400f); /*Continue normal operation *//* Better reconfigure all used registers */ mach32_accelstate = R_UNKNOWN; CRITICAL = 0; /* Obviously we are idle */ puts("\asvgalib: mach32: Warning! GE_Engine timed out, draw command\n" "was probably corrupted! If you have a very fast machine (10*Pentium)\n" "raise BUSYWAIT and ADDIWAIT in mach32.c, may also be a driver/card bug,\n" "so report detailed info to me (Michael Weller).\nBUT:\n" "This reaction is normal when svgalib is killed in a very critical operation\n" "by a fatal signal like INT (pressing ^C). In this situation this reset just\n" "guarantees that you can continue working on the console, so in this case\n" "PLEASE don't bloat my mailbox with bug reports. Thx, Michael."); printf("POST-Mortem:\n\tSubsys stat: %04x - %sIOerror (is usually a queue overrun)\n" "\tGE stat : %04x - engine %s, %sdata ready for host.\n\tQueue stat : %04x\n", ioerr, (ioerr & 4) ? "" : "no ", ge_stat, (ge_stat & GE_BUSY) ? "busy" : "idle", (ge_stat & 0x100) ? "" : "no ", queue_stat);}static void mach32_setstate(accelstate which){ /* Set GE registers to values assumed elsewhere */ mach32_accelstate = which; checkqueue(10); /*Effectively switch off hardware clipping: */ outw(MULTI_FUNC_CNTL, 0x1000 | (0xfff & -1)); /*TOP */ outw(MULTI_FUNC_CNTL, 0x2000 | (0xfff & -1)); /*LEFT */ outw(MULTI_FUNC_CNTL, 0x3000 | 1535); /*BOTTOM */ outw(MULTI_FUNC_CNTL, 0x4000 | 1535); /*RIGHT */ /*Same for ATI EXT commands: */ outw(EXT_SCISSOR_T, 0xfff & -512); /*TOP */ outw(EXT_SCISSOR_L, 0xfff & -512); /*LEFT */ outw(EXT_SCISSOR_B, 1535); /*BOTTOM */ outw(EXT_SCISSOR_R, 1535); /*RIGHT */ outw(MULTI_FUNC_CNTL, 0xa000); outw(DP_CONFIG, 0x3291); checkqueue(4); outw(DEST_CMP_FN, 0); if (which == R_STANDARD) { checkqueue(2); outw(BKGD_MIX, 0x0027); /* Not used .. however ensure PIX_TRANS is not used */ outw(ALU_FG_FN, 7); } else { checkqueue(5); outw(GE_OFFSET_LO, mach32_ge_off_l); outw(GE_OFFSET_HI, mach32_ge_off_h); outw(GE_PITCH, mach32_ge_pitch); outw(BKGD_MIX, mach32_bkgd_alu_fn); outw(FRGD_MIX, mach32_frgd_alu_fn | 0x20); checkqueue(6); outw(ALU_BG_FN, mach32_bkgd_alu_fn); outw(ALU_FG_FN, mach32_frgd_alu_fn); outw(FRGD_COLOR, mach32_frgd_col); outw(BKGD_COLOR, mach32_bkgd_col); outw(RD_MASK, (infotable[CM].colors == 32768) ? 0x7fff : 0xffff); outw(LINEDRAW_OPT, 0); }}static void mach32_setdisplaystart(int address){#ifdef DEBUG printf("mach32_setdisplaystart(%x)\n", address);#endif mach32_ge_off_l = address >> 2; outw(CRT_OFFSET_LO, mach32_ge_off_l); mach32_ge_off_h = 0xff & (address >> 18); outw(CRT_OFFSET_HI, mach32_ge_off_h); if (mach32_accelstate == R_EXTENDED) { checkqueue(2); outw(GE_OFFSET_LO, mach32_ge_off_l); outw(GE_OFFSET_HI, mach32_ge_off_h); } __svgalib_vga_driverspecs.setdisplaystart(address);}static void mach32_setlogicalwidth(int width){ register int mywidth;#ifdef DEBUG printf("mach32_setlogicalwidth(%d)\n", width);#endif if (infotable[CM].bytesperpixel) { /* always >= 1 for Mach32 modes */ /*Unfortunately the Mach32 expects this value in Pixels not bytes: */ mywidth = width / (infotable[CM].bytesperpixel); mywidth = (mywidth >> 3) & 0xff;#ifdef DEBUG printf("mach32_setlogicalwidth: Mach32 width to %d pels.\n", mywidth * 8);#endif outw(CRT_PITCH, mywidth); mach32_ge_pitch = mywidth; if (mach32_accelstate == R_EXTENDED) { checkqueue(1); outw(GE_PITCH, mywidth); } } __svgalib_vga_driverspecs.setlogicalwidth(width);}static void mach32_setpage(int page){ register unsigned short tmp;#ifdef DEBUG printf("mach32_setpage(%d)\n", page);#endif if (mach32_pagemode != PAGE_BOTH) { outb(ATIPORT, ATISEL(0x3E)); tmp = inb(ATIPORT + 1) & 0xf7; tmp = (tmp << 8) | ATISEL(0x3E); outw(ATIPORT, tmp); mach32_pagemode = PAGE_BOTH; } tmp = (page << 9) & 0x1e00; outw(ATIPORT, ATISEL(0x32) | tmp); outb(ATIPORT, ATISEL(0x2e)); tmp = (inb(ATIPORT + 1) & 0xfc) | ((page >> 4) & 3); outw(ATIPORT, ATISEL(0x2e) | (tmp << 8));}static void mach32_setwrpage(int page){ register unsigned short tmp; if (mach32_pagemode != PAGE_DIFF) { outb(ATIPORT, ATISEL(0x3E)); outw(ATIPORT, (ATISEL(0x3E) << 8) | (inb(ATIPORT + 1) | 8)); mach32_pagemode = PAGE_DIFF; } outb(ATIPORT, ATISEL(0x32)); tmp = inb(ATIPORT + 1) & 0xe1; outw(ATIPORT, (ATISEL(0x32) << 8) | ((page << 1) & 0x1e)); outb(ATIPORT, ATISEL(0x2e)); tmp = inb(ATIPORT + 1) & 0xfc; outw(ATIPORT, (ATISEL(0x2e) << 8) | tmp | ((page >> 4) & 3));}static void mach32_setrdpage(int page){ register unsigned short tmp; if (mach32_pagemode != PAGE_DIFF) { outb(ATIPORT, ATISEL(0x3E)); outw(ATIPORT, (ATISEL(0x3E) << 8) | (inb(ATIPORT + 1) | 8)); mach32_pagemode = PAGE_DIFF; } outb(ATIPORT, ATISEL(0x32)); tmp = inb(ATIPORT + 1) & 0x1e; if (page & 8) tmp |= 1; outw(ATIPORT, (ATISEL(0x32) << 8) | tmp | ((page << 5) & 0xe0)); outb(ATIPORT, ATISEL(0x2e)); tmp = inb(ATIPORT + 1) & 0xf3; outw(ATIPORT, (ATISEL(0x2e) << 8) | tmp | ((page >> 2) & 0xc));}static void mach32_setappage(int page){ outw(MEM_CFG, (mach32_memcfg | (0xc & (page << 2))));}static int mach32_sav_dac(int offset, unsigned char regs[]){/* I was unable to read out the actual DAC_config, so we just save which mode we are in: */ regs[offset] = mach32_dacmode;#ifdef DEBUG printf("mach32_sav_dac(%d,...): Dac:%d, dac_mode:%d\n", offset, mach32_dac, regs[offset]);#endif return offset + 1;}static inline void clean_clocks(void){ outw(CLOCK_SEL, (inw(CLOCK_SEL) & ~0x7f) | 0x11);}static int mach32_set_dac(int dac_mode, int clock_intended, int xres){ unsigned short act_ge_conf; const unsigned char *dac_reg; act_ge_conf = inw(R_EXT_GE_CONF) & 0x8fff;#ifdef DEBUG printf("mach32_set_dac(%d,%d): Dac:%d\n", dac_mode, clock_intended, mach32_dac);#endif mach32_dacmode = dac_mode; dac_mode &= 0x7f; mach32_blankadj((mach32_dac == MACH32_ATI68830) ? 0x4 : 0xc); switch (mach32_dac) { case MACH32_SC11483: dac_reg = mach32_dac1;#ifdef DEBUG fputs("DAC1: ", stdout);#endif if (dac_mode <= DAC_MODE565) goto dac1_4; break; case MACH32_ATI6871: /*This one is a nightmare: */ clean_clocks(); outw(EXT_GE_CONF, 0x201a); switch (dac_mode) { default: case DAC_MODE8: case DAC_MODEMUX: outb(DAC1, 0x00); outb(DAC2, 0x30); outb(DAC3, 0x2d);#ifdef DEBUG puts("DAC2: 0x00 0x30 0x2d (8bpp)");#endif if (dac_mode != DAC_MODEMUX) break; outb(DAC2, 0x09); outb(DAC3, 0x1d); outb(DAC1, 0x01); mach32_blankadj(1);#ifdef DEBUG puts("DAC2: 0x01 0x09 0x1d (8bpp MUX)");#endif break; case DAC_MODE555: case DAC_MODE565: case DAC_MODERGB: mach32_blankadj(1); case DAC_MODE32B: outb(DAC1, 0x01); if ((!(clock_intended & 0xc0)) && (!(mach32_dacmode & DAC_SEMICLK))) { outb(DAC2, 0x00);#ifdef DEBUG puts("DAC2: 0x01 0x00 0x0d (16/24bpp)");#endif } else { clock_intended &= 0xff3f;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -