📄 chips.c
字号:
#define CT_540 4#define CT_545 5#define CT_546 6#define CT_548 7#define CT_550 8#define CT_554 9#define CT_555 10#define CT_8554 11#define CT_9000 12#define CT_4300 13static CardSpecs *cardspecs;/*----------------------------------------------------------------------*//*----------------------------------------------------------------------*/static void nothing(void){}/*----------------------------------------------------------------------*//* Fill in chipset specific mode information *//*----------------------------------------------------------------------*/static void CHIPS_getmodeinfo(int mode, vga_modeinfo * modeinfo){#ifdef DEBUG printf("CHIPS: CHIPS_getmodeinfo(%d, *)\n", mode);#endif if (modeinfo->bytesperpixel > 0) { modeinfo->maxpixels = video_memory * 1024 / modeinfo->bytesperpixel; } else { modeinfo->maxpixels = video_memory * 1024; } modeinfo->maxlogicalwidth = 2040; modeinfo->linewidth_unit = 8; modeinfo->startaddressrange = 0xfffff; modeinfo->memory = video_memory; if (mode == G320x200x256) { /* Special case: bank boundary may not fall within display. */ modeinfo->startaddressrange = 0xf0000; /* Hack: disable page flipping capability for the moment. */ modeinfo->startaddressrange = 0xffff; modeinfo->maxpixels = 65536; } modeinfo->haveblit = 0; if (CHIPS_interlaced(mode)) { modeinfo->flags |= IS_INTERLACED; } if (CHIPSchipset != CT_520) { modeinfo->flags |= EXT_INFO_AVAILABLE | CAPABLE_LINEAR; }#if defined(seperated_read_write_bank) if (ctisHiQV) { /* HiQV doesn't have seperate Read/Write pages */ modeinfo->flags &= ~HAVE_RWPAGE; } else { modeinfo->flags |= HAVE_RWPAGE; }#else modeinfo->flags &= ~HAVE_RWPAGE;#endif}static void ctHWCalcClock(unsigned char *vclk, unsigned int Clock){#ifdef DEBUG printf("CHIPS: ctHWCalcClock(*, %d)\n", Clock);#endif vclk[MSR] = (Clock << 2) & 0xC; vclk[XR54] = vclk[MSR]; vclk[XR33] = 0;}#define Fref 14318180/* * This is Ken Raeburn's <raeburn@raeburn.org> clock * calculation code just modified a little bit to fit in here. */static void ctCalcClock(unsigned char *vclk, unsigned int Clock){ int M, N, P, PSN, PSNx; int bestM=0, bestN=0, bestP=0, bestPSN=0; double bestError, abest = 42, bestFout=0; double target; double Fvco, Fout; double error, aerror; int M_min = 3; /* Hack to deal with problem of Toshiba 720CDT clock */ int M_max = ctisHiQV ? 63 : 127;#ifdef DEBUG printf("CHIPS: ctCalcClock(*, %d)\n", Clock);#endif /* Other parameters available on the 65548 but not the 65545, and * not documented in the Clock Synthesizer doc in rev 1.0 of the * 65548 datasheet: * * + XR30[4] = 0, VCO divider loop uses divide by 4 (same as 65545) * 1, VCO divider loop uses divide by 16 * * + XR30[5] = 1, reference clock is divided by 5 * * Other parameters available on the 65550 and not on the 65545 * * + XRCB[2] = 0, VCO divider loop uses divide by 4 (same as 65545) * 1, VCO divider loop uses divide by 16 * * + XRCB[1] = 1, reference clock is divided by 5 * * + XRCB[7] = Vclk = Mclk * * + XRCA[0:1] = 2 MSB of a 10 bit M-Divisor * * + XRCA[4:5] = 2 MSB of a 10 bit N-Divisor * * I haven't put in any support for those here. For simplicity, * they should be set to 0 on the 65548, and left untouched on * earlier chips. */ target = Clock * 1000; for (PSNx = 0; PSNx <= 1; PSNx++) { int low_N, high_N; double Fref4PSN; PSN = PSNx ? 1 : 4; low_N = 3; high_N = 127; while (Fref / (PSN * low_N) > 2.0e6) low_N++; while (Fref / (PSN * high_N) < 150.0e3) high_N--; Fref4PSN = Fref * 4 / PSN; for (N = low_N; N <= high_N; N++) { double tmp = Fref4PSN / N; for (P = ctisHiQV ? 1 : 0; P <= 5; P++) { /* to force post divisor on Toshiba 720CDT */ double Fvco_desired = target * (1 << P); double M_desired = Fvco_desired / tmp; /* Which way will M_desired be rounded? Do all three just to * be safe. */ int M_low = M_desired - 1; int M_hi = M_desired + 1; if (M_hi < M_min || M_low > M_max) continue; if (M_low < M_min) M_low = M_min; if (M_hi > M_max) M_hi = M_max; for (M = M_low; M <= M_hi; M++) { Fvco = tmp * M; if (Fvco <= 48.0e6) continue; if (Fvco > 220.0e6) break; Fout = Fvco / (1 << P); error = (target - Fout) / target; aerror = (error < 0) ? -error : error; if (aerror < abest) { abest = aerror; bestError = error; bestM = M; bestN = N; bestP = P; bestPSN = PSN; bestFout = Fout; } } } } } if (ctisHiQV) { vclk[MSR] = 3 << 2; /* Leave non-clock bits of FR03 alone */ vclk[HiQVFR03] = (vclk[HiQVFR03] & 0xF3) | vclk[MSR]; vclk[VCLK(0)] = bestM - 2; vclk[VCLK(1)] = bestN - 2; vclk[VCLK(2)] = 0; vclk[VCLK(3)] = (bestP << 4) + (bestPSN == 1);#ifdef DEBUG if (__svgalib_driver_report) { printf("Probed Freq: %.2f MHz", (float)(Clock / 1000.)); printf("VCLK(0) = %x, ",VCLK(0)); printf("VCLK(1) = %x, ",VCLK(1)); printf("VCLK(2) = %x, ",VCLK(2)); printf("VCLK(3) = %x\n",VCLK(3)); printf(", vclk[0]=%X, vclk[1]=%X, vclk[2]=%X, vlck[3]=%X\n", vclk[VCLK(0)], vclk[VCLK(1)], vclk[VCLK(2)], vclk[VCLK(3)]); printf("Freq used: %.2f MHz\n", bestFout / 1.0e6); }#endif return; } else { vclk[MSR] = 3 << 2; /* Leave non-clock bits of XR54 alone */ vclk[XR54] = (vclk[XR54] & 0xF3) | vclk[MSR]; vclk[VCLK(0)] = (bestP << 1) + (bestPSN == 1); vclk[VCLK(1)] = bestM - 2; vclk[VCLK(2)] = bestN - 2;#ifdef DEBUG if (__svgalib_driver_report) { printf("Probed Freq: %.2f MHz", (float)(Clock / 1000.)); printf(", vclk[0]=%X, vclk[1]=%X, vclk[2]=%X\n", vclk[VCLK(0)], vclk[VCLK(1)], vclk[VCLK(2)]); printf("Freq used: %.2f MHz\n", bestFout / 1.0e6); }#endif return; } }static void ctClockSave(unsigned char regs[]){ unsigned char xr54, msr, temp; int i; unsigned int Clk;#ifdef DEBUG printf("CHIPS: ctClockSave\n");#endif msr = inb(0x3CC); /* save the standard VGA clock registers */ regs[MSR] = msr; if (ctisHiQV) { outb(0x3D0,0x03); regs[HiQVFR03] = inb(0x3D1);/* save alternate clock select reg. */ temp = (regs[HiQVFR03] & 0xC) >> 2; if (temp == 3) temp = 2; temp = temp << 2; for (i = 0; i < 4; i++) { outb(0x3D6,0xC0 + i + temp); regs[VCLK(i)] = inb(0x3D7); } } else { outb(0x3D6,0x33); /* get status of MCLK/VCLK select reg.*/ regs[XR33] = inb(0x3D7); outb(0x3D6,0x54); /* save alternate clock select reg. */ xr54 = inb(0x3D7); regs[XR54] = xr54; if ((CHIPSchipset == CT_535 || CHIPSchipset == CT_540 || CHIPSchipset == CT_545 || CHIPSchipset == CT_546 || CHIPSchipset == CT_548 || CHIPSchipset == CT_4300) && (((xr54 & 0xC) == 0xC) || ((xr54 & 0xC) == 0x8))) { if (ctTextClock) { Clk = ctTextClock; } else {#ifdef CHIPS_PROBE_TEXT_CLOCK register int status = vgaIOBase + 0xA; int maskval = 0x08; unsigned long cnt, rcnt, sync; int Clk1, Clk2; sigset_t sig2block; /* If we are using a programmable clock, then there * is no way to be sure that the register values * correspond to those currently uploaded to the VCO. * Hence we use the same ugly hack XFree uses to probe * the value of the clock */ /* Disable the interrupts */ sigfillset(&sig2block); sigprocmask(SIG_BLOCK, &sig2block, (sigset_t *)NULL); /* Select Clk1 */ outb(0x3C2, (msr & 0xF2) | 0x4 | ctVgaIOBaseFlag); outb(0x3D6,0x54); outb(0x3D7,((xr54 & 0xF3) | 0x4)); usleep(50000); /* let VCO stabilise */ cnt = 0; sync = 200000; while ((inb(status) & maskval) == 0x00) if (sync-- == 0) goto finishClk1; /* Something appears to be happening, so reset sync count */ sync = 200000; while ((inb(status) & maskval) == maskval) if (sync-- == 0) goto finishClk1; /* Something appears to be happening, so reset sync count */ sync = 200000; while ((inb(status) & maskval) == 0x00) if (sync-- == 0) goto finishClk1; for (rcnt = 0; rcnt < 5; rcnt++) { while (!(inb(status) & maskval)) cnt++; while ((inb(status) & maskval)) cnt++; } finishClk1: Clk1 = cnt; /* Select Clk2 or Clk3 */ outb(0x3C2, (msr & 0xFE) | ctVgaIOBaseFlag); outb(0x3D6,0x54); outb(0x3D7,xr54); usleep(50000); /* let VCO stabilise */ cnt = 0; sync = 200000; while ((inb(status) & maskval) == 0x00) if (sync-- == 0) goto finishClk2; /* Something appears to be happening, so reset sync count */ sync = 200000; while ((inb(status) & maskval) == maskval) if (sync-- == 0) goto finishClk2; /* Something appears to be happening, so reset sync count */ sync = 200000; while ((inb(status) & maskval) == 0x00) if (sync-- == 0) goto finishClk2; for (rcnt = 0; rcnt < 5; rcnt++) { while (!(inb(status) & maskval)) cnt++; while ((inb(status) & maskval)) cnt++; } finishClk2: Clk2 = cnt; /* Re-enable the interrupts */ sigprocmask(SIG_UNBLOCK, &sig2block, (sigset_t *)NULL); Clk = (int)(0.5 + (((float)28322) * Clk1) / Clk2);#else /* CHIPS_PROBE_TEXT_CLOCK */ if (ctLCD) { Clk = LCD_TXT_CLOCK_FREQ; } else { Clk = CRT_TXT_CLOCK_FREQ; }#endif } /* Find a set of register settings that will give this * clock */ ctCalcClock(regs, Clk); } } return;}static void ctClockRestore(const unsigned char regs[])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -