17dd7cddfSDavid du Colombier /* Copyright (C) 1989, 1992, 1993 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: gdevsco.c,v 1.6 2002/06/16 05:48:55 lpd Exp $ */
187dd7cddfSDavid du Colombier /* 17Jul91 - wb - based on gdevpcfb.c */
197dd7cddfSDavid du Colombier /* 31Jul91 - Rick Calder rick@rick.att.com - ifdefs for AT&T UNIX 4.0 2.1 */
207dd7cddfSDavid du Colombier /* 13Sep91 - wb - modify for gs24b2 */
217dd7cddfSDavid du Colombier /* 9Mar92 - wb - modify for gs24b4 */
227dd7cddfSDavid du Colombier /* generate SCO Xenix/Unix style memory mapped ioctl output */
237dd7cddfSDavid du Colombier #include "memory_.h"
247dd7cddfSDavid du Colombier #include "gx.h"
257dd7cddfSDavid du Colombier #include "gserrors.h"
267dd7cddfSDavid du Colombier #include "gxdevice.h"
277dd7cddfSDavid du Colombier #include "gdevpcfb.h"
287dd7cddfSDavid du Colombier #include <signal.h>
297dd7cddfSDavid du Colombier
307dd7cddfSDavid du Colombier #ifdef M_XENIX
317dd7cddfSDavid du Colombier #include <sys/console.h> /* SCO Xenix and SCO UNIX */
327dd7cddfSDavid du Colombier #ifndef CONSIO
337dd7cddfSDavid du Colombier #include <sys/machdep.h> /* Xenix needs this also */
347dd7cddfSDavid du Colombier #endif
357dd7cddfSDavid du Colombier #else
367dd7cddfSDavid du Colombier #include <sys/kd.h> /* AT&T SVR4 */
377dd7cddfSDavid du Colombier #endif
387dd7cddfSDavid du Colombier
397dd7cddfSDavid du Colombier #if defined(__STDC__)
403ff48bf5SDavid du Colombier #include <stdlib.h>
417dd7cddfSDavid du Colombier #else
42*593dc095SDavid du Colombier extern char *getenv(const char *);
437dd7cddfSDavid du Colombier #endif
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier #if defined(M_XENIX)
463ff48bf5SDavid du Colombier #include <prototypes.h>
473ff48bf5SDavid du Colombier #include <fcntl.h>
487dd7cddfSDavid du Colombier #else
49*593dc095SDavid du Colombier extern int ioctl(int, int,...);
50*593dc095SDavid du Colombier extern int open(const char *, int,...);
517dd7cddfSDavid du Colombier #endif
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier private int console_fd = -1; /* file descriptor of console */
547dd7cddfSDavid du Colombier fb_ptr fb_addr; /* address of frame buffer for unix */
557dd7cddfSDavid du Colombier private int cur_mode = -1; /* current video mode */
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier /* open the console */
587dd7cddfSDavid du Colombier /* possible files to open:
597dd7cddfSDavid du Colombier * /dev/console = current system console
607dd7cddfSDavid du Colombier * /dev/vga = vga monitor
617dd7cddfSDavid du Colombier * /dev/tty = current terminal
627dd7cddfSDavid du Colombier */
637dd7cddfSDavid du Colombier
64*593dc095SDavid du Colombier private void open_console(void);
657dd7cddfSDavid du Colombier
667dd7cddfSDavid du Colombier private void
open_console()677dd7cddfSDavid du Colombier open_console()
687dd7cddfSDavid du Colombier {
697dd7cddfSDavid du Colombier const char *dev;
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier if (console_fd != -1)
727dd7cddfSDavid du Colombier return;
737dd7cddfSDavid du Colombier dev = getenv("GSDEVICE");
747dd7cddfSDavid du Colombier if (dev == NULL || *dev == '\0')
757dd7cddfSDavid du Colombier dev = "/dev/tty";
767dd7cddfSDavid du Colombier console_fd = open(dev, 0);
777dd7cddfSDavid du Colombier if (console_fd == -1) {
787dd7cddfSDavid du Colombier ega_close((gx_device *) NULL);
797dd7cddfSDavid du Colombier eprintf1("unable to map display '%s'\n", dev);
807dd7cddfSDavid du Colombier perror("open_console");
817dd7cddfSDavid du Colombier exit(1);
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier }
847dd7cddfSDavid du Colombier
857dd7cddfSDavid du Colombier #if defined(__GNUC__)
867dd7cddfSDavid du Colombier /* Done with inline assembly in gdevpcfb.h */
877dd7cddfSDavid du Colombier #else
887dd7cddfSDavid du Colombier /* Output to a port */
897dd7cddfSDavid du Colombier void
outportb(uint port,byte data)907dd7cddfSDavid du Colombier outportb(uint port, byte data)
917dd7cddfSDavid du Colombier {
927dd7cddfSDavid du Colombier int i;
937dd7cddfSDavid du Colombier struct port_io_arg pio;
947dd7cddfSDavid du Colombier
957dd7cddfSDavid du Colombier if (console_fd == -1)
967dd7cddfSDavid du Colombier open_console();
977dd7cddfSDavid du Colombier pio.args[0].dir = OUT_ON_PORT;
987dd7cddfSDavid du Colombier pio.args[0].port = port;
997dd7cddfSDavid du Colombier pio.args[0].data = data;
1007dd7cddfSDavid du Colombier pio.args[1].port = 0;
1017dd7cddfSDavid du Colombier pio.args[2].port = 0;
1027dd7cddfSDavid du Colombier pio.args[3].port = 0;
1037dd7cddfSDavid du Colombier i = ioctl(console_fd, CONSIO, (long)(&pio));
1047dd7cddfSDavid du Colombier if (i == -1) {
1057dd7cddfSDavid du Colombier ega_close((gx_device *) NULL);
1067dd7cddfSDavid du Colombier eprintf("error setting device register\n");
1077dd7cddfSDavid du Colombier perror("outportb");
1087dd7cddfSDavid du Colombier exit(1);
1097dd7cddfSDavid du Colombier }
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier
1127dd7cddfSDavid du Colombier /* Output to 2 consecutive ports */
1137dd7cddfSDavid du Colombier void
outport2(uint port,byte index,byte data)1147dd7cddfSDavid du Colombier outport2(uint port, byte index, byte data)
1157dd7cddfSDavid du Colombier {
1167dd7cddfSDavid du Colombier int i;
1177dd7cddfSDavid du Colombier struct port_io_arg pio;
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier if (console_fd == -1)
1207dd7cddfSDavid du Colombier open_console();
1217dd7cddfSDavid du Colombier pio.args[0].dir = OUT_ON_PORT;
1227dd7cddfSDavid du Colombier pio.args[0].port = port;
1237dd7cddfSDavid du Colombier pio.args[0].data = index;
1247dd7cddfSDavid du Colombier pio.args[1].dir = OUT_ON_PORT;
1257dd7cddfSDavid du Colombier pio.args[1].port = port + 1;
1267dd7cddfSDavid du Colombier pio.args[1].data = data;
1277dd7cddfSDavid du Colombier pio.args[2].port = 0;
1287dd7cddfSDavid du Colombier pio.args[3].port = 0;
1297dd7cddfSDavid du Colombier i = ioctl(console_fd, CONSIO, (long)(&pio));
1307dd7cddfSDavid du Colombier if (i == -1) {
1317dd7cddfSDavid du Colombier ega_close((gx_device *) NULL);
1327dd7cddfSDavid du Colombier eprintf("error setting device register\n");
1337dd7cddfSDavid du Colombier perror("outport2");
1347dd7cddfSDavid du Colombier exit(1);
1357dd7cddfSDavid du Colombier }
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier #endif
1387dd7cddfSDavid du Colombier
1397dd7cddfSDavid du Colombier /* interrupt signal handler */
1407dd7cddfSDavid du Colombier /* restore the video mode and exit */
1417dd7cddfSDavid du Colombier private void
ega_int_handler(int sig)1427dd7cddfSDavid du Colombier ega_int_handler(int sig)
1437dd7cddfSDavid du Colombier {
1447dd7cddfSDavid du Colombier ega_close((gx_device *) NULL);
1457dd7cddfSDavid du Colombier eprintf("GS exiting...\n");
1467dd7cddfSDavid du Colombier exit(1);
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier
1497dd7cddfSDavid du Colombier /*
1507dd7cddfSDavid du Colombier * FIXME to make this work, the SIGCONT handler must restore the
1517dd7cddfSDavid du Colombier * the video state, including all the registers.
1527dd7cddfSDavid du Colombier * For now, I made the SIGSTOP handler exit just call the SIGINT handler
1537dd7cddfSDavid du Colombier */
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier #ifdef SIGTSTP
1567dd7cddfSDavid du Colombier /* user tried to stop us. restore video and stop */
1577dd7cddfSDavid du Colombier private void
ega_tstp_handler(int sig)1587dd7cddfSDavid du Colombier ega_tstp_handler(int sig)
1597dd7cddfSDavid du Colombier {
1607dd7cddfSDavid du Colombier #if 1
1617dd7cddfSDavid du Colombier ega_int_handler(sig);
1627dd7cddfSDavid du Colombier #else
1637dd7cddfSDavid du Colombier /* Preferable, but sco does not restore the monitor corretly */
1647dd7cddfSDavid du Colombier signal(SIGTSTP, ega_tstp_handler);
1657dd7cddfSDavid du Colombier ega_close((gx_device *) NULL);
1667dd7cddfSDavid du Colombier eprintf("GS stopping...\n");
1677dd7cddfSDavid du Colombier signal(SIGSTOP, SIG_DFL);
1687dd7cddfSDavid du Colombier kill(getpid(), SIGSTOP);
1697dd7cddfSDavid du Colombier #endif
1707dd7cddfSDavid du Colombier }
1717dd7cddfSDavid du Colombier #endif /* SIGTSTP */
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier #ifdef SIGCONT
1747dd7cddfSDavid du Colombier /* we were unstopped. reopen video */
1757dd7cddfSDavid du Colombier private void
ega_cont_handler(int sig)1767dd7cddfSDavid du Colombier ega_cont_handler(int sig)
1777dd7cddfSDavid du Colombier {
1787dd7cddfSDavid du Colombier #if 1
1797dd7cddfSDavid du Colombier ega_int_handler(sig);
1807dd7cddfSDavid du Colombier #else
1817dd7cddfSDavid du Colombier signal(SIGCONT, ega_cont_handler);
1827dd7cddfSDavid du Colombier ega_set_mode(cur_mode);
1837dd7cddfSDavid du Colombier #endif
1847dd7cddfSDavid du Colombier }
1857dd7cddfSDavid du Colombier #endif /* SIGCONT */
1867dd7cddfSDavid du Colombier
1877dd7cddfSDavid du Colombier /* ------ Internal routines ------ */
1887dd7cddfSDavid du Colombier
1897dd7cddfSDavid du Colombier /* Catch signals so we can restore the video mode on exit. */
1907dd7cddfSDavid du Colombier void
pcfb_set_signals(gx_device * dev)1917dd7cddfSDavid du Colombier pcfb_set_signals(gx_device * dev)
1927dd7cddfSDavid du Colombier {
1937dd7cddfSDavid du Colombier signal(SIGINT, ega_int_handler);
1947dd7cddfSDavid du Colombier signal(SIGTERM, ega_int_handler);
1957dd7cddfSDavid du Colombier #ifdef SIGTSTP
1967dd7cddfSDavid du Colombier signal(SIGTSTP, ega_tstp_handler);
1977dd7cddfSDavid du Colombier #endif
1987dd7cddfSDavid du Colombier #ifdef SIGCONT
1997dd7cddfSDavid du Colombier signal(SIGCONT, ega_cont_handler);
2007dd7cddfSDavid du Colombier #endif
2017dd7cddfSDavid du Colombier }
2027dd7cddfSDavid du Colombier
2037dd7cddfSDavid du Colombier /* Read the device mode */
2047dd7cddfSDavid du Colombier void
pcfb_get_state(pcfb_bios_state * pbs)2057dd7cddfSDavid du Colombier pcfb_get_state(pcfb_bios_state * pbs)
2067dd7cddfSDavid du Colombier {
2077dd7cddfSDavid du Colombier int mode;
2087dd7cddfSDavid du Colombier
2097dd7cddfSDavid du Colombier open_console();
2107dd7cddfSDavid du Colombier mode = ioctl(console_fd, CONS_CURRENT, 0L);
2117dd7cddfSDavid du Colombier if (mode == -1) {
2127dd7cddfSDavid du Colombier #ifdef __linux__
2137dd7cddfSDavid du Colombier mode = M_ENH_C80x25;
2147dd7cddfSDavid du Colombier #else
2157dd7cddfSDavid du Colombier ega_close((gx_device *) NULL);
2167dd7cddfSDavid du Colombier eprintf("unable to get current console mode\n");
2177dd7cddfSDavid du Colombier perror("pcfb_get_state");
2187dd7cddfSDavid du Colombier exit(1);
2197dd7cddfSDavid du Colombier #endif
2207dd7cddfSDavid du Colombier }
2217dd7cddfSDavid du Colombier pbs->display_mode =
2227dd7cddfSDavid du Colombier (mode == M_ENH_CG640 || mode == M_CG640x350 ? 0x10 :
2237dd7cddfSDavid du Colombier #ifdef M_VGA12
2247dd7cddfSDavid du Colombier mode == M_VGA12 ? 0x12 :
2257dd7cddfSDavid du Colombier #endif
2267dd7cddfSDavid du Colombier 0x03);
2277dd7cddfSDavid du Colombier }
2287dd7cddfSDavid du Colombier
2297dd7cddfSDavid du Colombier /* Set the device mode */
2307dd7cddfSDavid du Colombier void
pcfb_set_mode(int mode)2317dd7cddfSDavid du Colombier pcfb_set_mode(int mode)
2327dd7cddfSDavid du Colombier {
2337dd7cddfSDavid du Colombier int i, mode1;
2347dd7cddfSDavid du Colombier
2357dd7cddfSDavid du Colombier open_console();
2367dd7cddfSDavid du Colombier cur_mode = mode;
2377dd7cddfSDavid du Colombier mode1 = -1;
2387dd7cddfSDavid du Colombier if (mode == 0x10)
2397dd7cddfSDavid du Colombier mode = SW_ENH_CG640;
2407dd7cddfSDavid du Colombier #ifdef SW_VGA12
2417dd7cddfSDavid du Colombier else if (mode == 0x12)
2427dd7cddfSDavid du Colombier mode = SW_VGA12;
2437dd7cddfSDavid du Colombier #endif
2447dd7cddfSDavid du Colombier else if (mode == 0x03) {
2457dd7cddfSDavid du Colombier #ifdef SW_VGA80x25
2467dd7cddfSDavid du Colombier mode = SW_VGA80x25;
2477dd7cddfSDavid du Colombier mode1 = SW_ENHC80x25;
2487dd7cddfSDavid du Colombier #else
2497dd7cddfSDavid du Colombier mode = SW_ENHC80x25;
2507dd7cddfSDavid du Colombier #endif
2517dd7cddfSDavid du Colombier } else {
2527dd7cddfSDavid du Colombier eprintf1("can not set to video mode %d\n", mode);
2537dd7cddfSDavid du Colombier exit(1);
2547dd7cddfSDavid du Colombier }
2557dd7cddfSDavid du Colombier i = ioctl(console_fd, mode, 0L);
2567dd7cddfSDavid du Colombier if (i == -1 && mode1 != -1)
2577dd7cddfSDavid du Colombier i = ioctl(console_fd, mode1, 0L);
2587dd7cddfSDavid du Colombier if (i == -1) {
2597dd7cddfSDavid du Colombier ega_close((gx_device *) NULL);
2607dd7cddfSDavid du Colombier eprintf("unable to set console mode\n");
2617dd7cddfSDavid du Colombier perror("pcfb_set_mode");
2627dd7cddfSDavid du Colombier exit(1);
2637dd7cddfSDavid du Colombier }
2647dd7cddfSDavid du Colombier #ifdef VGA_IOPRIVL
2657dd7cddfSDavid du Colombier if (ioctl(console_fd, VGA_IOPRIVL, 1) == -1) {
2667dd7cddfSDavid du Colombier ega_close((gx_device *) NULL);
2677dd7cddfSDavid du Colombier eprintf("unable to get I/O privilege\n");
2687dd7cddfSDavid du Colombier perror("pcfb_set_mode");
2697dd7cddfSDavid du Colombier exit(1);
2707dd7cddfSDavid du Colombier }
2717dd7cddfSDavid du Colombier #endif
2727dd7cddfSDavid du Colombier i = ioctl(console_fd, MAPCONS, 0L);
2737dd7cddfSDavid du Colombier if (i == -1) {
2747dd7cddfSDavid du Colombier ega_close((gx_device *) NULL);
2757dd7cddfSDavid du Colombier eprintf("unable to map console adaptor's display memory\n");
2767dd7cddfSDavid du Colombier perror("pcfb_set_mode");
2777dd7cddfSDavid du Colombier exit(1);
2787dd7cddfSDavid du Colombier }
2797dd7cddfSDavid du Colombier fb_addr = (fb_ptr) (i);
2807dd7cddfSDavid du Colombier }
2817dd7cddfSDavid du Colombier
2827dd7cddfSDavid du Colombier /* Restore the device state */
2837dd7cddfSDavid du Colombier void
pcfb_set_state(const pcfb_bios_state * pbs)2847dd7cddfSDavid du Colombier pcfb_set_state(const pcfb_bios_state * pbs)
2857dd7cddfSDavid du Colombier {
2867dd7cddfSDavid du Colombier pcfb_set_mode(pbs->display_mode);
2877dd7cddfSDavid du Colombier }
288