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