opmbell.c revision 1.23 1 1.23 isaki /* $NetBSD: opmbell.c,v 1.23 2009/01/18 05:00:39 isaki Exp $ */
2 1.1 oki
3 1.1 oki /*
4 1.1 oki * Copyright (c) 1995 MINOURA Makoto, Takuya Harakawa.
5 1.1 oki * All rights reserved.
6 1.1 oki *
7 1.1 oki * Redistribution and use in source and binary forms, with or without
8 1.1 oki * modification, are permitted provided that the following conditions
9 1.1 oki * are met:
10 1.1 oki * 1. Redistributions of source code must retain the above copyright
11 1.1 oki * notice, this list of conditions and the following disclaimer.
12 1.1 oki * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 oki * notice, this list of conditions and the following disclaimer in the
14 1.1 oki * documentation and/or other materials provided with the distribution.
15 1.1 oki * 3. All advertising materials mentioning features or use of this software
16 1.1 oki * must display the following acknowledgement:
17 1.1 oki * This product includes software developed by MINOURA Makoto,
18 1.1 oki * Takuya Harakawa.
19 1.1 oki * 4. Neither the name of the authors may be used to endorse or promote
20 1.1 oki * products derived from this software without specific prior written
21 1.1 oki * permission.
22 1.1 oki *
23 1.1 oki * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 oki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 oki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 oki * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 oki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 oki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 oki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 oki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 oki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 oki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 oki * SUCH DAMAGE.
34 1.1 oki *
35 1.1 oki */
36 1.1 oki
37 1.1 oki /*
38 1.1 oki * bell device driver
39 1.1 oki */
40 1.11 lukem
41 1.11 lukem #include <sys/cdefs.h>
42 1.23 isaki __KERNEL_RCSID(0, "$NetBSD: opmbell.c,v 1.23 2009/01/18 05:00:39 isaki Exp $");
43 1.1 oki
44 1.1 oki #include "bell.h"
45 1.1 oki #if NBELL > 0
46 1.1 oki
47 1.1 oki #if NBELL > 1
48 1.1 oki #undef NBELL
49 1.1 oki #define NBELL 1
50 1.1 oki #endif
51 1.1 oki
52 1.1 oki #include <sys/param.h>
53 1.1 oki #include <sys/errno.h>
54 1.1 oki #include <sys/uio.h>
55 1.1 oki #include <sys/device.h>
56 1.1 oki #include <sys/malloc.h>
57 1.1 oki #include <sys/file.h>
58 1.1 oki #include <sys/systm.h>
59 1.7 thorpej #include <sys/callout.h>
60 1.5 oki #include <sys/conf.h>
61 1.10 jdolecek #include <sys/event.h>
62 1.18 isaki #include <sys/kernel.h>
63 1.1 oki
64 1.12 minoura #include <machine/opmbellio.h>
65 1.12 minoura
66 1.12 minoura #include <x68k/dev/opmvar.h>
67 1.1 oki
68 1.6 minoura /* In opm.c. */
69 1.13 chs void opm_set_volume(int, int);
70 1.13 chs void opm_set_key(int, int);
71 1.13 chs void opm_set_voice(int, struct opm_voice *);
72 1.13 chs void opm_key_on(u_char);
73 1.13 chs void opm_key_off(u_char);
74 1.6 minoura
75 1.13 chs static u_int bell_pitchtokey(u_int);
76 1.13 chs static void bell_timeout(void *);
77 1.1 oki
78 1.1 oki struct bell_softc {
79 1.1 oki int sc_flags;
80 1.1 oki u_char ch;
81 1.1 oki u_char volume;
82 1.1 oki u_int pitch;
83 1.1 oki u_int msec;
84 1.1 oki u_int key;
85 1.1 oki };
86 1.1 oki
87 1.1 oki struct bell_softc *bell_softc;
88 1.1 oki
89 1.20 ad callout_t bell_ch;
90 1.7 thorpej
91 1.1 oki static struct opm_voice vtab[NBELL];
92 1.1 oki
93 1.12 minoura static struct opm_voice bell_voice = DEFAULT_BELL_VOICE;
94 1.12 minoura
95 1.1 oki /* sc_flags values */
96 1.1 oki #define BELLF_READ 0x01
97 1.1 oki #define BELLF_WRITE 0x02
98 1.1 oki #define BELLF_ALIVE 0x04
99 1.1 oki #define BELLF_OPEN 0x08
100 1.1 oki #define BELLF_OUT 0x10
101 1.1 oki #define BELLF_ON 0x20
102 1.1 oki
103 1.1 oki #define UNIT(x) minor(x)
104 1.1 oki
105 1.13 chs void bell_on(struct bell_softc *);
106 1.13 chs void bell_off(struct bell_softc *);
107 1.13 chs void opm_bell(void);
108 1.13 chs void opm_bell_on(void);
109 1.13 chs void opm_bell_off(void);
110 1.13 chs int opm_bell_setup(struct bell_info *);
111 1.13 chs int bellmstohz(int);
112 1.5 oki
113 1.13 chs void bellattach(int);
114 1.9 gehenna
115 1.9 gehenna dev_type_open(bellopen);
116 1.9 gehenna dev_type_close(bellclose);
117 1.9 gehenna dev_type_ioctl(bellioctl);
118 1.9 gehenna
119 1.9 gehenna const struct cdevsw bell_cdevsw = {
120 1.9 gehenna bellopen, bellclose, noread, nowrite, bellioctl,
121 1.10 jdolecek nostop, notty, nopoll, nommap, nokqfilter,
122 1.9 gehenna };
123 1.5 oki
124 1.16 isaki void
125 1.13 chs bellattach(int num)
126 1.1 oki {
127 1.13 chs u_long size;
128 1.13 chs struct bell_softc *sc;
129 1.1 oki int unit;
130 1.1 oki
131 1.1 oki if (num <= 0)
132 1.1 oki return;
133 1.20 ad callout_init(&bell_ch, 0);
134 1.1 oki size = num * sizeof(struct bell_softc);
135 1.23 isaki bell_softc = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
136 1.23 isaki if (bell_softc == NULL) {
137 1.4 christos printf("WARNING: no memory for opm bell\n");
138 1.1 oki return;
139 1.1 oki }
140 1.1 oki
141 1.1 oki for (unit = 0; unit < num; unit++) {
142 1.1 oki sc = &bell_softc[unit];
143 1.1 oki sc->sc_flags = BELLF_ALIVE;
144 1.1 oki sc->ch = BELL_CHANNEL;
145 1.1 oki sc->volume = BELL_VOLUME;
146 1.1 oki sc->pitch = BELL_PITCH;
147 1.1 oki sc->msec = BELL_DURATION;
148 1.1 oki sc->key = bell_pitchtokey(sc->pitch);
149 1.1 oki
150 1.1 oki /* setup initial voice parameter */
151 1.8 wiz memcpy(&vtab[unit], &bell_voice, sizeof(bell_voice));
152 1.1 oki opm_set_voice(sc->ch, &vtab[unit]);
153 1.1 oki
154 1.4 christos printf("bell%d: YM2151 OPM bell emulation.\n", unit);
155 1.1 oki }
156 1.1 oki }
157 1.1 oki
158 1.16 isaki int
159 1.14 christos bellopen(dev_t dev, int flags, int mode, struct lwp *l)
160 1.1 oki {
161 1.13 chs int unit = UNIT(dev);
162 1.13 chs struct bell_softc *sc = &bell_softc[unit];
163 1.1 oki
164 1.1 oki if (unit >= NBELL || !(sc->sc_flags & BELLF_ALIVE))
165 1.1 oki return ENXIO;
166 1.1 oki
167 1.1 oki if (sc->sc_flags & BELLF_OPEN)
168 1.1 oki return EBUSY;
169 1.1 oki
170 1.1 oki sc->sc_flags |= BELLF_OPEN;
171 1.1 oki sc->sc_flags |= (flags & (FREAD | FWRITE));
172 1.1 oki
173 1.1 oki return 0;
174 1.1 oki }
175 1.1 oki
176 1.16 isaki int
177 1.14 christos bellclose(dev_t dev, int flags, int mode, struct lwp *l)
178 1.1 oki {
179 1.1 oki int unit = UNIT(dev);
180 1.1 oki struct bell_softc *sc = &bell_softc[unit];
181 1.1 oki
182 1.1 oki sc->sc_flags &= ~BELLF_OPEN;
183 1.5 oki return 0;
184 1.1 oki }
185 1.1 oki
186 1.16 isaki int
187 1.15 christos bellioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
188 1.1 oki {
189 1.1 oki int unit = UNIT(dev);
190 1.1 oki struct bell_softc *sc = &bell_softc[unit];
191 1.1 oki
192 1.1 oki switch (cmd) {
193 1.1 oki case BELLIOCGPARAM:
194 1.1 oki {
195 1.17 isaki struct bell_info *bp = (struct bell_info *)addr;
196 1.17 isaki if (!(sc->sc_flags & FREAD))
197 1.17 isaki return EBADF;
198 1.17 isaki
199 1.17 isaki bp->volume = sc->volume;
200 1.17 isaki bp->pitch = sc->pitch;
201 1.17 isaki bp->msec = sc->msec;
202 1.17 isaki break;
203 1.1 oki }
204 1.1 oki
205 1.1 oki case BELLIOCSPARAM:
206 1.1 oki {
207 1.17 isaki struct bell_info *bp = (struct bell_info *)addr;
208 1.1 oki
209 1.17 isaki if (!(sc->sc_flags & FWRITE))
210 1.17 isaki return EBADF;
211 1.1 oki
212 1.17 isaki return opm_bell_setup(bp);
213 1.1 oki }
214 1.1 oki
215 1.1 oki case BELLIOCGVOICE:
216 1.17 isaki if (!(sc->sc_flags & FREAD))
217 1.17 isaki return EBADF;
218 1.1 oki
219 1.17 isaki if (addr == NULL)
220 1.17 isaki return EFAULT;
221 1.1 oki
222 1.17 isaki memcpy(addr, &vtab[unit], sizeof(struct opm_voice));
223 1.17 isaki break;
224 1.1 oki
225 1.1 oki case BELLIOCSVOICE:
226 1.17 isaki if (!(sc->sc_flags & FWRITE))
227 1.17 isaki return EBADF;
228 1.1 oki
229 1.17 isaki if (addr == NULL)
230 1.17 isaki return EFAULT;
231 1.1 oki
232 1.17 isaki memcpy(&vtab[unit], addr, sizeof(struct opm_voice));
233 1.17 isaki opm_set_voice(sc->ch, &vtab[unit]);
234 1.17 isaki break;
235 1.1 oki
236 1.1 oki default:
237 1.17 isaki return EINVAL;
238 1.1 oki }
239 1.1 oki return 0;
240 1.1 oki }
241 1.1 oki
242 1.1 oki /*
243 1.1 oki * The next table is used for calculating KeyCode/KeyFraction pair
244 1.1 oki * from frequency.
245 1.1 oki */
246 1.1 oki
247 1.1 oki static u_int note[] = {
248 1.13 chs 0x0800, 0x0808, 0x0810, 0x081c,
249 1.13 chs 0x0824, 0x0830, 0x0838, 0x0844,
250 1.13 chs 0x084c, 0x0858, 0x0860, 0x086c,
251 1.13 chs 0x0874, 0x0880, 0x0888, 0x0890,
252 1.13 chs 0x089c, 0x08a4, 0x08b0, 0x08b8,
253 1.13 chs 0x08c4, 0x08cc, 0x08d8, 0x08e0,
254 1.13 chs 0x08ec, 0x08f4, 0x0900, 0x0908,
255 1.13 chs 0x0910, 0x091c, 0x0924, 0x092c,
256 1.13 chs 0x0938, 0x0940, 0x0948, 0x0954,
257 1.13 chs 0x095c, 0x0968, 0x0970, 0x0978,
258 1.13 chs 0x0984, 0x098c, 0x0994, 0x09a0,
259 1.13 chs 0x09a8, 0x09b4, 0x09bc, 0x09c4,
260 1.13 chs 0x09d0, 0x09d8, 0x09e0, 0x09ec,
261 1.13 chs 0x09f4, 0x0a00, 0x0a08, 0x0a10,
262 1.13 chs 0x0a18, 0x0a20, 0x0a28, 0x0a30,
263 1.13 chs 0x0a38, 0x0a44, 0x0a4c, 0x0a54,
264 1.13 chs 0x0a5c, 0x0a64, 0x0a6c, 0x0a74,
265 1.13 chs 0x0a80, 0x0a88, 0x0a90, 0x0a98,
266 1.13 chs 0x0aa0, 0x0aa8, 0x0ab0, 0x0ab8,
267 1.13 chs 0x0ac4, 0x0acc, 0x0ad4, 0x0adc,
268 1.13 chs 0x0ae4, 0x0aec, 0x0af4, 0x0c00,
269 1.13 chs 0x0c08, 0x0c10, 0x0c18, 0x0c20,
270 1.13 chs 0x0c28, 0x0c30, 0x0c38, 0x0c40,
271 1.13 chs 0x0c48, 0x0c50, 0x0c58, 0x0c60,
272 1.13 chs 0x0c68, 0x0c70, 0x0c78, 0x0c84,
273 1.13 chs 0x0c8c, 0x0c94, 0x0c9c, 0x0ca4,
274 1.13 chs 0x0cac, 0x0cb4, 0x0cbc, 0x0cc4,
275 1.13 chs 0x0ccc, 0x0cd4, 0x0cdc, 0x0ce4,
276 1.13 chs 0x0cec, 0x0cf4, 0x0d00, 0x0d04,
277 1.13 chs 0x0d0c, 0x0d14, 0x0d1c, 0x0d24,
278 1.13 chs 0x0d2c, 0x0d34, 0x0d3c, 0x0d44,
279 1.13 chs 0x0d4c, 0x0d54, 0x0d5c, 0x0d64,
280 1.13 chs 0x0d6c, 0x0d74, 0x0d7c, 0x0d80,
281 1.13 chs 0x0d88, 0x0d90, 0x0d98, 0x0da0,
282 1.13 chs 0x0da8, 0x0db0, 0x0db8, 0x0dc0,
283 1.13 chs 0x0dc8, 0x0dd0, 0x0dd8, 0x0de0,
284 1.13 chs 0x0de8, 0x0df0, 0x0df8, 0x0e00,
285 1.13 chs 0x0e04, 0x0e0c, 0x0e14, 0x0e1c,
286 1.13 chs 0x0e24, 0x0e28, 0x0e30, 0x0e38,
287 1.13 chs 0x0e40, 0x0e48, 0x0e50, 0x0e54,
288 1.13 chs 0x0e5c, 0x0e64, 0x0e6c, 0x0e74,
289 1.13 chs 0x0e7c, 0x0e80, 0x0e88, 0x0e90,
290 1.13 chs 0x0e98, 0x0ea0, 0x0ea8, 0x0eac,
291 1.13 chs 0x0eb4, 0x0ebc, 0x0ec4, 0x0ecc,
292 1.13 chs 0x0ed4, 0x0ed8, 0x0ee0, 0x0ee8,
293 1.13 chs 0x0ef0, 0x0ef8, 0x1000, 0x1004,
294 1.13 chs 0x100c, 0x1014, 0x1018, 0x1020,
295 1.13 chs 0x1028, 0x1030, 0x1034, 0x103c,
296 1.13 chs 0x1044, 0x104c, 0x1050, 0x1058,
297 1.13 chs 0x1060, 0x1064, 0x106c, 0x1074,
298 1.13 chs 0x107c, 0x1080, 0x1088, 0x1090,
299 1.13 chs 0x1098, 0x109c, 0x10a4, 0x10ac,
300 1.13 chs 0x10b0, 0x10b8, 0x10c0, 0x10c8,
301 1.13 chs 0x10cc, 0x10d4, 0x10dc, 0x10e4,
302 1.13 chs 0x10e8, 0x10f0, 0x10f8, 0x1100,
303 1.13 chs 0x1104, 0x110c, 0x1110, 0x1118,
304 1.13 chs 0x1120, 0x1124, 0x112c, 0x1134,
305 1.13 chs 0x1138, 0x1140, 0x1148, 0x114c,
306 1.13 chs 0x1154, 0x1158, 0x1160, 0x1168,
307 1.13 chs 0x116c, 0x1174, 0x117c, 0x1180,
308 1.13 chs 0x1188, 0x1190, 0x1194, 0x119c,
309 1.13 chs 0x11a4, 0x11a8, 0x11b0, 0x11b4,
310 1.13 chs 0x11bc, 0x11c4, 0x11c8, 0x11d0,
311 1.13 chs 0x11d8, 0x11dc, 0x11e4, 0x11ec,
312 1.13 chs 0x11f0, 0x11f8, 0x1200, 0x1204,
313 1.13 chs 0x120c, 0x1210, 0x1218, 0x121c,
314 1.13 chs 0x1224, 0x1228, 0x1230, 0x1238,
315 1.13 chs 0x123c, 0x1244, 0x1248, 0x1250,
316 1.13 chs 0x1254, 0x125c, 0x1260, 0x1268,
317 1.13 chs 0x1270, 0x1274, 0x127c, 0x1280,
318 1.13 chs 0x1288, 0x128c, 0x1294, 0x129c,
319 1.13 chs 0x12a0, 0x12a8, 0x12ac, 0x12b4,
320 1.13 chs 0x12b8, 0x12c0, 0x12c4, 0x12cc,
321 1.13 chs 0x12d4, 0x12d8, 0x12e0, 0x12e4,
322 1.13 chs 0x12ec, 0x12f0, 0x12f8, 0x1400,
323 1.13 chs 0x1404, 0x1408, 0x1410, 0x1414,
324 1.13 chs 0x141c, 0x1420, 0x1428, 0x142c,
325 1.13 chs 0x1434, 0x1438, 0x1440, 0x1444,
326 1.13 chs 0x1448, 0x1450, 0x1454, 0x145c,
327 1.13 chs 0x1460, 0x1468, 0x146c, 0x1474,
328 1.13 chs 0x1478, 0x1480, 0x1484, 0x1488,
329 1.13 chs 0x1490, 0x1494, 0x149c, 0x14a0,
330 1.13 chs 0x14a8, 0x14ac, 0x14b4, 0x14b8,
331 1.13 chs 0x14c0, 0x14c4, 0x14c8, 0x14d0,
332 1.13 chs 0x14d4, 0x14dc, 0x14e0, 0x14e8,
333 1.13 chs 0x14ec, 0x14f4, 0x14f8, 0x1500,
334 1.13 chs 0x1504, 0x1508, 0x1510, 0x1514,
335 1.13 chs 0x1518, 0x1520, 0x1524, 0x1528,
336 1.13 chs 0x1530, 0x1534, 0x1538, 0x1540,
337 1.13 chs 0x1544, 0x154c, 0x1550, 0x1554,
338 1.13 chs 0x155c, 0x1560, 0x1564, 0x156c,
339 1.13 chs 0x1570, 0x1574, 0x157c, 0x1580,
340 1.13 chs 0x1588, 0x158c, 0x1590, 0x1598,
341 1.13 chs 0x159c, 0x15a0, 0x15a8, 0x15ac,
342 1.13 chs 0x15b0, 0x15b8, 0x15bc, 0x15c4,
343 1.13 chs 0x15c8, 0x15cc, 0x15d4, 0x15d8,
344 1.13 chs 0x15dc, 0x15e4, 0x15e8, 0x15ec,
345 1.13 chs 0x15f4, 0x15f8, 0x1600, 0x1604,
346 1.13 chs 0x1608, 0x160c, 0x1614, 0x1618,
347 1.13 chs 0x161c, 0x1620, 0x1628, 0x162c,
348 1.13 chs 0x1630, 0x1638, 0x163c, 0x1640,
349 1.13 chs 0x1644, 0x164c, 0x1650, 0x1654,
350 1.13 chs 0x165c, 0x1660, 0x1664, 0x1668,
351 1.13 chs 0x1670, 0x1674, 0x1678, 0x1680,
352 1.13 chs 0x1684, 0x1688, 0x168c, 0x1694,
353 1.13 chs 0x1698, 0x169c, 0x16a0, 0x16a8,
354 1.13 chs 0x16ac, 0x16b0, 0x16b8, 0x16bc,
355 1.13 chs 0x16c0, 0x16c4, 0x16cc, 0x16d0,
356 1.13 chs 0x16d4, 0x16dc, 0x16e0, 0x16e4,
357 1.13 chs 0x16e8, 0x16f0, 0x16f4, 0x16f8,
358 1.1 oki };
359 1.1 oki
360 1.16 isaki static u_int
361 1.13 chs bell_pitchtokey(u_int pitch)
362 1.1 oki {
363 1.13 chs int i, oct;
364 1.13 chs u_int key;
365 1.1 oki
366 1.13 chs i = 16 * pitch / 440;
367 1.13 chs for (oct = -1; i > 0; i >>= 1, oct++)
368 1.13 chs ;
369 1.1 oki
370 1.13 chs i = (pitch * 16 - (440 * (1 << oct))) / (1 << oct);
371 1.13 chs key = (oct << 12) + note[i];
372 1.1 oki
373 1.13 chs return key;
374 1.1 oki }
375 1.1 oki
376 1.1 oki /*
377 1.1 oki * The next table is a little trikcy table of volume factors.
378 1.1 oki * Its values have been calculated as table[i] = -15 * log10(i/100)
379 1.1 oki * with an obvious exception for i = 0; This log-table converts a linear
380 1.1 oki * volume-scaling (0...100) to a logarithmic scaling as present in the
381 1.16 isaki * OPM chips. so: Volume 50% = 6 db.
382 1.1 oki */
383 1.1 oki
384 1.1 oki static u_char vol_table[] = {
385 1.13 chs 0x7f, 0x35, 0x2d, 0x28, 0x25, 0x22, 0x20, 0x1e,
386 1.13 chs 0x1d, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15,
387 1.13 chs 0x15, 0x14, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11,
388 1.13 chs 0x10, 0x10, 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0d,
389 1.13 chs 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0a,
390 1.13 chs 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x08, 0x08,
391 1.13 chs 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
392 1.13 chs 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05,
393 1.13 chs 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
394 1.13 chs 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
395 1.13 chs 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
396 1.13 chs 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
397 1.13 chs 0x00, 0x00, 0x00, 0x00, 0x00,
398 1.1 oki };
399 1.1 oki
400 1.16 isaki void
401 1.13 chs bell_on(struct bell_softc *sc)
402 1.1 oki {
403 1.13 chs int sps;
404 1.1 oki
405 1.13 chs sps = spltty();
406 1.13 chs opm_set_volume(sc->ch, vol_table[sc->volume]);
407 1.13 chs opm_set_key(sc->ch, sc->key);
408 1.13 chs splx(sps);
409 1.1 oki
410 1.13 chs opm_key_on(sc->ch);
411 1.13 chs sc->sc_flags |= BELLF_ON;
412 1.1 oki }
413 1.1 oki
414 1.16 isaki void
415 1.13 chs bell_off(struct bell_softc *sc)
416 1.1 oki {
417 1.13 chs if (sc->sc_flags & BELLF_ON) {
418 1.13 chs opm_key_off(sc->ch);
419 1.13 chs sc->sc_flags &= ~BELLF_ON;
420 1.13 chs }
421 1.1 oki }
422 1.1 oki
423 1.16 isaki void
424 1.13 chs opm_bell(void)
425 1.1 oki {
426 1.13 chs struct bell_softc *sc = &bell_softc[0];
427 1.13 chs int ticks;
428 1.1 oki
429 1.13 chs if (sc->msec != 0) {
430 1.13 chs if (sc->sc_flags & BELLF_OUT) {
431 1.13 chs bell_timeout(0);
432 1.13 chs } else if (sc->sc_flags & BELLF_ON)
433 1.13 chs return;
434 1.1 oki
435 1.13 chs ticks = bellmstohz(sc->msec);
436 1.1 oki
437 1.13 chs bell_on(sc);
438 1.13 chs sc->sc_flags |= BELLF_OUT;
439 1.1 oki
440 1.13 chs callout_reset(&bell_ch, ticks, bell_timeout, NULL);
441 1.13 chs }
442 1.1 oki }
443 1.1 oki
444 1.16 isaki static void
445 1.13 chs bell_timeout(void *arg)
446 1.1 oki {
447 1.13 chs struct bell_softc *sc = &bell_softc[0];
448 1.1 oki
449 1.19 isaki sc->sc_flags &= ~BELLF_OUT;
450 1.13 chs bell_off(sc);
451 1.13 chs callout_stop(&bell_ch);
452 1.1 oki }
453 1.1 oki
454 1.16 isaki void
455 1.13 chs opm_bell_on(void)
456 1.1 oki {
457 1.13 chs struct bell_softc *sc = &bell_softc[0];
458 1.13 chs
459 1.13 chs if (sc->sc_flags & BELLF_OUT)
460 1.13 chs bell_timeout(0);
461 1.13 chs if (sc->sc_flags & BELLF_ON)
462 1.13 chs return;
463 1.1 oki
464 1.13 chs bell_on(sc);
465 1.13 chs }
466 1.1 oki
467 1.16 isaki void
468 1.13 chs opm_bell_off(void)
469 1.13 chs {
470 1.13 chs struct bell_softc *sc = &bell_softc[0];
471 1.13 chs
472 1.13 chs if (sc->sc_flags & BELLF_ON)
473 1.13 chs bell_off(sc);
474 1.1 oki }
475 1.1 oki
476 1.16 isaki int
477 1.13 chs opm_bell_setup(struct bell_info *data)
478 1.1 oki {
479 1.13 chs struct bell_softc *sc = &bell_softc[0];
480 1.1 oki
481 1.13 chs /* bounds check */
482 1.13 chs if (data->pitch > MAXBPITCH || data->pitch < MINBPITCH ||
483 1.13 chs data->volume > MAXBVOLUME || data->msec > MAXBTIME) {
484 1.13 chs return EINVAL;
485 1.13 chs } else {
486 1.13 chs sc->volume = data->volume;
487 1.13 chs sc->pitch = data->pitch;
488 1.13 chs sc->msec = data->msec;
489 1.13 chs sc->key = bell_pitchtokey(data->pitch);
490 1.13 chs }
491 1.13 chs return 0;
492 1.1 oki }
493 1.1 oki
494 1.16 isaki int
495 1.13 chs bellmstohz(int m)
496 1.13 chs {
497 1.13 chs int h = m;
498 1.13 chs
499 1.13 chs if (h > 0) {
500 1.13 chs h = h * hz / 1000;
501 1.13 chs if (h == 0)
502 1.13 chs h = 1000 / hz;
503 1.13 chs }
504 1.13 chs return h;
505 1.1 oki }
506 1.1 oki
507 1.1 oki #endif
508