root/dev/isa/mpu401.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mpu_find
  2. mpu_waitready
  3. mpu_reset
  4. mpu_open
  5. mpu_close
  6. mpu_readinput
  7. mpu_output
  8. mpu_getinfo
  9. mpu_intr

    1 /*      $OpenBSD: mpu401.c,v 1.10 2006/04/07 22:41:33 jsg Exp $ */
    2 /*      $NetBSD: mpu401.c,v 1.3 1998/11/25 22:17:06 augustss Exp $      */
    3 
    4 /*
    5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (augustss@netbsd.org).
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/errno.h>
   43 #include <sys/ioctl.h>
   44 #include <sys/syslog.h>
   45 #include <sys/device.h>
   46 #include <sys/proc.h>
   47 #include <sys/buf.h>
   48 
   49 #include <machine/cpu.h>
   50 #include <machine/intr.h>
   51 #include <machine/bus.h>
   52 
   53 #include <dev/midi_if.h>
   54 
   55 #include <dev/isa/isavar.h>
   56 #include <dev/isa/isadmavar.h>
   57 
   58 #include <dev/ic/mpuvar.h>
   59 
   60 #ifndef splaudio
   61 #define splaudio() splbio()     /* XXX found in audio_if.h normally */
   62 #endif
   63 
   64 #ifdef AUDIO_DEBUG
   65 #define DPRINTF(x)      if (mpu401debug) printf x
   66 #define DPRINTFN(n,x)   if (mpu401debug >= (n)) printf x
   67 int     mpu401debug = 0;
   68 #else
   69 #define DPRINTF(x)
   70 #define DPRINTFN(n,x)
   71 #endif
   72 
   73 #define MPU_GETSTATUS(iot, ioh) (bus_space_read_1(iot, ioh, MPU_STATUS))
   74 
   75 int     mpu_reset(struct mpu_softc *);
   76 static  __inline int mpu_waitready(struct mpu_softc *);
   77 void    mpu_readinput(struct mpu_softc *);
   78 
   79 struct cfdriver mpu_cd = {
   80         NULL, "mpu", DV_DULL
   81 };
   82 
   83 struct midi_hw_if mpu_midi_hw_if = {
   84         mpu_open,
   85         mpu_close,
   86         mpu_output,
   87         0,                      /* flush */
   88         mpu_getinfo,
   89         0,                      /* ioctl */
   90 };
   91 
   92 int
   93 mpu_find(v)
   94         void *v;
   95 {
   96         struct mpu_softc *sc = v;
   97 
   98         if (MPU_GETSTATUS(sc->iot, sc->ioh) == 0xff) {
   99                 DPRINTF(("mpu_find: No status\n"));
  100                 goto bad;
  101         }
  102         sc->open = 0;
  103         sc->intr = 0;
  104         if (mpu_reset(sc) == 0)
  105                 return 1;
  106 bad:
  107         return 0;
  108 }
  109 
  110 static __inline int
  111 mpu_waitready(sc)
  112         struct mpu_softc *sc;
  113 {
  114         int i;
  115 
  116         for(i = 0; i < MPU_MAXWAIT; i++) {
  117                 if (!(MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_OUTPUT_BUSY))
  118                         return 0;
  119                 delay(10);
  120         }
  121         return 1;
  122 }
  123 
  124 int
  125 mpu_reset(sc)
  126         struct mpu_softc *sc;
  127 {
  128         bus_space_tag_t iot = sc->iot;
  129         bus_space_handle_t ioh = sc->ioh;
  130         int i;
  131         int s;
  132 
  133         if (mpu_waitready(sc)) {
  134                 DPRINTF(("mpu_reset: not ready\n"));
  135                 return EIO;
  136         }
  137         s = splaudio();         /* Don't let the interrupt get our ACK. */
  138         bus_space_write_1(iot, ioh, MPU_COMMAND, MPU_RESET);
  139         for(i = 0; i < 2*MPU_MAXWAIT; i++) {
  140                 if (!(MPU_GETSTATUS(iot, ioh) & MPU_INPUT_EMPTY) &&
  141                     bus_space_read_1(iot, ioh, MPU_DATA) == MPU_ACK) {
  142                         splx(s);
  143                         return 0;
  144                 }
  145         }
  146         splx(s);
  147         DPRINTF(("mpu_reset: No ACK\n"));
  148         return EIO;
  149 }
  150 
  151 int
  152 mpu_open(v, flags, iintr, ointr, arg)
  153         void *v;
  154         int flags;
  155         void (*iintr)(void *, int);
  156         void (*ointr)(void *);
  157         void *arg;
  158 {
  159         struct mpu_softc *sc = v;
  160 
  161         DPRINTF(("mpu_open: sc=%p\n", sc));
  162 
  163         if (sc->open)
  164                 return EBUSY;
  165         if (mpu_reset(sc) != 0)
  166                 return EIO;
  167 
  168         bus_space_write_1(sc->iot, sc->ioh, MPU_COMMAND, MPU_UART_MODE);
  169         sc->open = 1;
  170         sc->intr = iintr;
  171         sc->arg = arg;
  172         return 0;
  173 }
  174 
  175 void
  176 mpu_close(v)
  177         void *v;
  178 {
  179         struct mpu_softc *sc = v;
  180 
  181         DPRINTF(("mpu_close: sc=%p\n", sc));
  182 
  183         sc->open = 0;
  184         sc->intr = 0;
  185         mpu_reset(sc); /* exit UART mode */
  186 }
  187 
  188 void
  189 mpu_readinput(sc)
  190         struct mpu_softc *sc;
  191 {
  192         bus_space_tag_t iot = sc->iot;
  193         bus_space_handle_t ioh = sc->ioh;
  194         int data;
  195 
  196         while(!(MPU_GETSTATUS(iot, ioh) & MPU_INPUT_EMPTY)) {
  197                 data = bus_space_read_1(iot, ioh, MPU_DATA);
  198                 DPRINTFN(3, ("mpu_rea: sc=%p 0x%02x\n", sc, data));
  199                 if (sc->intr)
  200                         sc->intr(sc->arg, data);
  201         }
  202 }
  203 
  204 int
  205 mpu_output(v, d)
  206         void *v;
  207         int d;
  208 {
  209         struct mpu_softc *sc = v;
  210         int s;
  211 
  212         DPRINTFN(3, ("mpu_output: sc=%p 0x%02x\n", sc, d));
  213         if (!(MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_INPUT_EMPTY)) {
  214                 s = splaudio();
  215                 mpu_readinput(sc);
  216                 splx(s);
  217         }
  218         if (mpu_waitready(sc)) {
  219                 DPRINTF(("mpu_output: not ready\n"));
  220                 return EIO;
  221         }
  222         bus_space_write_1(sc->iot, sc->ioh, MPU_DATA, d);
  223         return 0;
  224 }
  225 
  226 void
  227 mpu_getinfo(addr, mi)
  228         void *addr;
  229         struct midi_info *mi;
  230 {
  231         mi->name = "MPU-401 MIDI UART";
  232         mi->props = 0;
  233 }
  234 
  235 int
  236 mpu_intr(v)
  237         void *v;
  238 {
  239         struct mpu_softc *sc = v;
  240 
  241         if (MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_INPUT_EMPTY) {
  242                 DPRINTF(("mpu_intr: no data\n"));
  243                 return 0;
  244         }
  245         mpu_readinput(sc);
  246         return 1;
  247 }

/* [<][>][^][v][top][bottom][index][help] */