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