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