int v_setmode(struct v_board_t *board, struct v_modeinfo_t *mode) { int tmp; int doubleclock=0; int M, N, P; int iob=board->io_base; /* switching to native mode */ v_out8(iob+MODEREG, NATIVE_MODE|VESA_MODE); /* flipping some bytes */ /* Must be something better to do than this -- FIX */ switch (mode->bitsperpixel) { case 32: v_out8(iob+MEMENDIAN, MEMENDIAN_NO); break; case 16: v_out8(iob+MEMENDIAN, MEMENDIAN_HW); break; case 8: v_out8(iob+MEMENDIAN, MEMENDIAN_END); break; } if (OFLG_ISSET(OPTION_OVERCLOCK_MEM, &vga256InfoRec.options)) { /* increase Mem/Sys clock to avoid nasty artifacts */ if (board->chip != V1000_DEVICE) { v_out32(iob+SCLKPLL, 0xa484d); /* mclk=110 sclk=55 */ /* M/N/P/P = 77/5/2/4 */ usleep(500); } } /* this has something to do with memory */ tmp=v_in32(iob+DRAMCTL)&0xdfff; /* reset bit 13 */ v_out32(iob+DRAMCTL, tmp|0x330000); /* program pixel clock */ if (board->chip == V1000_DEVICE) { if (110.0 < V1000CalcClock(mode->clock/1000.0, &M, &N, &P)) { P++; doubleclock=1; } set_PLL(iob, combineNMP(N, M, P)); } else { tmp = (~0x1800) & v_in32(iob+DRAMCTL); v_out32(iob+DRAMCTL, tmp); V2200CalcClock(mode->clock/1000.0, &M, &N, &P); v_out32(iob+PCLKPLL, v2kcombineNMP(N, M, P)); } usleep(500); /* init the ramdac */ v_initdac(board, mode->bitsperpixel, doubleclock); v_out32(iob+CRTCHORZ, HORZ(mode->hsyncstart-mode->hdisplay, mode->hsyncend-mode->hsyncstart, mode->htotal-mode->hsyncend, mode->hdisplay)); v_out32(iob+CRTCVERT, VERT(mode->vsyncstart-mode->vdisplay, mode->vsyncend-mode->vsyncstart, mode->vtotal-mode->vsyncend, mode->vdisplay)); /* fill in the mode parameters */ memcpy(&(board->mode), mode, sizeof(struct v_modeinfo_t)); board->mode.fifosize=128; board->mode.pll_m=M; board->mode.pll_n=N; board->mode.pll_p=P; board->mode.doubleclock=doubleclock; if (0 == board->mode.virtualwidth) board->mode.virtualwidth=board->mode.screenwidth; board->init=1; v_setframebase(board, 0); /* Need to fix up syncs */ /* enable the display */ v_out32(iob+CRTCCTL, CTL(0, mode->hsynchi, mode->vsynchi) |mode->pixelformat |CRTCCTL_VIDEOFIFOSIZE128 |CRTCCTL_HSYNCENABLE |CRTCCTL_VSYNCENABLE |CRTCCTL_VIDEOENABLE); return 0; }
void s3CleanUp(void) { int i; unsigned char tmp; outb(vgaCRIndex, 0x39); outb(vgaCRReg, 0xa5); if (s3MmioMem != NULL ) { WaitIdle(); VerticalRetraceWait(); ((mmtr)s3MmioMem)->memport_regs.regs.fifo_control = oldS3->fifo[0]; WaitIdle(); /* Don't ask... */ ((mmtr)s3MmioMem)->memport_regs.regs.streams_timeout = oldS3->fifo[1]; } #if 1 /* This seems to help, but maybe a wait for */ /* VSYNC would be better than WaitIdleEmpty(). */ /* STREAMS disable code, for 24 & 32 Bpp */ if ( ( s3InfoRec.bitsPerPixel == 32 || s3InfoRec.bitsPerPixel == 24 ) && s3MmioMem != NULL ) { /* temp - KJB */ ((mmtr)s3MmioMem)->streams_regs.regs.prim_fbaddr0 = 0; /* ((y * s3DisplayWidth + (x & ~3)) * s3Bpp) */ /* & ~3 */; /* end temp */ outb(vgaCRIndex, 0x67); tmp = inb(vgaCRReg); /* WaitIdleEmpty(); */ /* Disable STREAMS processor */ outb( vgaCRReg, tmp & ~0x0C ); } #endif vgaProtect(TRUE); if (s3NewMmio) { outb (vgaCRIndex, 0x58); outb (vgaCRReg, s3SAM256); /* disable linear mode */ } /* end BL */ WaitQueue(8); outb(vgaCRIndex, 0x35); tmp = inb(vgaCRReg); outb(vgaCRReg, (tmp & 0xf0)); cebank(); if (s3NewMmio) { outb(vgaCRIndex, 0x53); outb(vgaCRReg, 0x00); } /* Restore S3 Trio32/64 ext. sequenzer (PLL) registers */ if (DAC_IS_TRIO) { outb(0x3c2, oldS3->Trio[0]); outb(0x3c4, 0x08); outb(0x3c5, 0x06); outb(0x3c4, 0x09); outb(0x3c5, oldS3->Trio[2]); outb(0x3c4, 0x0a); outb(0x3c5, oldS3->Trio[3]); outb(0x3c4, 0x0b); outb(0x3c5, oldS3->Trio[4]); outb(0x3c4, 0x0d); outb(0x3c5, oldS3->Trio[5]); outb(0x3c4, 0x10); outb(0x3c5, oldS3->Trio[8]); outb(0x3c4, 0x11); outb(0x3c5, oldS3->Trio[9]); outb(0x3c4, 0x12); outb(0x3c5, oldS3->Trio[10]); outb(0x3c4, 0x13); outb(0x3c5, oldS3->Trio[11]); outb(0x3c4, 0x1a); outb(0x3c5, oldS3->Trio[12]); outb(0x3c4, 0x1b); outb(0x3c5, oldS3->Trio[13]); outb(0x3c4, 0x15); tmp = inb(0x3c5) & ~0x21; outb(0x3c5, tmp | 0x03); outb(0x3c5, tmp | 0x23); outb(0x3c5, tmp | 0x03); outb(0x3c4, 0x15); outb(0x3c5, oldS3->Trio[6]); outb(0x3c4, 0x18); outb(0x3c5, oldS3->Trio[7]); outb(0x3c4, 0x08); outb(0x3c5, oldS3->Trio[1]); } /* restore s3 special bits */ /* restore 801 specific registers */ for (i = 32; i < 46; i++) { outb(vgaCRIndex, 0x40 + i); outb(vgaCRReg, oldS3->s3sysreg[i]); } for (i = 0; i < 16; i++) { if (!((1 << i) & reg50_mask)) continue; outb(vgaCRIndex, 0x50 + i); outb(vgaCRReg, oldS3->s3sysreg[i + 16]); } for (i = 0; i < 5; i++) { outb(vgaCRIndex, 0x30 + i); outb(vgaCRReg, oldS3->s3reg[i]); outb(vgaCRIndex, 0x38 + i); outb(vgaCRReg, oldS3->s3reg[5 + i]); } outb(vgaCRIndex, 0x36); outb(vgaCRReg, oldS3->s3reg[10]); for (i = 0; i < 16; i++) { outb(vgaCRIndex, 0x40 + i); outb(vgaCRReg, oldS3->s3sysreg[i]); } outb(vgaCRIndex, 0x45); inb(vgaCRReg); /* reset color stack pointer */ outb(vgaCRIndex, 0x4A); for (i = 0; i < 4; i++) outb(vgaCRReg, oldS3->ColorStack[i]); outb(vgaCRIndex, 0x45); inb(vgaCRReg); /* reset color stack pointer */ outb(vgaCRIndex, 0x4B); for (i = 4; i < 8; i++) outb(vgaCRReg, oldS3->ColorStack[i]); if (OFLG_ISSET(CLOCK_OPTION_ICS2595, &s3InfoRec.clockOptions)){ outb(vgaCRIndex, 0x42); outb(vgaCRReg, (oldS3->s3sysreg[2] & 0xf0) | 0x01); outb(vgaCRIndex, 0x5c); /* switch back to 28MHz clock */ outb(vgaCRReg, 0x20); outb(vgaCRReg, 0x00); } vgaHWRestore((vgaHWPtr)oldS3); outb(0x3c2, old_clock); i = inb(0x3CC); if (savedVgaIOBase == 0x3B0) i &= 0xFE; else i |= 0x01; outb(0x3C2, i); vgaIOBase = savedVgaIOBase; vgaCRIndex = vgaIOBase + 4; vgaCRReg = vgaIOBase + 5; vgaProtect(FALSE); #ifdef PC98 crtswitch(0); #endif xf86DisableIOPorts(s3InfoRec.scrnIndex); }
/* * mach8Probe -- * probe and initialize the hardware driver */ Bool mach8Probe() { int j, memavail, rounding; short temp; DisplayModePtr pMode, pEnd, pmaxX = NULL, pmaxY = NULL; int maxX, maxY; OFlagSet validOptions; int tx, ty; mach8InfoRec.maxClock = mach8MaxClock; xf86ClearIOPortList(mach8InfoRec.scrnIndex); xf86AddIOPorts(mach8InfoRec.scrnIndex, Num_mach8_IOPorts, mach8_IOPorts); if (mach8InfoRec.chipset) { if (StrCaseCmp(mach8InfoRec.chipset, "mach8")) { ErrorF("Chipset specified in XF86Config is not \"mach8\" (%s)!\n", mach8InfoRec.chipset); return(FALSE); } xf86EnableIOPorts(mach8InfoRec.scrnIndex); } else { xf86EnableIOPorts(mach8InfoRec.scrnIndex); /* Reset the 8514/A, and disable all interrupts. */ outw(SUBSYS_CNTL, GPCTRL_RESET | CHPTEST_NORMAL); outw(SUBSYS_CNTL, GPCTRL_ENAB | CHPTEST_NORMAL); /* Check to see if an 8514/A is actually installed by writing to * the ERR_TERM register, and reading back. The 0x5a5a value is * entirely arbitrary. */ outw(ERR_TERM, 0x5a5a); ProbeWaitIdleEmpty(); if (inw(ERR_TERM) != 0x5a5a) { ErrorF("%s: No 8514/A registers detected!\n", mach8InfoRec.name); xf86DisableIOPorts(mach8InfoRec.scrnIndex); return(FALSE); } /* 6 mar 93 TCG : let's make certain */ outw(ERR_TERM, 0x2525); ProbeWaitIdleEmpty(); if (inw(ERR_TERM) != 0x2525) { ErrorF("%s: No 8514/A registers detected!\n", mach8InfoRec.name); xf86DisableIOPorts(mach8InfoRec.scrnIndex); return(FALSE); } temp = inw(ROM_ADDR_1); outw(ROM_ADDR_1, 0x5555); ProbeWaitIdleEmpty(); if (inw(ROM_ADDR_1) != 0x5555) { ErrorF("%s: No ATI accelerator detected\n", mach8InfoRec.name); xf86DisableIOPorts(mach8InfoRec.scrnIndex); return(FALSE); } outw(ROM_ADDR_1, 0x2a2a); ProbeWaitIdleEmpty(); if (inw(ROM_ADDR_1) != 0x2a2a) { ErrorF("%s: No ATI accelerator detected\n", mach8InfoRec.name); xf86DisableIOPorts(mach8InfoRec.scrnIndex); return(FALSE); } outw(ROM_ADDR_1, temp); outw(DESTX_DIASTP, 0xaaaa); ProbeWaitIdleEmpty(); if ((inw(READ_SRC_X) != 0xaaaa) && xf86Verbose) { outw(DESTX_DIASTP, 0x5555); ProbeWaitIdleEmpty(); if (inw(READ_SRC_X) == 0x0555) { ErrorF("%s %s: Mach-32 detected, used as a Mach-8\n", XCONFIG_PROBED, mach8InfoRec.name); } else ErrorF("%s %s: Mach-8 detected\n", XCONFIG_PROBED, mach8InfoRec.name); } } OFLG_ZERO(&validOptions); OFLG_SET(OPTION_CSYNC, &validOptions); xf86VerifyOptions(&validOptions, &mach8InfoRec); if (!mach8InfoRec.clocks) { outw(DISP_CNTL, DISPEN_DISAB /*| INTERLACE*/ | MEMCFG_4 | ODDBNKENAB); /* 13-jun-93 TCG : set up dummy video mode */ outw(SHADOW_SET, 1); outw(SHADOW_CTL, 0); outw(SHADOW_SET, 2); outw(SHADOW_CTL, 0); outw(SHADOW_SET, 0); outw(ADVFUNC_CNTL, DISABPASSTHRU); /* vt: 480 488 +31 528 hz: 640 656 +248 920 */ outw(V_TOTAL, 0x420); outw(V_DISP, 0x3c0); outw(V_SYNC_STRT, 0x3d0); outw(V_SYNC_WID, 0x1f); outw(H_TOTAL, 0x72); outw(H_DISP, 0x4f); outw(H_SYNC_STRT, 0x51); outw(H_SYNC_WID, 0x1f); outw(DAC_MASK, 0x00); outw(DISP_CNTL, DISPEN_ENAB | MEMCFG_4 | ODDBNKENAB); /* 2-oct-93 TCG : detect clocks with dif4 fix */ mach8clkprobedif4fix = TRUE; xf86GetClocks(16, mach8ClockSelect, (void (*)())NoopDDA, (SaveScreenProcPtr)NoopDDA, DISP_STAT, 2, 7, 44900, &mach8InfoRec); outw(CLOCK_SEL, 0); /* reset pass-through */ mach8clkprobedif4fix = FALSE; outw(SHADOW_SET, 1); outw(SHADOW_CTL, 0x3f); outw(SHADOW_SET, 2); outw(SHADOW_CTL, 0x3f); outw(SHADOW_SET, 0); outw(DAC_MASK, 0xff); for (j = 0; j < 16; j++) mach8InfoRec.clock[j + 16] = mach8InfoRec.clock[j] / 2; mach8InfoRec.clocks = 32; } temp = inw(CONFIG_STATUS_1); if (!mach8InfoRec.videoRam) { switch((temp & 0x60) >> 5) { case 0: mach8InfoRec.videoRam = 512; break; case 1: mach8InfoRec.videoRam = 1024; break; default: /* 2 & 3 reserved in mach-8, used in mach-32 ? */ mach8InfoRec.videoRam = 1024; break; } } mach8InfoRec.chipset = "mach8"; xf86ProbeFailed = FALSE; mach8DramUsed = (temp & 0x10) != 0; if (xf86Verbose) { ErrorF("%s %s: (mem: %dk %cRAM numclocks: %d)", OFLG_ISSET(XCONFIG_VIDEORAM,&mach8InfoRec.xconfigFlag) ? XCONFIG_GIVEN : XCONFIG_PROBED, mach8InfoRec.name, mach8InfoRec.videoRam, mach8DramUsed ? 'D' : 'V', mach8InfoRec.clocks); for (j=0; j < mach8InfoRec.clocks; j++) { if ((j % 8) == 0) ErrorF("\n%s %s: clocks:", OFLG_ISSET(XCONFIG_CLOCKS,&mach8InfoRec.xconfigFlag) ? XCONFIG_GIVEN : XCONFIG_PROBED, mach8InfoRec.name); ErrorF(" %6.2f", (double)mach8InfoRec.clock[j]/1000.0); } ErrorF("\n"); } memavail = mach8InfoRec.videoRam*1024; if (mach8InfoRec.virtualX > 0 && mach8InfoRec.virtualX * mach8InfoRec.virtualY > memavail) { ErrorF("%s: Too little memory for virtual resolution %d %d\n", mach8InfoRec.name, mach8InfoRec.virtualX, mach8InfoRec.virtualY); return(FALSE); } maxX = maxY = -1; pMode = mach8InfoRec.modes; if (pMode == NULL) { ErrorF("No modes supplied in XF86Config\n"); return(FALSE); } pEnd = NULL; tx = mach8InfoRec.virtualX; ty = mach8InfoRec.virtualY; do { DisplayModePtr pModeSv; /* * xf86LookupMode returns FALSE if it ran into an invalid * parameter */ if(xf86LookupMode(pMode, &mach8InfoRec, LOOKUP_DEFAULT) == FALSE) { pModeSv=pMode->next; xf86DeleteMode(&mach8InfoRec, pMode); pMode = pModeSv; } else if (pMode->HDisplay > 1024) { pModeSv=pMode->next; ErrorF("%s %s: Width to large for mode %s (max 1024)\n", XCONFIG_PROBED, mach8InfoRec.name, pMode->name); xf86DeleteMode(&mach8InfoRec, pMode); pMode = pModeSv; } else if (pMode->HDisplay * pMode->VDisplay > memavail) { pModeSv=pMode->next; ErrorF("%s %s: Too little memory for mode %s\n", XCONFIG_PROBED, mach8InfoRec.name, pMode->name); xf86DeleteMode(&mach8InfoRec, pMode); pMode = pModeSv; } else if (((tx > 0) && (pMode->HDisplay > tx)) || ((ty > 0) && (pMode->VDisplay > ty))) { pModeSv=pMode->next; ErrorF("%s %s: Resolution %dx%d too large for virtual %dx%d\n", XCONFIG_PROBED, mach8InfoRec.name, pMode->HDisplay, pMode->VDisplay, tx, ty); xf86DeleteMode(&mach8InfoRec, pMode); pMode = pModeSv; } else { /* * Successfully looked up this mode. If pEnd isn't * initialized, set it to this mode. */ if(pEnd == (DisplayModePtr) NULL) pEnd = pMode; if (pMode->HDisplay > maxX) { maxX = pMode->HDisplay; pmaxX = pMode; } if (pMode->VDisplay > maxY) { maxY = pMode->VDisplay; pmaxY = pMode; } pMode = pMode->next; } } while (pMode != pEnd); mach8InfoRec.virtualX = max(maxX, mach8InfoRec.virtualX); mach8InfoRec.virtualY = max(maxY, mach8InfoRec.virtualY); rounding = 8; if (mach8InfoRec.virtualX % rounding) { mach8InfoRec.virtualX -= mach8InfoRec.virtualX % rounding; ErrorF("%s %s: Virtual width rounded down to a multiple of %d (%d)\n", XCONFIG_PROBED, mach8InfoRec.name, rounding, mach8InfoRec.virtualX); if (mach8InfoRec.virtualX < maxX) { ErrorF( "%s: Rounded down virtual width (%d) is too small for mode %s", mach8InfoRec.name, mach8InfoRec.virtualX, pmaxX->name); return(FALSE); } ErrorF("%s: Virtual width rounded down to a multiple of %d (%d)\n", mach8InfoRec.name, rounding, mach8InfoRec.virtualX); } if (mach8InfoRec.virtualX > 1024) { ErrorF("%s: Virtual width must be no greater than 1024\n",mach8InfoRec.name); return(FALSE); } if ( mach8InfoRec.virtualX * mach8InfoRec.virtualY > memavail) { if (mach8InfoRec.virtualX != maxX || mach8InfoRec.virtualY != maxY) ErrorF( "%s: Too little memory to accomodate virtual size and mode %s\n", mach8InfoRec.name, (mach8InfoRec.virtualX == maxX) ? pmaxX->name : pmaxY->name); else ErrorF("%s: Too little memory to accomodate modes %s and %s\n", mach8InfoRec.name, pmaxX->name, pmaxY->name); return(FALSE); } if (xf86Verbose) ErrorF("%s %s: Virtual resolution set to %dx%d\n", OFLG_ISSET(XCONFIG_VIRTUAL,&mach8InfoRec.xconfigFlag) ? XCONFIG_GIVEN : XCONFIG_PROBED, mach8InfoRec.name, mach8InfoRec.virtualX, mach8InfoRec.virtualY); return(TRUE); }