xref: /freebsd/lib/libvgl/main.c (revision 7f3dea244c40159a41ab22da77a434d7c5b5e85a)
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