1 /* $NetBSD: mpu.c,v 1.16 2008/03/27 10:22:01 xtraeme Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (augustss@NetBSD.org).
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: mpu.c,v 1.16 2008/03/27 10:22:01 xtraeme Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/errno.h>
38 #include <sys/ioctl.h>
39 #include <sys/syslog.h>
40 #include <sys/device.h>
48 #include <dev/midi_if.h>
50 #include <dev/ic/mpuvar.h>
53 #define DPRINTF(x) if (mpudebug) printf x
54 #define DPRINTFN(n,x) if (mpudebug >= (n)) printf x
63 #define MPU_RESET 0xff
64 #define MPU_UART_MODE 0x3f
67 #define MPU_OUTPUT_BUSY 0x40
68 #define MPU_INPUT_EMPTY 0x80
70 #define MPU_MAXWAIT 10000 /* usec/10 to wait */
72 #define MPU_GETSTATUS(iot, ioh) (bus_space_read_1(iot, ioh, MPU_STATUS))
74 static int mpu_reset(struct mpu_softc
*);
75 static inline int mpu_waitready(struct mpu_softc
*);
76 static void mpu_readinput(struct mpu_softc
*);
78 static int mpu_open(void *, int,
79 void (*iintr
)(void *, int),
80 void (*ointr
)(void *), void *arg
);
81 static void mpu_close(void *);
82 static int mpu_output(void *, int);
83 static void mpu_getinfo(void *, struct midi_info
*);
85 const struct midi_hw_if mpu_midi_hw_if
= {
94 mpu_find(struct mpu_softc
*sc
)
96 if (MPU_GETSTATUS(sc
->iot
, sc
->ioh
) == 0xff) {
97 DPRINTF(("%s: No status\n", __func__
));
102 if (mpu_reset(sc
) == 0)
109 mpu_attach(struct mpu_softc
*sc
)
111 midi_attach_mi(&mpu_midi_hw_if
, sc
, sc
->sc_dev
);
115 mpu_waitready(struct mpu_softc
*sc
)
119 for(i
= 0; i
< MPU_MAXWAIT
; i
++) {
120 if (!(MPU_GETSTATUS(sc
->iot
, sc
->ioh
) & MPU_OUTPUT_BUSY
))
128 mpu_reset(struct mpu_softc
*sc
)
130 bus_space_tag_t iot
= sc
->iot
;
131 bus_space_handle_t ioh
= sc
->ioh
;
135 if (mpu_waitready(sc
)) {
136 DPRINTF(("%s: not ready\n", __func__
));
139 s
= splaudio(); /* Don't let the interrupt get our ACK. */
140 bus_space_write_1(iot
, ioh
, MPU_COMMAND
, MPU_RESET
);
141 for(i
= 0; i
< 2*MPU_MAXWAIT
; i
++) {
142 if (!(MPU_GETSTATUS(iot
, ioh
) & MPU_INPUT_EMPTY
) &&
143 bus_space_read_1(iot
, ioh
, MPU_DATA
) == MPU_ACK
) {
149 DPRINTF(("%s: No ACK\n", __func__
));
154 mpu_open(void *addr
, int flags
, void (*iintr
)(void *, int),
155 void (*ointr
)(void *), void *arg
)
157 struct mpu_softc
*sc
= addr
;
159 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
163 #ifndef AUDIO_NO_POWER_CTL
165 sc
->powerctl(sc
->powerarg
, 1);
167 if (mpu_reset(sc
) != 0) {
168 #ifndef AUDIO_NO_POWER_CTL
170 sc
->powerctl(sc
->powerarg
, 0);
175 bus_space_write_1(sc
->iot
, sc
->ioh
, MPU_COMMAND
, MPU_UART_MODE
);
183 mpu_close(void *addr
)
185 struct mpu_softc
*sc
= addr
;
187 DPRINTF(("%s: sc=%p\n", __func__
, sc
));
191 mpu_reset(sc
); /* exit UART mode */
193 #ifndef AUDIO_NO_POWER_CTL
195 sc
->powerctl(sc
->powerarg
, 0);
200 mpu_readinput(struct mpu_softc
*sc
)
202 bus_space_tag_t iot
= sc
->iot
;
203 bus_space_handle_t ioh
= sc
->ioh
;
206 while(!(MPU_GETSTATUS(iot
, ioh
) & MPU_INPUT_EMPTY
)) {
207 data
= bus_space_read_1(iot
, ioh
, MPU_DATA
);
208 DPRINTFN(3, ("%s: sc=%p 0x%02x\n", __func__
, sc
, data
));
210 sc
->intr(sc
->arg
, data
);
215 mpu_output(void *addr
, int d
)
217 struct mpu_softc
*sc
= addr
;
220 DPRINTFN(3, ("%s: sc=%p 0x%02x\n", __func__
, sc
, d
));
221 if (!(MPU_GETSTATUS(sc
->iot
, sc
->ioh
) & MPU_INPUT_EMPTY
)) {
226 if (mpu_waitready(sc
)) {
227 DPRINTF(("%s:: not ready\n", __func__
));
230 bus_space_write_1(sc
->iot
, sc
->ioh
, MPU_DATA
, d
);
235 mpu_getinfo(void *addr
, struct midi_info
*mi
)
237 struct mpu_softc
*sc
= addr
;
239 mi
->name
= sc
->model
;
246 struct mpu_softc
*sc
= addr
;
248 if (MPU_GETSTATUS(sc
->iot
, sc
->ioh
) & MPU_INPUT_EMPTY
) {
249 DPRINTF(("%s: no data\n", __func__
));