/* $OpenBSD: nec86.c,v 1.3 2016/09/19 06:46:43 ratchov Exp $ */ /* $NecBSD: nec86.c,v 1.11 1999/07/23 11:04:39 honda Exp $ */ /* $NetBSD$ */ /* * [NetBSD for NEC PC-98 series] * Copyright (c) 1996, 1997, 1998 * NetBSD/pc98 porting staff. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * nec86.c * * NEC PC-9801-86 SoundBoard PCM driver for NetBSD/pc98. * Written by NAGAO Tadaaki, Feb 10, 1996. * * Modified by N. Honda, Mar 7, 1998 */ #include #include #include #include #include #include #include #include /* PC_BASE */ #include #include #include #include #include #include #include #define NEC_SCR_SIDMASK 0xf0 #define NEC_SCR_MASK 0x0f #define NEC_SCR_EXT_ENABLE 0x01 /* * Define our interface to the higher level audio driver. */ struct audio_hw_if nec86_hw_if = { .open = nec86hw_open, .close = nec86hw_close, .set_params = nec86hw_set_params, .round_blocksize = nec86hw_round_blocksize, .commit_settings = nec86hw_commit_settings, .init_output = nec86hw_pdma_init_output, .init_input = nec86hw_pdma_init_input, .start_output = nec86hw_pdma_output, .start_input = nec86hw_pdma_input, .halt_output = nec86hw_halt_pdma, .halt_input = nec86hw_halt_pdma, .speaker_ctl = nec86hw_speaker_ctl, .setfd = nec86hw_setfd, .set_port = nec86hw_mixer_set_port, .get_port = nec86hw_mixer_get_port, .query_devinfo = nec86hw_mixer_query_devinfo, .allocm = NULL, .freem = NULL, .round_buffersize = NULL, .get_props = nec86_get_props, .trigger_output = NULL, .trigger_input = NULL }; /* * YAMAHA YM2608(OPNA) register read/write functions */ #define YM_INDEX 0 #define YM_DATA 2 void nec86_ym_read(struct nec86_softc *, u_int8_t, u_int8_t *); void nec86_ym_write(struct nec86_softc *, u_int8_t, u_int8_t); void nec86_ym_read(struct nec86_softc *sc, u_int8_t index, u_int8_t *data) { bus_space_write_1(sc->sc_ym_iot, sc->sc_ym_iobase + sc->sc_ym_ioh, YM_INDEX, index); delay(100); *data = bus_space_read_1(sc->sc_ym_iot, sc->sc_ym_iobase + sc->sc_ym_ioh, YM_DATA); delay(100); } void nec86_ym_write(struct nec86_softc *sc, u_int8_t index, u_int8_t data) { bus_space_write_1(sc->sc_ym_iot, sc->sc_ym_iobase + sc->sc_ym_ioh, YM_INDEX, index); delay(100); bus_space_write_1(sc->sc_ym_iot, sc->sc_ym_iobase + sc->sc_ym_ioh, YM_DATA, data); delay(100); } /* * Probe for NEC PC-9801-86 SoundBoard hardware. */ int nec86_probesubr(bus_space_tag_t iot, bus_space_handle_t ioh, bus_space_handle_t n86ioh) { u_int8_t data; #ifdef notyet if (nec86hw_probesubr(iot, ioh) != 0) return -1; #endif /* notyet */ if (n86ioh == 0) return -1; data = bus_space_read_1(iot, n86ioh, NEC86_SOUND_ID); switch (data & NEC_SCR_SIDMASK) { #if 0 /* XXX - PC-9801-73 not yet supported. */ case 0x20: case 0x30: break; #endif case 0x40: case 0x50: break; default: /* No supported board found. */ return -1; /*NOTREACHED*/ } return ((data & NEC_SCR_SIDMASK) >> 4) - 2; } /* * Attach hardware to driver, attach hardware driver to audio * pseudo-device driver. */ #define MODEL0_NAME "PC-9801-73 soundboard" #define MODEL1_NAME "PC-9801-86 soundboard" void nec86_attachsubr(struct nec86_softc *sc) { struct nec86hw_softc *ysc = &sc->sc_nec86hw; bus_space_tag_t iot = sc->sc_n86iot; bus_space_handle_t n86ioh = sc->sc_n86ioh; char *boardname[] = {MODEL0_NAME, MODEL0_NAME, MODEL1_NAME, MODEL1_NAME}; u_int8_t data; int model; if ((model = nec86_probesubr(iot, n86ioh, n86ioh)) < 0) { printf("%s: missing hardware\n", ysc->sc_dev.dv_xname); return; } ysc->model = model; /* enable YM2608(ONPA) */ data = bus_space_read_1(iot, n86ioh, NEC86_SOUND_ID); data &= ~NEC_SCR_MASK; data |= NEC_SCR_EXT_ENABLE; bus_space_write_1(iot, n86ioh, NEC86_SOUND_ID, data); switch (ysc->model) { case 2: /* base I/O port for YM2608(OPNA) is 0x188 */ sc->sc_ym_ioh = OPNA_IOBASE1; break; case 3: /* base I/O port for YM2608(OPNA) is 0x288 */ sc->sc_ym_ioh = OPNA_IOBASE2; break; default: /* can not happen; set to factory default */ sc->sc_ym_ioh = OPNA_IOBASE1; break; } /* YM2608 I/O port set (IOA:input IOB:output) */ nec86_ym_read(sc, 0x07, &data); data &= 0x3f; data |= 0x80; nec86_ym_write(sc, 0x07, data); /* YM2608 register 0x0e has C-bus interrupt level information */ nec86_ym_read(sc, 0x0e, &data); switch (data & 0xc0) { case 0x00: sc->sc_intlevel = 0; break; case 0x40: sc->sc_intlevel = 6; break; case 0x80: sc->sc_intlevel = 4; break; case 0xc0: sc->sc_intlevel = 5; /* factory default setting */ break; default: /* can not happen; set to factory default */ sc->sc_intlevel = 5; break; } /* reset YM2608 timer A and B: XXX need this? */ data = 0x30; nec86_ym_write(sc, 0x27, data); printf(" int %d", sc->sc_intlevel); nec86hw_attach(ysc); if (sc->sc_attached == 0) { printf(": %s\n", boardname[ysc->model]); audio_attach_mi(&nec86_hw_if, ysc, &ysc->sc_dev); sc->sc_attached = 1; } }