ULONG SavMob_DisplayVideo(ULONG BufferOffset) { BYTE val; if (!(pRegs->chipflags&SAVMOB_NEED_RESETUP)) { OUTREG(SEC_STREAM_FBUF_ADDR0,BufferOffset); OUTREG(SEC_STREAM_DOUBLE_BUFFER,0); pRegs->BufAddr=BufferOffset; return RC_SUCCESS; } //if total resetup needed, we must reprogram all registers //unlock extended regs VGAOUT16(vgaCRIndex,0x4838); VGAOUT16(vgaCRIndex,0xa039); VGAOUT16(0x3c4,0x0608); VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 ); val = VGAIN8( vgaCRReg ) | ENABLE_STREAM1; // Wait for VBLANK. VerticalRetraceWait(); // Fire up streams! VGAOUT16( vgaCRIndex, (val << 8) | EXT_MISC_CTRL2 ); //Setup FIFO for PS VGAOUT8(vgaCRIndex,0x90); val=(((CurrModeInfo.ulScanLineSize)>>11)&0x07)|0x80; VGAOUT8(vgaCRReg,val); VGAOUT8(vgaCRIndex,0x91); val=((CurrModeInfo.ulScanLineSize)>>3)&0xff; VGAOUT8(vgaCRReg,val); //Setup FIFO for SS VGAOUT8(vgaCRIndex,0x92); val=((pRegs->Stride>>11)&0x07)|0x80; VGAOUT8(vgaCRReg,val); VGAOUT8(vgaCRIndex,0x93); val=(pRegs->Stride>>3)&0xff; VGAOUT8(vgaCRReg,val); OUTREG(PRI_STREAM_BUFFERSIZE,(CurrModeInfo.ulScanLineSize*CurrModeInfo.ulVertResolution)>>3); OUTREG(PRI_STREAM_FBUF_ADDR0,0); OUTREG(PRI_STREAM_STRIDE,CurrModeInfo.ulScanLineSize); OUTREG(SEC_STREAM_HSCALING,pRegs->HScaling); OUTREG(SEC_STREAM_VSCALING,pRegs->VScaling); OUTREG(SEC_STREAM_FBUF_ADDR0,BufferOffset); OUTREG(SEC_STREAM_FBUF_ADDR1,BufferOffset); OUTREG(SEC_STREAM_FBUF_ADDR2,BufferOffset); OUTREG(SEC_STREAM_STRIDE,pRegs->Stride); OUTREG(SEC_STREAM_WINDOW_START,pRegs->WindowStart); OUTREG(SEC_STREAM_WINDOW_SZ,pRegs->WindowSize); OUTREG(SEC_STREAM_CKEY_LOW,pRegs->ColorKeyLow); OUTREG(SEC_STREAM_CKEY_UPPER,pRegs->ColorKeyHigh); OUTREG(BLEND_CONTROL,pRegs->BlendControl); OUTREG(SEC_STREAM_COLOR_CONVERT1,pRegs->ColorConvert1); OUTREG(SEC_STREAM_COLOR_CONVERT2,pRegs->ColorConvert2); OUTREG(SEC_STREAM_COLOR_CONVERT3,pRegs->ColorConvert3); pRegs->chipflags&=~SAVMOB_NEED_RESETUP; return RC_SUCCESS; }
ULONG SavMob_HideVideo(void) { BYTE val; //unlock extended regs VGAOUT16(vgaCRIndex,0x4838); VGAOUT16(vgaCRIndex,0xa039); VGAOUT16(0x3c4,0x0608); VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 ); val = VGAIN8( vgaCRReg ) & NO_STREAMS; // Wait for VBLANK. VerticalRetraceWait(); // Kill streams! VGAOUT16( vgaCRIndex, (val << 8) | EXT_MISC_CTRL2 ); pRegs->chipflags|=SAVMOB_NEED_RESETUP; return RC_SUCCESS; }
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); }
static void Virge_GEReset(const DisplayModeEx& mode) { SharedInfo& si = *gInfo.sharedInfo; if (si.chipType == S3_TRIO_3D) Virge_NopAllCmdSets(); gInfo.WaitIdleEmpty(); if (si.chipType == S3_TRIO_3D) { bool ge_was_on = false; snooze(10000); for (int r = 1; r < 10; r++) { uint8 resetidx = 0x66; VerticalRetraceWait(); uint8 tmp = ReadCrtcReg(resetidx); VerticalRetraceWait(); IN_SUBSYS_STAT(); // turn off the GE if (tmp & 0x01) { WriteCrtcReg(resetidx, tmp); ge_was_on = true; snooze(10000); } IN_SUBSYS_STAT(); WriteCrtcReg(resetidx, tmp | 0x02); snooze(10000); VerticalRetraceWait(); WriteCrtcReg(resetidx, tmp & ~0x02); snooze(10000); if (ge_was_on) { tmp |= 0x01; WriteCrtcReg(resetidx, tmp); snooze(10000); } VerticalRetraceWait(); Virge_NopAllCmdSets(); gInfo.WaitIdleEmpty(); WriteReg32(DEST_SRC_STR, mode.bytesPerRow << 16 | mode.bytesPerRow); snooze(10000); if ((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000) { TRACE("Restarting S3 graphics engine reset %2d ...%lx\n", r, IN_SUBSYS_STAT() ); } else break; } } else { uint8 regIndex = (si.chipType == S3_VIRGE_VX ? 0x63 : 0x66); uint8 tmp = ReadCrtcReg(regIndex); snooze(10000); // try multiple times to avoid lockup of VIRGE/MX for (int r = 1; r < 10; r++) { WriteCrtcReg(regIndex, tmp | 0x02); snooze(10000); WriteCrtcReg(regIndex, tmp & ~0x02); snooze(10000); gInfo.WaitIdleEmpty(); WriteReg32(DEST_SRC_STR, mode.bytesPerRow << 16 | mode.bytesPerRow); snooze(10000); if (((IN_SUBSYS_STAT() & 0x3f00) != 0x3000)) { TRACE("Restarting S3 graphics engine reset %2d ...\n", r); } else break; } } gInfo.WaitQueue(2); WriteReg32(SRC_BASE, 0); WriteReg32(DEST_BASE, 0); gInfo.WaitQueue(4); WriteReg32(CLIP_L_R, ((0) << 16) | mode.timing.h_display); WriteReg32(CLIP_T_B, ((0) << 16) | mode.timing.v_display); WriteReg32(MONO_PAT_0, ~0); WriteReg32(MONO_PAT_1, ~0); if (si.chipType == S3_TRIO_3D) Virge_NopAllCmdSets(); }
static void Virge_WriteMode(const DisplayModeEx& mode, VirgeRegRec& regRec) { // This function writes out all of the standard VGA and extended S3 registers // needed to setup a video mode. TRACE("Virge_WriteMode()\n"); SharedInfo& si = *gInfo.sharedInfo; // First reset GE to make sure nothing is going on. if (ReadCrtcReg(si.chipType == S3_VIRGE_VX ? 0x63 : 0x66) & 0x01) Virge_GEReset(mode); // As per databook, always disable STREAMS before changing modes. if ((ReadCrtcReg(0x67) & 0x0c) == 0x0c) { // STREAMS running, disable it VerticalRetraceWait(); WriteReg32(FIFO_CONTROL_REG, 0xC000); WriteCrtcReg(0x67, 0x00, 0x0c); // disable STREAMS processor } // Restore S3 extended regs. WriteCrtcReg(0x63, regRec.CR63); WriteCrtcReg(0x66, regRec.CR66); WriteCrtcReg(0x3a, regRec.CR3A); WriteCrtcReg(0x31, regRec.CR31); WriteCrtcReg(0x58, regRec.CR58); // Extended mode timings registers. WriteCrtcReg(0x53, regRec.CR53); WriteCrtcReg(0x5d, regRec.CR5D); WriteCrtcReg(0x5e, regRec.CR5E); WriteCrtcReg(0x3b, regRec.CR3B); WriteCrtcReg(0x3c, regRec.CR3C); WriteCrtcReg(0x43, regRec.CR43); WriteCrtcReg(0x65, regRec.CR65); WriteCrtcReg(0x6d, regRec.CR6D); // Restore the desired video mode with CR67. WriteCrtcReg(0x67, 0x50, 0xf0); // possible hardware bug on VX? snooze(10000); WriteCrtcReg(0x67, regRec.CR67 & ~0x0c); // Don't enable STREAMS // Other mode timing and extended regs. WriteCrtcReg(0x34, regRec.CR34); if (si.chipType != S3_TRIO_3D && si.chipType != S3_VIRGE_MX) { WriteCrtcReg(0x40, regRec.CR40); } if (S3_VIRGE_MX_SERIES(si.chipType)) { WriteCrtcReg(0x41, regRec.CR41); } WriteCrtcReg(0x42, regRec.CR42); WriteCrtcReg(0x45, regRec.CR45); WriteCrtcReg(0x51, regRec.CR51); WriteCrtcReg(0x54, regRec.CR54); // Memory timings. WriteCrtcReg(0x68, regRec.CR68); WriteCrtcReg(0x69, regRec.CR69); WriteCrtcReg(0x33, regRec.CR33); if (si.chipType == S3_TRIO_3D_2X || S3_VIRGE_GX2_SERIES(si.chipType) /* MXTESTME */ || S3_VIRGE_MX_SERIES(si.chipType) ) { WriteCrtcReg(0x85, regRec.CR85); } if (si.chipType == S3_VIRGE_DXGX) { WriteCrtcReg(0x86, regRec.CR86); } if ( (si.chipType == S3_VIRGE_GX2) || S3_VIRGE_MX_SERIES(si.chipType) ) { WriteCrtcReg(0x7b, regRec.CR7B); WriteCrtcReg(0x7d, regRec.CR7D); WriteCrtcReg(0x87, regRec.CR87); WriteCrtcReg(0x92, regRec.CR92); WriteCrtcReg(0x93, regRec.CR93); } if (si.chipType == S3_VIRGE_DXGX || S3_VIRGE_GX2_SERIES(si.chipType) || S3_VIRGE_MX_SERIES(si.chipType) || si.chipType == S3_TRIO_3D) { WriteCrtcReg(0x90, regRec.CR90); WriteCrtcReg(0x91, regRec.CR91); } WriteSeqReg(0x08, 0x06); // unlock extended sequencer regs // Restore extended sequencer regs for DCLK. WriteSeqReg(0x12, regRec.SR12); WriteSeqReg(0x13, regRec.SR13); if (S3_VIRGE_GX2_SERIES(si.chipType) || S3_VIRGE_MX_SERIES(si.chipType)) { WriteSeqReg(0x29, regRec.SR29); } if (S3_VIRGE_MX_SERIES(si.chipType)) { WriteSeqReg(0x54, regRec.SR54); WriteSeqReg(0x55, regRec.SR55); WriteSeqReg(0x56, regRec.SR56); WriteSeqReg(0x57, regRec.SR57); } WriteSeqReg(0x18, regRec.SR18); // Load new m,n PLL values for DCLK & MCLK. uint8 tmp = ReadSeqReg(0x15) & ~0x21; WriteSeqReg(0x15, tmp | 0x03); WriteSeqReg(0x15, tmp | 0x23); WriteSeqReg(0x15, tmp | 0x03); WriteSeqReg(0x15, regRec.SR15); if (si.chipType == S3_TRIO_3D) { WriteSeqReg(0x0a, regRec.SR0A); WriteSeqReg(0x0f, regRec.SR0F); } // Now write out CR67 in full, possibly starting STREAMS. VerticalRetraceWait(); WriteCrtcReg(0x67, 0x50); // For possible bug on VX?! snooze(10000); WriteCrtcReg(0x67, regRec.CR67); uint8 cr66 = ReadCrtcReg(0x66); WriteCrtcReg(0x66, cr66 | 0x80); WriteCrtcReg(0x3a, regRec.CR3A | 0x80); // Now, before we continue, check if this mode has the graphic engine ON. // If yes, then we reset it. if (si.chipType == S3_VIRGE_VX) { if (regRec.CR63 & 0x01) Virge_GEReset(mode); } else { if (regRec.CR66 & 0x01) Virge_GEReset(mode); } VerticalRetraceWait(); if (S3_VIRGE_GX2_SERIES(si.chipType) || S3_VIRGE_MX_SERIES(si.chipType) ) { WriteCrtcReg(0x85, 0x1f); // primary stream threshold } // Set the standard CRTC vga regs. WriteCrtcReg(0x11, 0x00, 0x80); // unlock CRTC reg's 0-7 by clearing bit 7 of cr11 for (int j = 0; j < NUM_ELEMENTS(regRec.CRTC); j++) { WriteCrtcReg(j, regRec.CRTC[j]); } // Setup HSYNC & VSYNC polarity and select clock source 2 (0x0c) for // programmable PLL. uint8 miscOutReg = 0x23 | 0x0c; if (!(mode.timing.flags & B_POSITIVE_HSYNC)) miscOutReg |= 0x40; if (!(mode.timing.flags & B_POSITIVE_VSYNC)) miscOutReg |= 0x80; WriteMiscOutReg(miscOutReg); WriteCrtcReg(0x66, cr66); WriteCrtcReg(0x3a, regRec.CR3A); return ; }