Annotation of sys/dev/wscons/wsdisplay_compat_usl.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: wsdisplay_compat_usl.c,v 1.19 2007/02/14 01:12:16 jsg Exp $ */
2: /* $NetBSD: wsdisplay_compat_usl.c,v 1.12 2000/03/23 07:01:47 thorpej Exp $ */
3:
4: /*
5: * Copyright (c) 1998
6: * Matthias Drochner. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27: *
28: */
29:
30: #include <sys/param.h>
31: #include <sys/systm.h>
32: #include <sys/timeout.h>
33: #include <sys/ioctl.h>
34: #include <sys/kernel.h>
35: #include <sys/proc.h>
36: #include <sys/signalvar.h>
37: #include <sys/malloc.h>
38: #include <sys/errno.h>
39:
40: #include <dev/wscons/wsconsio.h>
41: #include <dev/wscons/wsdisplayvar.h>
42: #include <dev/wscons/wscons_callbacks.h>
43: #include <dev/wscons/wsdisplay_usl_io.h>
44:
45: #ifdef WSDISPLAY_DEBUG
46: #define DPRINTF(x) if (wsdisplaydebug) printf x
47: int wsdisplaydebug = 0;
48: #else
49: #define DPRINTF(x)
50: #endif
51:
52: struct usl_syncdata {
53: struct wsscreen *s_scr;
54: struct proc *s_proc;
55: pid_t s_pid;
56: int s_flags;
57: #define SF_DETACHPENDING 1
58: #define SF_ATTACHPENDING 2
59: int s_acqsig, s_relsig;
60: int s_frsig; /* unused */
61: void (*s_callback)(void *, int, int);
62: void *s_cbarg;
63: struct timeout s_attach_ch;
64: struct timeout s_detach_ch;
65: };
66:
67: int usl_sync_init(struct wsscreen *, struct usl_syncdata **,
68: struct proc *, int, int, int);
69: void usl_sync_done(struct usl_syncdata *);
70: int usl_sync_check(struct usl_syncdata *);
71: struct usl_syncdata *usl_sync_get(struct wsscreen *);
72:
73: int usl_detachproc(void *, int, void (*)(void *, int, int), void *);
74: int usl_detachack(struct usl_syncdata *, int);
75: void usl_detachtimeout(void *);
76: int usl_attachproc(void *, int, void (*)(void *, int, int), void *);
77: int usl_attachack(struct usl_syncdata *, int);
78: void usl_attachtimeout(void *);
79:
80: static const struct wscons_syncops usl_syncops = {
81: usl_detachproc,
82: usl_attachproc,
83: #define _usl_sync_check ((int (*)(void *))usl_sync_check)
84: _usl_sync_check,
85: #define _usl_sync_destroy ((void (*)(void *))usl_sync_done)
86: _usl_sync_destroy
87: };
88:
89: #ifndef WSCOMPAT_USL_SYNCTIMEOUT
90: #define WSCOMPAT_USL_SYNCTIMEOUT 5 /* seconds */
91: #endif
92: static int wscompat_usl_synctimeout = WSCOMPAT_USL_SYNCTIMEOUT;
93:
94: int
95: usl_sync_init(scr, sdp, p, acqsig, relsig, frsig)
96: struct wsscreen *scr;
97: struct usl_syncdata **sdp;
98: struct proc *p;
99: int acqsig, relsig, frsig;
100: {
101: struct usl_syncdata *sd;
102: int res;
103:
104: if (acqsig <= 0 || acqsig >= NSIG || relsig <= 0 || relsig >= NSIG ||
105: frsig <= 0 || frsig >= NSIG)
106: return (EINVAL);
107: sd = malloc(sizeof(struct usl_syncdata), M_DEVBUF, M_NOWAIT);
108: if (!sd)
109: return (ENOMEM);
110: sd->s_scr = scr;
111: sd->s_proc = p;
112: sd->s_pid = p->p_pid;
113: sd->s_flags = 0;
114: sd->s_acqsig = acqsig;
115: sd->s_relsig = relsig;
116: sd->s_frsig = frsig;
117: timeout_set(&sd->s_attach_ch, usl_attachtimeout, sd);
118: timeout_set(&sd->s_detach_ch, usl_detachtimeout, sd);
119: res = wsscreen_attach_sync(scr, &usl_syncops, sd);
120: if (res) {
121: free(sd, M_DEVBUF);
122: return (res);
123: }
124: *sdp = sd;
125: return (0);
126: }
127:
128: void
129: usl_sync_done(sd)
130: struct usl_syncdata *sd;
131: {
132: if (sd->s_flags & SF_DETACHPENDING) {
133: timeout_del(&sd->s_detach_ch);
134: (*sd->s_callback)(sd->s_cbarg, 0, 0);
135: }
136: if (sd->s_flags & SF_ATTACHPENDING) {
137: timeout_del(&sd->s_attach_ch);
138: (*sd->s_callback)(sd->s_cbarg, ENXIO, 0);
139: }
140: wsscreen_detach_sync(sd->s_scr);
141: free(sd, M_DEVBUF);
142: }
143:
144: int
145: usl_sync_check(sd)
146: struct usl_syncdata *sd;
147: {
148: if (sd->s_proc == pfind(sd->s_pid))
149: return (1);
150: DPRINTF(("usl_sync_check: process %d died\n", sd->s_pid));
151: usl_sync_done(sd);
152: return (0);
153: }
154:
155: struct usl_syncdata *
156: usl_sync_get(scr)
157: struct wsscreen *scr;
158: {
159: struct usl_syncdata *sd;
160:
161: if (wsscreen_lookup_sync(scr, &usl_syncops, (void **)&sd))
162: return (0);
163: return (sd);
164: }
165:
166: int
167: usl_detachproc(cookie, waitok, callback, cbarg)
168: void *cookie;
169: int waitok;
170: void (*callback)(void *, int, int);
171: void *cbarg;
172: {
173: struct usl_syncdata *sd = cookie;
174:
175: if (!usl_sync_check(sd))
176: return (0);
177:
178: /* we really need a callback */
179: if (!callback)
180: return (EINVAL);
181:
182: /*
183: * Normally, this is called from the controlling process.
184: * It is supposed to reply with a VT_RELDISP ioctl(), so
185: * it is not useful to tsleep() here.
186: */
187: sd->s_callback = callback;
188: sd->s_cbarg = cbarg;
189: sd->s_flags |= SF_DETACHPENDING;
190: psignal(sd->s_proc, sd->s_relsig);
191: timeout_add(&sd->s_detach_ch, wscompat_usl_synctimeout * hz);
192:
193: return (EAGAIN);
194: }
195:
196: int
197: usl_detachack(sd, ack)
198: struct usl_syncdata *sd;
199: int ack;
200: {
201: if (!(sd->s_flags & SF_DETACHPENDING)) {
202: DPRINTF(("usl_detachack: not detaching\n"));
203: return (EINVAL);
204: }
205:
206: timeout_del(&sd->s_detach_ch);
207: sd->s_flags &= ~SF_DETACHPENDING;
208:
209: if (sd->s_callback)
210: (*sd->s_callback)(sd->s_cbarg, (ack ? 0 : EIO), 1);
211:
212: return (0);
213: }
214:
215: void
216: usl_detachtimeout(arg)
217: void *arg;
218: {
219: struct usl_syncdata *sd = arg;
220:
221: DPRINTF(("usl_detachtimeout\n"));
222:
223: if (!(sd->s_flags & SF_DETACHPENDING)) {
224: DPRINTF(("usl_detachtimeout: not detaching\n"));
225: return;
226: }
227:
228: sd->s_flags &= ~SF_DETACHPENDING;
229:
230: if (sd->s_callback)
231: (*sd->s_callback)(sd->s_cbarg, EIO, 0);
232:
233: (void) usl_sync_check(sd);
234: }
235:
236: int
237: usl_attachproc(cookie, waitok, callback, cbarg)
238: void *cookie;
239: int waitok;
240: void (*callback)(void *, int, int);
241: void *cbarg;
242: {
243: struct usl_syncdata *sd = cookie;
244:
245: if (!usl_sync_check(sd))
246: return (0);
247:
248: /* we really need a callback */
249: if (!callback)
250: return (EINVAL);
251:
252: sd->s_callback = callback;
253: sd->s_cbarg = cbarg;
254: sd->s_flags |= SF_ATTACHPENDING;
255: psignal(sd->s_proc, sd->s_acqsig);
256: timeout_add(&sd->s_attach_ch, wscompat_usl_synctimeout * hz);
257:
258: return (EAGAIN);
259: }
260:
261: int
262: usl_attachack(sd, ack)
263: struct usl_syncdata *sd;
264: int ack;
265: {
266: if (!(sd->s_flags & SF_ATTACHPENDING)) {
267: DPRINTF(("usl_attachack: not attaching\n"));
268: return (EINVAL);
269: }
270:
271: timeout_del(&sd->s_attach_ch);
272: sd->s_flags &= ~SF_ATTACHPENDING;
273:
274: if (sd->s_callback)
275: (*sd->s_callback)(sd->s_cbarg, (ack ? 0 : EIO), 1);
276:
277: return (0);
278: }
279:
280: void
281: usl_attachtimeout(arg)
282: void *arg;
283: {
284: struct usl_syncdata *sd = arg;
285:
286: DPRINTF(("usl_attachtimeout\n"));
287:
288: if (!(sd->s_flags & SF_ATTACHPENDING)) {
289: DPRINTF(("usl_attachtimeout: not attaching\n"));
290: return;
291: }
292:
293: sd->s_flags &= ~SF_ATTACHPENDING;
294:
295: if (sd->s_callback)
296: (*sd->s_callback)(sd->s_cbarg, EIO, 0);
297:
298: (void) usl_sync_check(sd);
299: }
300:
301: int
302: wsdisplay_usl_ioctl1(sc, cmd, data, flag, p)
303: struct wsdisplay_softc *sc;
304: u_long cmd;
305: caddr_t data;
306: int flag;
307: struct proc *p;
308: {
309: int idx, maxidx;
310:
311: switch (cmd) {
312: case VT_OPENQRY:
313: maxidx = wsdisplay_maxscreenidx(sc);
314: for (idx = 0; idx <= maxidx; idx++) {
315: if (wsdisplay_screenstate(sc, idx) == 0) {
316: *(int *)data = idx + 1;
317: return (0);
318: }
319: }
320: return (ENXIO);
321: case VT_GETACTIVE:
322: idx = wsdisplay_getactivescreen(sc);
323: *(int *)data = idx + 1;
324: return (0);
325: case VT_ACTIVATE:
326: idx = *(int *)data - 1;
327: if (idx < 0)
328: return (EINVAL);
329: return (wsdisplay_switch((struct device *)sc, idx, 1));
330: case VT_WAITACTIVE:
331: idx = *(int *)data - 1;
332: if (idx < 0)
333: return (EINVAL);
334: return (wsscreen_switchwait(sc, idx));
335: case VT_GETSTATE:
336: #define ss ((struct vt_stat *)data)
337: idx = wsdisplay_getactivescreen(sc);
338: ss->v_active = idx + 1;
339: ss->v_state = 0;
340: maxidx = wsdisplay_maxscreenidx(sc);
341: for (idx = 0; idx <= maxidx; idx++)
342: if (wsdisplay_screenstate(sc, idx) == EBUSY)
343: ss->v_state |= (1 << (idx + 1));
344: #undef ss
345: return (0);
346:
347: #ifdef WSDISPLAY_COMPAT_PCVT
348: case VGAPCVTID:
349: #define id ((struct pcvtid *)data)
350: strlcpy(id->name, "pcvt", sizeof id->name);
351: id->rmajor = 3;
352: id->rminor = 32;
353: #undef id
354: return (0);
355: #endif
356: #ifdef WSDISPLAY_COMPAT_SYSCONS
357: case CONS_GETVERS:
358: *(int *)data = 0x200; /* version 2.0 */
359: return (0);
360: #endif
361:
362: default:
363: return (-1);
364: }
365:
366: return (0);
367: }
368:
369: int
370: wsdisplay_usl_ioctl2(sc, scr, cmd, data, flag, p)
371: struct wsdisplay_softc *sc;
372: struct wsscreen *scr;
373: u_long cmd;
374: caddr_t data;
375: int flag;
376: struct proc *p;
377: {
378: int intarg, res;
379: u_long req;
380: void *arg;
381: struct usl_syncdata *sd;
382: struct wskbd_bell_data bd;
383:
384: switch (cmd) {
385: case VT_SETMODE:
386: #define newmode ((struct vt_mode *)data)
387: if (newmode->mode == VT_PROCESS) {
388: res = usl_sync_init(scr, &sd, p, newmode->acqsig,
389: newmode->relsig, newmode->frsig);
390: if (res)
391: return (res);
392: } else {
393: sd = usl_sync_get(scr);
394: if (sd)
395: usl_sync_done(sd);
396: }
397: #undef newmode
398: return (0);
399: case VT_GETMODE:
400: #define cmode ((struct vt_mode *)data)
401: sd = usl_sync_get(scr);
402: if (sd) {
403: cmode->mode = VT_PROCESS;
404: cmode->relsig = sd->s_relsig;
405: cmode->acqsig = sd->s_acqsig;
406: cmode->frsig = sd->s_frsig;
407: } else
408: cmode->mode = VT_AUTO;
409: #undef cmode
410: return (0);
411: case VT_RELDISP:
412: #define d (*(int *)data)
413: sd = usl_sync_get(scr);
414: if (!sd)
415: return (EINVAL);
416: switch (d) {
417: case VT_FALSE:
418: case VT_TRUE:
419: return (usl_detachack(sd, (d == VT_TRUE)));
420: case VT_ACKACQ:
421: return (usl_attachack(sd, 1));
422: default:
423: return (EINVAL);
424: }
425: #undef d
426: return (0);
427:
428: #if defined(__i386__)
429: case KDENABIO:
430: if (suser(p, 0) || securelevel > 0)
431: return (EPERM);
432: /* FALLTHROUGH */
433: case KDDISABIO:
434: #if defined(COMPAT_FREEBSD)
435: {
436: struct trapframe *fp = (struct trapframe *)p->p_md.md_regs;
437: extern struct emul emul_freebsd_aout;
438: extern struct emul emul_freebsd_elf;
439:
440: if (p->p_emul == &emul_freebsd_aout ||
441: p->p_emul == &emul_freebsd_elf) {
442: if (cmd == KDENABIO)
443: fp->tf_eflags |= PSL_IOPL;
444: else
445: fp->tf_eflags &= ~PSL_IOPL;
446: }
447: }
448: #endif
449: return (0);
450: #else
451: case KDENABIO:
452: case KDDISABIO:
453: /*
454: * This is a lie, but non-x86 platforms are not supposed to
455: * issue these ioctls anyway.
456: */
457: return (0);
458: #endif
459: case KDSETRAD:
460: /* XXX ignore for now */
461: return (0);
462:
463: default:
464: return (-1);
465:
466: /*
467: * the following are converted to wsdisplay ioctls
468: */
469: case KDSETMODE:
470: req = WSDISPLAYIO_SMODE;
471: #define d (*(int *)data)
472: switch (d) {
473: case KD_GRAPHICS:
474: intarg = WSDISPLAYIO_MODE_MAPPED;
475: break;
476: case KD_TEXT:
477: intarg = WSDISPLAYIO_MODE_EMUL;
478: break;
479: default:
480: return (EINVAL);
481: }
482: #undef d
483: arg = &intarg;
484: break;
485: case KDMKTONE:
486: req = WSKBDIO_COMPLEXBELL;
487: #define d (*(int *)data)
488: if (d) {
489: #define PCVT_SYSBEEPF 1193182
490: if (d >> 16) {
491: bd.which = WSKBD_BELL_DOPERIOD;
492: bd.period = d >> 16; /* ms */
493: }
494: else
495: bd.which = 0;
496: if (d & 0xffff) {
497: bd.which |= WSKBD_BELL_DOPITCH;
498: bd.pitch = PCVT_SYSBEEPF/(d & 0xffff); /* Hz */
499: }
500: } else
501: bd.which = 0; /* default */
502: #undef d
503: arg = &bd;
504: break;
505: case KDSETLED:
506: req = WSKBDIO_SETLEDS;
507: intarg = 0;
508: #define d (*(int *)data)
509: if (d & LED_CAP)
510: intarg |= WSKBD_LED_CAPS;
511: if (d & LED_NUM)
512: intarg |= WSKBD_LED_NUM;
513: if (d & LED_SCR)
514: intarg |= WSKBD_LED_SCROLL;
515: #undef d
516: arg = &intarg;
517: break;
518: case KDGETLED:
519: req = WSKBDIO_GETLEDS;
520: arg = &intarg;
521: break;
522: #ifdef WSDISPLAY_COMPAT_RAWKBD
523: case KDSKBMODE:
524: req = WSKBDIO_SETMODE;
525: switch (*(int *)data) {
526: case K_RAW:
527: intarg = WSKBD_RAW;
528: break;
529: case K_XLATE:
530: intarg = WSKBD_TRANSLATED;
531: break;
532: default:
533: return (EINVAL);
534: }
535: arg = &intarg;
536: break;
537: case KDGKBMODE:
538: req = WSKBDIO_GETMODE;
539: arg = &intarg;
540: break;
541: #endif
542: }
543:
544: res = wsdisplay_internal_ioctl(sc, scr, req, arg, flag, p);
545: if (res)
546: return (res);
547:
548: switch (cmd) {
549: case KDGETLED:
550: #define d (*(int *)data)
551: d = 0;
552: if (intarg & WSKBD_LED_CAPS)
553: d |= LED_CAP;
554: if (intarg & WSKBD_LED_NUM)
555: d |= LED_NUM;
556: if (intarg & WSKBD_LED_SCROLL)
557: d |= LED_SCR;
558: #undef d
559: break;
560: #ifdef WSDISPLAY_COMPAT_RAWKBD
561: case KDGKBMODE:
562: *(int *)data = (intarg == WSKBD_RAW ? K_RAW : K_XLATE);
563: break;
564: #endif
565: }
566:
567: return (0);
568: }
CVSweb