1 /* Copyright (C) 1989, 1992, 1993 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gdevsco.c,v 1.6 2002/06/16 05:48:55 lpd Exp $ */
18 /* 17Jul91 - wb - based on gdevpcfb.c */
19 /* 31Jul91 - Rick Calder rick@rick.att.com - ifdefs for AT&T UNIX 4.0 2.1 */
20 /* 13Sep91 - wb - modify for gs24b2 */
21 /* 9Mar92 - wb - modify for gs24b4 */
22 /* generate SCO Xenix/Unix style memory mapped ioctl output */
23 #include "memory_.h"
24 #include "gx.h"
25 #include "gserrors.h"
26 #include "gxdevice.h"
27 #include "gdevpcfb.h"
28 #include <signal.h>
29
30 #ifdef M_XENIX
31 #include <sys/console.h> /* SCO Xenix and SCO UNIX */
32 #ifndef CONSIO
33 #include <sys/machdep.h> /* Xenix needs this also */
34 #endif
35 #else
36 #include <sys/kd.h> /* AT&T SVR4 */
37 #endif
38
39 #if defined(__STDC__)
40 #include <stdlib.h>
41 #else
42 extern char *getenv(const char *);
43 #endif
44
45 #if defined(M_XENIX)
46 #include <prototypes.h>
47 #include <fcntl.h>
48 #else
49 extern int ioctl(int, int,...);
50 extern int open(const char *, int,...);
51 #endif
52
53 private int console_fd = -1; /* file descriptor of console */
54 fb_ptr fb_addr; /* address of frame buffer for unix */
55 private int cur_mode = -1; /* current video mode */
56
57 /* open the console */
58 /* possible files to open:
59 * /dev/console = current system console
60 * /dev/vga = vga monitor
61 * /dev/tty = current terminal
62 */
63
64 private void open_console(void);
65
66 private void
open_console()67 open_console()
68 {
69 const char *dev;
70
71 if (console_fd != -1)
72 return;
73 dev = getenv("GSDEVICE");
74 if (dev == NULL || *dev == '\0')
75 dev = "/dev/tty";
76 console_fd = open(dev, 0);
77 if (console_fd == -1) {
78 ega_close((gx_device *) NULL);
79 eprintf1("unable to map display '%s'\n", dev);
80 perror("open_console");
81 exit(1);
82 }
83 }
84
85 #if defined(__GNUC__)
86 /* Done with inline assembly in gdevpcfb.h */
87 #else
88 /* Output to a port */
89 void
outportb(uint port,byte data)90 outportb(uint port, byte data)
91 {
92 int i;
93 struct port_io_arg pio;
94
95 if (console_fd == -1)
96 open_console();
97 pio.args[0].dir = OUT_ON_PORT;
98 pio.args[0].port = port;
99 pio.args[0].data = data;
100 pio.args[1].port = 0;
101 pio.args[2].port = 0;
102 pio.args[3].port = 0;
103 i = ioctl(console_fd, CONSIO, (long)(&pio));
104 if (i == -1) {
105 ega_close((gx_device *) NULL);
106 eprintf("error setting device register\n");
107 perror("outportb");
108 exit(1);
109 }
110 }
111
112 /* Output to 2 consecutive ports */
113 void
outport2(uint port,byte index,byte data)114 outport2(uint port, byte index, byte data)
115 {
116 int i;
117 struct port_io_arg pio;
118
119 if (console_fd == -1)
120 open_console();
121 pio.args[0].dir = OUT_ON_PORT;
122 pio.args[0].port = port;
123 pio.args[0].data = index;
124 pio.args[1].dir = OUT_ON_PORT;
125 pio.args[1].port = port + 1;
126 pio.args[1].data = data;
127 pio.args[2].port = 0;
128 pio.args[3].port = 0;
129 i = ioctl(console_fd, CONSIO, (long)(&pio));
130 if (i == -1) {
131 ega_close((gx_device *) NULL);
132 eprintf("error setting device register\n");
133 perror("outport2");
134 exit(1);
135 }
136 }
137 #endif
138
139 /* interrupt signal handler */
140 /* restore the video mode and exit */
141 private void
ega_int_handler(int sig)142 ega_int_handler(int sig)
143 {
144 ega_close((gx_device *) NULL);
145 eprintf("GS exiting...\n");
146 exit(1);
147 }
148
149 /*
150 * FIXME to make this work, the SIGCONT handler must restore the
151 * the video state, including all the registers.
152 * For now, I made the SIGSTOP handler exit just call the SIGINT handler
153 */
154
155 #ifdef SIGTSTP
156 /* user tried to stop us. restore video and stop */
157 private void
ega_tstp_handler(int sig)158 ega_tstp_handler(int sig)
159 {
160 #if 1
161 ega_int_handler(sig);
162 #else
163 /* Preferable, but sco does not restore the monitor corretly */
164 signal(SIGTSTP, ega_tstp_handler);
165 ega_close((gx_device *) NULL);
166 eprintf("GS stopping...\n");
167 signal(SIGSTOP, SIG_DFL);
168 kill(getpid(), SIGSTOP);
169 #endif
170 }
171 #endif /* SIGTSTP */
172
173 #ifdef SIGCONT
174 /* we were unstopped. reopen video */
175 private void
ega_cont_handler(int sig)176 ega_cont_handler(int sig)
177 {
178 #if 1
179 ega_int_handler(sig);
180 #else
181 signal(SIGCONT, ega_cont_handler);
182 ega_set_mode(cur_mode);
183 #endif
184 }
185 #endif /* SIGCONT */
186
187 /* ------ Internal routines ------ */
188
189 /* Catch signals so we can restore the video mode on exit. */
190 void
pcfb_set_signals(gx_device * dev)191 pcfb_set_signals(gx_device * dev)
192 {
193 signal(SIGINT, ega_int_handler);
194 signal(SIGTERM, ega_int_handler);
195 #ifdef SIGTSTP
196 signal(SIGTSTP, ega_tstp_handler);
197 #endif
198 #ifdef SIGCONT
199 signal(SIGCONT, ega_cont_handler);
200 #endif
201 }
202
203 /* Read the device mode */
204 void
pcfb_get_state(pcfb_bios_state * pbs)205 pcfb_get_state(pcfb_bios_state * pbs)
206 {
207 int mode;
208
209 open_console();
210 mode = ioctl(console_fd, CONS_CURRENT, 0L);
211 if (mode == -1) {
212 #ifdef __linux__
213 mode = M_ENH_C80x25;
214 #else
215 ega_close((gx_device *) NULL);
216 eprintf("unable to get current console mode\n");
217 perror("pcfb_get_state");
218 exit(1);
219 #endif
220 }
221 pbs->display_mode =
222 (mode == M_ENH_CG640 || mode == M_CG640x350 ? 0x10 :
223 #ifdef M_VGA12
224 mode == M_VGA12 ? 0x12 :
225 #endif
226 0x03);
227 }
228
229 /* Set the device mode */
230 void
pcfb_set_mode(int mode)231 pcfb_set_mode(int mode)
232 {
233 int i, mode1;
234
235 open_console();
236 cur_mode = mode;
237 mode1 = -1;
238 if (mode == 0x10)
239 mode = SW_ENH_CG640;
240 #ifdef SW_VGA12
241 else if (mode == 0x12)
242 mode = SW_VGA12;
243 #endif
244 else if (mode == 0x03) {
245 #ifdef SW_VGA80x25
246 mode = SW_VGA80x25;
247 mode1 = SW_ENHC80x25;
248 #else
249 mode = SW_ENHC80x25;
250 #endif
251 } else {
252 eprintf1("can not set to video mode %d\n", mode);
253 exit(1);
254 }
255 i = ioctl(console_fd, mode, 0L);
256 if (i == -1 && mode1 != -1)
257 i = ioctl(console_fd, mode1, 0L);
258 if (i == -1) {
259 ega_close((gx_device *) NULL);
260 eprintf("unable to set console mode\n");
261 perror("pcfb_set_mode");
262 exit(1);
263 }
264 #ifdef VGA_IOPRIVL
265 if (ioctl(console_fd, VGA_IOPRIVL, 1) == -1) {
266 ega_close((gx_device *) NULL);
267 eprintf("unable to get I/O privilege\n");
268 perror("pcfb_set_mode");
269 exit(1);
270 }
271 #endif
272 i = ioctl(console_fd, MAPCONS, 0L);
273 if (i == -1) {
274 ega_close((gx_device *) NULL);
275 eprintf("unable to map console adaptor's display memory\n");
276 perror("pcfb_set_mode");
277 exit(1);
278 }
279 fb_addr = (fb_ptr) (i);
280 }
281
282 /* Restore the device state */
283 void
pcfb_set_state(const pcfb_bios_state * pbs)284 pcfb_set_state(const pcfb_bios_state * pbs)
285 {
286 pcfb_set_mode(pbs->display_mode);
287 }
288