Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / ic / mpu.c
blob1c8fcd06d1738539f9a951f98b937aeb5a9bc0ba
1 /* $NetBSD: mpu.c,v 1.16 2008/03/27 10:22:01 xtraeme Exp $ */
3 /*
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
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
12 * are met:
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>
41 #include <sys/proc.h>
42 #include <sys/buf.h>
44 #include <sys/cpu.h>
45 #include <sys/intr.h>
46 #include <sys/bus.h>
48 #include <dev/midi_if.h>
50 #include <dev/ic/mpuvar.h>
52 #ifdef AUDIO_DEBUG
53 #define DPRINTF(x) if (mpudebug) printf x
54 #define DPRINTFN(n,x) if (mpudebug >= (n)) printf x
55 int mpudebug = 0;
56 #else
57 #define DPRINTF(x)
58 #define DPRINTFN(n,x)
59 #endif
61 #define MPU_DATA 0
62 #define MPU_COMMAND 1
63 #define MPU_RESET 0xff
64 #define MPU_UART_MODE 0x3f
65 #define MPU_ACK 0xfe
66 #define MPU_STATUS 1
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 = {
86 mpu_open,
87 mpu_close,
88 mpu_output,
89 mpu_getinfo,
90 0, /* ioctl */
93 int
94 mpu_find(struct mpu_softc *sc)
96 if (MPU_GETSTATUS(sc->iot, sc->ioh) == 0xff) {
97 DPRINTF(("%s: No status\n", __func__));
98 goto bad;
100 sc->open = 0;
101 sc->intr = 0;
102 if (mpu_reset(sc) == 0)
103 return 1;
104 bad:
105 return 0;
108 void
109 mpu_attach(struct mpu_softc *sc)
111 midi_attach_mi(&mpu_midi_hw_if, sc, sc->sc_dev);
114 static inline int
115 mpu_waitready(struct mpu_softc *sc)
117 int i;
119 for(i = 0; i < MPU_MAXWAIT; i++) {
120 if (!(MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_OUTPUT_BUSY))
121 return 0;
122 delay(10);
124 return 1;
127 static int
128 mpu_reset(struct mpu_softc *sc)
130 bus_space_tag_t iot = sc->iot;
131 bus_space_handle_t ioh = sc->ioh;
132 int i;
133 int s;
135 if (mpu_waitready(sc)) {
136 DPRINTF(("%s: not ready\n", __func__));
137 return EIO;
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) {
144 splx(s);
145 return 0;
148 splx(s);
149 DPRINTF(("%s: No ACK\n", __func__));
150 return EIO;
153 static int
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));
161 if (sc->open)
162 return EBUSY;
163 #ifndef AUDIO_NO_POWER_CTL
164 if (sc->powerctl)
165 sc->powerctl(sc->powerarg, 1);
166 #endif
167 if (mpu_reset(sc) != 0) {
168 #ifndef AUDIO_NO_POWER_CTL
169 if (sc->powerctl)
170 sc->powerctl(sc->powerarg, 0);
171 #endif
172 return EIO;
175 bus_space_write_1(sc->iot, sc->ioh, MPU_COMMAND, MPU_UART_MODE);
176 sc->open = 1;
177 sc->intr = iintr;
178 sc->arg = arg;
179 return 0;
182 static void
183 mpu_close(void *addr)
185 struct mpu_softc *sc = addr;
187 DPRINTF(("%s: sc=%p\n", __func__, sc));
189 sc->open = 0;
190 sc->intr = 0;
191 mpu_reset(sc); /* exit UART mode */
193 #ifndef AUDIO_NO_POWER_CTL
194 if (sc->powerctl)
195 sc->powerctl(sc->powerarg, 0);
196 #endif
199 static void
200 mpu_readinput(struct mpu_softc *sc)
202 bus_space_tag_t iot = sc->iot;
203 bus_space_handle_t ioh = sc->ioh;
204 int data;
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));
209 if (sc->intr)
210 sc->intr(sc->arg, data);
214 static int
215 mpu_output(void *addr, int d)
217 struct mpu_softc *sc = addr;
218 int s;
220 DPRINTFN(3, ("%s: sc=%p 0x%02x\n", __func__, sc, d));
221 if (!(MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_INPUT_EMPTY)) {
222 s = splaudio();
223 mpu_readinput(sc);
224 splx(s);
226 if (mpu_waitready(sc)) {
227 DPRINTF(("%s:: not ready\n", __func__));
228 return EIO;
230 bus_space_write_1(sc->iot, sc->ioh, MPU_DATA, d);
231 return 0;
234 static void
235 mpu_getinfo(void *addr, struct midi_info *mi)
237 struct mpu_softc *sc = addr;
239 mi->name = sc->model;
240 mi->props = 0;
244 mpu_intr(void *addr)
246 struct mpu_softc *sc = addr;
248 if (MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_INPUT_EMPTY) {
249 DPRINTF(("%s: no data\n", __func__));
250 return 0;
251 } else {
252 mpu_readinput(sc);
253 return 1;