First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / os-support / bsd / bsd_init.c
blob07f031fa8f1859aee01bd4fd698e5b7baef3b13a
1 /*
2 * Copyright 1992 by Rich Murphey <Rich@Rice.edu>
3 * Copyright 1993 by David Wexelblat <dwex@goblin.org>
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the names of Rich Murphey and David Wexelblat
10 * not be used in advertising or publicity pertaining to distribution of
11 * the software without specific, written prior permission. Rich Murphey and
12 * David Wexelblat make no representations about the suitability of this
13 * software for any purpose. It is provided "as is" without express or
14 * implied warranty.
16 * RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO
17 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 * FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT BE LIABLE FOR
19 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
21 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 #ifdef HAVE_XORG_CONFIG_H
27 #include <xorg-config.h>
28 #endif
30 #include <X11/X.h>
32 #include "compiler.h"
34 #include "xf86.h"
35 #include "xf86Priv.h"
36 #include "xf86_OSlib.h"
38 #include <sys/utsname.h>
39 #include <sys/ioctl.h>
40 #include <stdlib.h>
41 #include <errno.h>
43 static Bool KeepTty = FALSE;
44 static int devConsoleFd = -1;
45 #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
46 static int VTnum = -1;
47 static int initialVT = -1;
48 #endif
50 #ifdef PCCONS_SUPPORT
51 /* Stock 0.1 386bsd pccons console driver interface */
52 #ifndef __OpenBSD__
53 # define PCCONS_CONSOLE_DEV1 "/dev/ttyv0"
54 #else
55 # define PCCONS_CONSOLE_DEV1 "/dev/ttyC0"
56 #endif
57 #define PCCONS_CONSOLE_DEV2 "/dev/vga"
58 #define PCCONS_CONSOLE_MODE O_RDWR|O_NDELAY
59 #endif
61 #ifdef SYSCONS_SUPPORT
62 /* The FreeBSD 1.1 version syscons driver uses /dev/ttyv0 */
63 #define SYSCONS_CONSOLE_DEV1 "/dev/ttyv0"
64 #define SYSCONS_CONSOLE_DEV2 "/dev/vga"
65 #define SYSCONS_CONSOLE_MODE O_RDWR|O_NDELAY
66 #endif
68 #ifdef PCVT_SUPPORT
69 /* Hellmuth Michaelis' pcvt driver */
70 #ifndef __OpenBSD__
71 # define PCVT_CONSOLE_DEV "/dev/ttyv0"
72 #else
73 # define PCVT_CONSOLE_DEV "/dev/ttyC0"
74 #endif
75 #define PCVT_CONSOLE_MODE O_RDWR|O_NDELAY
76 #endif
78 #if defined(WSCONS_SUPPORT) && defined(__NetBSD__)
79 /* NetBSD's new console driver */
80 #define WSCONS_PCVT_COMPAT_CONSOLE_DEV "/dev/ttyE0"
81 #endif
83 #ifdef __GLIBC__
84 #define setpgrp setpgid
85 #endif
87 #define CHECK_DRIVER_MSG \
88 "Check your kernel's console driver configuration and /dev entries"
90 static char *supported_drivers[] = {
91 #ifdef PCCONS_SUPPORT
92 "pccons (with X support)",
93 #endif
94 #ifdef SYSCONS_SUPPORT
95 "syscons",
96 #endif
97 #ifdef PCVT_SUPPORT
98 "pcvt",
99 #endif
100 #ifdef WSCONS_SUPPORT
101 "wscons",
102 #endif
107 * Functions to probe for the existance of a supported console driver.
108 * Any function returns either a valid file descriptor (driver probed
109 * succesfully), -1 (driver not found), or uses FatalError() if the
110 * driver was found but proved to not support the required mode to run
111 * an X server.
114 typedef int (*xf86ConsOpen_t)(void);
116 #ifdef PCCONS_SUPPORT
117 static int xf86OpenPccons(void);
118 #endif /* PCCONS_SUPPORT */
120 #ifdef SYSCONS_SUPPORT
121 static int xf86OpenSyscons(void);
122 #endif /* SYSCONS_SUPPORT */
124 #ifdef PCVT_SUPPORT
125 static int xf86OpenPcvt(void);
126 #endif /* PCVT_SUPPORT */
128 #ifdef WSCONS_SUPPORT
129 static int xf86OpenWScons(void);
130 #endif
133 * The sequence of the driver probes is important; start with the
134 * driver that is best distinguishable, and end with the most generic
135 * driver. (Otherwise, pcvt would also probe as syscons, and either
136 * pcvt or syscons might succesfully probe as pccons.)
138 static xf86ConsOpen_t xf86ConsTab[] = {
139 #ifdef PCVT_SUPPORT
140 xf86OpenPcvt,
141 #endif
142 #ifdef SYSCONS_SUPPORT
143 xf86OpenSyscons,
144 #endif
145 #ifdef PCCONS_SUPPORT
146 xf86OpenPccons,
147 #endif
148 #ifdef WSCONS_SUPPORT
149 xf86OpenWScons,
150 #endif
151 (xf86ConsOpen_t)NULL
155 void
156 xf86OpenConsole()
158 int i, fd = -1;
159 xf86ConsOpen_t *driver;
160 #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
161 int result;
162 struct utsname uts;
163 vtmode_t vtmode;
164 #endif
166 if (serverGeneration == 1)
168 /* check if we are run with euid==0 */
169 if (geteuid() != 0)
171 FatalError("xf86OpenConsole: Server must be suid root");
174 if (!KeepTty)
177 * detaching the controlling tty solves problems of kbd character
178 * loss. This is not interesting for CO driver, because it is
179 * exclusive.
181 setpgrp(0, getpid());
182 if ((i = open("/dev/tty",O_RDWR)) >= 0)
184 ioctl(i,TIOCNOTTY,(char *)0);
185 close(i);
189 /* detect which driver we are running on */
190 for (driver = xf86ConsTab; *driver; driver++)
192 if ((fd = (*driver)()) >= 0)
193 break;
196 /* Check that a supported console driver was found */
197 if (fd < 0)
199 char cons_drivers[80] = {0, };
200 for (i = 0; i < sizeof(supported_drivers) / sizeof(char *); i++)
202 if (i)
204 strcat(cons_drivers, ", ");
206 strcat(cons_drivers, supported_drivers[i]);
208 FatalError(
209 "%s: No console driver found\n\tSupported drivers: %s\n\t%s",
210 "xf86OpenConsole", cons_drivers, CHECK_DRIVER_MSG);
212 #if 0 /* stdin is already closed in OsInit() */
213 fclose(stdin);
214 #endif
215 xf86Info.consoleFd = fd;
216 xf86Info.screenFd = fd;
218 switch (xf86Info.consType)
220 #ifdef PCCONS_SUPPORT
221 case PCCONS:
222 if (ioctl (xf86Info.consoleFd, CONSOLE_X_MODE_ON, 0) < 0)
224 FatalError("%s: CONSOLE_X_MODE_ON failed (%s)\n%s",
225 "xf86OpenConsole", strerror(errno),
226 CHECK_DRIVER_MSG);
229 * Hack to prevent keyboard hanging when syslogd closes
230 * /dev/console
232 if ((devConsoleFd = open("/dev/console", O_WRONLY,0)) < 0)
234 xf86Msg(X_WARNING,
235 "xf86OpenConsole: couldn't open /dev/console (%s)\n",
236 strerror(errno));
238 break;
239 #endif
240 #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
241 case SYSCONS:
242 /* as of FreeBSD 2.2.8, syscons driver does not need the #1 vt
243 * switching anymore. Here we check for FreeBSD 3.1 and up.
244 * Add cases for other *BSD that behave the same.
246 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
247 uname (&uts);
248 i = atof(uts.release) * 100;
249 if (i >= 310) goto acquire_vt;
250 #endif
251 /* otherwise fall through */
252 case PCVT:
254 * First activate the #1 VT. This is a hack to allow a server
255 * to be started while another one is active. There should be
256 * a better way.
258 if (initialVT != 1) {
260 if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 1) != 0)
262 xf86Msg(X_WARNING,
263 "xf86OpenConsole: VT_ACTIVATE failed\n");
265 sleep(1);
268 acquire_vt:
270 * now get the VT
272 SYSCALL(result =
273 ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno));
274 if (result != 0)
276 xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
278 SYSCALL(result =
279 ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno));
280 if (result != 0)
282 xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
285 signal(SIGUSR1, xf86VTRequest);
287 vtmode.mode = VT_PROCESS;
288 vtmode.relsig = SIGUSR1;
289 vtmode.acqsig = SIGUSR1;
290 vtmode.frsig = SIGUSR1;
291 if (ioctl(xf86Info.consoleFd, VT_SETMODE, &vtmode) < 0)
293 FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed");
295 #if !defined(USE_DEV_IO) && !defined(USE_I386_IOPL)
296 if (ioctl(xf86Info.consoleFd, KDENABIO, 0) < 0)
298 FatalError("xf86OpenConsole: KDENABIO failed (%s)",
299 strerror(errno));
301 #endif
302 if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0)
304 FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed");
306 break;
307 #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
308 #ifdef WSCONS_SUPPORT
309 case WSCONS:
310 fprintf(stderr, "xf86OpenConsole\n");
311 /* xf86Info.consoleFd = open("/dev/wskbd0", 0); */
312 break;
313 #endif
316 else
318 /* serverGeneration != 1 */
319 #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
320 if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT)
322 if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
324 xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
327 #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
329 return;
333 #ifdef PCCONS_SUPPORT
335 static int
336 xf86OpenPccons()
338 int fd = -1;
340 if ((fd = open(PCCONS_CONSOLE_DEV1, PCCONS_CONSOLE_MODE, 0))
341 >= 0 ||
342 (fd = open(PCCONS_CONSOLE_DEV2, PCCONS_CONSOLE_MODE, 0))
343 >= 0)
345 if (ioctl(fd, CONSOLE_X_MODE_OFF, 0) < 0)
347 FatalError(
348 "%s: CONSOLE_X_MODE_OFF failed (%s)\n%s\n%s",
349 "xf86OpenPccons",
350 strerror(errno),
351 "Was expecting pccons driver with X support",
352 CHECK_DRIVER_MSG);
354 xf86Info.consType = PCCONS;
355 xf86Msg(X_PROBED, "Using pccons driver with X support\n");
357 return fd;
360 #endif /* PCCONS_SUPPORT */
362 #ifdef SYSCONS_SUPPORT
364 static int
365 xf86OpenSyscons()
367 int fd = -1;
368 vtmode_t vtmode;
369 char vtname[12];
370 struct stat status;
371 long syscons_version;
372 MessageType from;
374 /* Check for syscons */
375 if ((fd = open(SYSCONS_CONSOLE_DEV1, SYSCONS_CONSOLE_MODE, 0)) >= 0
376 || (fd = open(SYSCONS_CONSOLE_DEV2, SYSCONS_CONSOLE_MODE, 0)) >= 0)
378 if (ioctl(fd, VT_GETMODE, &vtmode) >= 0)
380 /* Get syscons version */
381 if (ioctl(fd, CONS_GETVERS, &syscons_version) < 0)
383 syscons_version = 0;
386 xf86Info.vtno = VTnum;
387 from = X_CMDLINE;
389 #ifdef VT_GETACTIVE
390 if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0)
391 initialVT = -1;
392 #endif
393 if (xf86Info.vtno == -1)
396 * For old syscons versions (<0x100), VT_OPENQRY returns
397 * the current VT rather than the next free VT. In this
398 * case, the server gets started on the current VT instead
399 * of the next free VT.
402 #if 0
403 /* check for the fixed VT_OPENQRY */
404 if (syscons_version >= 0x100)
406 #endif
407 if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0)
409 /* No free VTs */
410 xf86Info.vtno = -1;
412 #if 0
414 #endif
416 if (xf86Info.vtno == -1)
419 * All VTs are in use. If initialVT was found, use it.
420 * Otherwise, if stdin is a VT, use that one.
421 * XXX stdin is already closed, so this won't work.
423 if (initialVT != -1)
425 xf86Info.vtno = initialVT;
427 else if ((fstat(0, &status) >= 0)
428 && S_ISCHR(status.st_mode)
429 && (ioctl(0, VT_GETMODE, &vtmode) >= 0))
431 /* stdin is a VT */
432 xf86Info.vtno = minor(status.st_rdev) + 1;
434 else
436 if (syscons_version >= 0x100)
438 FatalError("%s: Cannot find a free VT",
439 "xf86OpenSyscons");
441 /* Should no longer reach here */
442 FatalError("%s: %s %s\n\t%s %s",
443 "xf86OpenSyscons",
444 "syscons versions prior to 1.0 require",
445 "either the",
446 "server's stdin be a VT",
447 "or the use of the vtxx server option");
450 from = X_PROBED;
453 close(fd);
454 #ifndef __OpenBSD__
455 sprintf(vtname, "/dev/ttyv%01x", xf86Info.vtno - 1);
456 #else
457 sprintf(vtname, "/dev/ttyC%01x", xf86Info.vtno - 1);
458 #endif
459 if ((fd = open(vtname, SYSCONS_CONSOLE_MODE, 0)) < 0)
461 FatalError("xf86OpenSyscons: Cannot open %s (%s)",
462 vtname, strerror(errno));
464 if (ioctl(fd, VT_GETMODE, &vtmode) < 0)
466 FatalError("xf86OpenSyscons: VT_GETMODE failed");
468 xf86Info.consType = SYSCONS;
469 xf86Msg(X_PROBED, "Using syscons driver with X support");
470 if (syscons_version >= 0x100)
472 xf86ErrorF(" (version %ld.%ld)\n", syscons_version >> 8,
473 syscons_version & 0xFF);
475 else
477 xf86ErrorF(" (version 0.x)\n");
479 xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
481 else
483 /* VT_GETMODE failed, probably not syscons */
484 close(fd);
485 fd = -1;
488 return fd;
491 #endif /* SYSCONS_SUPPORT */
494 #ifdef PCVT_SUPPORT
496 static int
497 xf86OpenPcvt()
499 /* This looks much like syscons, since pcvt is API compatible */
500 int fd = -1;
501 vtmode_t vtmode;
502 char vtname[12], *vtprefix;
503 struct stat status;
504 struct pcvtid pcvt_version;
506 #ifndef __OpenBSD__
507 vtprefix = "/dev/ttyv";
508 #else
509 vtprefix = "/dev/ttyC";
510 #endif
512 fd = open(PCVT_CONSOLE_DEV, PCVT_CONSOLE_MODE, 0);
513 #ifdef WSCONS_PCVT_COMPAT_CONSOLE_DEV
514 if (fd < 0)
516 fd = open(WSCONS_PCVT_COMPAT_CONSOLE_DEV, PCVT_CONSOLE_MODE, 0);
517 vtprefix = "/dev/ttyE";
519 #endif
520 if (fd >= 0)
522 if (ioctl(fd, VGAPCVTID, &pcvt_version) >= 0)
524 if(ioctl(fd, VT_GETMODE, &vtmode) < 0)
526 FatalError("%s: VT_GETMODE failed\n%s%s\n%s",
527 "xf86OpenPcvt",
528 "Found pcvt driver but X11 seems to be",
529 " not supported.", CHECK_DRIVER_MSG);
532 xf86Info.vtno = VTnum;
534 if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0)
535 initialVT = -1;
537 if (xf86Info.vtno == -1)
539 if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0)
541 /* No free VTs */
542 xf86Info.vtno = -1;
545 if (xf86Info.vtno == -1)
548 * All VTs are in use. If initialVT was found, use it.
549 * Otherwise, if stdin is a VT, use that one.
550 * XXX stdin is already closed, so this won't work.
552 if (initialVT != -1)
554 xf86Info.vtno = initialVT;
556 else if ((fstat(0, &status) >= 0)
557 && S_ISCHR(status.st_mode)
558 && (ioctl(0, VT_GETMODE, &vtmode) >= 0))
560 /* stdin is a VT */
561 xf86Info.vtno = minor(status.st_rdev) + 1;
563 else
565 FatalError("%s: Cannot find a free VT",
566 "xf86OpenPcvt");
571 close(fd);
572 sprintf(vtname, "%s%01x", vtprefix, xf86Info.vtno - 1);
573 if ((fd = open(vtname, PCVT_CONSOLE_MODE, 0)) < 0)
575 FatalError("xf86OpenPcvt: Cannot open %s (%s)",
576 vtname, strerror(errno));
578 if (ioctl(fd, VT_GETMODE, &vtmode) < 0)
580 FatalError("xf86OpenPcvt: VT_GETMODE failed");
582 xf86Info.consType = PCVT;
583 #ifdef WSCONS_SUPPORT
584 xf86Msg(X_PROBED,
585 "Using wscons driver in pcvt compatibility mode "
586 "(version %d.%d)\n",
587 pcvt_version.rmajor, pcvt_version.rminor);
588 #else
589 xf86Msg(X_PROBED, "Using pcvt driver (version %d.%d)\n",
590 pcvt_version.rmajor, pcvt_version.rminor);
591 #endif
593 else
595 /* Not pcvt */
596 close(fd);
597 fd = -1;
600 return fd;
603 #endif /* PCVT_SUPPORT */
605 #ifdef WSCONS_SUPPORT
607 static int
608 xf86OpenWScons()
610 int fd = -1;
611 int mode = WSDISPLAYIO_MODE_MAPPED;
612 int i;
613 char ttyname[16];
615 /* XXX Is this ok? */
616 for (i = 0; i < 8; i++) {
617 #if defined(__NetBSD__)
618 sprintf(ttyname, "/dev/ttyE%d", i);
619 #elif defined(__OpenBSD__)
620 sprintf(ttyname, "/dev/ttyC%d", i);
621 #endif
622 if ((fd = open(ttyname, 2)) != -1)
623 break;
625 if (fd != -1) {
626 if (ioctl(fd, WSDISPLAYIO_SMODE, &mode) < 0) {
627 FatalError("%s: WSDISPLAYIO_MODE_MAPPED failed (%s)\n%s",
628 "xf86OpenConsole", strerror(errno),
629 CHECK_DRIVER_MSG);
631 xf86Info.consType = WSCONS;
632 xf86Msg(X_PROBED, "Using wscons driver\n");
634 return fd;
637 #endif /* WSCONS_SUPPORT */
639 void
640 xf86CloseConsole()
642 #if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT)
643 struct vt_mode VT;
644 #endif
646 switch (xf86Info.consType)
648 #ifdef PCCONS_SUPPORT
649 case PCCONS:
650 ioctl (xf86Info.consoleFd, CONSOLE_X_MODE_OFF, 0);
651 break;
652 #endif /* PCCONS_SUPPORT */
653 #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
654 case SYSCONS:
655 case PCVT:
656 ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT); /* Back to text mode */
657 if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
659 VT.mode = VT_AUTO;
660 ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* dflt vt handling */
662 #if !defined(USE_DEV_IO) && !defined(USE_I386_IOPL)
663 if (ioctl(xf86Info.consoleFd, KDDISABIO, 0) < 0)
665 xf86FatalError("xf86CloseConsole: KDDISABIO failed (%s)",
666 strerror(errno));
668 #endif
669 if (initialVT != -1)
670 ioctl(xf86Info.consoleFd, VT_ACTIVATE, initialVT);
671 break;
672 #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
673 #ifdef WSCONS_SUPPORT
674 case WSCONS:
676 int mode = WSDISPLAYIO_MODE_EMUL;
677 ioctl(xf86Info.screenFd, WSDISPLAYIO_SMODE, &mode);
678 break;
680 #endif
683 if (xf86Info.screenFd != xf86Info.consoleFd)
685 close(xf86Info.screenFd);
686 close(xf86Info.consoleFd);
687 if ((xf86Info.consoleFd = open("/dev/console",O_RDONLY,0)) <0)
689 xf86FatalError("xf86CloseConsole: Cannot open /dev/console (%s)",
690 strerror(errno));
693 close(xf86Info.consoleFd);
694 if (devConsoleFd >= 0)
695 close(devConsoleFd);
696 return;
700 xf86ProcessArgument(int argc, char *argv[], int i)
703 * Keep server from detaching from controlling tty. This is useful
704 * when debugging (so the server can receive keyboard signals.
706 if (!strcmp(argv[i], "-keeptty"))
708 KeepTty = TRUE;
709 return(1);
711 #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
712 if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
714 if (sscanf(argv[i], "vt%2d", &VTnum) == 0 ||
715 VTnum < 1 || VTnum > 12)
717 UseMsg();
718 VTnum = -1;
719 return(0);
721 return(1);
723 #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
724 return(0);
727 void
728 xf86UseMsg()
730 #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
731 ErrorF("vtXX use the specified VT number (1-12)\n");
732 #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
733 ErrorF("-keeptty ");
734 ErrorF("don't detach controlling tty (for debugging only)\n");
735 return;