main.c revision 50476
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: head/lib/libvgl/main.c 50476 1999-08-28 00:22:10Z peter $
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
40VGLBitmap *VGLDisplay;
41
42static int VGLMode;
43static int VGLOldMode;
44static byte *VGLBuf;
45static byte *VGLMem;
46static int VGLSwitchPending;
47static int VGLOnDisplay;
48static int VGLInitDone = 0;
49
50void
51VGLEnd()
52{
53struct 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
86static void
87VGLAbort()
88{
89  VGLEnd();
90  exit(0);
91}
92
93static void
94VGLSwitch()
95{
96  if (!VGLOnDisplay)
97    VGLOnDisplay = 1;
98  else
99    VGLOnDisplay = 0;
100  VGLSwitchPending = 1;
101  signal(SIGUSR1, VGLSwitch);
102}
103
104int
105VGLInit(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
192void
193VGLCheckSwitch()
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