1 1.14 pgoyette /* $NetBSD: wsbell.c,v 1.14 2022/03/31 19:30:17 pgoyette Exp $ */ 2 1.1 nat 3 1.1 nat /*- 4 1.1 nat * Copyright (c) 2017 Nathanial Sloss <nathanialsloss (at) yahoo.com.au> 5 1.1 nat * All rights reserved. 6 1.1 nat * 7 1.1 nat * Copyright (c) 2006 The NetBSD Foundation, Inc. 8 1.1 nat * All rights reserved. 9 1.1 nat * 10 1.1 nat * This code is derived from software contributed to The NetBSD Foundation 11 1.1 nat * by Julio M. Merino Vidal. 12 1.1 nat * 13 1.1 nat * Redistribution and use in source and binary forms, with or without 14 1.1 nat * modification, are permitted provided that the following conditions 15 1.1 nat * are met: 16 1.1 nat * 1. Redistributions of source code must retain the above copyright 17 1.1 nat * notice, this list of conditions and the following disclaimer. 18 1.1 nat * 2. Redistributions in binary form must reproduce the above copyright 19 1.1 nat * notice, this list of conditions and the following disclaimer in the 20 1.1 nat * documentation and/or other materials provided with the distribution. 21 1.1 nat * 22 1.1 nat * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 1.1 nat * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 1.1 nat * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 1.1 nat * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 1.1 nat * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 1.1 nat * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 1.1 nat * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 1.1 nat * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 1.1 nat * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 1.1 nat * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 1.1 nat * POSSIBILITY OF SUCH DAMAGE. 33 1.1 nat */ 34 1.1 nat 35 1.1 nat /* 36 1.1 nat * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. 37 1.1 nat * 38 1.1 nat * Redistribution and use in source and binary forms, with or without 39 1.1 nat * modification, are permitted provided that the following conditions 40 1.1 nat * are met: 41 1.1 nat * 1. Redistributions of source code must retain the above copyright 42 1.1 nat * notice, this list of conditions and the following disclaimer. 43 1.1 nat * 2. Redistributions in binary form must reproduce the above copyright 44 1.1 nat * notice, this list of conditions and the following disclaimer in the 45 1.1 nat * documentation and/or other materials provided with the distribution. 46 1.1 nat * 3. All advertising materials mentioning features or use of this software 47 1.1 nat * must display the following acknowledgement: 48 1.1 nat * This product includes software developed by Christopher G. Demetriou 49 1.1 nat * for the NetBSD Project. 50 1.1 nat * 4. The name of the author may not be used to endorse or promote products 51 1.1 nat * derived from this software without specific prior written permission 52 1.1 nat * 53 1.1 nat * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 54 1.1 nat * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 55 1.1 nat * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 56 1.1 nat * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 57 1.1 nat * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 58 1.1 nat * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 59 1.1 nat * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 60 1.1 nat * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 61 1.1 nat * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 62 1.1 nat * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 63 1.1 nat */ 64 1.1 nat 65 1.1 nat /* 66 1.1 nat * Copyright (c) 1992, 1993 67 1.1 nat * The Regents of the University of California. All rights reserved. 68 1.1 nat * 69 1.1 nat * This software was developed by the Computer Systems Engineering group 70 1.1 nat * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 71 1.1 nat * contributed to Berkeley. 72 1.1 nat * 73 1.1 nat * All advertising materials mentioning features or use of this software 74 1.1 nat * must display the following acknowledgement: 75 1.1 nat * This product includes software developed by the University of 76 1.1 nat * California, Lawrence Berkeley Laboratory. 77 1.1 nat * 78 1.1 nat * Redistribution and use in source and binary forms, with or without 79 1.1 nat * modification, are permitted provided that the following conditions 80 1.1 nat * are met: 81 1.1 nat * 1. Redistributions of source code must retain the above copyright 82 1.1 nat * notice, this list of conditions and the following disclaimer. 83 1.1 nat * 2. Redistributions in binary form must reproduce the above copyright 84 1.1 nat * notice, this list of conditions and the following disclaimer in the 85 1.1 nat * documentation and/or other materials provided with the distribution. 86 1.1 nat * 3. Neither the name of the University nor the names of its contributors 87 1.1 nat * may be used to endorse or promote products derived from this software 88 1.1 nat * without specific prior written permission. 89 1.1 nat * 90 1.1 nat * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 91 1.1 nat * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 92 1.1 nat * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 93 1.1 nat * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 94 1.1 nat * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 95 1.1 nat * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 96 1.1 nat * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 97 1.1 nat * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 98 1.1 nat * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 99 1.1 nat * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 100 1.1 nat * SUCH DAMAGE. 101 1.1 nat * 102 1.1 nat * @(#)ms.c 8.1 (Berkeley) 6/11/93 103 1.1 nat */ 104 1.1 nat 105 1.1 nat /* 106 1.1 nat * Keyboard Bell driver. 107 1.1 nat */ 108 1.1 nat 109 1.1 nat #include <sys/cdefs.h> 110 1.14 pgoyette __KERNEL_RCSID(0, "$NetBSD: wsbell.c,v 1.14 2022/03/31 19:30:17 pgoyette Exp $"); 111 1.1 nat 112 1.2 pgoyette #if defined(_KERNEL_OPT) 113 1.1 nat #include "wsmux.h" 114 1.2 pgoyette #endif 115 1.1 nat 116 1.1 nat #include <sys/param.h> 117 1.1 nat #include <sys/conf.h> 118 1.1 nat #include <sys/ioctl.h> 119 1.1 nat #include <sys/poll.h> 120 1.1 nat #include <sys/fcntl.h> 121 1.1 nat #include <sys/kernel.h> 122 1.1 nat #include <sys/condvar.h> 123 1.1 nat #include <sys/mutex.h> 124 1.8 nat #include <sys/kauth.h> 125 1.1 nat #include <sys/kthread.h> 126 1.1 nat #include <sys/proc.h> 127 1.1 nat #include <sys/syslog.h> 128 1.1 nat #include <sys/systm.h> 129 1.1 nat #include <sys/tty.h> 130 1.1 nat #include <sys/signalvar.h> 131 1.1 nat #include <sys/device.h> 132 1.1 nat #include <sys/vnode.h> 133 1.1 nat #include <sys/callout.h> 134 1.2 pgoyette #include <sys/module.h> 135 1.1 nat 136 1.1 nat #include <dev/wscons/wsconsio.h> 137 1.1 nat #include <dev/wscons/wsbellvar.h> 138 1.1 nat #include <dev/wscons/wsbellmuxvar.h> 139 1.1 nat #include <dev/wscons/wsbelldata.h> 140 1.1 nat 141 1.1 nat #include <dev/spkrio.h> 142 1.1 nat 143 1.2 pgoyette #include "ioconf.h" 144 1.2 pgoyette 145 1.1 nat #if defined(WSMUX_DEBUG) && NWSMUX > 0 146 1.1 nat #define DPRINTF(x) if (wsmuxdebug) printf x 147 1.1 nat #define DPRINTFN(n,x) if (wsmuxdebug > (n)) printf x 148 1.1 nat extern int wsmuxdebug; 149 1.1 nat #else 150 1.1 nat #define DPRINTF(x) 151 1.1 nat #define DPRINTFN(n,x) 152 1.1 nat #endif 153 1.1 nat 154 1.1 nat static void bell_thread(void *); 155 1.1 nat static inline void spkr_audio_play(struct wsbell_softc *, u_int, u_int, u_int); 156 1.1 nat 157 1.1 nat static int wsbell_match(device_t, cfdata_t, void *); 158 1.1 nat static void wsbell_attach(device_t, device_t, void *); 159 1.1 nat static int wsbell_detach(device_t, int); 160 1.1 nat static int wsbell_activate(device_t, enum devact); 161 1.1 nat 162 1.1 nat #if NWSMUX > 0 163 1.1 nat static int wsbell_mux_open(struct wsevsrc *, struct wseventvar *); 164 1.1 nat static int wsbell_mux_close(struct wsevsrc *); 165 1.1 nat 166 1.1 nat static int wsbelldoopen(struct wsbell_softc *, struct wseventvar *); 167 1.1 nat static int wsbelldoioctl(device_t, u_long, void *, int, struct lwp *); 168 1.1 nat 169 1.1 nat static int wsbell_do_ioctl(struct wsbell_softc *, u_long, void *, 170 1.1 nat int, struct lwp *); 171 1.1 nat 172 1.1 nat #endif 173 1.1 nat 174 1.1 nat CFATTACH_DECL_NEW(wsbell, sizeof (struct wsbell_softc), 175 1.1 nat wsbell_match, wsbell_attach, wsbell_detach, wsbell_activate); 176 1.1 nat 177 1.1 nat extern dev_type_open(spkropen); 178 1.1 nat extern dev_type_close(spkrclose); 179 1.1 nat extern dev_type_ioctl(spkrioctl); 180 1.1 nat 181 1.1 nat const struct cdevsw wsbell_cdevsw = { 182 1.1 nat .d_open = noopen, 183 1.1 nat .d_close = noclose, 184 1.1 nat .d_read = noread, 185 1.1 nat .d_write = nowrite, 186 1.1 nat .d_ioctl = noioctl, 187 1.1 nat .d_stop = nostop, 188 1.1 nat .d_tty = notty, 189 1.1 nat .d_poll = nopoll, 190 1.1 nat .d_mmap = nommap, 191 1.1 nat .d_kqfilter = nokqfilter, 192 1.1 nat .d_discard = nodiscard, 193 1.1 nat .d_flag = D_OTHER 194 1.1 nat }; 195 1.1 nat 196 1.1 nat #if NWSMUX > 0 197 1.1 nat struct wssrcops wsbell_srcops = { 198 1.1 nat WSMUX_BELL, 199 1.1 nat wsbell_mux_open, wsbell_mux_close, wsbelldoioctl, wsbelldoioctl, NULL 200 1.1 nat }; 201 1.1 nat #endif 202 1.1 nat 203 1.1 nat int 204 1.1 nat wsbell_match(device_t parent, cfdata_t match, void *aux) 205 1.1 nat { 206 1.1 nat return (1); 207 1.1 nat } 208 1.1 nat 209 1.1 nat void 210 1.1 nat wsbell_attach(device_t parent, device_t self, void *aux) 211 1.1 nat { 212 1.10 isaki struct wsbell_softc *sc = device_private(self); 213 1.1 nat struct wsbelldev_attach_args *ap = aux; 214 1.1 nat #if NWSMUX > 0 215 1.1 nat int mux, error; 216 1.1 nat #endif 217 1.1 nat 218 1.1 nat sc->sc_base.me_dv = self; 219 1.1 nat sc->sc_accesscookie = ap->accesscookie; 220 1.1 nat 221 1.7 nat sc->sc_dying = false; 222 1.1 nat sc->sc_spkr = device_unit(parent); 223 1.1 nat sc->sc_bell_data = wskbd_default_bell_data; 224 1.1 nat #if NWSMUX > 0 225 1.1 nat sc->sc_base.me_ops = &wsbell_srcops; 226 1.1 nat mux = device_cfdata(self)->wsbelldevcf_mux; 227 1.1 nat if (mux >= 0) { 228 1.1 nat error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base); 229 1.1 nat if (error) 230 1.1 nat aprint_error(" attach error=%d", error); 231 1.1 nat else 232 1.1 nat aprint_normal(" mux %d", mux); 233 1.1 nat } 234 1.1 nat #else 235 1.1 nat if (device_cfdata(self)->wsbelldevcf_mux >= 0) 236 1.1 nat aprint_normal(" (mux ignored)"); 237 1.1 nat #endif 238 1.1 nat 239 1.1 nat aprint_naive("\n"); 240 1.1 nat aprint_normal("\n"); 241 1.1 nat 242 1.1 nat if (!pmf_device_register(self, NULL, NULL)) 243 1.1 nat aprint_error_dev(self, "couldn't establish power handler\n"); 244 1.1 nat 245 1.1 nat mutex_init(&sc->sc_bellock, MUTEX_DEFAULT, IPL_SCHED); 246 1.1 nat cv_init(&sc->sc_bellcv, "bellcv"); 247 1.1 nat 248 1.1 nat kthread_create(PRI_BIO, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL, 249 1.1 nat bell_thread, sc, &sc->sc_bellthread, "%s", device_xname(self)); 250 1.1 nat } 251 1.1 nat 252 1.1 nat int 253 1.1 nat wsbell_activate(device_t self, enum devact act) 254 1.1 nat { 255 1.1 nat struct wsbell_softc *sc = device_private(self); 256 1.1 nat 257 1.1 nat if (act == DVACT_DEACTIVATE) 258 1.7 nat sc->sc_dying = true; 259 1.1 nat return (0); 260 1.1 nat } 261 1.1 nat 262 1.1 nat int 263 1.1 nat wsbell_detach(device_t self, int flags) 264 1.1 nat { 265 1.1 nat struct wsbell_softc *sc = device_private(self); 266 1.1 nat struct wseventvar *evar; 267 1.1 nat int maj, mn; 268 1.1 nat int s; 269 1.1 nat 270 1.1 nat #if NWSMUX > 0 271 1.1 nat /* Tell parent mux we're leaving. */ 272 1.1 nat if (sc->sc_base.me_parent != NULL) { 273 1.1 nat DPRINTF(("wsbell_detach:\n")); 274 1.1 nat wsmux_detach_sc(&sc->sc_base); 275 1.1 nat } 276 1.1 nat #endif 277 1.1 nat 278 1.1 nat /* If we're open ... */ 279 1.1 nat evar = sc->sc_base.me_evp; 280 1.1 nat if (evar != NULL && evar->io != NULL) { 281 1.1 nat s = spltty(); 282 1.1 nat if (--sc->sc_refcnt >= 0) { 283 1.1 nat struct wscons_event event; 284 1.1 nat 285 1.1 nat /* Wake everyone by generating a dummy event. */ 286 1.1 nat event.type = 0; 287 1.1 nat event.value = 0; 288 1.1 nat if (wsevent_inject(evar, &event, 1) != 0) 289 1.1 nat wsevent_wakeup(evar); 290 1.1 nat 291 1.1 nat /* Wait for processes to go away. */ 292 1.1 nat if (tsleep(sc, PZERO, "wsmdet", hz * 60)) 293 1.1 nat printf("wsbell_detach: %s didn't detach\n", 294 1.1 nat device_xname(self)); 295 1.1 nat } 296 1.1 nat splx(s); 297 1.1 nat } 298 1.1 nat 299 1.1 nat /* locate the major number */ 300 1.1 nat maj = cdevsw_lookup_major(&wsbell_cdevsw); 301 1.1 nat 302 1.1 nat /* Nuke the vnodes for any open instances (calls close). */ 303 1.1 nat mn = device_unit(self); 304 1.1 nat vdevgone(maj, mn, mn, VCHR); 305 1.1 nat 306 1.1 nat mutex_enter(&sc->sc_bellock); 307 1.7 nat sc->sc_dying = true; 308 1.1 nat 309 1.1 nat cv_broadcast(&sc->sc_bellcv); 310 1.1 nat mutex_exit(&sc->sc_bellock); 311 1.1 nat 312 1.1 nat kthread_join(sc->sc_bellthread); 313 1.1 nat cv_destroy(&sc->sc_bellcv); 314 1.1 nat mutex_destroy(&sc->sc_bellock); 315 1.1 nat 316 1.1 nat return (0); 317 1.1 nat } 318 1.1 nat 319 1.1 nat #if NWSMUX > 0 320 1.1 nat int 321 1.1 nat wsbelldoopen(struct wsbell_softc *sc, struct wseventvar *evp) 322 1.1 nat { 323 1.1 nat return (0); 324 1.1 nat } 325 1.1 nat 326 1.1 nat /* A wrapper around the ioctl() workhorse to make reference counting easy. */ 327 1.1 nat int 328 1.1 nat wsbelldoioctl(device_t dv, u_long cmd, void *data, int flag, 329 1.1 nat struct lwp *l) 330 1.1 nat { 331 1.1 nat struct wsbell_softc *sc = device_private(dv); 332 1.1 nat int error; 333 1.1 nat 334 1.1 nat sc->sc_refcnt++; 335 1.1 nat error = wsbell_do_ioctl(sc, cmd, data, flag, l); 336 1.1 nat if (--sc->sc_refcnt < 0) 337 1.1 nat wakeup(sc); 338 1.1 nat return (error); 339 1.1 nat } 340 1.1 nat 341 1.1 nat int 342 1.1 nat wsbell_do_ioctl(struct wsbell_softc *sc, u_long cmd, void *data, 343 1.1 nat int flag, struct lwp *l) 344 1.1 nat { 345 1.1 nat struct wskbd_bell_data *ubdp, *kbdp; 346 1.8 nat int error; 347 1.8 nat 348 1.7 nat if (sc->sc_dying == true) 349 1.1 nat return (EIO); 350 1.1 nat 351 1.1 nat /* 352 1.1 nat * Try the wsbell specific ioctls. 353 1.1 nat */ 354 1.1 nat switch (cmd) { 355 1.1 nat case WSKBDIO_SETBELL: 356 1.1 nat if ((flag & FWRITE) == 0) 357 1.1 nat return (EACCES); 358 1.1 nat kbdp = &sc->sc_bell_data; 359 1.8 nat setbell: 360 1.1 nat ubdp = (struct wskbd_bell_data *)data; 361 1.1 nat SETBELL(kbdp, ubdp, kbdp); 362 1.1 nat return (0); 363 1.1 nat 364 1.1 nat case WSKBDIO_GETBELL: 365 1.1 nat kbdp = &sc->sc_bell_data; 366 1.8 nat getbell: 367 1.1 nat ubdp = (struct wskbd_bell_data *)data; 368 1.1 nat SETBELL(ubdp, kbdp, kbdp); 369 1.1 nat return (0); 370 1.1 nat 371 1.8 nat case WSKBDIO_SETDEFAULTBELL: 372 1.8 nat if ((error = kauth_authorize_device(l->l_cred, 373 1.8 nat KAUTH_DEVICE_WSCONS_KEYBOARD_BELL, NULL, NULL, 374 1.8 nat NULL, NULL)) != 0) 375 1.8 nat return (error); 376 1.8 nat kbdp = &wskbd_default_bell_data; 377 1.8 nat goto setbell; 378 1.8 nat 379 1.8 nat 380 1.8 nat case WSKBDIO_GETDEFAULTBELL: 381 1.8 nat kbdp = &wskbd_default_bell_data; 382 1.8 nat goto getbell; 383 1.8 nat 384 1.1 nat case WSKBDIO_BELL: 385 1.1 nat if ((flag & FWRITE) == 0) 386 1.1 nat return (EACCES); 387 1.1 nat spkr_audio_play(sc, sc->sc_bell_data.pitch, 388 1.1 nat sc->sc_bell_data.period, sc->sc_bell_data.volume); 389 1.1 nat 390 1.1 nat return 0; 391 1.1 nat 392 1.1 nat case WSKBDIO_COMPLEXBELL: 393 1.1 nat if ((flag & FWRITE) == 0) 394 1.1 nat return (EACCES); 395 1.1 nat if (data == NULL) 396 1.1 nat return 0; 397 1.12 isaki ubdp = (struct wskbd_bell_data *)data; 398 1.12 isaki SETBELL(ubdp, ubdp, &sc->sc_bell_data); 399 1.12 isaki spkr_audio_play(sc, ubdp->pitch, ubdp->period, ubdp->volume); 400 1.1 nat return 0; 401 1.10 isaki } 402 1.1 nat 403 1.1 nat return (EPASSTHROUGH); 404 1.1 nat } 405 1.1 nat #endif 406 1.1 nat 407 1.1 nat static void 408 1.1 nat bell_thread(void *arg) 409 1.1 nat { 410 1.1 nat struct wsbell_softc *sc = arg; 411 1.1 nat struct vbell_args *vb = &sc->sc_bell_args; 412 1.1 nat tone_t tone; 413 1.1 nat u_int vol; 414 1.10 isaki 415 1.1 nat for (;;) { 416 1.1 nat mutex_enter(&sc->sc_bellock); 417 1.1 nat cv_wait_sig(&sc->sc_bellcv, &sc->sc_bellock); 418 1.10 isaki 419 1.7 nat if (sc->sc_dying == true) { 420 1.1 nat mutex_exit(&sc->sc_bellock); 421 1.1 nat kthread_exit(0); 422 1.1 nat } 423 1.10 isaki 424 1.1 nat tone.frequency = vb->pitch; 425 1.11 isaki /* 426 1.11 isaki * period (derived from wskbd) is in msec. 427 1.11 isaki * duration (derived from spkr) is in units of 10msec. 428 1.11 isaki */ 429 1.11 isaki tone.duration = vb->period / 10; 430 1.1 nat vol = vb->volume; 431 1.1 nat mutex_exit(&sc->sc_bellock); 432 1.1 nat 433 1.1 nat if (spkropen(sc->sc_spkr, FWRITE, 0, NULL) != 0) 434 1.1 nat continue; 435 1.1 nat spkrioctl(sc->sc_spkr, SPKRSETVOL, &vol, 0, curlwp); 436 1.1 nat spkrioctl(sc->sc_spkr, SPKRTONE, &tone, 0, curlwp); 437 1.1 nat spkrclose(sc->sc_spkr, FWRITE, 0, curlwp); 438 1.1 nat } 439 1.1 nat } 440 1.1 nat 441 1.1 nat static inline void 442 1.1 nat spkr_audio_play(struct wsbell_softc *sc, u_int pitch, u_int period, u_int volume) 443 1.1 nat { 444 1.1 nat 445 1.1 nat mutex_enter(&sc->sc_bellock); 446 1.1 nat sc->sc_bell_args.pitch = pitch; 447 1.11 isaki sc->sc_bell_args.period = period; 448 1.1 nat sc->sc_bell_args.volume = volume; 449 1.1 nat 450 1.1 nat cv_broadcast(&sc->sc_bellcv); 451 1.1 nat mutex_exit(&sc->sc_bellock); 452 1.1 nat } 453 1.1 nat 454 1.1 nat #if NWSMUX > 0 455 1.1 nat int 456 1.1 nat wsbell_mux_open(struct wsevsrc *me, struct wseventvar *evp) 457 1.1 nat { 458 1.1 nat struct wsbell_softc *sc = (struct wsbell_softc *)me; 459 1.1 nat 460 1.1 nat if (sc->sc_base.me_evp != NULL) 461 1.1 nat return (EBUSY); 462 1.1 nat 463 1.1 nat return wsbelldoopen(sc, evp); 464 1.1 nat } 465 1.1 nat 466 1.1 nat int 467 1.1 nat wsbell_mux_close(struct wsevsrc *me) 468 1.1 nat { 469 1.1 nat struct wsbell_softc *sc = (struct wsbell_softc *)me; 470 1.1 nat 471 1.1 nat sc->sc_base.me_evp = NULL; 472 1.1 nat 473 1.1 nat return (0); 474 1.1 nat } 475 1.1 nat #endif /* NWSMUX > 0 */ 476 1.2 pgoyette 477 1.2 pgoyette MODULE(MODULE_CLASS_DRIVER, wsbell, "spkr"); 478 1.2 pgoyette 479 1.2 pgoyette #ifdef _MODULE 480 1.2 pgoyette int wsbell_bmajor = -1, wsbell_cmajor = -1; 481 1.2 pgoyette 482 1.2 pgoyette #include "ioconf.c" 483 1.2 pgoyette #endif 484 1.2 pgoyette 485 1.2 pgoyette static int 486 1.2 pgoyette wsbell_modcmd(modcmd_t cmd, void *arg) 487 1.2 pgoyette { 488 1.2 pgoyette int error = 0; 489 1.2 pgoyette 490 1.2 pgoyette switch (cmd) { 491 1.2 pgoyette case MODULE_CMD_INIT: 492 1.2 pgoyette #ifdef _MODULE 493 1.2 pgoyette error = devsw_attach("wsbell", NULL, &wsbell_bmajor, 494 1.2 pgoyette &wsbell_cdevsw, &wsbell_cmajor); 495 1.2 pgoyette if (error) 496 1.2 pgoyette break; 497 1.2 pgoyette 498 1.2 pgoyette error = config_init_component(cfdriver_ioconf_wsbell, 499 1.2 pgoyette cfattach_ioconf_wsbell, cfdata_ioconf_wsbell); 500 1.2 pgoyette if (error) 501 1.2 pgoyette devsw_detach(NULL, &wsbell_cdevsw); 502 1.2 pgoyette #endif 503 1.2 pgoyette break; 504 1.2 pgoyette 505 1.2 pgoyette case MODULE_CMD_FINI: 506 1.2 pgoyette #ifdef _MODULE 507 1.2 pgoyette error = config_fini_component(cfdriver_ioconf_wsbell, 508 1.2 pgoyette cfattach_ioconf_wsbell, cfdata_ioconf_wsbell); 509 1.14 pgoyette if (error == 0) 510 1.14 pgoyette devsw_detach(NULL, &wsbell_cdevsw); 511 1.2 pgoyette #endif 512 1.2 pgoyette break; 513 1.2 pgoyette 514 1.2 pgoyette default: 515 1.2 pgoyette error = ENOTTY; 516 1.2 pgoyette break; 517 1.2 pgoyette } 518 1.2 pgoyette 519 1.2 pgoyette return error; 520 1.2 pgoyette } 521