File:
[DragonFly] /
src /
sys /
dev /
video /
pcvt /
i386 /
Attic /
pcvt_drv.c
Revision
1.10:
download - view:
text,
annotated -
select for diffs
Wed May 19 22:52:54 2004 UTC (9 years, 1 month ago) by
dillon
Branches:
MAIN
CVS tags:
HEAD,
DragonFly_Snap13Sep2004,
DragonFly_1_0_REL,
DragonFly_1_0_RC1,
DragonFly_1_0A_REL
Device layer rollup commit.
* cdevsw_add() is now required. cdevsw_add() and cdevsw_remove() may specify
a mask/match indicating the range of supported minor numbers. Multiple
cdevsw_add()'s using the same major number, but distinctly different
ranges, may be issued. All devices that failed to call cdevsw_add() before
now do.
* cdevsw_remove() now automatically marks all devices within its supported
range as being destroyed.
* vnode->v_rdev is no longer resolved when the vnode is created. Instead,
only v_udev (a newly added field) is resolved. v_rdev is resolved when
the vnode is opened and cleared on the last close.
* A great deal of code was making rather dubious assumptions with regards
to the validity of devices associated with vnodes, primarily due to
the persistence of a device structure due to being indexed by (major, minor)
instead of by (cdevsw, major, minor). In particular, if you run a program
which connects to a USB device and then you pull the USB device and plug
it back in, the vnode subsystem will continue to believe that the device
is open when, in fact, it isn't (because it was destroyed and recreated).
In particular, note that all the VFS mount procedures now check devices
via v_udev instead of v_rdev prior to calling VOP_OPEN(), since v_rdev
is NULL prior to the first open.
* The disk layer's device interaction has been rewritten. The disk layer
(i.e. the slice and disklabel management layer) no longer overloads
its data onto the device structure representing the underlying physical
disk. Instead, the disk layer uses the new cdevsw_add() functionality
to register its own cdevsw using the underlying device's major number,
and simply does NOT register the underlying device's cdevsw. No
confusion is created because the device hash is now based on
(cdevsw,major,minor) rather then (major,minor).
NOTE: This also means that underlying raw disk devices may use the entire
device minor number instead of having to reserve the bits used by the disk
layer, and also means that can we (theoretically) stack a fully
disklabel-supported 'disk' on top of any block device.
* The new reference counting scheme prevents this by associating a device
with a cdevsw and disconnecting the device from its cdevsw when the cdevsw
is removed. Additionally, all udev2dev() lookups run through the cdevsw
mask/match and only successfully find devices still associated with an
active cdevsw.
* Major work on MFS: MFS no longer shortcuts vnode and device creation. It
now creates a real vnode and a real device and implements real open and
close VOPs. Additionally, due to the disk layer changes, MFS is no longer
limited to 255 mounts. The new limit is 16 million. Since MFS creates a
real device node, mount_mfs will now create a real /dev/mfs<PID> device
that can be read from userland (e.g. so you can dump an MFS filesystem).
* BUF AND DEVICE STRATEGY changes. The struct buf contains a b_dev field.
In order to properly handle stacked devices we now require that the b_dev
field be initialized before the device strategy routine is called. This
required some additional work in various VFS implementations. To enforce
this requirement, biodone() now sets b_dev to NODEV. The new disk layer
will adjust b_dev before forwarding a request to the actual physical
device.
* A bug in the ISO CD boot sequence which resulted in a panic has been fixed.
Testing by: lots of people, but David Rhodus found the most aggregious bugs.
1: /*
2: * Copyright (c) 1999 Hellmuth Michaelis
3: *
4: * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
5: *
6: * Copyright (c) 1992, 1993 Brian Dunford-Shore and Scott Turner.
7: *
8: * Copyright (c) 1993 Charles Hannum.
9: *
10: * All rights reserved.
11: *
12: * Parts of this code regarding the NetBSD interface were written
13: * by Charles Hannum.
14: *
15: * This code is derived from software contributed to Berkeley by
16: * William Jolitz and Don Ahn.
17: *
18: * Redistribution and use in source and binary forms, with or without
19: * modification, are permitted provided that the following conditions
20: * are met:
21: * 1. Redistributions of source code must retain the above copyright
22: * notice, this list of conditions and the following disclaimer.
23: * 2. Redistributions in binary form must reproduce the above copyright
24: * notice, this list of conditions and the following disclaimer in the
25: * documentation and/or other materials provided with the distribution.
26: * 3. All advertising materials mentioning features or use of this software
27: * must display the following acknowledgement:
28: * This product includes software developed by
29: * Hellmuth Michaelis, Brian Dunford-Shore, Joerg Wunsch, Scott Turner
30: * and Charles Hannum.
31: * 4. The name authors may not be used to endorse or promote products
32: * derived from this software without specific prior written permission.
33: *
34: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
35: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
37: * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
38: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
39: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
40: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
41: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44: */
45:
46: /*---------------------------------------------------------------------------*
47: *
48: * pcvt_drv.c VT220 Driver Main Module / OS - Interface
49: * ---------------------------------------------------------
50: *
51: * Last Edit-Date: [Mon Dec 27 14:03:36 1999]
52: *
53: * $FreeBSD: src/sys/i386/isa/pcvt/pcvt_drv.c,v 1.63.2.1 2001/02/26 04:23:13 jlemon Exp $
54: * $DragonFly: src/sys/dev/video/pcvt/i386/pcvt_drv.c,v 1.10 2004/05/19 22:52:54 dillon Exp $
55: *
56: *---------------------------------------------------------------------------*/
57:
58: #include "use_vt.h"
59: #if NVT > 0
60:
61: #define EXTERN /* allocate mem */
62:
63: #include "pcvt_hdr.h" /* global include */
64:
65: #if PCVT_FREEBSD >= 200
66: #include <sys/bus.h>
67: #include <machine/stdarg.h>
68: #else
69: #include "machine/stdarg.h"
70: #endif
71:
72: extern int getchar (void);
73:
74: #if PCVT_NETBSD
75: extern u_short *Crtat;
76: #endif /* PCVT_NETBSD */
77:
78: static void vgapelinit(void); /* read initial VGA DAC palette */
79:
80: #if defined XSERVER && !PCVT_USL_VT_COMPAT
81: static int pcvt_xmode_set(int on, struct thread *td); /* initialize for X mode */
82: #endif /* XSERVER && !PCVT_USL_VT_COMPAT */
83:
84: #ifdef _DEV_KBD_KBDREG_H_
85: static void detect_kbd(void *arg);
86: static kbd_callback_func_t pcevent;
87: #endif
88:
89: static cn_probe_t pccnprobe;
90: static cn_init_t pccninit;
91: static cn_term_t pccnterm;
92: static cn_getc_t pccngetc;
93: static cn_checkc_t pccncheckc;
94: static cn_putc_t pccnputc;
95:
96: CONS_DRIVER(pc, pccnprobe, pccninit, pccnterm, pccngetc, pccncheckc, pccnputc,
97: NULL);
98:
99: static d_open_t pcopen;
100: static d_close_t pcclose;
101: static d_ioctl_t pcioctl;
102: static d_mmap_t pcmmap;
103:
104: #define CDEV_MAJOR 12
105: struct cdevsw pc_cdevsw = {
106: /* name */ "vt",
107: /* maj */ CDEV_MAJOR,
108: /* flags */ D_TTY | D_KQFILTER,
109: /* port */ NULL,
110: /* clone */ NULL,
111:
112: /* open */ pcopen,
113: /* close */ pcclose,
114: /* read */ ttyread,
115: /* write */ ttywrite,
116: /* ioctl */ pcioctl,
117: /* poll */ ttypoll,
118: /* mmap */ pcmmap,
119: /* strategy */ nostrategy,
120: /* dump */ nodump,
121: /* psize */ nopsize,
122: /* kqfilter */ ttykqfilter
123: };
124:
125: #if PCVT_NETBSD > 100 /* NetBSD-current Feb 20 1995 */
126: int
127: pcprobe(struct device *parent, void *match, void *aux)
128: #else
129: #if PCVT_NETBSD > 9
130: int
131: pcprobe(struct device *parent, struct device *self, void *aux)
132: #else
133: int
134: pcprobe(struct isa_device *dev)
135: #endif /* PCVT_NETBSD > 9 */
136: #endif /* PCVT_NETBSD > 100 */
137: {
138: #ifdef _DEV_KBD_KBDREG_H_
139: int i;
140:
141: if (kbd == NULL) {
142: reset_keyboard = 0;
143: kbd_configure(KB_CONF_PROBE_ONLY);
144: i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)dev->id_unit);
145: if ((i < 0) || ((kbd = kbd_get_keyboard(i)) == NULL))
146: return (-1);
147: }
148: reset_keyboard = 1; /* it's now safe to do kbd reset */
149: #endif /* _DEV_KBD_KBDREG_H_ */
150:
151: kbd_code_init();
152:
153: #if PCVT_NETBSD > 9
154: ((struct isa_attach_args *)aux)->ia_iosize = 16;
155: return 1;
156: #else
157: #ifdef _DEV_KBD_KBDREG_H_
158: return (-1);
159: #elif PCVT_NETBSD || PCVT_FREEBSD
160: return (16);
161: #else
162: return 1;
163: #endif /* PCVT_NETBSD || PCVT_FREEBSD */
164: #endif /* PCVT_NETBSD > 9 */
165:
166: }
167:
168: #if PCVT_NETBSD > 9
169: void
170: pcattach(struct device *parent, struct device *self, void *aux)
171: {
172: struct isa_attach_args *ia = aux;
173: static struct intrhand vthand;
174: #else
175: int
176: pcattach(struct isa_device *dev)
177: {
178: #endif /* PCVT_NETBSD > 9 */
179:
180: int i;
181:
182: vt_coldmalloc(); /* allocate memory for screens */
183:
184: #ifdef _DEV_KBD_KBDREG_H_
185: if (kbd == NULL)
186: timeout(detect_kbd, (void *)dev->id_unit, hz*2);
187: #endif /* _DEV_KBD_KBDREG_H_ */
188:
189: #if PCVT_NETBSD || PCVT_FREEBSD
190:
191: #if PCVT_NETBSD > 9
192: printf(": ");
193: #else
194: printf("vt%d: ", dev->id_unit);
195: #endif /* PCVT_NETBSD > 9 */
196:
197: switch(adaptor_type)
198: {
199: case MDA_ADAPTOR:
200: printf("mda");
201: break;
202:
203: case CGA_ADAPTOR:
204: printf("cga");
205: break;
206:
207: case EGA_ADAPTOR:
208: printf("ega");
209: break;
210:
211: case VGA_ADAPTOR:
212: printf("%s, ", (char *)vga_string(vga_type));
213: if(can_do_132col)
214: printf("80/132 col");
215: else
216: printf("80 col");
217: vgapelinit();
218: break;
219:
220: default:
221: printf("unknown");
222: break;
223: }
224:
225: if(color == 0)
226: printf(", mono");
227: else
228: printf(", color");
229:
230: printf(", %d scr, ", totalscreens);
231:
232: switch(keyboard_type)
233: {
234: case KB_AT:
235: printf("at-");
236: break;
237:
238: case KB_MFII:
239: printf("mf2-");
240: break;
241:
242: default:
243: printf("unknown ");
244: break;
245: }
246:
247: printf("kbd, [R%s]\n", PCVT_REL);
248:
249: #if PCVT_NETBSD || (PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
250:
251: for(i = 0; i < totalscreens; i++)
252: {
253:
254: #if PCVT_NETBSD
255: pc_tty[i] = ttymalloc();
256: vs[i].vs_tty = pc_tty[i];
257: #else /* !PCVT_NETBSD */
258: pccons[i] = ttymalloc(pccons[i]);
259: vs[i].vs_tty = pccons[i];
260: #endif /* PCVT_NETBSD */
261:
262: }
263:
264: #if PCVT_EMU_MOUSE
265: #if PCVT_NETBSD
266: pc_tty[totalscreens] = ttymalloc(); /* the mouse emulator tty */
267: #else /* !PCVT_NETBSD */
268: /* the mouse emulator tty */
269: pc_tty[totalscreens] = ttymalloc(pccons[totalscreens]);
270: #endif /* PCVT_NETBSD */
271: #endif /* PCVT_EMU_MOUSE */
272:
273: #if PCVT_NETBSD
274: pcconsp = pc_tty[0];
275: #else /* !PCVT_NETBSD */
276: pcconsp = pccons[0];
277: #endif /* PCVT_NETBSD */
278:
279: #endif /* #if PCVT_NETBSD || (PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
280:
281: #else /* !PCVT_NETBSD && !PCVT_FREEBSD*/
282:
283: switch(adaptor_type)
284: {
285: case MDA_ADAPTOR:
286: printf(" <mda");
287: break;
288:
289: case CGA_ADAPTOR:
290: printf(" <cga");
291: break;
292:
293: case EGA_ADAPTOR:
294: printf(" <ega");
295: break;
296:
297: case VGA_ADAPTOR:
298: printf(" <%s,", (char *)vga_string(vga_type));
299: if(can_do_132col)
300: printf("80/132 col");
301: else
302: printf("80 col");
303: vgapelinit();
304: break;
305:
306: default:
307: printf(" <unknown");
308: break;
309: }
310:
311: if(color == 0)
312: printf(",mono");
313: else
314: printf(",color");
315:
316: printf(",%d scr,", totalscreens);
317:
318: switch(keyboard_type)
319: {
320: case KB_AT:
321: printf("at-");
322: break;
323:
324: case KB_MFII:
325: printf("mf2-");
326: break;
327:
328: default:
329: printf("unknown ");
330: break;
331: }
332:
333: printf("kbd,[R%s]>", PCVT_REL);
334:
335: #endif /* PCVT_NETBSD || PCVT_FREEBSD */
336:
337: #if !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
338: cdevsw_add(&pc_cdevsw, 0, 0);
339: for(i = 0; i < totalscreens; i++)
340: {
341: ttyregister(&pccons[i]);
342: vs[i].vs_tty = &pccons[i];
343: make_dev(&pc_cdevsw, i, UID_ROOT, GID_WHEEL, 0600, "ttyv%r", i);
344: }
345: #endif /* !PCVT_NETBSD && !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
346:
347: async_update(UPDATE_START); /* start asynchronous updates */
348:
349: #if PCVT_NETBSD > 9
350:
351: vthand.ih_fun = pcrint;
352: vthand.ih_arg = 0;
353: vthand.ih_level = IPL_TTY;
354:
355: #if (PCVT_NETBSD > 100) && defined(IST_EDGE)
356: intr_establish(ia->ia_irq, IST_EDGE, &vthand);
357: #else /* PCVT_NETBSD > 100 */
358: intr_establish(ia->ia_irq, &vthand);
359: #endif /* PCVT_NETBSD > 100 */
360:
361: #else /* PCVT_NETBSD > 9 */
362:
363: dev->id_ointr = pcrint;
364:
365: return 1;
366:
367: #endif /* PCVT_NETBSD > 9 */
368:
369: }
370:
371: /* had a look at the friedl driver */
372:
373: #if !PCVT_NETBSD
374:
375: struct tty *
376: get_pccons(Dev_t dev)
377: {
378: int i = minor(dev);
379:
380: #if PCVT_EMU_MOUSE
381: if(i == totalscreens)
382: #if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
383: return(&pccons[i]);
384: #else
385: return(pccons[i]);
386: #endif /* !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
387: #endif /* PCVT_EMU_MOUSE */
388:
389: if(i >= PCVT_NSCREENS)
390: return(NULL);
391: #if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
392: return(&pccons[i]);
393: #else
394: return(pccons[i]);
395: #endif
396: }
397:
398: #else
399:
400: struct tty *
401: get_pccons(Dev_t dev)
402: {
403: int i = minor(dev);
404:
405: #if PCVT_EMU_MOUSE
406: if(i == totalscreens)
407: return(pc_tty[i]);
408: #endif /* PCVT_EMU_MOUSE */
409:
410: if(i >= PCVT_NSCREENS)
411: return(NULL);
412: return(pc_tty[i]);
413: }
414:
415: #endif /* !PCVT_NETBSD */
416:
417: /*---------------------------------------------------------------------------*
418: * /dev/ttyc0, /dev/ttyc1, etc.
419: *---------------------------------------------------------------------------*/
420: int
421: pcopen(Dev_t dev, int flag, int mode, struct thread *td)
422: {
423: struct tty *tp;
424: struct video_state *vsx;
425: int s, retval;
426: int winsz = 0;
427: int i = minor(dev);
428:
429: #if PCVT_EMU_MOUSE
430: if(i == totalscreens)
431: vsx = 0;
432: else
433: #endif /* PCVT_EMU_MOUSE */
434:
435: vsx = &vs[i];
436:
437: if((tp = get_pccons(dev)) == NULL)
438: return ENXIO;
439:
440: dev->si_tty = tp;
441:
442: #if PCVT_EMU_MOUSE
443: if(i == totalscreens)
444: {
445: if(mouse.opened == 0)
446: mouse.buttons = mouse.extendedseen =
447: mouse.breakseen = mouse.lastmove.tv_sec = 0;
448: mouse.minor = i;
449: mouse.opened++;
450: }
451: else
452: #endif /* PCVT_EMU_MOUSE */
453:
454: vsx->openf++;
455:
456: tp->t_oproc = pcstart;
457: tp->t_param = pcparam;
458: tp->t_stop = nottystop;
459: tp->t_dev = dev;
460:
461: if ((tp->t_state & TS_ISOPEN) == 0)
462: {
463:
464: #ifdef TS_WOPEN /* not (FreeBSD-1.1.5 or FreeBSD some time after 2.0.5) */
465: tp->t_state |= TS_WOPEN;
466: #endif
467:
468: ttychars(tp);
469: tp->t_iflag = TTYDEF_IFLAG;
470: tp->t_oflag = TTYDEF_OFLAG;
471: tp->t_cflag = TTYDEF_CFLAG;
472: tp->t_lflag = TTYDEF_LFLAG;
473: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
474: pcparam(tp, &tp->t_termios);
475: (*linesw[tp->t_line].l_modem)(tp, 1); /* fake connection */
476: winsz = 1; /* set winsize later */
477: }
478: else if (tp->t_state & TS_XCLUDE && suser(td))
479: return (EBUSY);
480:
481: #if PCVT_NETBSD || (PCVT_FREEBSD >= 200)
482: retval = ((*linesw[tp->t_line].l_open)(dev, tp));
483: #else
484: retval = ((*linesw[tp->t_line].l_open)(dev, tp, flag));
485: #endif /* PCVT_NETBSD || (PCVT_FREEBSD >= 200) */
486:
487: if(winsz == 1)
488: {
489:
490: /*
491: * The line discipline has clobbered t_winsize if TS_ISOPEN
492: * was clear. (NetBSD PR #400 from Bill Sommerfeld)
493: * We have to do this after calling the open routine, because
494: * it does some other things in other/older *BSD releases -hm
495: */
496:
497: s = spltty();
498:
499: tp->t_winsize.ws_col = vsx->maxcol;
500: tp->t_winsize.ws_row = vsx->screen_rows;
501: tp->t_winsize.ws_xpixel = (vsx->maxcol == 80)? 720: 1056;
502: tp->t_winsize.ws_ypixel = 400;
503:
504: splx(s);
505: }
506:
507: return(retval);
508: }
509:
510: int
511: pcclose(Dev_t dev, int flag, int mode, struct thread *td)
512: {
513: struct tty *tp;
514: struct video_state *vsx;
515: int i = minor(dev);
516:
517: #if PCVT_EMU_MOUSE
518: if(i == totalscreens)
519: vsx = 0;
520: else
521: #endif /* PCVT_EMU_MOUSE */
522:
523: vsx = &vs[i];
524:
525: if((tp = get_pccons(dev)) == NULL)
526: return ENXIO;
527:
528: (*linesw[tp->t_line].l_close)(tp, flag);
529: ttyclose(tp);
530:
531: #if PCVT_EMU_MOUSE
532: if(i == totalscreens)
533: mouse.opened = 0;
534: else
535: #endif /* PCVT_EMU_MOUSE */
536:
537: vsx->openf = 0;
538:
539: #if PCVT_USL_VT_COMPAT
540: #if PCVT_EMU_MOUSE
541:
542: if(i == totalscreens)
543: return (0);
544:
545: #endif /* PCVT_EMU_MOUSE */
546:
547: reset_usl_modes(vsx);
548:
549: #endif /* PCVT_USL_VT_COMPAT */
550:
551: return(0);
552: }
553:
554: int
555: pcioctl(Dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
556: {
557: int error;
558: struct tty *tp;
559:
560: if((tp = get_pccons(dev)) == NULL)
561: return(ENXIO);
562:
563: /* note that some ioctl's are global, e.g. KBSTPMAT: There is
564: * only one keyboard and different repeat rates for instance between
565: * sessions are a suspicious wish. If you really need this make the
566: * appropriate variables arrays
567: */
568:
569: #if PCVT_EMU_MOUSE
570: if(minor(dev) == totalscreens)
571: {
572: if((error = mouse_ioctl(dev, cmd, data)) >= 0)
573: return error;
574: goto do_standard;
575: }
576: #endif /* PCVT_EMU_MOUSE */
577:
578: #ifdef XSERVER
579: #if PCVT_USL_VT_COMPAT
580:
581: if((error = usl_vt_ioctl(dev, cmd, data, flag, td->td_proc)) >= 0)
582: return error;
583:
584: /*
585: * just for compatibility:
586: * XFree86 < 2.0 and SuperProbe still might use it
587: *
588: * NB: THIS IS A HACK! Do not use it unless you explicitly need.
589: * Especially, since the vty is not put into process-controlled
590: * mode (this would require the application to co-operate), any
591: * attempts to switch vtys while this kind of X mode is active
592: * may cause serious trouble.
593: */
594: switch(cmd)
595: {
596: case CONSOLE_X_MODE_ON:
597: {
598: int i;
599:
600: if((error = usl_vt_ioctl(dev, KDENABIO, 0, flag, td->td_proc)) > 0)
601: return error;
602:
603: i = KD_GRAPHICS;
604: if((error = usl_vt_ioctl(dev, KDSETMODE, (caddr_t)&i, flag, td->td_proc))
605: > 0)
606: return error;
607:
608: i = K_RAW;
609: error = usl_vt_ioctl(dev, KDSKBMODE, (caddr_t)&i, flag, td->td_proc);
610: return error;
611: }
612:
613: case CONSOLE_X_MODE_OFF:
614: {
615: int i;
616:
617: (void)usl_vt_ioctl(dev, KDDISABIO, 0, flag, td->td_proc);
618:
619: i = KD_TEXT;
620: (void)usl_vt_ioctl(dev, KDSETMODE, (caddr_t)&i, flag, td->td_proc);
621:
622: i = K_XLATE;
623: (void)usl_vt_ioctl(dev, KDSKBMODE, (caddr_t)&i, flag, td->td_proc);
624: return 0;
625: }
626:
627:
628: case CONSOLE_X_BELL:
629:
630: /*
631: * If `data' is non-null, the first int value denotes
632: * the pitch, the second a duration. Otherwise, behaves
633: * like BEL.
634: */
635:
636: if (data)
637: {
638:
639: #if PCVT_NETBSD
640: sysbeep(((int *)data)[0],
641: ((int *)data)[1] * hz / 1000);
642: #else /* PCVT_NETBSD */
643: sysbeep(PCVT_SYSBEEPF / ((int *)data)[0],
644: ((int *)data)[1] * hz / 3000);
645: #endif /* PCVT_NETBSD */
646:
647: }
648: else
649: {
650: sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
651: }
652: return (0);
653:
654: default: /* fall through */ ;
655: }
656:
657: #else /* PCVT_USL_VT_COMPAT */
658:
659: switch(cmd)
660: {
661: case CONSOLE_X_MODE_ON:
662: return pcvt_xmode_set(1, td->td_proc);
663:
664: case CONSOLE_X_MODE_OFF:
665: return pcvt_xmode_set(0, td->td_proc);
666:
667: case CONSOLE_X_BELL:
668:
669: /*
670: * If `data' is non-null, the first int value denotes
671: * the pitch, the second a duration. Otherwise, behaves
672: * like BEL.
673: */
674:
675: if (data)
676: {
677:
678: #if PCVT_NETBSD
679: sysbeep(((int *)data)[0],
680: ((int *)data)[1] * hz / 1000);
681: #else /* PCVT_NETBSD */
682: sysbeep(PCVT_SYSBEEPF / ((int *)data)[0],
683: ((int *)data)[1] * hz / 3000);
684: #endif /* PCVT_NETBSD */
685:
686: }
687: else
688: {
689: sysbeep(PCVT_SYSBEEPF / 1493, hz / 4);
690: }
691: return (0);
692:
693: default: /* fall through */ ;
694: }
695:
696: #endif /* PCVT_USL_VT_COMPAT */
697: #endif /* XSERVER */
698:
699: if((error = kbdioctl(dev,cmd,data,flag)) >= 0)
700: return error;
701:
702: if((error = vgaioctl(dev,cmd,data,flag)) >= 0)
703: return error;
704:
705: #if PCVT_EMU_MOUSE
706: do_standard:
707: #endif
708:
709: #if PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200
710: if((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td))
711: != ENOIOCTL)
712: return (error);
713: #else
714: if((error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag)) >= 0)
715: return(error);
716: #endif /* PCVT_NETBSD > 9 || PCVT_FREEBSD >= 200 */
717:
718: #if PCVT_NETBSD > 9
719: if((error = ttioctl(tp, cmd, data, flag, td)) >= 0)
720: return (error);
721: #else
722: if((error = ttioctl(tp, cmd, data, flag)) != ENOIOCTL)
723: return (error);
724: #endif /* PCVT_NETBSD > 9 */
725:
726: return (ENOTTY);
727: }
728:
729: int
730: pcmmap(Dev_t dev, vm_offset_t offset, int nprot)
731: {
732: if (offset > 0x20000 - PAGE_SIZE)
733: return -1;
734: return i386_btop((0xa0000 + offset));
735: }
736:
737: /*---------------------------------------------------------------------------*
738: *
739: * handle a keyboard receive interrupt
740: *
741: * NOTE: the keyboard is multiplexed by means of "pcconsp"
742: * between virtual screens. pcconsp - switching is done in
743: * the vgapage() routine
744: *
745: *---------------------------------------------------------------------------*/
746:
747: #if PCVT_KBD_FIFO
748:
749: u_char pcvt_kbd_fifo[PCVT_KBD_FIFO_SZ];
750: static int pcvt_kbd_wptr = 0;
751: int pcvt_kbd_rptr = 0;
752: short pcvt_kbd_count= 0;
753: static u_char pcvt_timeout_scheduled = 0;
754:
755: static void
756: pcvt_timeout(void *arg)
757: {
758: u_char *cp;
759:
760: #if PCVT_SLOW_INTERRUPT
761: int s;
762: #endif
763:
764: pcvt_timeout_scheduled = 0;
765:
766: #if PCVT_SCREENSAVER
767: pcvt_scrnsv_reset();
768: #endif /* PCVT_SCREENSAVER */
769:
770: while (pcvt_kbd_count)
771: {
772: if (((cp = sgetc(1)) != 0) &&
773: (vs[current_video_screen].openf))
774: {
775:
776: #if PCVT_NULLCHARS
777: if(*cp == '\0')
778: {
779: /* pass a NULL character */
780: (*linesw[pcconsp->t_line].l_rint)('\0', pcconsp);
781: }
782: /* XXX */ else
783: #endif /* PCVT_NULLCHARS */
784:
785: while (*cp)
786: (*linesw[pcconsp->t_line].l_rint)(*cp++ & 0xff, pcconsp);
787: }
788:
789: PCVT_DISABLE_INTR ();
790:
791: if (!pcvt_kbd_count)
792: pcvt_timeout_scheduled = 0;
793:
794: PCVT_ENABLE_INTR ();
795: }
796:
797: return;
798: }
799: #endif
800:
801: #ifdef _DEV_KBD_KBDREG_H_
802: static void
803: detect_kbd(void *arg)
804: {
805: int unit = (int)arg;
806: int i;
807:
808: if (kbd != NULL)
809: return;
810: i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)unit);
811: if (i >= 0)
812: kbd = kbd_get_keyboard(i);
813: if (kbd != NULL)
814: {
815: reset_keyboard = 1; /* ok to reset the keyboard */
816: kbd_code_init();
817: return;
818: }
819: reset_keyboard = 0;
820: timeout(detect_kbd, (void *)unit, hz*2);
821: }
822:
823: int
824: pcevent(keyboard_t *thiskbd, int event, void *arg)
825: {
826: int unit = (int)arg;
827:
828: if (thiskbd != kbd)
829: return EINVAL; /* shouldn't happen */
830:
831: switch (event) {
832: case KBDIO_KEYINPUT:
833: pcrint(unit);
834: return 0;
835: case KBDIO_UNLOADING:
836: reset_keyboard = 0;
837: kbd = NULL;
838: kbd_release(thiskbd, (void *)&kbd);
839: timeout(detect_kbd, (void *)unit, hz*4);
840: return 0;
841: default:
842: return EINVAL;
843: }
844: }
845: #endif /* _DEV_KBD_KBDREG_H_ */
846:
847: void
848: pcrint(int unit)
849: {
850:
851: #if PCVT_KBD_FIFO
852: u_char dt;
853: u_char ret = -1;
854:
855: # if PCVT_SLOW_INTERRUPT
856: int s;
857: # endif
858:
859: # ifdef _DEV_KBD_KBDREG_H_
860: int c;
861: # endif
862:
863: #else /* !PCVT_KBD_FIFO */
864: u_char *cp;
865: #endif /* PCVT_KBD_FIFO */
866:
867: #if PCVT_SCREENSAVER
868: pcvt_scrnsv_reset();
869: #endif /* PCVT_SCREENSAVER */
870:
871: #if PCVT_KBD_FIFO
872: if (kbd_polling)
873: {
874: sgetc(1);
875: return;
876: }
877:
878: # ifndef _DEV_KBD_KBDREG_H_
879: while (inb(CONTROLLER_CTRL) & STATUS_OUTPBF) /* check 8042 buffer */
880: {
881: ret = 1; /* got something */
882:
883: PCVT_KBD_DELAY(); /* 7 us delay */
884:
885: dt = inb(CONTROLLER_DATA); /* get it 8042 data */
886: # else
887: while ((c = (*kbdsw[kbd->kb_index]->read)(kbd, FALSE)) != -1)
888: {
889: ret = 1; /* got something */
890: dt = c;
891: # endif /* _DEV_KBD_KBDREG_H_ */
892:
893: if (pcvt_kbd_count >= PCVT_KBD_FIFO_SZ) /* fifo overflow ? */
894: {
895: log (LOG_WARNING, "pcvt: keyboard buffer overflow\n");
896: }
897: else
898: {
899: pcvt_kbd_fifo[pcvt_kbd_wptr++] = dt; /* data -> fifo */
900:
901: PCVT_DISABLE_INTR (); /* XXX necessary ? */
902: pcvt_kbd_count++; /* update fifo count */
903: PCVT_ENABLE_INTR ();
904:
905: if (pcvt_kbd_wptr >= PCVT_KBD_FIFO_SZ)
906: pcvt_kbd_wptr = 0; /* wraparound pointer */
907: }
908: }
909:
910: if (ret == 1) /* got data from keyboard ? */
911: {
912: if (!pcvt_timeout_scheduled) /* if not already active .. */
913: {
914: PCVT_DISABLE_INTR ();
915: pcvt_timeout_scheduled = 1; /* flag active */
916: timeout(pcvt_timeout, NULL, hz / 100); /* fire off */
917: PCVT_ENABLE_INTR ();
918: }
919: }
920:
921: #else /* !PCVT_KBD_FIFO */
922:
923: if((cp = sgetc(1)) == 0)
924: return;
925:
926: if (kbd_polling)
927: return;
928:
929: if(!(vs[current_video_screen].openf)) /* XXX was vs[minor(dev)] */
930: return;
931:
932: #if PCVT_NULLCHARS
933: if(*cp == '\0')
934: {
935: /* pass a NULL character */
936: (*linesw[pcconsp->t_line].l_rint)('\0', pcconsp);
937: return;
938: }
939: #endif /* PCVT_NULLCHARS */
940:
941: while (*cp)
942: (*linesw[pcconsp->t_line].l_rint)(*cp++ & 0xff, pcconsp);
943:
944: #endif /* PCVT_KBD_FIFO */
945: }
946:
947:
948: #if PCVT_NETBSD || PCVT_FREEBSD >= 200
949:
950: void
951: pcstart(struct tty *tp)
952: {
953: struct clist *rbp;
954: int s, len;
955: u_char buf[PCVT_PCBURST];
956:
957: s = spltty();
958:
959: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
960: goto out;
961:
962: tp->t_state |= TS_BUSY;
963:
964: splx(s);
965:
966: async_update(UPDATE_KERN);
967:
968: rbp = &tp->t_outq;
969:
970: /*
971: * Call q_to_b() at spltty() to ensure that the queue is empty when
972: * the loop terminates.
973: */
974:
975: s = spltty();
976:
977: while((len = q_to_b(rbp, buf, PCVT_PCBURST)) > 0)
978: {
979: if(vs[minor(tp->t_dev)].scrolling)
980: sgetc(31337);
981:
982: /*
983: * We need to do this outside spl since it could be fairly
984: * expensive and we don't want our serial ports to overflow.
985: */
986: splx(s);
987: sput(&buf[0], 0, len, minor(tp->t_dev));
988: s = spltty();
989: }
990:
991: tp->t_state &= ~TS_BUSY;
992:
993: #ifndef TS_ASLEEP /* FreeBSD some time after 2.0.5 */
994: ttwwakeup(tp);
995: #else
996: if (rbp->c_cc <= tp->t_lowat)
997: {
998: if (tp->t_state&TS_ASLEEP)
999: {
1000: tp->t_state &= ~TS_ASLEEP;
1001: wakeup((caddr_t)rbp);
1002: }
1003: selwakeup(&tp->t_wsel);
1004: }
1005: #endif
1006: out:
1007: splx(s);
1008: }
1009:
1010: void
1011: pcstop(struct tty *tp, int flag)
1012: {
1013: }
1014:
1015: #else /* PCVT_NETBSD || PCVT_FREEBSD >= 200 */
1016:
1017: void
1018: pcstart(struct tty *tp)
1019: {
1020: int s;
1021: unsigned char c;
1022:
1023: s = spltty();
1024:
1025: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1026: {
1027: goto out;
1028: }
1029:
1030: for(;;)
1031: {
1032:
1033: #if !(PCVT_FREEBSD > 114)
1034:
1035: #if !(PCVT_FREEBSD > 111)
1036: if (RB_LEN(&tp->t_out) <= tp->t_lowat)
1037: #else
1038: if (RB_LEN(tp->t_out) <= tp->t_lowat)
1039: #endif
1040: {
1041: if (tp->t_state&TS_ASLEEP)
1042: {
1043: tp->t_state &= ~TS_ASLEEP;
1044: #if !(PCVT_FREEBSD > 111)
1045: wakeup((caddr_t)&tp->t_out);
1046: #else
1047: wakeup((caddr_t)tp->t_out);
1048: #endif
1049: }
1050:
1051: if (tp->t_wsel)
1052: {
1053: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
1054: tp->t_wsel = 0;
1055: tp->t_state &= ~TS_WCOLL;
1056: }
1057: }
1058:
1059: #else /* PCVT_FREEBSD > 114 */
1060: if (tp->t_state & (TS_SO_OCOMPLETE | TS_SO_OLOWAT)
1061: || tp->t_wsel) {
1062: ttwwakeup(tp);
1063: }
1064: #endif /* !PCVT_FREEBSD > 114 */
1065:
1066: #if !(PCVT_FREEBSD > 111)
1067: if (RB_LEN(&tp->t_out) == 0)
1068: #else
1069: if (RB_LEN(tp->t_out) == 0)
1070: #endif
1071: {
1072: goto out;
1073: }
1074:
1075: #if !(PCVT_FREEBSD > 111)
1076: c = getc(&tp->t_out);
1077: #else
1078: c = getc(tp->t_out);
1079: #endif
1080:
1081: tp->t_state |= TS_BUSY; /* patch from Frank Maclachlan */
1082: splx(s);
1083: sput(&c, 0, 1, minor(tp->t_dev));
1084: spltty();
1085: tp->t_state &= ~TS_BUSY; /* patch from Frank Maclachlan */
1086: }
1087: out:
1088: splx(s);
1089: }
1090:
1091: #endif /* PCVT_NETBSD || PCVT_FREEBSD >= 200 */
1092:
1093: /*---------------------------------------------------------------------------*
1094: * /dev/console
1095: *---------------------------------------------------------------------------*/
1096:
1097: #if !PCVT_NETBSD /* has moved to cons.c in netbsd-current */
1098: void
1099: consinit() /* init for kernel messages during boot */
1100: {
1101: }
1102: #endif /* PCVT_NETBSD */
1103:
1104: #if PCVT_FREEBSD > 205
1105: static void
1106: #else
1107: int
1108: #endif
1109: pccnprobe(struct consdev *cp)
1110: {
1111: int unit = 0;
1112: int i;
1113:
1114: /* See if this driver is disabled in probe hint. */
1115: if (resource_int_value("vt", unit, "disabled", &i) == 0 && i) {
1116: cp->cn_pri = CN_DEAD;
1117: return;
1118: }
1119:
1120: #ifdef _DEV_KBD_KBDREG_H_
1121: kbd_configure(KB_CONF_PROBE_ONLY);
1122: if (kbd_find_keyboard("*", unit) < 0)
1123: {
1124: cp->cn_pri = CN_DEAD;
1125: return;
1126: }
1127: #endif /* _DEV_KBD_KBDREG_H_ */
1128:
1129: /* initialize required fields */
1130:
1131: cp->cn_dev = make_adhoc_dev(&pc_cdevsw, 0);
1132: cp->cn_pri = CN_INTERNAL;
1133:
1134: #if !PCVT_NETBSD
1135:
1136: #if !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200)
1137: cp->cn_tp = &pccons[0];
1138: #else
1139: cp->cn_tp = pccons[0];
1140: #endif /* !(PCVT_FREEBSD > 110 && PCVT_FREEBSD < 200) */
1141:
1142: #endif /* !PCVT_NETBSD */
1143:
1144: #if PCVT_FREEBSD <= 205
1145: return 1;
1146: #endif
1147: }
1148:
1149: #if PCVT_FREEBSD > 205
1150: static void
1151: #else
1152: int
1153: #endif
1154: pccninit(struct consdev *cp)
1155: {
1156: int unit = 0;
1157: int i;
1158:
1159: pcvt_is_console = 1;
1160:
1161: #ifdef _DEV_KBD_KBDREG_H_
1162: /*
1163: * Don't reset the keyboard via `kbdio' just yet.
1164: * The system clock has not been calibrated...
1165: */
1166: reset_keyboard = 0;
1167:
1168: if (kbd)
1169: {
1170: kbd_release(kbd, (void *)&kbd);
1171: kbd = NULL;
1172: }
1173: i = kbd_allocate("*", -1, (void *)&kbd, pcevent, (void *)unit);
1174: if (i >= 0)
1175: kbd = kbd_get_keyboard(i);
1176:
1177: #if PCVT_SCANSET == 2
1178: /*
1179: * Turn off scancode translation early so that UserConfig
1180: * and DDB can read the keyboard.
1181: */
1182: if (kbd)
1183: {
1184: empty_both_buffers(*(KBDC *)kbd->kb_data, 10);
1185: set_controller_command_byte(*(KBDC *)kbd->kb_data,
1186: KBD_TRANSLATION, 0);
1187: }
1188: #endif /* PCVT_SCANSET == 2 */
1189:
1190: #endif /* _DEV_KBD_KBDREG_H_ */
1191:
1192: #if PCVT_FREEBSD <= 205
1193: return 0;
1194: #endif
1195: }
1196:
1197: static void
1198: pccnterm(struct consdev *cp)
1199: {
1200: #ifdef _DEV_KBD_KBDREG_H_
1201: if (kbd)
1202: {
1203: kbd_release(kbd, (void *)&kbd);
1204: kbd = NULL;
1205: }
1206: #endif /* _DEV_KBD_KBDREG_H_ */
1207: }
1208:
1209: #if PCVT_FREEBSD > 205
1210: static void
1211: #else
1212: int
1213: #endif
1214: pccnputc(Dev_t dev, U_char c)
1215: {
1216:
1217: #if PCVT_SW0CNOUTP
1218:
1219: if(current_video_screen != 0)
1220: {
1221:
1222: #if !PCVT_USL_VT_COMPAT
1223: vgapage(0);
1224: #else
1225: switch_screen(0, 0);
1226: #endif /* !PCVT_USL_VT_COMPAT */
1227:
1228: }
1229:
1230: #endif /* PCVT_SW0CNOUTP */
1231:
1232: if (c == '\n')
1233: sput("\r", 1, 1, 0);
1234:
1235: sput((char *) &c, 1, 1, 0);
1236:
1237: async_update(UPDATE_KERN);
1238:
1239: #if PCVT_FREEBSD <= 205
1240: return 0;
1241: #endif
1242: }
1243:
1244: static int
1245: pccngetc(Dev_t dev)
1246: {
1247: int s;
1248: static u_char *cp, cbuf[4]; /* Temp buf for multi-char key sequence. */
1249: u_char c;
1250:
1251: #ifdef XSERVER
1252:
1253: #if !PCVT_USL_VT_COMPAT
1254: if (pcvt_xmode)
1255: return 0;
1256: #else /* !PCVT_USL_VT_COMPAT */
1257: if (pcvt_kbd_raw)
1258: return 0;
1259: #endif /* !PCVT_USL_VT_COMPAT */
1260:
1261: #endif /* XSERVER */
1262:
1263: if (cp && *cp)
1264: /*
1265: * We still have a pending key sequence, e.g.
1266: * from an arrow key. Deliver this one first.
1267: */
1268: return (*cp++);
1269:
1270: #ifdef _DEV_KBD_KBDREG_H_
1271: if (kbd == NULL)
1272: return 0;
1273: #endif
1274:
1275: s = spltty(); /* block pcrint while we poll */
1276: kbd_polling = 1;
1277: #ifdef _DEV_KBD_KBDREG_H_
1278: (*kbdsw[kbd->kb_index]->enable)(kbd);
1279: #endif
1280: cp = sgetc(0);
1281: #ifdef _DEV_KBD_KBDREG_H_
1282: (*kbdsw[kbd->kb_index]->disable)(kbd);
1283: #endif
1284: kbd_polling = 0;
1285: splx(s);
1286: c = *cp++;
1287: if (c && *cp) {
1288: /* Preserve the multi-char sequence for the next call. */
1289: bcopy(cp, cbuf, 3); /* take care for a trailing '\0' */
1290: cp = cbuf;
1291: } else
1292: cp = 0;
1293:
1294: #if ! (PCVT_FREEBSD >= 201)
1295: /* this belongs to cons.c */
1296: if (c == '\r')
1297: c = '\n';
1298: #endif /* ! (PCVT_FREEBSD >= 201) */
1299:
1300: return c;
1301: }
1302:
1303: #if PCVT_FREEBSD >= 200
1304: static int
1305: pccncheckc(Dev_t dev)
1306: {
1307: char *cp;
1308: int x;
1309:
1310: #ifdef _DEV_KBD_KBDREG_H_
1311: if (kbd == NULL)
1312: return 0;
1313: #endif
1314:
1315: x = spltty();
1316: kbd_polling = 1;
1317: #ifdef _DEV_KBD_KBDREG_H_
1318: (*kbdsw[kbd->kb_index]->enable)(kbd);
1319: #endif
1320: cp = sgetc(1);
1321: #ifdef _DEV_KBD_KBDREG_H_
1322: (*kbdsw[kbd->kb_index]->disable)(kbd);
1323: #endif
1324: kbd_polling = 0;
1325: splx(x);
1326: return (cp == NULL ? -1 : *cp);
1327: }
1328: #endif /* PCVT_FREEBSD >= 200 */
1329:
1330: #if PCVT_NETBSD >= 100
1331: void
1332: pccnpollc(Dev_t dev, int on)
1333: {
1334: kbd_polling = on;
1335: if (!on) {
1336: int s;
1337:
1338: /*
1339: * If disabling polling, make sure there are no bytes left in
1340: * the FIFO, holding up the interrupt line. Otherwise we
1341: * won't get any further interrupts.
1342: */
1343: s = spltty();
1344: pcrint();
1345: splx(s);
1346: }
1347: }
1348: #endif /* PCVT_NETBSD >= 100 */
1349:
1350: /*---------------------------------------------------------------------------*
1351: * Set line parameters
1352: *---------------------------------------------------------------------------*/
1353: int
1354: pcparam(struct tty *tp, struct termios *t)
1355: {
1356: int cflag = t->c_cflag;
1357:
1358: /* and copy to tty */
1359:
1360: tp->t_ispeed = t->c_ispeed;
1361: tp->t_ospeed = t->c_ospeed;
1362: tp->t_cflag = cflag;
1363:
1364: return(0);
1365: }
1366:
1367: /*----------------------------------------------------------------------*
1368: * read initial VGA palette (as stored by VGA ROM BIOS) into
1369: * palette save area
1370: *----------------------------------------------------------------------*/
1371: void
1372: vgapelinit(void)
1373: {
1374: unsigned idx;
1375: struct rgb *val;
1376:
1377: /* first, read all and store to first screen's save buffer */
1378: for(idx = 0, val = vs[0].palette; idx < NVGAPEL; idx++, val++)
1379: vgapaletteio(idx, val, 0 /* read it */);
1380:
1381: /* now, duplicate for remaining screens */
1382: for(idx = 1; idx < PCVT_NSCREENS; idx++)
1383: bcopy(vs[0].palette, vs[idx].palette,
1384: NVGAPEL * sizeof(struct rgb));
1385: }
1386:
1387: #if defined XSERVER && !PCVT_USL_VT_COMPAT
1388: /*----------------------------------------------------------------------*
1389: * initialize for X mode
1390: * i.e.: grant current process (the X server) all IO privileges,
1391: * and mark in static variable so other hooks can test for it,
1392: * save all loaded fonts and screen pages to pageable buffers;
1393: * if parameter `on' is false, the same procedure is done reverse.
1394: *----------------------------------------------------------------------*/
1395: static int
1396: pcvt_xmode_set(int on, struct thread *td)
1397: {
1398: static unsigned char *saved_fonts[NVGAFONTS];
1399:
1400: #if PCVT_SCREENSAVER
1401: static unsigned saved_scrnsv_tmo = 0;
1402: #endif /* PCVT_SCREENSAVER */
1403:
1404: #if (PCVT_NETBSD > 9) || (PCVT_FREEBSD > 102)
1405: struct trapframe *fp;
1406: #else
1407: struct syscframe *fp;
1408: #endif /* PCVT_NETBSD > 9 */
1409:
1410: int error, i;
1411:
1412: /* X will only run on VGA and Hercules adaptors */
1413:
1414: if(adaptor_type != VGA_ADAPTOR && adaptor_type != MDA_ADAPTOR)
1415: return (EINVAL);
1416:
1417: #if PCVT_NETBSD > 9
1418: fp = (struct trapframe *)p->p_regs;
1419: #else
1420: fp = (struct syscframe *)p->p_regs;
1421: #endif /* PCVT_NETBSD > 9 */
1422:
1423: if(on)
1424: {
1425: /*
1426: * Test whether the calling process has super-user privileges
1427: * and we're in insecure mode.
1428: * This prevents us from granting the potential security hole
1429: * `IO priv' to insufficiently privileged processes.
1430: */
1431: error = suser(td);
1432: if (error != 0)
1433: return (error);
1434: if (securelevel > 0)
1435: return (EPERM);
1436:
1437: if(pcvt_xmode)
1438: return 0;
1439:
1440: pcvt_xmode = pcvt_kbd_raw = 1;
1441:
1442: for(i = 0; i < totalfonts; i++)
1443: {
1444: if(vgacs[i].loaded)
1445: {
1446: saved_fonts[i] = (unsigned char *)
1447: malloc(32 * 256, M_DEVBUF, M_WAITOK);
1448: if(saved_fonts[i] == 0)
1449: {
1450: printf(
1451: "pcvt_xmode_set: no font buffer available\n");
1452: return (EAGAIN);
1453: }
1454: else
1455: {
1456: vga_move_charset(i, saved_fonts[i], 1);
1457: }
1458: }
1459: else
1460: {
1461: saved_fonts[i] = 0;
1462: }
1463: }
1464:
1465: #if PCVT_SCREENSAVER
1466: if(saved_scrnsv_tmo = scrnsv_timeout)
1467: pcvt_set_scrnsv_tmo(0); /* turn it off */
1468: #endif /* PCVT_SCREENSAVER */
1469:
1470: async_update(UPDATE_STOP); /* turn off */
1471:
1472: /* disable text output and save screen contents */
1473: /* video board memory -> kernel memory */
1474:
1475: bcopy(vsp->Crtat, vsp->Memory,
1476: vsp->screen_rowsize * vsp->maxcol * CHR);
1477:
1478: vsp->Crtat = vsp->Memory; /* operate in memory now */
1479:
1480: #ifndef _DEV_KBD_KBDREG_H_
1481:
1482: #if PCVT_SCANSET == 2
1483: /* put keyboard to return ancient PC scan codes */
1484: kbc_8042cmd(CONTR_WRITE);
1485: #if PCVT_USEKBDSEC /* security enabled */
1486: outb(CONTROLLER_DATA,
1487: (COMMAND_SYSFLG|COMMAND_IRQEN|COMMAND_PCSCAN));
1488: #else /* security disabled */
1489: outb(CONTROLLER_DATA,
1490: (COMMAND_INHOVR|COMMAND_SYSFLG|COMMAND_IRQEN|COMMAND_PCSCAN));
1491: #endif /* PCVT_USEKBDSEC */
1492: #endif /* PCVT_SCANSET == 2 */
1493:
1494: #else /* _DEV_KBD_KBDREG_H_ */
1495:
1496: #if PCVT_SCANSET == 2
1497: /* put keyboard to return ancient PC scan codes */
1498: set_controller_command_byte(*(KBDC *)kbd->kb_data,
1499: KBD_TRANSLATION, KBD_TRANSLATION);
1500: #endif /* PCVT_SCANSET == 2 */
1501:
1502: #endif /* !_DEV_KBD_KBDREG_H_ */
1503:
1504: #if PCVT_NETBSD > 9
1505: fp->tf_eflags |= PSL_IOPL;
1506: #else
1507: fp->sf_eflags |= PSL_IOPL;
1508: #endif /* PCVT_NETBSD > 9 */
1509:
1510: }
1511: else
1512: {
1513: if(!pcvt_xmode) /* verify if in X */
1514: return 0;
1515:
1516: pcvt_xmode = pcvt_kbd_raw = 0;
1517:
1518: for(i = 0; i < totalfonts; i++)
1519: {
1520: if(saved_fonts[i])
1521: {
1522: vga_move_charset(i, saved_fonts[i], 0);
1523: free(saved_fonts[i], M_DEVBUF);
1524: saved_fonts[i] = 0;
1525: }
1526: }
1527:
1528: #if PCVT_NETBSD > 9
1529: fp->tf_eflags &= ~PSL_IOPL;
1530: #else
1531: fp->sf_eflags &= ~PSL_IOPL;
1532: #endif /* PCVT_NETBSD > 9 */
1533:
1534: #if PCVT_SCREENSAVER
1535: if(saved_scrnsv_tmo)
1536: pcvt_set_scrnsv_tmo(saved_scrnsv_tmo);
1537: #endif /* PCVT_SCREENSAVER */
1538:
1539: #ifndef _DEV_KBD_KBDREG_H_
1540:
1541: #if PCVT_SCANSET == 2
1542: kbc_8042cmd(CONTR_WRITE);
1543: #if PCVT_USEKBDSEC /* security enabled */
1544: outb(CONTROLLER_DATA,
1545: (COMMAND_SYSFLG|COMMAND_IRQEN));
1546: #else /* security disabled */
1547: outb(CONTROLLER_DATA,
1548: (COMMAND_INHOVR|COMMAND_SYSFLG|COMMAND_IRQEN));
1549: #endif /* PCVT_USEKBDSEC */
1550: #endif /* PCVT_SCANSET == 2 */
1551:
1552: #else /* _DEV_KBD_KBDREG_H_ */
1553:
1554: #if PCVT_SCANSET == 2
1555: set_controller_command_byte(*(KBDC *)kbd->kb_data,
1556: KBD_TRANSLATION, 0);
1557: #endif /* PCVT_SCANSET == 2 */
1558:
1559: #endif /* !_DEV_KBD_KBDREG_H_ */
1560:
1561: if(adaptor_type == MDA_ADAPTOR)
1562: {
1563: /*
1564: * Due to the fact that HGC registers are write-only,
1565: * the Xserver can only make guesses about the state
1566: * the HGC adaptor has been before turning on X mode.
1567: * Thus, the display must be re-enabled now, and the
1568: * cursor shape and location restored.
1569: */
1570: outb(GN_DMCNTLM, 0x28); /* enable display, text mode */
1571: outb(addr_6845, CRTC_CURSORH); /* select high register */
1572: outb(addr_6845+1,
1573: ((vsp->Crtat + vsp->cur_offset) - Crtat) >> 8);
1574: outb(addr_6845, CRTC_CURSORL); /* select low register */
1575: outb(addr_6845+1,
1576: ((vsp->Crtat + vsp->cur_offset) - Crtat));
1577:
1578: outb(addr_6845, CRTC_CURSTART); /* select high register */
1579: outb(addr_6845+1, vsp->cursor_start);
1580: outb(addr_6845, CRTC_CUREND); /* select low register */
1581: outb(addr_6845+1, vsp->cursor_end);
1582: }
1583:
1584: /* restore screen and re-enable text output */
1585: /* kernel memory -> video board memory */
1586:
1587: bcopy(vsp->Memory, Crtat,
1588: vsp->screen_rowsize * vsp->maxcol * CHR);
1589:
1590: vsp->Crtat = Crtat; /* operate on-screen now */
1591:
1592: /* set crtc screen memory start address */
1593:
1594: outb(addr_6845, CRTC_STARTADRH);
1595: outb(addr_6845+1, (vsp->Crtat - Crtat) >> 8);
1596: outb(addr_6845, CRTC_STARTADRL);
1597: outb(addr_6845+1, (vsp->Crtat - Crtat));
1598:
1599: async_update(UPDATE_START);
1600: }
1601: return 0;
1602: }
1603: #endif /* XSERVER && !PCVT_USL_VT_COMPAT */
1604:
1605: #endif /* NVT > 0 */
1606:
1607: /*-------------------------- E O F -------------------------------------*/