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