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 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 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 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 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 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 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 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 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 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 284 pcfb_set_state(const pcfb_bios_state * pbs) 285 { 286 pcfb_set_mode(pbs->display_mode); 287 } 288