xref: /openbsd/sys/arch/luna88k/cbus/nec86.c (revision c8819f5d)
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