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