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