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