This source file includes following definitions.
- usl_sync_init
- usl_sync_done
- usl_sync_check
- usl_sync_get
- usl_detachproc
- usl_detachack
- usl_detachtimeout
- usl_attachproc
- usl_attachack
- usl_attachtimeout
- wsdisplay_usl_ioctl1
- wsdisplay_usl_ioctl2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
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
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
179 if (!callback)
180 return (EINVAL);
181
182
183
184
185
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
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;
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
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
455
456
457 return (0);
458 #endif
459 case KDSETRAD:
460
461 return (0);
462
463 default:
464 return (-1);
465
466
467
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;
493 }
494 else
495 bd.which = 0;
496 if (d & 0xffff) {
497 bd.which |= WSKBD_BELL_DOPITCH;
498 bd.pitch = PCVT_SYSBEEPF/(d & 0xffff);
499 }
500 } else
501 bd.which = 0;
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 }