/* $XConsortium: gvg_driver.c,v 1.3 95/01/16 13:18:16 kaleb Exp $ */ /* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/gvga/gvg_driver.c,v 3.7 1995/05/27 03:16:49 dawes Exp $ */ /* * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Thomas Roell not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Thomas Roell makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Thomas Roell, roell@informatik.tu-muenchen.de * */ #include "X.h" #include "input.h" #include "screenint.h" #include "dix.h" #include "compiler.h" #include "xf86.h" #include "xf86Priv.h" #include "xf86_OSlib.h" #include "xf86_HWlib.h" #include "vga.h" typedef struct { vgaHWRec std; /* good old IBM VGA */ unsigned char ExtCtrlReg1; unsigned char ExtCtrlReg2; unsigned char ExtCtrlReg3; unsigned char ExtCtrlReg4; unsigned char ExtCtrlReg5; unsigned char MemSegReg; } vgaGVGARec, *vgaGVGAPtr; static Bool GVGAProbe(); static char * GVGAIdent(); static Bool GVGAClockSelect(); static void GVGAEnterLeave(); static Bool GVGAInit(); static Bool GVGAValidMode(); static void * GVGASave(); static void GVGARestore(); static void GVGAAdjust(); extern void GVGASetRead(); extern void GVGASetWrite(); extern void GVGASetReadWrite(); vgaVideoChipRec GVGA = { GVGAProbe, GVGAIdent, GVGAEnterLeave, GVGAInit, GVGAValidMode, GVGASave, GVGARestore, GVGAAdjust, vgaHWSaveScreen, (void (*)())NoopDDA, (void (*)())NoopDDA, GVGASetRead, GVGASetWrite, GVGASetReadWrite, 0x10000, 0x10000, 16, 0xFFFF, 0x00000, 0x10000, 0x00000, 0x10000, TRUE, /* Uses 2 banks */ VGA_NO_DIVIDE_VERT, {0,}, 16, FALSE, 0, 0, FALSE, FALSE, NULL, 1, }; #define new ((vgaGVGAPtr)vgaNewVideoState) /* * GVGAIdent */ static char * GVGAIdent(n) int n; { static char *chipsets[] = {"gvga"}; if (n + 1 > sizeof(chipsets) / sizeof(char *)) return(NULL); else return(chipsets[n]); } /* * GVGAClockSelect -- * select one of the possible clocks ... */ static Bool GVGAClockSelect(no) int no; { static unsigned char save1, save2; unsigned char temp; switch(no) { case CLK_REG_SAVE: save1 = inb(0x3CC); outb(0x3C4, 0x07); save2 = inb(0x3C5); break; case CLK_REG_RESTORE: outb(0x3C2, save1); outw(0x3C4, 0x07 | (save2 << 8)); break; default: temp = inb(0x3CC); outb(0x3C2, ( temp & 0xf3) | ((no << 2) & 0x0C)); outb(0x3C4, 0x07); temp = inb(0x3C5); outb(0x3C5, (temp & 0xFE) | ((no & 0x04) >> 2)); } return(TRUE); } /* * GVGAProbe -- * check up whether a GVGA based board is installed */ static Bool GVGAProbe() { /* * Set up I/O ports to be used by this card */ xf86ClearIOPortList(vga256InfoRec.scrnIndex); xf86AddIOPorts(vga256InfoRec.scrnIndex, Num_VGA_IOPorts, VGA_IOPorts); if (vga256InfoRec.chipset) { if (StrCaseCmp(vga256InfoRec.chipset, GVGAIdent(0))) return (FALSE); if (!vga256InfoRec.videoRam) vga256InfoRec.videoRam = 512; } else { unsigned char offset, signature[4]; if (xf86ReadBIOS(vga256InfoRec.BIOSbase, 0x37, &offset, 1) != 1) return(FALSE); if (xf86ReadBIOS(vga256InfoRec.BIOSbase, offset, signature, 4) != 4) return(FALSE); if ((signature[0] != 0x77) || ((signature[1] == 0x33) || (signature[1] == 0x55)) || ((signature[2] != 0x66) && (signature[2] != 0x99)) || ((signature[3] != 0x99) && (signature[3] != 0x66))) return(FALSE); if (!vga256InfoRec.videoRam) switch(signature[1]) { case 0x00: case 0x22: vga256InfoRec.videoRam = 256; break; case 0x11: default: vga256InfoRec.videoRam = 512; break; } } GVGAEnterLeave(ENTER); if (!vga256InfoRec.clocks) vgaGetClocks(8, GVGAClockSelect); vga256InfoRec.chipset = GVGAIdent(0); vga256InfoRec.bankedMono = TRUE; return(TRUE); } /* * GVGAEnterLeave -- * enable/disable io-mapping */ static void GVGAEnterLeave(enter) Bool enter; { unsigned char temp; if (enter) { xf86EnableIOPorts(vga256InfoRec.scrnIndex); vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5); outb(vgaIOBase + 5, temp & 0x7F); } else xf86DisableIOPorts(vga256InfoRec.scrnIndex); } /* * GVGARestore -- * restore a video mode */ static void GVGARestore(restore) vgaGVGAPtr restore; { outw(0x3C4, 0x0006); /* segment select */ vgaHWRestore((vgaHWPtr)restore); outw(vgaIOBase + 4, (restore->ExtCtrlReg1 << 8) | 0x2F); outw(0x3C4, (restore->MemSegReg << 8) | 0x06); if (restore->std.NoClock >= 0) outw(0x3C4, (restore->ExtCtrlReg2 << 8) | 0x07); outw(0x3C4, (restore->ExtCtrlReg3 << 8) | 0x08); outw(0x3C4, (restore->ExtCtrlReg4 << 8) | 0x10); outw(0x3CE, (restore->ExtCtrlReg5 << 8) | 0x09); } /* * GVGASave -- * save the current video mode */ static void * GVGASave(save) vgaGVGAPtr save; { unsigned char temp; outb(0x3C4, 0x06); temp = inb(0x3C5); outb(0x3C5, 0x00); /* segment select */ save = (vgaGVGAPtr)vgaHWSave((vgaHWPtr)save, sizeof(vgaGVGARec)); save->MemSegReg = temp; outb(vgaIOBase + 4, 0x2f); save->ExtCtrlReg1 = inb(vgaIOBase + 5); outb(0x3C4, 0x07); save->ExtCtrlReg2 = inb(0x3C5); outb(0x3C4, 0x08); save->ExtCtrlReg3 = inb(0x3C5); outb(0x3C4, 0x10); save->ExtCtrlReg4 = inb(0x3C5); outb(0x3CE, 0x09); save->ExtCtrlReg5 = inb(0x3CF); return ((void *) save); } /* * GVGAInit -- * Handle the initialization, etc. of a screen. */ static Bool GVGAInit(mode) DisplayModePtr mode; { if (!vgaHWInit(mode,sizeof(vgaGVGARec))) return(FALSE); #ifndef MONOVGA new->std.Sequencer[4] = 0x06; /* use the FAST 256 Color Mode */ new->std.Attribute[16] = 0x01; new->ExtCtrlReg1 = 0x02; #else new->ExtCtrlReg1 = 0x00; /* Not sure about this (DHD) */ #endif new->ExtCtrlReg2 = 0x06 | (new->std.NoClock >= 0) ? ((int)(new->std.NoClock & 0x04) >> 2) : 0; new->ExtCtrlReg3 = 0x20; new->ExtCtrlReg4 = 0x24; new->ExtCtrlReg5 = 0x08; return(TRUE); } /* * GVGAAdjust -- * adjust the current video frame to display the mousecursor */ static void GVGAAdjust(x, y) int x, y; { int Base =(y * vga256InfoRec.displayWidth + x + 3) >> 3; outw(vgaIOBase + 4, (Base & 0x00FF00) | 0x0C); outw(vgaIOBase + 4, ((Base & 0x00FF) << 8) | 0x0D); } /* * GVGAValidMode -- * */ static Bool GVGAValidMode(mode) DisplayModePtr mode; { return TRUE; }