1*c8819f5dSkn /* $OpenBSD: nec86.c,v 1.9 2022/11/02 10:41:34 kn Exp $ */
209871713Saoyama /* $NecBSD: nec86.c,v 1.11 1999/07/23 11:04:39 honda Exp $ */
309871713Saoyama /* $NetBSD$ */
409871713Saoyama
509871713Saoyama /*
609871713Saoyama * [NetBSD for NEC PC-98 series]
709871713Saoyama * Copyright (c) 1996, 1997, 1998
809871713Saoyama * NetBSD/pc98 porting staff. All rights reserved.
909871713Saoyama *
1009871713Saoyama * Redistribution and use in source and binary forms, with or without
1109871713Saoyama * modification, are permitted provided that the following conditions
1209871713Saoyama * are met:
1309871713Saoyama * 1. Redistributions of source code must retain the above copyright
1409871713Saoyama * notice, this list of conditions and the following disclaimer.
1509871713Saoyama * 2. Redistributions in binary form must reproduce the above copyright
1609871713Saoyama * notice, this list of conditions and the following disclaimer in the
1709871713Saoyama * documentation and/or other materials provided with the distribution.
1809871713Saoyama * 3. The name of the author may not be used to endorse or promote products
1909871713Saoyama * derived from this software without specific prior written permission.
2009871713Saoyama *
2109871713Saoyama * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2209871713Saoyama * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2309871713Saoyama * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2409871713Saoyama * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2509871713Saoyama * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2609871713Saoyama * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2709871713Saoyama * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2809871713Saoyama * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2909871713Saoyama * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3009871713Saoyama * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3109871713Saoyama * POSSIBILITY OF SUCH DAMAGE.
3209871713Saoyama */
3309871713Saoyama
3409871713Saoyama /*
3509871713Saoyama * nec86.c
3609871713Saoyama *
3709871713Saoyama * NEC PC-9801-86 SoundBoard PCM driver for NetBSD/pc98.
3809871713Saoyama * Written by NAGAO Tadaaki, Feb 10, 1996.
3909871713Saoyama *
4009871713Saoyama * Modified by N. Honda, Mar 7, 1998
4109871713Saoyama */
4209871713Saoyama
4309871713Saoyama #include <sys/param.h>
4409871713Saoyama #include <sys/systm.h>
4509871713Saoyama #include <sys/errno.h>
4609871713Saoyama #include <sys/ioctl.h>
4709871713Saoyama #include <sys/syslog.h>
4809871713Saoyama #include <sys/device.h>
4909871713Saoyama #include <sys/proc.h>
5009871713Saoyama
5109871713Saoyama #include <machine/board.h> /* PC_BASE */
5209871713Saoyama #include <machine/bus.h>
5309871713Saoyama #include <machine/cpu.h>
5409871713Saoyama
5509871713Saoyama #include <sys/audioio.h>
5609871713Saoyama #include <dev/audio_if.h>
5709871713Saoyama
5809871713Saoyama #include <luna88k/cbus/nec86reg.h>
5909871713Saoyama #include <luna88k/cbus/nec86hwvar.h>
6009871713Saoyama #include <luna88k/cbus/nec86var.h>
6109871713Saoyama
6209871713Saoyama #define NEC_SCR_SIDMASK 0xf0
6309871713Saoyama #define NEC_SCR_MASK 0x0f
6409871713Saoyama #define NEC_SCR_EXT_ENABLE 0x01
6509871713Saoyama
6609871713Saoyama /*
6709871713Saoyama * Define our interface to the higher level audio driver.
6809871713Saoyama */
6909871713Saoyama
700d6a2fdeSmiod const struct audio_hw_if nec86_hw_if = {
7109871713Saoyama .open = nec86hw_open,
7209871713Saoyama .close = nec86hw_close,
7309871713Saoyama .set_params = nec86hw_set_params,
7409871713Saoyama .round_blocksize = nec86hw_round_blocksize,
7509871713Saoyama .commit_settings = nec86hw_commit_settings,
7609871713Saoyama .init_output = nec86hw_pdma_init_output,
7709871713Saoyama .init_input = nec86hw_pdma_init_input,
7809871713Saoyama .start_output = nec86hw_pdma_output,
7909871713Saoyama .start_input = nec86hw_pdma_input,
8009871713Saoyama .halt_output = nec86hw_halt_pdma,
8109871713Saoyama .halt_input = nec86hw_halt_pdma,
8209871713Saoyama .set_port = nec86hw_mixer_set_port,
8309871713Saoyama .get_port = nec86hw_mixer_get_port,
8409871713Saoyama .query_devinfo = nec86hw_mixer_query_devinfo,
8509871713Saoyama };
8609871713Saoyama
8709871713Saoyama /*
8809871713Saoyama * YAMAHA YM2608(OPNA) register read/write functions
8909871713Saoyama */
9009871713Saoyama #define YM_INDEX 0
9109871713Saoyama #define YM_DATA 2
9209871713Saoyama
9309871713Saoyama void nec86_ym_read(struct nec86_softc *, u_int8_t, u_int8_t *);
9409871713Saoyama void nec86_ym_write(struct nec86_softc *, u_int8_t, u_int8_t);
9509871713Saoyama
9609871713Saoyama void
nec86_ym_read(struct nec86_softc * sc,u_int8_t index,u_int8_t * data)9709871713Saoyama nec86_ym_read(struct nec86_softc *sc, u_int8_t index, u_int8_t *data) {
9809871713Saoyama bus_space_write_1(sc->sc_ym_iot,
9909871713Saoyama sc->sc_ym_iobase + sc->sc_ym_ioh, YM_INDEX, index);
10009871713Saoyama delay(100);
10109871713Saoyama *data = bus_space_read_1(sc->sc_ym_iot,
10209871713Saoyama sc->sc_ym_iobase + sc->sc_ym_ioh, YM_DATA);
10309871713Saoyama delay(100);
10409871713Saoyama }
10509871713Saoyama
10609871713Saoyama void
nec86_ym_write(struct nec86_softc * sc,u_int8_t index,u_int8_t data)10709871713Saoyama nec86_ym_write(struct nec86_softc *sc, u_int8_t index, u_int8_t data) {
10809871713Saoyama bus_space_write_1(sc->sc_ym_iot,
10909871713Saoyama sc->sc_ym_iobase + sc->sc_ym_ioh, YM_INDEX, index);
11009871713Saoyama delay(100);
11109871713Saoyama bus_space_write_1(sc->sc_ym_iot,
11209871713Saoyama sc->sc_ym_iobase + sc->sc_ym_ioh, YM_DATA, data);
11309871713Saoyama delay(100);
11409871713Saoyama }
11509871713Saoyama
11609871713Saoyama /*
11709871713Saoyama * Probe for NEC PC-9801-86 SoundBoard hardware.
11809871713Saoyama */
11909871713Saoyama int
nec86_probesubr(bus_space_tag_t iot,bus_space_handle_t ioh,bus_space_handle_t n86ioh)12009871713Saoyama nec86_probesubr(bus_space_tag_t iot, bus_space_handle_t ioh,
12109871713Saoyama bus_space_handle_t n86ioh)
12209871713Saoyama {
12309871713Saoyama u_int8_t data;
12409871713Saoyama
12509871713Saoyama #ifdef notyet
12609871713Saoyama if (nec86hw_probesubr(iot, ioh) != 0)
12709871713Saoyama return -1;
12809871713Saoyama #endif /* notyet */
12909871713Saoyama
13009871713Saoyama if (n86ioh == 0)
13109871713Saoyama return -1;
13209871713Saoyama
13309871713Saoyama data = bus_space_read_1(iot, n86ioh, NEC86_SOUND_ID);
13409871713Saoyama
13509871713Saoyama switch (data & NEC_SCR_SIDMASK) {
13609871713Saoyama #if 0 /* XXX - PC-9801-73 not yet supported. */
13709871713Saoyama case 0x20:
13809871713Saoyama case 0x30:
13909871713Saoyama break;
14009871713Saoyama #endif
14109871713Saoyama case 0x40:
14209871713Saoyama case 0x50:
14309871713Saoyama break;
14409871713Saoyama default: /* No supported board found. */
14509871713Saoyama return -1;
14609871713Saoyama /*NOTREACHED*/
14709871713Saoyama }
14809871713Saoyama
14909871713Saoyama return ((data & NEC_SCR_SIDMASK) >> 4) - 2;
15009871713Saoyama }
15109871713Saoyama
15209871713Saoyama /*
15309871713Saoyama * Attach hardware to driver, attach hardware driver to audio
15409871713Saoyama * pseudo-device driver.
15509871713Saoyama */
15609871713Saoyama #define MODEL0_NAME "PC-9801-73 soundboard"
15709871713Saoyama #define MODEL1_NAME "PC-9801-86 soundboard"
15809871713Saoyama
15909871713Saoyama void
nec86_attachsubr(struct nec86_softc * sc)16009871713Saoyama nec86_attachsubr(struct nec86_softc *sc)
16109871713Saoyama {
16209871713Saoyama struct nec86hw_softc *ysc = &sc->sc_nec86hw;
16309871713Saoyama bus_space_tag_t iot = sc->sc_n86iot;
16409871713Saoyama bus_space_handle_t n86ioh = sc->sc_n86ioh;
16509871713Saoyama char *boardname[] =
16609871713Saoyama {MODEL0_NAME, MODEL0_NAME, MODEL1_NAME, MODEL1_NAME};
16709871713Saoyama u_int8_t data;
16809871713Saoyama int model;
16909871713Saoyama
17009871713Saoyama if ((model = nec86_probesubr(iot, n86ioh, n86ioh)) < 0) {
17109871713Saoyama printf("%s: missing hardware\n", ysc->sc_dev.dv_xname);
17209871713Saoyama return;
17309871713Saoyama }
17409871713Saoyama ysc->model = model;
17509871713Saoyama
17609871713Saoyama /* enable YM2608(ONPA) */
17709871713Saoyama data = bus_space_read_1(iot, n86ioh, NEC86_SOUND_ID);
17809871713Saoyama data &= ~NEC_SCR_MASK;
17909871713Saoyama data |= NEC_SCR_EXT_ENABLE;
18009871713Saoyama bus_space_write_1(iot, n86ioh, NEC86_SOUND_ID, data);
18109871713Saoyama
18209871713Saoyama switch (ysc->model) {
18309871713Saoyama case 2: /* base I/O port for YM2608(OPNA) is 0x188 */
18409871713Saoyama sc->sc_ym_ioh = OPNA_IOBASE1;
18509871713Saoyama break;
18609871713Saoyama case 3: /* base I/O port for YM2608(OPNA) is 0x288 */
18709871713Saoyama sc->sc_ym_ioh = OPNA_IOBASE2;
18809871713Saoyama break;
18909871713Saoyama default:
19009871713Saoyama /* can not happen; set to factory default */
19109871713Saoyama sc->sc_ym_ioh = OPNA_IOBASE1;
19209871713Saoyama break;
19309871713Saoyama }
19409871713Saoyama
19509871713Saoyama /* YM2608 I/O port set (IOA:input IOB:output) */
19609871713Saoyama nec86_ym_read(sc, 0x07, &data);
19709871713Saoyama data &= 0x3f;
19809871713Saoyama data |= 0x80;
19909871713Saoyama nec86_ym_write(sc, 0x07, data);
20009871713Saoyama
20109871713Saoyama /* YM2608 register 0x0e has C-bus interrupt level information */
20209871713Saoyama nec86_ym_read(sc, 0x0e, &data);
20309871713Saoyama switch (data & 0xc0) {
20409871713Saoyama case 0x00:
20509871713Saoyama sc->sc_intlevel = 0;
20609871713Saoyama break;
20709871713Saoyama case 0x40:
20809871713Saoyama sc->sc_intlevel = 6;
20909871713Saoyama break;
21009871713Saoyama case 0x80:
21109871713Saoyama sc->sc_intlevel = 4;
21209871713Saoyama break;
21309871713Saoyama case 0xc0:
21409871713Saoyama sc->sc_intlevel = 5; /* factory default setting */
21509871713Saoyama break;
21609871713Saoyama default:
21709871713Saoyama /* can not happen; set to factory default */
21809871713Saoyama sc->sc_intlevel = 5;
21909871713Saoyama break;
22009871713Saoyama }
22109871713Saoyama
22209871713Saoyama /* reset YM2608 timer A and B: XXX need this? */
22309871713Saoyama data = 0x30;
22409871713Saoyama nec86_ym_write(sc, 0x27, data);
22509871713Saoyama
22609871713Saoyama printf(" int %d", sc->sc_intlevel);
22709871713Saoyama
22809871713Saoyama nec86hw_attach(ysc);
22909871713Saoyama
23009871713Saoyama if (sc->sc_attached == 0) {
23109871713Saoyama printf(": %s\n", boardname[ysc->model]);
2322baa08e2Santon audio_attach_mi(&nec86_hw_if, ysc, NULL, &ysc->sc_dev);
23309871713Saoyama sc->sc_attached = 1;
23409871713Saoyama }
23509871713Saoyama }
236