diff options
author | Dirk Hohndel <dirk.hohndel@intel.com> | 1999-11-19 13:54:06 +0000 |
---|---|---|
committer | Dirk Hohndel <dirk.hohndel@intel.com> | 1999-11-19 13:54:06 +0000 |
commit | f13b792a3a8d307a18cd6a41aa5a06622009e42f (patch) | |
tree | 5d7e7eb1dd3d69a9a408d0082c031c6121d625ea /hw/kdrive/linux.c |
3336. Fx up new MMIO macros (#3337, Matt Grossman).xf-3_9_16fxf-3_9_16exf-3_9_16dxf-3_9_16Z
3335. Clean up compiler warnings in lib/font/bitmap (#3411, Matt Grossman).
3334. TGA fixes, add sync on green (#3410, Matt Grossman).
3333. Fix NULL pointer dereference in libXaw (#3406, Christopher Sekiya).
3332. Add Rage128 support (#3405, Rik Faith, funded by ATI).
3331. Add MTRR support for NetBSD and OpenBSD. Add new NetBSD aperture
driver (#3404, Matthieu Herrb).
3330. Xterm patch #121 (#3402, Thomas Dickey).
3329. Rendition driver bugfixes and alpha related cleanups (#3400, Dejan
Ilic, Marc Langenbach, Egbert Eich).
3328. Add void input device (#3392, Frederic Lepied).
3327. Changed the Xon serial option to be able to select xon/xoff for
input, output or both. Add support for Graphire models. Change wacom
init phase to use new Xoff option (#3391, Frederic Lepied).
3326. Change the SwapAxes option to SwapXY in elographics/microtouch driver
to match an already existing option in the Dynapro driver. Add a Focus
class capability to the elographics driver (#3395, Patrick Lecoanet).
3325. Update mouse rate handling (#3388, Harald Koenig).
3324. Fix NULL pointer dereference in misprite.c (#3380, Edward Wang).
3323. Add FBDev and ShadowFB support to glint driver. Add new option
"NoWriteBitmap" (#3383, Michel Daenzer).
3322. Update SuperProbe to handle S3 Savage4, Savage200 and clean up
Trio3D/Savage3D detection (#3382,3384 Harald Koenig).
3321. Add new framebuffer code and tiny X DDX architecture (#3379, Keith
Packard).
3320. Add DGA2 documentation (#3378, Mark Vojkovich).
3319. Update XFree86 manpage wrt -bpp/-depth/-fbbpp (#3377, Andy Isaacson).
3318. Make SuperProbe check primary cards, only (#3374, Harald Koenig).
3317. Add SilkenMouse to *BSD (#3373, Matthieu Herrb).
3316. Allow SilkenMouse to work if not all drivers of an OS support SIGIO
(#3372, Keith Packard).
3315. Fix a few problems in TGA driver and add support for backing store
and SilkenMouse (#3371, Matt Grossman).
3314. Add smarter scheduler (#3370, Keith Packard).
3313. Xterm patch #120 (#3369, Thomas Dickey).
3312. Enable xf86SetKbdRate function on Solaris 8 (#3364, David Holland).
3311. Fix some bugs and add acceleration to Rendition server (#3360, Dejan
Ilic).
3310. Make raw DDC information available as properties in the root window
(#3357, Andrew Aitchison).
3309. Fix for xf86CreateRootWindow (#3355, Andrew Aitchison).
3308. Add manpage for the chips driver (#3353, David Bateman).
3307. Update contact info (#3352, Andrew van der Stock).
3306. Add kbd rate support for Linux (#3363, Harald Koenig).
3305. Update Portuguese XKB map (#3351, Joao Esteves, Francisco Colaco).
3304. Fix text clipping in 3dfx driver (#3349, Henrik Harmsen).
3303. Fix S3 ViRGE hw cursor (#3348, Harald Koenig).
3302. Fix clipping in 3dfx driver (#3342, Daryll Strauss).
3301. Enable SilkenMouse for 3dfx driver (#3341, Henrik Harmsen).
3300. Enable SIGIO support on LynxOS (#3339, Thomas Mueller).
3299. Get TRUE defined in sigio.c. Fix xterm compile problem on ISC (#3338,
Michael Rohleder).
3298. Correct DPMS suspend/standby modes for 3dfx driver (#3336, Henrik
Harmsen)
3297. Xterm patch #119 (#3335, Thomas Dickey).
Diffstat (limited to 'hw/kdrive/linux.c')
-rw-r--r-- | hw/kdrive/linux.c | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/hw/kdrive/linux.c b/hw/kdrive/linux.c new file mode 100644 index 000000000..67ac83af2 --- /dev/null +++ b/hw/kdrive/linux.c @@ -0,0 +1,322 @@ +/* + * $Id$ + * + * Copyright © 1999 Keith Packard + * + * 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 name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD 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. + */ +/* $XFree86: $ */ + +#include "kdrive.h" +#include <errno.h> +#include <signal.h> +#include <linux/vt.h> +#include <linux/kd.h> +#include <sys/stat.h> +#include <keysym.h> + +static int vtno; +int LinuxConsoleFd; +static int activeVT; +static Bool enabled; + +void +LinuxVTRequest (int sig) +{ + kdSwitchPending = TRUE; +} + +/* Check before chowning -- this avoids touching the file system */ +void +LinuxCheckChown (char *file) +{ + struct stat st; + __uid_t u; + __gid_t g; + + if (stat (file, &st) < 0) + return; + u = getuid (); + g = getgid (); + if (st.st_uid != u || st.st_gid != g) + chown (file, u, g); +} + +int +LinuxInit () +{ + int i, fd; + char vtname[11]; + struct vt_stat vts; + struct stat statb; + + LinuxConsoleFd = -1; + /* check if we're run with euid==0 */ + if (geteuid() != 0) + { + FatalError("LinuxInit: Server must be suid root\n"); + } + + if ((fd = open("/dev/tty0",O_WRONLY,0)) < 0) + { + FatalError( + "LinuxInit: Cannot open /dev/tty0 (%s)\n", + strerror(errno)); + } + if ((ioctl(fd, VT_OPENQRY, &vtno) < 0) || + (vtno == -1)) + { + FatalError("xf86OpenConsole: Cannot find a free VT\n"); + } + close(fd); + +/* ErrorF("(using VT number %d)\n\n", vtno); */ + + sprintf(vtname,"/dev/tty%d",vtno); /* /dev/tty1-64 */ + + if ((LinuxConsoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) < 0) + { + FatalError("LinuxInit: Cannot open %s (%s)\n", + vtname, strerror(errno)); + } + + /* change ownership of the vt */ + LinuxCheckChown (vtname); + + /* + * the current VT device we're running on is not "console", we want + * to grab all consoles too + * + * Why is this needed? + */ + LinuxCheckChown ("/dev/tty0"); + /* + * Linux doesn't switch to an active vt after the last close of a vt, + * so we do this ourselves by remembering which is active now. + */ + if (ioctl(LinuxConsoleFd, VT_GETSTATE, &vts) == 0) + { + activeVT = vts.v_active; + } + + return 1; +} + +Bool +LinuxFindPci (CARD16 vendor, CARD16 device, CARD32 count, KdCardAttr *attr) +{ + FILE *f; + char line[2048], *l, *end; + CARD32 bus, id, mode, addr; + int n; + CARD32 ven_dev; + Bool ret = FALSE; + + ven_dev = (((CARD32) vendor) << 16) | ((CARD32) device); + f = fopen ("/proc/bus/pci/devices", "r"); + if (!f) + return FALSE; + while (fgets (line, sizeof (line)-1, f)) + { + line[sizeof(line)-1] = '\0'; + l = line; + bus = strtoul (l, &end, 16); + if (end == l) + continue; + l = end; + id = strtoul (l, &end, 16); + if (end == l) + continue; + l = end; + if (id != ven_dev) + continue; + if (count--) + continue; + (void) strtoul (l, &end, 16); + if (end == l) + continue; + l = end; + n = 0; + for (;;) + { + addr = strtoul (l, &end, 16); + if (end == l) + break; + if (addr & 1) + attr->io = addr & ~0xf; + else + { + if (n == KD_MAX_CARD_ADDRESS) + break; + attr->address[n++] = addr & ~0xf; + } + l = end; + } + while (n > 0) + { + if (attr->address[n-1] != 0) + break; + n--; + } + attr->naddr = n; + ret = TRUE; + break; + } + fclose (f); + return ret; +} + +void +LinuxEnable (void) +{ + struct sigaction act; + struct vt_mode VT; + + if (enabled) + return; + if (kdSwitchPending) + { + kdSwitchPending = FALSE; + ioctl (LinuxConsoleFd, VT_RELDISP, VT_ACKACQ); + } + /* + * now get the VT + */ + if (ioctl(LinuxConsoleFd, VT_ACTIVATE, vtno) != 0) + { + ErrorF("LinuxInit: VT_ACTIVATE failed\n"); + } + if (ioctl(LinuxConsoleFd, VT_WAITACTIVE, vtno) != 0) + { + ErrorF("LinuxInit: VT_WAITACTIVE failed\n"); + } + if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) < 0) + { + FatalError ("LinuxInit: VT_GETMODE failed\n"); + } + + act.sa_handler = LinuxVTRequest; + sigemptyset (&act.sa_mask); + act.sa_flags = 0; + act.sa_restorer = 0; + sigaction (SIGUSR1, &act, 0); + + VT.mode = VT_PROCESS; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + if (ioctl(LinuxConsoleFd, VT_SETMODE, &VT) < 0) + { + FatalError("LinuxInit: VT_SETMODE VT_PROCESS failed\n"); + } + if (ioctl(LinuxConsoleFd, KDSETMODE, KD_GRAPHICS) < 0) + { + FatalError("LinuxInit: KDSETMODE KD_GRAPHICS failed\n"); + } + enabled = TRUE; +} + +Bool +LinuxSpecialKey (KeySym sym) +{ + struct vt_stat vts; + int con; + + if (XK_F1 <= sym && sym <= XK_F12) + { + con = sym - XK_F1 + 1; + ioctl (LinuxConsoleFd, VT_GETSTATE, &vts); + if (con != vts.v_active && (vts.v_state & (1 << con))) + { + ioctl (LinuxConsoleFd, VT_ACTIVATE, con); + return TRUE; + } + } + return FALSE; +} + +void +LinuxDisable (void) +{ + ioctl(LinuxConsoleFd, KDSETMODE, KD_TEXT); /* Back to text mode ... */ + if (kdSwitchPending) + { + kdSwitchPending = FALSE; + ioctl (LinuxConsoleFd, VT_RELDISP, 1); + } + enabled = FALSE; +} + +void +LinuxFini (void) +{ + struct vt_mode VT; + struct vt_stat vts; + int fd; + + if (LinuxConsoleFd < 0) + return; + + if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) != -1) + { + VT.mode = VT_AUTO; + ioctl(LinuxConsoleFd, VT_SETMODE, &VT); /* set dflt vt handling */ + } + ioctl (LinuxConsoleFd, VT_GETSTATE, &vts); + /* + * Find a legal VT to switch to, either the one we started from + * or the lowest active one that isn't ours + */ + if (activeVT < 0 || + activeVT == vts.v_active || + !(vts.v_state & (1 << activeVT))) + { + for (activeVT = 1; activeVT < 16; activeVT++) + if (activeVT != vtno && (vts.v_state & (1 << activeVT))) + break; + if (activeVT == 16) + activeVT = -1; + } + /* + * Perform a switch back to the active VT when we were started + */ + if (activeVT >= -1) + { + ioctl (LinuxConsoleFd, VT_ACTIVATE, activeVT); + ioctl (LinuxConsoleFd, VT_WAITACTIVE, activeVT); + activeVT = -1; + } + close(LinuxConsoleFd); /* make the vt-manager happy */ + fd = open ("/dev/tty0", O_RDWR|O_NDELAY, 0); + if (fd >= 0) + { + ioctl (fd, VT_GETSTATE, &vts); + if (ioctl (fd, VT_DISALLOCATE, vtno) < 0) + fprintf (stderr, "Can't deallocate console %d errno %d\n", vtno, errno); + close (fd); + } + return; +} + +KdOsFuncs LinuxFuncs = { + LinuxInit, + LinuxEnable, + LinuxSpecialKey, + LinuxDisable, + LinuxFini, +}; |