diff options
Diffstat (limited to 'hw/xfree86/os-support/sco/sco_init.c')
-rw-r--r-- | hw/xfree86/os-support/sco/sco_init.c | 503 |
1 files changed, 283 insertions, 220 deletions
diff --git a/hw/xfree86/os-support/sco/sco_init.c b/hw/xfree86/os-support/sco/sco_init.c index a61dcdfce..389664647 100644 --- a/hw/xfree86/os-support/sco/sco_init.c +++ b/hw/xfree86/os-support/sco/sco_init.c @@ -1,261 +1,324 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sco/sco_init.c,v 3.10.2.1 1998/02/06 22:36:53 hohndel Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/sco/sco_init.c,v 3.14 2002/11/20 23:00:44 dawes Exp $ */ /* - * Copyright 1993 by David McCullough <davidm@stallion.oz.au> - * Copyright 1993 by David Wexelblat <dwex@goblin.org> + * Copyright 2001 by J. Kean Johnston <jkj@sco.com> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting - * documentation, and that the names of David McCullough and David Wexelblat - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. David McCullough and - * David Wexelblat makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * DAVID MCCULLOUGH AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD - * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL DAVID MCCULLOUGH OR DAVID WEXELBLAT BE - * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * documentation, and that the name J. Kean Johnston not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. J. Kean Johnston makes no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. * + * J. KEAN JOHNSTON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL J. KEAN JOHNSTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. */ -/* $Xorg: sco_init.c,v 1.3 2000/08/17 19:51:28 cpqbld Exp $ */ +/* $XConsortium$ */ + +/* Re-written May 2001 to represent the current state of reality */ #include "X.h" #include "Xmd.h" -#include "input.h" -#include "scrnintstr.h" #include "compiler.h" #include "xf86.h" -#include "xf86Procs.h" +#include "xf86Priv.h" #include "xf86_OSlib.h" static Bool KeepTty = FALSE; static int VTnum = -1; +static char *vtdevice = NULL; static int sco_console_mode = -1; -extern void xf86VTRequest( -#if NeedFunctionPrototypes - int -#endif -); +extern Bool mpxLock; -void xf86OpenConsole() +void +xf86OpenConsole() { - int fd,wc; - struct vt_mode VT; - struct stat status; - char vtname[11]; - - if (serverGeneration == 1) - { - /* check if we're run with euid==0 */ - if (geteuid() != 0) - { - FatalError("xf86OpenConsole: Server must be running with root " - "permissions\n" - "You should be using Xwrapper to start the server or xdm.\n" - "We strongly advise against making the server SUID root!\n"); - } - - /* - * setup the virtual terminal manager - * - * SCO vts start at tty01 which is vt00, if you could call them VT's. - * We use the numbers 1..X as it fits nicer with the device naming - * scheme. - * - * In os/osinit.c we took the precuation of not closing stdin so that - * we can use the current vt if no vt was specified on the command line - * - * Under SCO VT_OPENQRY does nothing at all - * if nothing was specified we try to determine the VT from stdin - */ - if ((VTnum != -1) && (VTnum != 0)) - { - wc = VTnum - 1; - } - else - { - if ((fstat(0, &status) >= 0) && (status.st_mode & S_IFCHR)) - { - wc = minor(status.st_rdev); - } - else - { - ErrorF("%s: Failed to stat stdin, using tty02 (%s)\n", - "xf86OpenConsole", strerror(errno)); - wc = 1; /* tty02 */ - } - } - ErrorF("(using VT number %d)\n\n", wc + 1); - - sprintf(vtname,"/dev/tty%02d", wc+1); /* /dev/tty[01-12] */ - - if ((xf86Info.consoleFd = open(vtname, O_RDWR | O_NDELAY, 0)) < 0) - { - FatalError("xf86OpenConsole: Cannot open %s (%s)\n", - vtname, strerror(errno)); - } - - /* now we can dispose of stdin */ - - if (freopen(vtname, "r+", stdin) == (FILE *) NULL) - { - FatalError("xf86OpenConsole: Cannot reopen stdin as %s (%s)\n", - vtname, strerror(errno)); - } - - /* now we can fixup stdout */ - - if (freopen(vtname, "r+", stdout) == (FILE *) NULL) - { - FatalError("xf86OpenConsole: Cannot reopen stdout as %s (%s)\n", - vtname, strerror(errno)); - } - - /* We activate the console just in case its not the one we are on */ - xf86Info.vtno = wc; - if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, wc) != 0) - { - ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); - } - - xf86Config(FALSE); /* Read XF86Config */ - - if (!KeepTty) - { - setpgrp(); - } - - /* - * now get the VT - */ - if ((sco_console_mode = ioctl(xf86Info.consoleFd, CONS_GET, 0L)) < 0) - { - FatalError("xf86OpenConsole: VT_GETMODE failed on console (%s)\n", - strerror(errno)); - } - if (ioctl(xf86Info.consoleFd, VGA_IOPRIVL, 1) < 0) - { - FatalError("xf86OpenConsole: VGA_IOPRIVL failed for VGA acc (%s)\n", - strerror(errno)); - } - if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) - { - FatalError("xf86OpenConsole: VT_GETMODE failed (%s)\n", + int fd,i, ioctl_ret; + struct vt_mode VT; + static char vtname[32]; + struct vid_info vidinf; + struct sigaction sigvtsw; + + if (serverGeneration == 1) { + /* check if we're run with euid==0 */ + if (geteuid() != 0) { + FatalError("xf86OpenConsole: Server must be setuid root\n"); + } + + /* + * Set up the virtual terminal (multiscreen in SCO parlance). + * For the actual console itself, screens are numbered from + * 1 to (usually) 16. However, it is possible to have a nested + * server, and it is also possible to be on a multi-console + * system such as MaxSpeed or SunRiver. Therefore, we should + * not make any assumptions about the TTY name we are on, and + * instead we rely on ttyname() to give us the real TTY name. + * Previously, XFree86 tried to determine the TTY name manually. + * This is wrong. The only time we need to futz with the TTY name + * if if we were given the name of a TTY to run on explicity on + * the command line. + */ + + if (VTnum == -1) { + /* + * We can query the current VT number using CONS_GETINFO. + */ + char *ttn; + + vidinf.size = sizeof(vidinf); + if (ioctl (0, CONS_GETINFO, &vidinf) < 0) { + FatalError ("xf86OpenConsole: Not on a console device " + "or error querying device (%s)\n", strerror (errno)); + } + + VTnum = vidinf.m_num + 1; /* 0-based */ + ttn = ttyname (0); + + if (ttn == (char *)0) { + ErrorF ("xf86OpenConsole: Error determining TTY name (%s)\n", + strerror(errno)); + snprintf (vtname, sizeof(vtname)-1, "/dev/tty%02d", VTnum); + } else { + strlcpy (vtname, ttn, sizeof(vtname)); + } + vtdevice = vtname; + } else if (VTnum == -2 || VTnum >= 0) { + /* + * An explicit device was specified. Make sure its a console device. + */ + if (VTnum != -2) { + snprintf (vtname, sizeof(vtname)-1, "/dev/tty%02d", VTnum); + vtdevice = vtname; + } + + fd = open (vtdevice, O_RDWR | O_NDELAY, 0); + if (fd < 0) { + FatalError ("xf86OpenConsole: Can not open device '%s' (%s)\n", + vtdevice, strerror(errno)); + } + + vidinf.size = sizeof(vidinf); + if (ioctl (fd, CONS_GETINFO, &vidinf) < 0) { + FatalError ("xf86OpenConsole: '%s' is not a console device " + "or error querying device (%s)\n", vtname, strerror (errno)); + } + VTnum = vidinf.m_num + 1; /* 0-based */ + close (fd); /* We're done with it for now */ + } + + ErrorF("(using VT%02d device %s)\n\n", VTnum, vtdevice); + + if ((xf86Info.consoleFd = open(vtdevice, O_RDWR | O_NDELAY, 0)) < 0) { + FatalError("xf86OpenConsole: Cannot open %s (%s)\n", vtdevice, strerror(errno)); - } - - signal(SIGUSR1, xf86VTRequest); - - VT.mode = VT_PROCESS; - VT.relsig = SIGUSR1; - VT.acqsig = SIGUSR1; - VT.frsig = SIGUSR1; - VT.waitv = 0; - if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0) - { - FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n"); - } - /* - * make sure the console driver thinks the console is in graphics - * mode. Under mono we have to do the two as the console driver only - * allows valid modes for the current video card and Herc or vga are - * the only devices currently supported. - */ - if (ioctl(xf86Info.consoleFd, SW_VGA12, 0) < 0) - if (ioctl(xf86Info.consoleFd, SW_HGC_P0, 0) < 0) - { - ErrorF("Failed to set graphics mode (%s)\n", - strerror(errno)); - } + } + /* Dispose of stdin and stdout */ + if (freopen(vtdevice, "r+", stdin) == (FILE *) NULL) { + FatalError("xf86OpenConsole: Cannot reopen stdin as %s (%s)\n", + vtdevice, strerror(errno)); } - else - { - /* serverGeneration != 1 */ - /* - * now get the VT - */ - if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) - { - ErrorF("xf86OpenConsole: VT_ACTIVATE failed\n"); - } + + if (freopen(vtname, "r+", stdout) == (FILE *) NULL) { + FatalError("xf86OpenConsole: Cannot reopen stdout as %s (%s)\n", + vtdevice, strerror(errno)); } - return; -} -void xf86CloseConsole() -{ - struct vt_mode VT; + /* + * We make 100% sure we use the correct VT number. This can get ugly + * where there are multi-consoles in use, so we make sure we query + * the kernel for the correct VT number. It knows best, we don't. + */ + vidinf.size = sizeof(vidinf); + if (ioctl (xf86Info.consoleFd, CONS_GETINFO, &vidinf) < 0) { + FatalError ("xf86OpenConsole: Failed to query console number (%s)\n", + strerror (errno)); + } + xf86Info.vtno = vidinf.m_num; - ioctl(xf86Info.consoleFd, VT_RELDISP, 1); - if (sco_console_mode != -1) - { - ioctl(xf86Info.consoleFd, MODESWITCH | sco_console_mode, 0L); + /* We activate the console just in case its not the one we are on */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed (%s)\n", strerror(errno)); } - if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1) - { - VT.mode = VT_AUTO; - ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* set dflt vt handling */ + + /* Disassociate from controling TTY */ + if (!KeepTty) { + setpgrp(); + } + + /* + * Now we get the current mode that the console device is on. We will + * use this later when we close the console device to restore it to + * that same mode. + */ + if ((sco_console_mode = ioctl(xf86Info.consoleFd, CONS_GET, 0L)) < 0) { + FatalError("xf86OpenConsole: CONS_GET failed on console (%s)\n", + strerror(errno)); } - close(xf86Info.consoleFd); /* make the vt-manager happy */ - return; + + if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) { + FatalError("xf86OpenConsole: VT_GETMODE failed (%s)\n", strerror(errno)); + } + + sigvtsw.sa_handler = xf86VTRequest; + sigfillset(&sigvtsw.sa_mask); + sigvtsw.sa_flags = 0; + + /* NOTE: Using sigaction means we dont have to re-arm the signal */ + sigaction(SIGUSR1, &sigvtsw, NULL); + + VT.mode = VT_PROCESS; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + VT.frsig = SIGINT; /* Not implemented */ + VT.waitv = 0; + + /* + * The SCO X server tries the following call 5 times. Lets do the same + * thing. It shouldn't really be required but sometimes things take a + * while to settle down when switching screens. *helpless shrug* I know + * its sucks but ... + */ + + ioctl_ret = 0; + for (i = 0; i < 5; i++) { + ioctl_ret = ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); + if (ioctl_ret >= 0) + break; + usleep(999999); /* Dont use nap() - it forces linking with -lx */ + } + + if (ioctl_ret < 0) { + FatalError("xf86OpenConsole: VT_SETMODE failed (%s)\n", strerror(errno)); + } + + /* + * Convince the console driver we are in graphics mode. + */ + if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) { + ErrorF("Failed to set graphics mode (%s)\n", strerror(errno)); + } + } else { /* serverGeneration != 1 */ + if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) { + ErrorF("xf86OpenConsole: VT_ACTIVATE failed (%s)\n", strerror(errno)); + } + } } -int xf86ProcessArgument(argc, argv, i) -int argc; -char *argv[]; -int i; +/* + * Restore the console to its previous state. This may cause flicker if + * the screen was previous in a graphics mode, because we first set it + * to text mode. This has the advantage of getting the console driver + * to do a soft reset on the card, which really does help settle the + * video card down again after coming out of Xfree86. + */ +void +xf86CloseConsole() { - /* - * Keep server from detaching from controlling tty. This is useful - * when debugging (so the server can receive keyboard signals. - */ - if (!strcmp(argv[i], "-keeptty")) - { - KeepTty = TRUE; - return(1); - } - if ((argv[i][0] == 'v') && (argv[i][1] == 't')) - { - if (sscanf(argv[i], "vt%2d", &VTnum) == 0) - { - UseMsg(); - VTnum = -1; - return(0); - } - return(1); - } - if (!strcmp(argv[i], "-crt")) - { - if ((++i > argc) || - (sscanf(argv[i], "/dev/tty%2d", &VTnum) == 0)) - { - UseMsg(); - VTnum = -1; - return(0); - } - else - { - return(2); - } - } - return(0); + struct vt_mode VT; + struct sigaction sigvtsw; + + /* Set text mode (possibly briefly) */ + ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT0); + + /* Restore the original mode */ + if (sco_console_mode != -1) { + ioctl(xf86Info.consoleFd, MODESWITCH | sco_console_mode, 0L); + } + + ioctl(xf86Info.consoleFd, VT_RELDISP, 1); /* Release the display */ + + sigvtsw.sa_handler = SIG_DFL; + sigfillset(&sigvtsw.sa_mask); + sigvtsw.sa_flags = 0; + + sigaction(SIGUSR1, &sigvtsw, NULL); + + VT.mode = VT_AUTO; + VT.waitv = 0; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + VT.frsig = SIGINT; + ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* Revert to auto handling */ + + close(xf86Info.consoleFd); /* We're done with the device */ +} + +int +xf86ProcessArgument(int argc, char *argv[], int i) +{ + /* + * Keep server from detaching from controlling tty. This is useful + * when debugging (so the server can receive keyboard signals). + */ + if (!strcmp(argv[i], "-keeptty")) { + KeepTty = TRUE; + return(1); + } + + /* + * By default, the X server wants to bind itself to CPU 0. This makes + * sure that the server has full access to the I/O ports at IOPL 3. + * Some SMP systems have trouble with I/O on CPU's other than 0. If, + * however, you have a system that is well behaved, you can specify + * this argument and let the scheduler decide which CPU the server + * should run on. + */ + if (!strcmp(argv[i], "-nompxlock")) { + mpxLock = FALSE; + return (1); + } + + /* + * Specify the VT number to run on (NOT the device). + */ + if ((argv[i][0] == 'v') && (argv[i][1] == 't')) { + if (sscanf(argv[i], "vt%2d", &VTnum) == 0) { + UseMsg(); + VTnum = -1; + return(0); + } + if (VTnum <= 0) { + UseMsg(); + VTnum = -1; + return(0); + } + return(1); + } + + /* + * Use a device the user specifies. + */ + if (!strcmp(argv[i], "-crt")) { + if (++i > argc) { + UseMsg(); + VTnum = -1; + return(0); + } else { + VTnum = -2; + vtdevice = argv[i]; + return(2); + } + } + return(0); } -void xf86UseMsg() +void +xf86UseMsg() { ErrorF("vtXX use the specified VT number\n"); - ErrorF("-crt /dev/ttyXX use the specified VT number\n"); + ErrorF("-crt DEVICE use the specified VT device\n"); + ErrorF("-nompxlock dont bind X server to CPU 0\n"); ErrorF("-keeptty "); ErrorF("don't detach controlling tty (for debugging only)\n"); - return; } |