1 /*- 2 * Copyright (c) 1991-1997 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <stdio.h> 32 #include <sys/types.h> 33 #include <sys/signal.h> 34 #include <sys/file.h> 35 #include <sys/ioctl.h> 36 #include <sys/mman.h> 37 #include <machine/console.h> 38 #include "vgl.h" 39 40 VGLBitmap *VGLDisplay; 41 42 static int VGLMode; 43 static int VGLOldMode; 44 static byte *VGLBuf; 45 static byte *VGLMem; 46 static int VGLSwitchPending; 47 static int VGLOnDisplay; 48 static int VGLInitDone = 0; 49 50 void 51 VGLEnd() 52 { 53 struct vt_mode smode; 54 55 if (!VGLInitDone) 56 return; 57 if (VGLOnDisplay && !VGLSwitchPending) { 58 outb(0x3c4, 0x02); 59 outb(0x3c5, 0x0f); 60 bzero(VGLMem, 64*1024); 61 } 62 if (VGLOldMode >= M_VESA_BASE) { 63 /* ugly, but necessary */ 64 ioctl(0, _IO('V', VGLOldMode - M_VESA_BASE), 0); 65 if (VGLOldMode == M_VESA_800x600) { 66 int size[3]; 67 size[0] = 80; 68 size[1] = 25; 69 size[2] = 16; 70 ioctl(0, KDRASTER, size); 71 } 72 } else { 73 ioctl(0, _IO('S', VGLOldMode), 0); 74 } 75 ioctl(0, KDDISABIO, 0); 76 ioctl(0, KDSETMODE, KD_TEXT); 77 smode.mode = VT_AUTO; 78 ioctl(0, VT_SETMODE, &smode); 79 free(VGLBuf); 80 free(VGLDisplay); 81 VGLKeyboardEnd(); 82 } 83 84 static void 85 VGLAbort() 86 { 87 VGLEnd(); 88 exit(0); 89 } 90 91 static void 92 VGLSwitch() 93 { 94 if (!VGLOnDisplay) 95 VGLOnDisplay = 1; 96 else 97 VGLOnDisplay = 0; 98 VGLSwitchPending = 1; 99 signal(SIGUSR1, VGLSwitch); 100 } 101 102 int 103 VGLInit(int mode) 104 { 105 struct vt_mode smode; 106 struct winsize winsz; 107 int error; 108 109 signal(SIGUSR1, VGLSwitch); 110 signal(SIGINT, VGLAbort); 111 signal(SIGTERM, VGLAbort); 112 signal(SIGSEGV, VGLAbort); 113 signal(SIGBUS, VGLAbort); 114 115 VGLOnDisplay = 1; 116 VGLSwitchPending = 0; 117 118 ioctl(0, CONS_GET, &VGLOldMode); 119 120 VGLMem = (byte*)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_FILE, 121 open("/dev/mem", O_RDWR), 0xA0000); 122 if (VGLMem <= (byte*)0) 123 return 1; 124 125 VGLBuf = (byte*)malloc(256*1024); 126 if (VGLBuf == NULL) 127 return 1; 128 129 VGLDisplay = (VGLBitmap*) malloc(sizeof(VGLBitmap)); 130 if (VGLDisplay == NULL) { 131 free(VGLBuf); 132 return 1; 133 } 134 135 switch (mode) { 136 case SW_BG640x480: case SW_CG640x480: 137 VGLDisplay->Type = VIDBUF4; 138 break; 139 case SW_VGA_CG320: 140 VGLDisplay->Type = VIDBUF8; 141 break; 142 case SW_VGA_MODEX: 143 VGLDisplay->Type = VIDBUF8X; 144 break; 145 default: 146 VGLEnd(); 147 return 1; 148 } 149 150 if ((error = ioctl(0, KDENABIO, 0))) 151 return error; 152 153 ioctl(0, VT_WAITACTIVE, 0); 154 ioctl(0, KDSETMODE, KD_GRAPHICS); 155 if ((error = ioctl(0, mode, 0))) { 156 ioctl(0, KDSETMODE, KD_TEXT); 157 ioctl(0, KDDISABIO, 0); 158 return error; 159 } 160 161 VGLMode = mode; 162 163 outb(0x3c4, 0x02); 164 outb(0x3c5, 0x0f); 165 bzero(VGLMem, 64*1024); 166 167 if (ioctl(0, TIOCGWINSZ, &winsz)) { 168 VGLEnd(); 169 return 1; 170 } 171 172 VGLDisplay->Bitmap = VGLMem; 173 VGLDisplay->Xsize = winsz.ws_xpixel; 174 VGLDisplay->Ysize = winsz.ws_ypixel; 175 VGLSavePalette(); 176 177 smode.mode = VT_PROCESS; 178 smode.waitv = 0; 179 smode.relsig = SIGUSR1; 180 smode.acqsig = SIGUSR1; 181 smode.frsig = SIGINT; 182 if (ioctl(0, VT_SETMODE, &smode) == -1) { 183 VGLEnd(); 184 return 1; 185 } 186 VGLTextSetFontFile((byte*)0); 187 VGLInitDone = 1; 188 return 0; 189 } 190 191 void 192 VGLCheckSwitch() 193 { 194 while (VGLSwitchPending) { 195 int i; 196 197 VGLSwitchPending = 0; 198 if (VGLOnDisplay) { 199 ioctl(0, KDENABIO, 0); 200 ioctl(0, KDSETMODE, KD_GRAPHICS); 201 ioctl(0, VGLMode, 0); 202 outb(0x3c6, 0xff); 203 for (i=0; i<4; i++) { 204 outb(0x3c4, 0x02); 205 outb(0x3c5, 0x01<<i); 206 bcopy(&VGLBuf[i*64*1024], VGLMem, 64*1024); 207 } 208 VGLRestorePalette(); 209 ioctl(0, VT_RELDISP, VT_ACKACQ); 210 VGLDisplay->Bitmap = VGLMem; 211 switch (VGLMode) { 212 case SW_BG640x480: case SW_CG640x480: 213 VGLDisplay->Type = VIDBUF4; 214 break; 215 case SW_VGA_CG320: 216 VGLDisplay->Type = VIDBUF8; 217 break; 218 case SW_VGA_MODEX: 219 VGLDisplay->Type = VIDBUF8X; 220 break; 221 default: 222 VGLDisplay->Type = VIDBUF8; /* XXX */ 223 break; 224 } 225 } 226 else { 227 for (i=0; i<4; i++) { 228 outb(0x3ce, 0x04); 229 outb(0x3cf, i); 230 bcopy(VGLMem, &VGLBuf[i*64*1024], 64*1024); 231 } 232 ioctl(0, VGLOldMode, 0); 233 ioctl(0, KDSETMODE, KD_TEXT); 234 ioctl(0, KDDISABIO, 0); 235 ioctl(0, VT_RELDISP, VT_TRUE); 236 VGLDisplay->Bitmap = VGLBuf; 237 VGLDisplay->Type = MEMBUF; 238 while (!VGLOnDisplay) pause(); 239 } 240 } 241 } 242 243