Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright 1992 by Rich Murphey <Rich@Rice.edu> | |
3 | * Copyright 1993 by David Wexelblat <dwex@goblin.org> | |
4 | * | |
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. | |
15 | * | |
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. | |
23 | * | |
24 | */ | |
25 | ||
26 | #ifdef HAVE_XORG_CONFIG_H | |
27 | #include <xorg-config.h> | |
28 | #endif | |
29 | ||
30 | #include <X11/X.h> | |
31 | ||
32 | #include "compiler.h" | |
33 | ||
34 | #include "xf86.h" | |
35 | #include "xf86Priv.h" | |
36 | #include "xf86_OSlib.h" | |
37 | ||
38 | #include <sys/utsname.h> | |
39 | #include <sys/ioctl.h> | |
40 | #include <stdlib.h> | |
41 | #include <errno.h> | |
42 | ||
43 | static Bool KeepTty = FALSE; | |
44 | ||
45 | #ifdef PCCONS_SUPPORT | |
46 | static int devConsoleFd = -1; | |
47 | #endif | |
48 | #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) | |
49 | static int VTnum = -1; | |
50 | static int initialVT = -1; | |
51 | #endif | |
52 | ||
53 | #ifdef PCCONS_SUPPORT | |
54 | /* Stock 0.1 386bsd pccons console driver interface */ | |
55 | #define PCCONS_CONSOLE_DEV1 "/dev/ttyv0" | |
56 | #define PCCONS_CONSOLE_DEV2 "/dev/vga" | |
57 | #define PCCONS_CONSOLE_MODE O_RDWR|O_NDELAY | |
58 | #endif | |
59 | ||
60 | #ifdef SYSCONS_SUPPORT | |
61 | /* The FreeBSD 1.1 version syscons driver uses /dev/ttyv0 */ | |
62 | #define SYSCONS_CONSOLE_DEV1 "/dev/ttyv0" | |
63 | #define SYSCONS_CONSOLE_DEV2 "/dev/vga" | |
64 | #define SYSCONS_CONSOLE_MODE O_RDWR|O_NDELAY | |
65 | #endif | |
66 | ||
67 | #ifdef PCVT_SUPPORT | |
68 | /* Hellmuth Michaelis' pcvt driver */ | |
69 | #ifndef __OpenBSD__ | |
70 | #define PCVT_CONSOLE_DEV "/dev/ttyv0" | |
71 | #else | |
72 | #define PCVT_CONSOLE_DEV "/dev/ttyC0" | |
73 | #endif | |
74 | #define PCVT_CONSOLE_MODE O_RDWR|O_NDELAY | |
75 | #endif | |
76 | ||
77 | #if defined(WSCONS_SUPPORT) && defined(__NetBSD__) | |
78 | /* NetBSD's new console driver */ | |
79 | #define WSCONS_PCVT_COMPAT_CONSOLE_DEV "/dev/ttyE0" | |
80 | #endif | |
81 | ||
82 | #ifdef __GLIBC__ | |
83 | #define setpgrp setpgid | |
84 | #endif | |
85 | ||
86 | #define CHECK_DRIVER_MSG \ | |
87 | "Check your kernel's console driver configuration and /dev entries" | |
88 | ||
89 | static char *supported_drivers[] = { | |
90 | #ifdef PCCONS_SUPPORT | |
91 | "pccons (with X support)", | |
92 | #endif | |
93 | #ifdef SYSCONS_SUPPORT | |
94 | "syscons", | |
95 | #endif | |
96 | #ifdef PCVT_SUPPORT | |
97 | "pcvt", | |
98 | #endif | |
99 | #ifdef WSCONS_SUPPORT | |
100 | "wscons", | |
101 | #endif | |
102 | }; | |
103 | ||
104 | /* | |
105 | * Functions to probe for the existance of a supported console driver. | |
106 | * Any function returns either a valid file descriptor (driver probed | |
107 | * succesfully), -1 (driver not found), or uses FatalError() if the | |
108 | * driver was found but proved to not support the required mode to run | |
109 | * an X server. | |
110 | */ | |
111 | ||
112 | typedef int (*xf86ConsOpen_t) (void); | |
113 | ||
114 | #ifdef PCCONS_SUPPORT | |
115 | static int xf86OpenPccons(void); | |
116 | #endif /* PCCONS_SUPPORT */ | |
117 | ||
118 | #ifdef SYSCONS_SUPPORT | |
119 | static int xf86OpenSyscons(void); | |
120 | #endif /* SYSCONS_SUPPORT */ | |
121 | ||
122 | #ifdef PCVT_SUPPORT | |
123 | static int xf86OpenPcvt(void); | |
124 | #endif /* PCVT_SUPPORT */ | |
125 | ||
126 | #ifdef WSCONS_SUPPORT | |
127 | static int xf86OpenWScons(void); | |
128 | #endif | |
129 | ||
130 | /* | |
131 | * The sequence of the driver probes is important; start with the | |
132 | * driver that is best distinguishable, and end with the most generic | |
133 | * driver. (Otherwise, pcvt would also probe as syscons, and either | |
134 | * pcvt or syscons might succesfully probe as pccons.) | |
135 | */ | |
136 | static xf86ConsOpen_t xf86ConsTab[] = { | |
137 | #ifdef PCVT_SUPPORT | |
138 | xf86OpenPcvt, | |
139 | #endif | |
140 | #ifdef SYSCONS_SUPPORT | |
141 | xf86OpenSyscons, | |
142 | #endif | |
143 | #ifdef PCCONS_SUPPORT | |
144 | xf86OpenPccons, | |
145 | #endif | |
146 | #ifdef WSCONS_SUPPORT | |
147 | xf86OpenWScons, | |
148 | #endif | |
149 | (xf86ConsOpen_t) NULL | |
150 | }; | |
151 | ||
152 | void | |
153 | xf86OpenConsole() | |
154 | { | |
155 | int i, fd = -1; | |
156 | xf86ConsOpen_t *driver; | |
157 | ||
158 | #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) | |
159 | int result; | |
160 | ||
161 | #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | |
162 | struct utsname uts; | |
163 | #endif | |
164 | vtmode_t vtmode; | |
165 | #endif | |
166 | ||
167 | if (serverGeneration == 1) { | |
168 | /* check if we are run with euid==0 */ | |
169 | if (geteuid() != 0) { | |
170 | FatalError("xf86OpenConsole: Server must be suid root"); | |
171 | } | |
172 | ||
173 | if (!KeepTty) { | |
174 | /* | |
175 | * detaching the controlling tty solves problems of kbd character | |
176 | * loss. This is not interesting for CO driver, because it is | |
177 | * exclusive. | |
178 | */ | |
179 | setpgrp(0, getpid()); | |
180 | if ((i = open("/dev/tty", O_RDWR)) >= 0) { | |
181 | ioctl(i, TIOCNOTTY, (char *) 0); | |
182 | close(i); | |
183 | } | |
184 | } | |
185 | ||
186 | /* detect which driver we are running on */ | |
187 | for (driver = xf86ConsTab; *driver; driver++) { | |
188 | if ((fd = (*driver) ()) >= 0) | |
189 | break; | |
190 | } | |
191 | ||
192 | /* Check that a supported console driver was found */ | |
193 | if (fd < 0) { | |
194 | char cons_drivers[80] = { 0, }; | |
195 | for (i = 0; i < sizeof(supported_drivers) / sizeof(char *); i++) { | |
196 | if (i) { | |
197 | strcat(cons_drivers, ", "); | |
198 | } | |
199 | strcat(cons_drivers, supported_drivers[i]); | |
200 | } | |
201 | FatalError | |
202 | ("%s: No console driver found\n\tSupported drivers: %s\n\t%s", | |
203 | "xf86OpenConsole", cons_drivers, CHECK_DRIVER_MSG); | |
204 | } | |
205 | xf86Info.consoleFd = fd; | |
206 | ||
207 | switch (xf86Info.consType) { | |
208 | #ifdef PCCONS_SUPPORT | |
209 | case PCCONS: | |
210 | if (ioctl(xf86Info.consoleFd, CONSOLE_X_MODE_ON, 0) < 0) { | |
211 | FatalError("%s: CONSOLE_X_MODE_ON failed (%s)\n%s", | |
212 | "xf86OpenConsole", strerror(errno), | |
213 | CHECK_DRIVER_MSG); | |
214 | } | |
215 | /* | |
216 | * Hack to prevent keyboard hanging when syslogd closes | |
217 | * /dev/console | |
218 | */ | |
219 | if ((devConsoleFd = open("/dev/console", O_WRONLY, 0)) < 0) { | |
220 | xf86Msg(X_WARNING, | |
221 | "xf86OpenConsole: couldn't open /dev/console (%s)\n", | |
222 | strerror(errno)); | |
223 | } | |
224 | break; | |
225 | #endif | |
226 | #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) | |
227 | case SYSCONS: | |
228 | /* as of FreeBSD 2.2.8, syscons driver does not need the #1 vt | |
229 | * switching anymore. Here we check for FreeBSD 3.1 and up. | |
230 | * Add cases for other *BSD that behave the same. | |
231 | */ | |
232 | #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | |
233 | uname(&uts); | |
234 | i = atof(uts.release) * 100; | |
235 | if (i >= 310) | |
236 | goto acquire_vt; | |
237 | #endif | |
238 | /* otherwise fall through */ | |
239 | case PCVT: | |
240 | #if !(defined(__NetBSD__) && (__NetBSD_Version__ >= 200000000)) | |
241 | /* | |
242 | * First activate the #1 VT. This is a hack to allow a server | |
243 | * to be started while another one is active. There should be | |
244 | * a better way. | |
245 | */ | |
246 | if (initialVT != 1) { | |
247 | ||
248 | if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 1) != 0) { | |
249 | xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n"); | |
250 | } | |
251 | sleep(1); | |
252 | } | |
253 | #endif | |
254 | acquire_vt: | |
255 | if (!xf86Info.ShareVTs) { | |
256 | /* | |
257 | * now get the VT | |
258 | */ | |
259 | SYSCALL(result = | |
260 | ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno)); | |
261 | if (result != 0) { | |
262 | xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n"); | |
263 | } | |
264 | SYSCALL(result = | |
265 | ioctl(xf86Info.consoleFd, VT_WAITACTIVE, | |
266 | xf86Info.vtno)); | |
267 | if (result != 0) { | |
268 | xf86Msg(X_WARNING, | |
269 | "xf86OpenConsole: VT_WAITACTIVE failed\n"); | |
270 | } | |
271 | ||
272 | signal(SIGUSR1, xf86VTRequest); | |
273 | ||
274 | vtmode.mode = VT_PROCESS; | |
275 | vtmode.relsig = SIGUSR1; | |
276 | vtmode.acqsig = SIGUSR1; | |
277 | vtmode.frsig = SIGUSR1; | |
278 | if (ioctl(xf86Info.consoleFd, VT_SETMODE, &vtmode) < 0) { | |
279 | FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed"); | |
280 | } | |
281 | #if !defined(__OpenBSD__) && !defined(USE_DEV_IO) && !defined(USE_I386_IOPL) | |
282 | if (ioctl(xf86Info.consoleFd, KDENABIO, 0) < 0) { | |
283 | FatalError("xf86OpenConsole: KDENABIO failed (%s)", | |
284 | strerror(errno)); | |
285 | } | |
286 | #endif | |
287 | if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) { | |
288 | FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed"); | |
289 | } | |
290 | } | |
291 | else { /* xf86Info.ShareVTs */ | |
292 | close(xf86Info.consoleFd); | |
293 | } | |
294 | break; | |
295 | #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ | |
296 | #ifdef WSCONS_SUPPORT | |
297 | case WSCONS: | |
298 | /* Nothing to do */ | |
299 | break; | |
300 | #endif | |
301 | } | |
302 | } | |
303 | else { | |
304 | /* serverGeneration != 1 */ | |
305 | #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) | |
306 | if (!xf86Info.ShareVTs && | |
307 | (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT)) { | |
308 | if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0) { | |
309 | xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n"); | |
310 | } | |
311 | } | |
312 | #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ | |
313 | } | |
314 | return; | |
315 | } | |
316 | ||
317 | #ifdef PCCONS_SUPPORT | |
318 | ||
319 | static int | |
320 | xf86OpenPccons() | |
321 | { | |
322 | int fd = -1; | |
323 | ||
324 | if ((fd = open(PCCONS_CONSOLE_DEV1, PCCONS_CONSOLE_MODE, 0)) | |
325 | >= 0 || (fd = open(PCCONS_CONSOLE_DEV2, PCCONS_CONSOLE_MODE, 0)) | |
326 | >= 0) { | |
327 | if (ioctl(fd, CONSOLE_X_MODE_OFF, 0) < 0) { | |
328 | FatalError("%s: CONSOLE_X_MODE_OFF failed (%s)\n%s\n%s", | |
329 | "xf86OpenPccons", | |
330 | strerror(errno), | |
331 | "Was expecting pccons driver with X support", | |
332 | CHECK_DRIVER_MSG); | |
333 | } | |
334 | xf86Info.consType = PCCONS; | |
335 | xf86Msg(X_PROBED, "Using pccons driver with X support\n"); | |
336 | } | |
337 | return fd; | |
338 | } | |
339 | ||
340 | #endif /* PCCONS_SUPPORT */ | |
341 | ||
342 | #ifdef SYSCONS_SUPPORT | |
343 | ||
344 | static int | |
345 | xf86OpenSyscons() | |
346 | { | |
347 | int fd = -1; | |
348 | vtmode_t vtmode; | |
349 | char vtname[12]; | |
350 | long syscons_version; | |
351 | MessageType from; | |
352 | ||
353 | /* Check for syscons */ | |
354 | if ((fd = open(SYSCONS_CONSOLE_DEV1, SYSCONS_CONSOLE_MODE, 0)) >= 0 | |
355 | || (fd = open(SYSCONS_CONSOLE_DEV2, SYSCONS_CONSOLE_MODE, 0)) >= 0) { | |
356 | if (ioctl(fd, VT_GETMODE, &vtmode) >= 0) { | |
357 | /* Get syscons version */ | |
358 | if (ioctl(fd, CONS_GETVERS, &syscons_version) < 0) { | |
359 | syscons_version = 0; | |
360 | } | |
361 | ||
362 | xf86Info.vtno = VTnum; | |
363 | from = X_CMDLINE; | |
364 | ||
365 | #ifdef VT_GETACTIVE | |
366 | if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0) | |
367 | initialVT = -1; | |
368 | #endif | |
369 | if (xf86Info.ShareVTs) | |
370 | xf86Info.vtno = initialVT; | |
371 | ||
372 | if (xf86Info.vtno == -1) { | |
373 | /* | |
374 | * For old syscons versions (<0x100), VT_OPENQRY returns | |
375 | * the current VT rather than the next free VT. In this | |
376 | * case, the server gets started on the current VT instead | |
377 | * of the next free VT. | |
378 | */ | |
379 | ||
380 | #if 0 | |
381 | /* check for the fixed VT_OPENQRY */ | |
382 | if (syscons_version >= 0x100) { | |
383 | #endif | |
384 | if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) { | |
385 | /* No free VTs */ | |
386 | xf86Info.vtno = -1; | |
387 | } | |
388 | #if 0 | |
389 | } | |
390 | #endif | |
391 | ||
392 | if (xf86Info.vtno == -1) { | |
393 | /* | |
394 | * All VTs are in use. If initialVT was found, use it. | |
395 | */ | |
396 | if (initialVT != -1) { | |
397 | xf86Info.vtno = initialVT; | |
398 | } | |
399 | else { | |
400 | if (syscons_version >= 0x100) { | |
401 | FatalError("%s: Cannot find a free VT", | |
402 | "xf86OpenSyscons"); | |
403 | } | |
404 | /* Should no longer reach here */ | |
405 | FatalError("%s: %s %s\n\t%s %s", | |
406 | "xf86OpenSyscons", | |
407 | "syscons versions prior to 1.0 require", | |
408 | "either the", | |
409 | "server's stdin be a VT", | |
410 | "or the use of the vtxx server option"); | |
411 | } | |
412 | } | |
413 | from = X_PROBED; | |
414 | } | |
415 | ||
416 | close(fd); | |
417 | snprintf(vtname, sizeof(vtname), "/dev/ttyv%01x", | |
418 | xf86Info.vtno - 1); | |
419 | if ((fd = open(vtname, SYSCONS_CONSOLE_MODE, 0)) < 0) { | |
420 | FatalError("xf86OpenSyscons: Cannot open %s (%s)", | |
421 | vtname, strerror(errno)); | |
422 | } | |
423 | if (ioctl(fd, VT_GETMODE, &vtmode) < 0) { | |
424 | FatalError("xf86OpenSyscons: VT_GETMODE failed"); | |
425 | } | |
426 | xf86Info.consType = SYSCONS; | |
427 | xf86Msg(X_PROBED, "Using syscons driver with X support"); | |
428 | if (syscons_version >= 0x100) { | |
429 | xf86ErrorF(" (version %ld.%ld)\n", syscons_version >> 8, | |
430 | syscons_version & 0xFF); | |
431 | } | |
432 | else { | |
433 | xf86ErrorF(" (version 0.x)\n"); | |
434 | } | |
435 | xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno); | |
436 | } | |
437 | else { | |
438 | /* VT_GETMODE failed, probably not syscons */ | |
439 | close(fd); | |
440 | fd = -1; | |
441 | } | |
442 | } | |
443 | return fd; | |
444 | } | |
445 | ||
446 | #endif /* SYSCONS_SUPPORT */ | |
447 | ||
448 | #ifdef PCVT_SUPPORT | |
449 | ||
450 | static int | |
451 | xf86OpenPcvt() | |
452 | { | |
453 | /* This looks much like syscons, since pcvt is API compatible */ | |
454 | int fd = -1; | |
455 | vtmode_t vtmode; | |
456 | char vtname[12], *vtprefix; | |
457 | struct pcvtid pcvt_version; | |
458 | ||
459 | #ifndef __OpenBSD__ | |
460 | vtprefix = "/dev/ttyv"; | |
461 | #else | |
462 | vtprefix = "/dev/ttyC"; | |
463 | #endif | |
464 | ||
465 | fd = open(PCVT_CONSOLE_DEV, PCVT_CONSOLE_MODE, 0); | |
466 | #ifdef WSCONS_PCVT_COMPAT_CONSOLE_DEV | |
467 | if (fd < 0) { | |
468 | fd = open(WSCONS_PCVT_COMPAT_CONSOLE_DEV, PCVT_CONSOLE_MODE, 0); | |
469 | vtprefix = "/dev/ttyE"; | |
470 | } | |
471 | #endif | |
472 | if (fd >= 0) { | |
473 | if (ioctl(fd, VGAPCVTID, &pcvt_version) >= 0) { | |
474 | if (ioctl(fd, VT_GETMODE, &vtmode) < 0) { | |
475 | FatalError("%s: VT_GETMODE failed\n%s%s\n%s", | |
476 | "xf86OpenPcvt", | |
477 | "Found pcvt driver but X11 seems to be", | |
478 | " not supported.", CHECK_DRIVER_MSG); | |
479 | } | |
480 | ||
481 | xf86Info.vtno = VTnum; | |
482 | ||
483 | if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0) | |
484 | initialVT = -1; | |
485 | ||
486 | if (xf86Info.vtno == -1) { | |
487 | if (ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) { | |
488 | /* No free VTs */ | |
489 | xf86Info.vtno = -1; | |
490 | } | |
491 | ||
492 | if (xf86Info.vtno == -1) { | |
493 | /* | |
494 | * All VTs are in use. If initialVT was found, use it. | |
495 | */ | |
496 | if (initialVT != -1) { | |
497 | xf86Info.vtno = initialVT; | |
498 | } | |
499 | else { | |
500 | FatalError("%s: Cannot find a free VT", "xf86OpenPcvt"); | |
501 | } | |
502 | } | |
503 | } | |
504 | ||
505 | close(fd); | |
506 | snprintf(vtname, sizeof(vtname), "%s%01x", vtprefix, | |
507 | xf86Info.vtno - 1); | |
508 | if ((fd = open(vtname, PCVT_CONSOLE_MODE, 0)) < 0) { | |
509 | ErrorF("xf86OpenPcvt: Cannot open %s (%s)", | |
510 | vtname, strerror(errno)); | |
511 | xf86Info.vtno = initialVT; | |
512 | snprintf(vtname, sizeof(vtname), "%s%01x", vtprefix, | |
513 | xf86Info.vtno - 1); | |
514 | if ((fd = open(vtname, PCVT_CONSOLE_MODE, 0)) < 0) { | |
515 | FatalError("xf86OpenPcvt: Cannot open %s (%s)", | |
516 | vtname, strerror(errno)); | |
517 | } | |
518 | } | |
519 | if (ioctl(fd, VT_GETMODE, &vtmode) < 0) { | |
520 | FatalError("xf86OpenPcvt: VT_GETMODE failed"); | |
521 | } | |
522 | xf86Info.consType = PCVT; | |
523 | #ifdef WSCONS_SUPPORT | |
524 | xf86Msg(X_PROBED, | |
525 | "Using wscons driver on %s in pcvt compatibility mode " | |
526 | "(version %d.%d)\n", vtname, | |
527 | pcvt_version.rmajor, pcvt_version.rminor); | |
528 | #else | |
529 | xf86Msg(X_PROBED, "Using pcvt driver (version %d.%d)\n", | |
530 | pcvt_version.rmajor, pcvt_version.rminor); | |
531 | #endif | |
532 | } | |
533 | else { | |
534 | /* Not pcvt */ | |
535 | close(fd); | |
536 | fd = -1; | |
537 | } | |
538 | } | |
539 | return fd; | |
540 | } | |
541 | ||
542 | #endif /* PCVT_SUPPORT */ | |
543 | ||
544 | #ifdef WSCONS_SUPPORT | |
545 | ||
546 | static int | |
547 | xf86OpenWScons() | |
548 | { | |
549 | int fd = -1; | |
550 | int mode = WSDISPLAYIO_MODE_MAPPED; | |
551 | int i; | |
552 | char ttyname[16]; | |
553 | ||
554 | /* XXX Is this ok? */ | |
555 | for (i = 0; i < 8; i++) { | |
556 | #if defined(__NetBSD__) | |
557 | snprintf(ttyname, sizeof(ttyname), "/dev/ttyE%d", i); | |
558 | #elif defined(__OpenBSD__) | |
559 | snprintf(ttyname, sizeof(ttyname), "/dev/ttyC%x", i); | |
560 | #endif | |
561 | if ((fd = open(ttyname, 2)) != -1) | |
562 | break; | |
563 | } | |
564 | if (fd != -1) { | |
565 | if (ioctl(fd, WSDISPLAYIO_SMODE, &mode) < 0) { | |
566 | FatalError("%s: WSDISPLAYIO_MODE_MAPPED failed (%s)\n%s", | |
567 | "xf86OpenConsole", strerror(errno), CHECK_DRIVER_MSG); | |
568 | } | |
569 | xf86Info.consType = WSCONS; | |
570 | xf86Msg(X_PROBED, "Using wscons driver\n"); | |
571 | } | |
572 | return fd; | |
573 | } | |
574 | ||
575 | #endif /* WSCONS_SUPPORT */ | |
576 | ||
577 | void | |
578 | xf86CloseConsole() | |
579 | { | |
580 | #if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) | |
581 | struct vt_mode VT; | |
582 | #endif | |
583 | ||
584 | if (xf86Info.ShareVTs) | |
585 | return; | |
586 | ||
587 | switch (xf86Info.consType) { | |
588 | #ifdef PCCONS_SUPPORT | |
589 | case PCCONS: | |
590 | ioctl(xf86Info.consoleFd, CONSOLE_X_MODE_OFF, 0); | |
591 | break; | |
592 | #endif /* PCCONS_SUPPORT */ | |
593 | #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) | |
594 | case SYSCONS: | |
595 | case PCVT: | |
596 | ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT); /* Back to text mode */ | |
597 | if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1) { | |
598 | VT.mode = VT_AUTO; | |
599 | ioctl(xf86Info.consoleFd, VT_SETMODE, &VT); /* dflt vt handling */ | |
600 | } | |
601 | #if !defined(__OpenBSD__) && !defined(USE_DEV_IO) && !defined(USE_I386_IOPL) | |
602 | if (ioctl(xf86Info.consoleFd, KDDISABIO, 0) < 0) { | |
603 | xf86FatalError("xf86CloseConsole: KDDISABIO failed (%s)", | |
604 | strerror(errno)); | |
605 | } | |
606 | #endif | |
607 | if (initialVT != -1) | |
608 | ioctl(xf86Info.consoleFd, VT_ACTIVATE, initialVT); | |
609 | break; | |
610 | #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ | |
611 | #ifdef WSCONS_SUPPORT | |
612 | case WSCONS: | |
613 | { | |
614 | int mode = WSDISPLAYIO_MODE_EMUL; | |
615 | ||
616 | ioctl(xf86Info.consoleFd, WSDISPLAYIO_SMODE, &mode); | |
617 | break; | |
618 | } | |
619 | #endif | |
620 | } | |
621 | ||
622 | close(xf86Info.consoleFd); | |
623 | #ifdef PCCONS_SUPPORT | |
624 | if (devConsoleFd >= 0) | |
625 | close(devConsoleFd); | |
626 | #endif | |
627 | return; | |
628 | } | |
629 | ||
630 | int | |
631 | xf86ProcessArgument(int argc, char *argv[], int i) | |
632 | { | |
633 | /* | |
634 | * Keep server from detaching from controlling tty. This is useful | |
635 | * when debugging (so the server can receive keyboard signals. | |
636 | */ | |
637 | if (!strcmp(argv[i], "-keeptty")) { | |
638 | KeepTty = TRUE; | |
639 | return 1; | |
640 | } | |
641 | #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) | |
642 | if ((argv[i][0] == 'v') && (argv[i][1] == 't')) { | |
643 | if (sscanf(argv[i], "vt%2d", &VTnum) == 0 || VTnum < 1 || VTnum > 12) { | |
644 | UseMsg(); | |
645 | VTnum = -1; | |
646 | return 0; | |
647 | } | |
648 | return 1; | |
649 | } | |
650 | #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ | |
651 | return 0; | |
652 | } | |
653 | ||
654 | void | |
655 | xf86UseMsg() | |
656 | { | |
657 | #if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT) | |
658 | ErrorF("vtXX use the specified VT number (1-12)\n"); | |
659 | #endif /* SYSCONS_SUPPORT || PCVT_SUPPORT */ | |
660 | ErrorF("-keeptty "); | |
661 | ErrorF("don't detach controlling tty (for debugging only)\n"); | |
662 | return; | |
663 | } |