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