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 /* 58 while (!VGLOnDisplay) pause(); 59 VGLCheckSwitch();; 60 */ 61 outb(0x3c4, 0x02); 62 outb(0x3c5, 0x0f); 63 bzero(VGLMem, 64*1024); 64 if (VGLOldMode >= M_VESA_BASE) { 65 /* ugly, but necessary */ 66 ioctl(0, _IO('V', VGLOldMode - M_VESA_BASE), 0); 67 if (VGLOldMode == M_VESA_800x600) { 68 int size[3]; 69 size[0] = 80; 70 size[1] = 25; 71 size[2] = 16; 72 ioctl(0, KDRASTER, size); 73 } 74 } else { 75 ioctl(0, _IO('S', VGLOldMode), 0); 76 } 77 ioctl(0, KDDISABIO, 0); 78 ioctl(0, KDSETMODE, KD_TEXT); 79 smode.mode = VT_AUTO; 80 ioctl(0, VT_SETMODE, &smode); 81 free(VGLBuf); 82 free(VGLDisplay); 83 VGLKeyboardEnd(); 84 } 85 86 static void 87 VGLAbort() 88 { 89 VGLEnd(); 90 exit(0); 91 } 92 93 static void 94 VGLSwitch() 95 { 96 if (!VGLOnDisplay) 97 VGLOnDisplay = 1; 98 else 99 VGLOnDisplay = 0; 100 VGLSwitchPending = 1; 101 signal(SIGUSR1, VGLSwitch); 102 } 103 104 int 105 VGLInit(int mode) 106 { 107 struct vt_mode smode; 108 struct winsize winsz; 109 int error; 110 111 signal(SIGUSR1, VGLSwitch); 112 signal(SIGINT, VGLAbort); 113 signal(SIGSEGV, VGLAbort); 114 signal(SIGBUS, VGLAbort); 115 116 VGLOnDisplay = 1; 117 VGLSwitchPending = 0; 118 119 ioctl(0, CONS_GET, &VGLOldMode); 120 121 VGLMem = (byte*)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_FILE, 122 open("/dev/mem", O_RDWR), 0xA0000); 123 if (VGLMem <= (byte*)0) 124 return 1; 125 126 VGLBuf = (byte*)malloc(256*1024); 127 if (VGLBuf == NULL) 128 return 1; 129 130 VGLDisplay = (VGLBitmap*) malloc(sizeof(VGLBitmap)); 131 if (VGLDisplay == NULL) { 132 free(VGLBuf); 133 return 1; 134 } 135 136 switch (mode) { 137 case SW_BG640x480: case SW_CG640x480: 138 VGLDisplay->Type = VIDBUF4; 139 break; 140 case SW_VGA_CG320: 141 VGLDisplay->Type = VIDBUF8; 142 break; 143 case SW_VGA_MODEX: 144 VGLDisplay->Type = VIDBUF8X; 145 break; 146 default: 147 VGLEnd(); 148 return 1; 149 } 150 151 if ((error = ioctl(0, KDENABIO, 0))) 152 return error; 153 154 ioctl(0, VT_WAITACTIVE, 0); 155 ioctl(0, KDSETMODE, KD_GRAPHICS); 156 if ((error = ioctl(0, mode, 0))) { 157 ioctl(0, KDSETMODE, KD_TEXT); 158 ioctl(0, KDDISABIO, 0); 159 return error; 160 } 161 162 VGLMode = mode; 163 164 outb(0x3c4, 0x02); 165 outb(0x3c5, 0x0f); 166 bzero(VGLMem, 64*1024); 167 168 if (ioctl(0, TIOCGWINSZ, &winsz)) { 169 VGLEnd(); 170 return 1; 171 } 172 173 VGLDisplay->Bitmap = VGLMem; 174 VGLDisplay->Xsize = winsz.ws_xpixel; 175 VGLDisplay->Ysize = winsz.ws_ypixel; 176 VGLSavePalette(); 177 178 smode.mode = VT_PROCESS; 179 smode.waitv = 0; 180 smode.relsig = SIGUSR1; 181 smode.acqsig = SIGUSR1; 182 smode.frsig = SIGINT; 183 if (ioctl(0, VT_SETMODE, &smode) == -1) { 184 VGLEnd(); 185 return 1; 186 } 187 VGLTextSetFontFile((byte*)0); 188 VGLInitDone = 1; 189 return 0; 190 } 191 192 void 193 VGLCheckSwitch() 194 { 195 if (VGLSwitchPending) { 196 int i; 197 198 VGLSwitchPending = 0; 199 if (VGLOnDisplay) { 200 ioctl(0, KDENABIO, 0); 201 ioctl(0, KDSETMODE, KD_GRAPHICS); 202 ioctl(0, VGLMode, 0); 203 outb(0x3c6, 0xff); 204 for (i=0; i<4; i++) { 205 outb(0x3c4, 0x02); 206 outb(0x3c5, 0x01<<i); 207 bcopy(&VGLBuf[i*64*1024], VGLMem, 64*1024); 208 } 209 VGLRestorePalette(); 210 ioctl(0, VT_RELDISP, VT_ACKACQ); 211 VGLDisplay->Bitmap = VGLMem; 212 switch (VGLMode) { 213 case SW_BG640x480: case SW_CG640x480: 214 VGLDisplay->Type = VIDBUF4; 215 break; 216 case SW_VGA_CG320: 217 VGLDisplay->Type = VIDBUF8; 218 break; 219 case SW_VGA_MODEX: 220 VGLDisplay->Type = VIDBUF8X; 221 break; 222 default: 223 VGLDisplay->Type = VIDBUF8; /* XXX */ 224 break; 225 } 226 } 227 else { 228 for (i=0; i<4; i++) { 229 outb(0x3ce, 0x04); 230 outb(0x3cf, i); 231 bcopy(VGLMem, &VGLBuf[i*64*1024], 64*1024); 232 } 233 ioctl(0, VGLOldMode, 0); 234 ioctl(0, KDSETMODE, KD_TEXT); 235 ioctl(0, KDDISABIO, 0); 236 ioctl(0, VT_RELDISP, VT_TRUE); 237 VGLDisplay->Bitmap = VGLBuf; 238 VGLDisplay->Type = MEMBUF; 239 } 240 } 241 while (!VGLOnDisplay) pause(); 242 } 243 244