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