1
/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/bsd/bsd_init.c,v 3.21 2003/09/24 02:43:34 dawes Exp $ */
3
* Copyright 1992 by Rich Murphey <Rich@Rice.edu>
4
* Copyright 1993 by David Wexelblat <dwex@goblin.org>
6
* Permission to use, copy, modify, distribute, and sell this software and its
7
* documentation for any purpose is hereby granted without fee, provided that
8
* the above copyright notice appear in all copies and that both that
9
* copyright notice and this permission notice appear in supporting
10
* documentation, and that the names of Rich Murphey and David Wexelblat
11
* not be used in advertising or publicity pertaining to distribution of
12
* the software without specific, written prior permission. Rich Murphey and
13
* David Wexelblat make no representations about the suitability of this
14
* software for any purpose. It is provided "as is" without express or
17
* RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO
18
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19
* FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT BE LIABLE FOR
20
* ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
22
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26
/* $XConsortium: bsd_init.c /main/8 1996/10/23 13:13:05 kaleb $ */
28
#ifdef HAVE_XORG_CONFIG_H
29
#include <xorg-config.h>
38
#include "xf86_OSlib.h"
40
#include <sys/utsname.h>
41
#include <sys/ioctl.h>
45
static Bool KeepTty = FALSE;
46
static int devConsoleFd = -1;
47
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
48
static int VTnum = -1;
49
static int initialVT = -1;
53
/* Stock 0.1 386bsd pccons console driver interface */
55
# define PCCONS_CONSOLE_DEV1 "/dev/ttyv0"
57
# define PCCONS_CONSOLE_DEV1 "/dev/ttyC0"
59
#define PCCONS_CONSOLE_DEV2 "/dev/vga"
60
#define PCCONS_CONSOLE_MODE O_RDWR|O_NDELAY
63
#ifdef SYSCONS_SUPPORT
64
/* The FreeBSD 1.1 version syscons driver uses /dev/ttyv0 */
65
#define SYSCONS_CONSOLE_DEV1 "/dev/ttyv0"
66
#define SYSCONS_CONSOLE_DEV2 "/dev/vga"
67
#define SYSCONS_CONSOLE_MODE O_RDWR|O_NDELAY
71
/* Hellmuth Michaelis' pcvt driver */
73
# define PCVT_CONSOLE_DEV "/dev/ttyv0"
75
# define PCVT_CONSOLE_DEV "/dev/ttyC0"
77
#define PCVT_CONSOLE_MODE O_RDWR|O_NDELAY
80
#if defined(WSCONS_SUPPORT) && defined(__NetBSD__)
81
/* NetBSD's new console driver */
82
#define WSCONS_PCVT_COMPAT_CONSOLE_DEV "/dev/ttyE0"
86
#define setpgrp setpgid
89
#define CHECK_DRIVER_MSG \
90
"Check your kernel's console driver configuration and /dev entries"
92
static char *supported_drivers[] = {
94
"pccons (with X support)",
96
#ifdef SYSCONS_SUPPORT
102
#ifdef WSCONS_SUPPORT
109
* Functions to probe for the existance of a supported console driver.
110
* Any function returns either a valid file descriptor (driver probed
111
* succesfully), -1 (driver not found), or uses FatalError() if the
112
* driver was found but proved to not support the required mode to run
116
typedef int (*xf86ConsOpen_t)(void);
118
#ifdef PCCONS_SUPPORT
119
static int xf86OpenPccons(void);
120
#endif /* PCCONS_SUPPORT */
122
#ifdef SYSCONS_SUPPORT
123
static int xf86OpenSyscons(void);
124
#endif /* SYSCONS_SUPPORT */
127
static int xf86OpenPcvt(void);
128
#endif /* PCVT_SUPPORT */
130
#ifdef WSCONS_SUPPORT
131
static int xf86OpenWScons(void);
135
* The sequence of the driver probes is important; start with the
136
* driver that is best distinguishable, and end with the most generic
137
* driver. (Otherwise, pcvt would also probe as syscons, and either
138
* pcvt or syscons might succesfully probe as pccons.)
140
static xf86ConsOpen_t xf86ConsTab[] = {
144
#ifdef SYSCONS_SUPPORT
147
#ifdef PCCONS_SUPPORT
150
#ifdef WSCONS_SUPPORT
161
xf86ConsOpen_t *driver;
162
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
168
if (serverGeneration == 1)
170
/* check if we are run with euid==0 */
173
FatalError("xf86OpenConsole: Server must be suid root");
179
* detaching the controlling tty solves problems of kbd character
180
* loss. This is not interesting for CO driver, because it is
183
setpgrp(0, getpid());
184
if ((i = open("/dev/tty",O_RDWR)) >= 0)
186
ioctl(i,TIOCNOTTY,(char *)0);
191
/* detect which driver we are running on */
192
for (driver = xf86ConsTab; *driver; driver++)
194
if ((fd = (*driver)()) >= 0)
198
/* Check that a supported console driver was found */
201
char cons_drivers[80] = {0, };
202
for (i = 0; i < sizeof(supported_drivers) / sizeof(char *); i++)
206
strcat(cons_drivers, ", ");
208
strcat(cons_drivers, supported_drivers[i]);
211
"%s: No console driver found\n\tSupported drivers: %s\n\t%s",
212
"xf86OpenConsole", cons_drivers, CHECK_DRIVER_MSG);
214
#if 0 /* stdin is already closed in OsInit() */
217
xf86Info.consoleFd = fd;
218
xf86Info.screenFd = fd;
220
switch (xf86Info.consType)
222
#ifdef PCCONS_SUPPORT
224
if (ioctl (xf86Info.consoleFd, CONSOLE_X_MODE_ON, 0) < 0)
226
FatalError("%s: CONSOLE_X_MODE_ON failed (%s)\n%s",
227
"xf86OpenConsole", strerror(errno),
231
* Hack to prevent keyboard hanging when syslogd closes
234
if ((devConsoleFd = open("/dev/console", O_WRONLY,0)) < 0)
237
"xf86OpenConsole: couldn't open /dev/console (%s)\n",
242
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
244
/* as of FreeBSD 2.2.8, syscons driver does not need the #1 vt
245
* switching anymore. Here we check for FreeBSD 3.1 and up.
246
* Add cases for other *BSD that behave the same.
248
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
250
i = atof(uts.release) * 100;
251
if (i >= 310) goto acquire_vt;
253
/* otherwise fall through */
256
* First activate the #1 VT. This is a hack to allow a server
257
* to be started while another one is active. There should be
260
if (initialVT != 1) {
262
if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 1) != 0)
265
"xf86OpenConsole: VT_ACTIVATE failed\n");
275
ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno));
278
xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
281
ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno));
284
xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
287
signal(SIGUSR1, xf86VTRequest);
289
vtmode.mode = VT_PROCESS;
290
vtmode.relsig = SIGUSR1;
291
vtmode.acqsig = SIGUSR1;
292
vtmode.frsig = SIGUSR1;
293
if (ioctl(xf86Info.consoleFd, VT_SETMODE, &vtmode) < 0)
295
FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed");
297
#if !defined(USE_DEV_IO) && !defined(USE_I386_IOPL)
298
if (ioctl(xf86Info.consoleFd, KDENABIO, 0) < 0)
300
FatalError("xf86OpenConsole: KDENABIO failed (%s)",
304
if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0)
306
FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed");
309
#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
310
#ifdef WSCONS_SUPPORT
312
fprintf(stderr, "xf86OpenConsole\n");
313
/* xf86Info.consoleFd = open("/dev/wskbd0", 0); */
320
/* serverGeneration != 1 */
321
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
322
if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT)
324
if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
326
xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
329
#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
335
#ifdef PCCONS_SUPPORT
342
if ((fd = open(PCCONS_CONSOLE_DEV1, PCCONS_CONSOLE_MODE, 0))
344
(fd = open(PCCONS_CONSOLE_DEV2, PCCONS_CONSOLE_MODE, 0))
347
if (ioctl(fd, CONSOLE_X_MODE_OFF, 0) < 0)
350
"%s: CONSOLE_X_MODE_OFF failed (%s)\n%s\n%s",
353
"Was expecting pccons driver with X support",
356
xf86Info.consType = PCCONS;
357
xf86Msg(X_PROBED, "Using pccons driver with X support\n");
362
#endif /* PCCONS_SUPPORT */
364
#ifdef SYSCONS_SUPPORT
373
long syscons_version;
376
/* Check for syscons */
377
if ((fd = open(SYSCONS_CONSOLE_DEV1, SYSCONS_CONSOLE_MODE, 0)) >= 0
378
|| (fd = open(SYSCONS_CONSOLE_DEV2, SYSCONS_CONSOLE_MODE, 0)) >= 0)
380
if (ioctl(fd, VT_GETMODE, &vtmode) >= 0)
382
/* Get syscons version */
383
if (ioctl(fd, CONS_GETVERS, &syscons_version) < 0)
388
xf86Info.vtno = VTnum;
392
if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0)
395
if (xf86Info.vtno == -1)
398
* For old syscons versions (<0x100), VT_OPENQRY returns
399
* the current VT rather than the next free VT. In this
400
* case, the server gets started on the current VT instead
401
* of the next free VT.
405
/* check for the fixed VT_OPENQRY */
406
if (syscons_version >= 0x100)
409
if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0)
418
if (xf86Info.vtno == -1)
421
* All VTs are in use. If initialVT was found, use it.
422
* Otherwise, if stdin is a VT, use that one.
423
* XXX stdin is already closed, so this won't work.
427
xf86Info.vtno = initialVT;
429
else if ((fstat(0, &status) >= 0)
430
&& S_ISCHR(status.st_mode)
431
&& (ioctl(0, VT_GETMODE, &vtmode) >= 0))
434
xf86Info.vtno = minor(status.st_rdev) + 1;
438
if (syscons_version >= 0x100)
440
FatalError("%s: Cannot find a free VT",
443
/* Should no longer reach here */
444
FatalError("%s: %s %s\n\t%s %s",
446
"syscons versions prior to 1.0 require",
448
"server's stdin be a VT",
449
"or the use of the vtxx server option");
457
sprintf(vtname, "/dev/ttyv%01x", xf86Info.vtno - 1);
459
sprintf(vtname, "/dev/ttyC%01x", xf86Info.vtno - 1);
461
if ((fd = open(vtname, SYSCONS_CONSOLE_MODE, 0)) < 0)
463
FatalError("xf86OpenSyscons: Cannot open %s (%s)",
464
vtname, strerror(errno));
466
if (ioctl(fd, VT_GETMODE, &vtmode) < 0)
468
FatalError("xf86OpenSyscons: VT_GETMODE failed");
470
xf86Info.consType = SYSCONS;
471
xf86Msg(X_PROBED, "Using syscons driver with X support");
472
if (syscons_version >= 0x100)
474
xf86ErrorF(" (version %ld.%ld)\n", syscons_version >> 8,
475
syscons_version & 0xFF);
479
xf86ErrorF(" (version 0.x)\n");
481
xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
485
/* VT_GETMODE failed, probably not syscons */
493
#endif /* SYSCONS_SUPPORT */
501
/* This looks much like syscons, since pcvt is API compatible */
504
char vtname[12], *vtprefix;
506
struct pcvtid pcvt_version;
509
vtprefix = "/dev/ttyv";
511
vtprefix = "/dev/ttyC";
514
fd = open(PCVT_CONSOLE_DEV, PCVT_CONSOLE_MODE, 0);
515
#ifdef WSCONS_PCVT_COMPAT_CONSOLE_DEV
518
fd = open(WSCONS_PCVT_COMPAT_CONSOLE_DEV, PCVT_CONSOLE_MODE, 0);
519
vtprefix = "/dev/ttyE";
524
if (ioctl(fd, VGAPCVTID, &pcvt_version) >= 0)
526
if(ioctl(fd, VT_GETMODE, &vtmode) < 0)
528
FatalError("%s: VT_GETMODE failed\n%s%s\n%s",
530
"Found pcvt driver but X11 seems to be",
531
" not supported.", CHECK_DRIVER_MSG);
534
xf86Info.vtno = VTnum;
536
if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0)
539
if (xf86Info.vtno == -1)
541
if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0)
547
if (xf86Info.vtno == -1)
550
* All VTs are in use. If initialVT was found, use it.
551
* Otherwise, if stdin is a VT, use that one.
552
* XXX stdin is already closed, so this won't work.
556
xf86Info.vtno = initialVT;
558
else if ((fstat(0, &status) >= 0)
559
&& S_ISCHR(status.st_mode)
560
&& (ioctl(0, VT_GETMODE, &vtmode) >= 0))
563
xf86Info.vtno = minor(status.st_rdev) + 1;
567
FatalError("%s: Cannot find a free VT",
574
sprintf(vtname, "%s%01x", vtprefix, xf86Info.vtno - 1);
575
if ((fd = open(vtname, PCVT_CONSOLE_MODE, 0)) < 0)
577
FatalError("xf86OpenPcvt: Cannot open %s (%s)",
578
vtname, strerror(errno));
580
if (ioctl(fd, VT_GETMODE, &vtmode) < 0)
582
FatalError("xf86OpenPcvt: VT_GETMODE failed");
584
xf86Info.consType = PCVT;
585
#ifdef WSCONS_SUPPORT
587
"Using wscons driver in pcvt compatibility mode "
589
pcvt_version.rmajor, pcvt_version.rminor);
591
xf86Msg(X_PROBED, "Using pcvt driver (version %d.%d)\n",
592
pcvt_version.rmajor, pcvt_version.rminor);
605
#endif /* PCVT_SUPPORT */
607
#ifdef WSCONS_SUPPORT
613
int mode = WSDISPLAYIO_MODE_MAPPED;
617
/* XXX Is this ok? */
618
for (i = 0; i < 8; i++) {
619
#if defined(__NetBSD__)
620
sprintf(ttyname, "/dev/ttyE%d", i);
621
#elif defined(__OpenBSD__)
622
sprintf(ttyname, "/dev/ttyC%d", i);
624
if ((fd = open(ttyname, 2)) != -1)
628
if (ioctl(fd, WSDISPLAYIO_SMODE, &mode) < 0) {
629
FatalError("%s: WSDISPLAYIO_MODE_MAPPED failed (%s)\n%s",
630
"xf86OpenConsole", strerror(errno),
633
xf86Info.consType = WSCONS;
634
xf86Msg(X_PROBED, "Using wscons driver\n");
639
#endif /* WSCONS_SUPPORT */
644
#if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT)
648
switch (xf86Info.consType)
650
#ifdef PCCONS_SUPPORT
652
ioctl (xf86Info.consoleFd, CONSOLE_X_MODE_OFF, 0);
654
#endif /* PCCONS_SUPPORT */
655
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
658
ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT); /* Back to text mode */
659
if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
662
ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* dflt vt handling */
664
#if !defined(USE_DEV_IO) && !defined(USE_I386_IOPL)
665
if (ioctl(xf86Info.consoleFd, KDDISABIO, 0) < 0)
667
xf86FatalError("xf86CloseConsole: KDDISABIO failed (%s)",
672
ioctl(xf86Info.consoleFd, VT_ACTIVATE, initialVT);
674
#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
675
#ifdef WSCONS_SUPPORT
678
int mode = WSDISPLAYIO_MODE_EMUL;
679
ioctl(xf86Info.screenFd, WSDISPLAYIO_SMODE, &mode);
685
if (xf86Info.screenFd != xf86Info.consoleFd)
687
close(xf86Info.screenFd);
688
close(xf86Info.consoleFd);
689
if ((xf86Info.consoleFd = open("/dev/console",O_RDONLY,0)) <0)
691
xf86FatalError("xf86CloseConsole: Cannot open /dev/console (%s)",
695
close(xf86Info.consoleFd);
696
if (devConsoleFd >= 0)
702
xf86ProcessArgument(int argc, char *argv[], int i)
705
* Keep server from detaching from controlling tty. This is useful
706
* when debugging (so the server can receive keyboard signals.
708
if (!strcmp(argv[i], "-keeptty"))
713
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
714
if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
716
if (sscanf(argv[i], "vt%2d", &VTnum) == 0 ||
717
VTnum < 1 || VTnum > 12)
725
#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
732
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
733
ErrorF("vtXX use the specified VT number (1-12)\n");
734
#endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */
736
ErrorF("don't detach controlling tty (for debugging only)\n");