#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/syslog.h>
#include <sys/device.h>
#include <sys/proc.h>
#include <machine/board.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <sys/audioio.h>
#include <dev/audio_if.h>
#include <luna88k/cbus/nec86reg.h>
#include <luna88k/cbus/nec86hwvar.h>
#include <luna88k/cbus/nec86var.h>
#define NEC_SCR_SIDMASK 0xf0
#define NEC_SCR_MASK 0x0f
#define NEC_SCR_EXT_ENABLE 0x01
const 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,
.set_port = nec86hw_mixer_set_port,
.get_port = nec86hw_mixer_get_port,
.query_devinfo = nec86hw_mixer_query_devinfo,
};
#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);
}
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
if (n86ioh == 0)
return -1;
data = bus_space_read_1(iot, n86ioh, NEC86_SOUND_ID);
switch (data & NEC_SCR_SIDMASK) {
#if 0
case 0x20:
case 0x30:
break;
#endif
case 0x40:
case 0x50:
break;
default:
return -1;
}
return ((data & NEC_SCR_SIDMASK) >> 4) - 2;
}
#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;
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:
sc->sc_ym_ioh = OPNA_IOBASE1;
break;
case 3:
sc->sc_ym_ioh = OPNA_IOBASE2;
break;
default:
sc->sc_ym_ioh = OPNA_IOBASE1;
break;
}
nec86_ym_read(sc, 0x07, &data);
data &= 0x3f;
data |= 0x80;
nec86_ym_write(sc, 0x07, data);
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;
break;
default:
sc->sc_intlevel = 5;
break;
}
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, NULL, &ysc->sc_dev);
sc->sc_attached = 1;
}
}