xref: /plan9/sys/src/cmd/gs/src/gdevsco.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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