The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/isa/mpu.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * The low level driver for Roland MPU-401 compatible Midi interfaces.
    3  * 
    4  * Copyright by Hannu Savolainen 1993
    5  * 
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions are
    8  * met: 1. Redistributions of source code must retain the above copyright
    9  * notice, this list of conditions and the following disclaimer. 2.
   10  * Redistributions in binary form must reproduce the above copyright notice,
   11  * this list of conditions and the following disclaimer in the documentation
   12  * and/or other materials provided with the distribution.
   13  * 
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
   15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   17  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   21  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  * 
   26  * Modified: Riccardo Facchetti  24 Mar 1995 - Added the Audio Excel DSP 16
   27  * initialization routine.
   28  *
   29  * Ported to the new Audio Driver by Luigi Rizzo:
   30  * (C) 1999 Seigo Tanimura
   31  *
   32  * This is the MPU401 midi interface driver for FreeBSD, based on the Luigi Sound Driver.
   33  * This handles io against /dev/midi, the midi {in, out}put event queues
   34  * and the event/message transmittion to/from an MPU401 interface.
   35  *
   36  * $FreeBSD: releng/5.2/sys/dev/sound/isa/mpu.c 121711 2003-10-29 21:54:37Z deischen $
   37  *
   38  */
   39 
   40 #include <dev/sound/midi/midi.h>
   41 #include <dev/sound/chip.h>
   42 #include <machine/cpufunc.h>
   43 
   44 #include <isa/isavar.h>
   45 #include <dev/ic/ns16550.h>
   46 
   47 static devclass_t midi_devclass;
   48 
   49 #ifndef DDB
   50 #undef DDB
   51 #define DDB(x)
   52 #endif /* DDB */
   53 
   54 #define MPU_DATAPORT   0
   55 #define MPU_CMDPORT    1
   56 #define MPU_STATPORT   1
   57 
   58 #define MPU_RESET      0xff
   59 #define MPU_UART       0x3f
   60 #define MPU_ACK        0xfe
   61 
   62 #define MPU_STATMASK   0xc0
   63 #define MPU_OUTPUTBUSY 0x40
   64 #define MPU_INPUTBUSY  0x80
   65 
   66 #define MPU_TRYDATA 50
   67 #define MPU_DELAY   25000
   68 
   69 /* Device flag.  */
   70 #define MPU_DF_NO_IRQ   1
   71 
   72 extern synthdev_info midisynth_op_desc;
   73 
   74 /* PnP IDs */
   75 static struct isa_pnp_id mpu_ids[] = {
   76         {0x01200001, "@H@2001 Midi Interface"}, /* @H@2001 */
   77         {0x01100001, "@H@1001 Midi Interface"}, /* @H@1001 */
   78 #if notdef
   79         /* TODO: write bridge driver for these devices */
   80         {0x0000630e, "CSC0000 Midi Interface"}, /* CSC0000 */
   81         {0x2100a865, "YMH0021 Midi Interface"}, /* YMH0021 */
   82         {0x80719304, "ADS7180 Midi Interface"}, /* ADS7180 */
   83         {0x0300561e, "GRV0003 Midi Interface"}, /* GRV0003 */
   84 #endif
   85 };
   86 
   87 /* These are the synthesizer and the midi interface information. */
   88 static struct synth_info mpu_synthinfo = {
   89         "MPU401 MIDI",
   90         0,
   91         SYNTH_TYPE_MIDI,
   92         0,
   93         0,
   94         128,
   95         128,
   96         128,
   97         SYNTH_CAP_INPUT,
   98 };
   99 
  100 static struct midi_info mpu_midiinfo = {
  101         "MPU401 MIDI",
  102         0,
  103         0,
  104         0,
  105 };
  106 
  107 /*
  108  * These functions goes into mpu_op_desc to get called
  109  * from sound.c.
  110  */
  111 
  112 static int mpu_probe(device_t dev);
  113 static int mpu_probe1(device_t dev);
  114 static int mpu_probe2(device_t dev);
  115 static int mpu_attach(device_t dev);
  116 static int mpusbc_probe(device_t dev);
  117 static int mpusbc_attach(device_t dev);
  118 
  119 static d_ioctl_t mpu_ioctl;
  120 static driver_intr_t mpu_intr;
  121 static midi_callback_t mpu_callback;
  122 
  123 /* Here is the parameter structure per a device. */
  124 struct mpu_softc {
  125         device_t dev; /* device information */
  126         mididev_info *devinfo; /* midi device information */
  127 
  128         struct mtx mtx; /* Mutex to protect the device. */
  129 
  130         struct resource *io; /* Base of io port */
  131         int io_rid; /* Io resource ID */
  132         u_long irq_val; /* Irq value */
  133         struct resource *irq; /* Irq */
  134         int irq_rid; /* Irq resource ID */
  135         void *ih; /* Interrupt cookie */
  136 
  137         int fflags; /* File flags */
  138 };
  139 
  140 typedef struct mpu_softc *sc_p;
  141 
  142 /* These functions are local. */
  143 static void mpu_startplay(sc_p scp);
  144 static void mpu_xmit(sc_p scp);
  145 static int mpu_resetmode(sc_p scp);
  146 static int mpu_uartmode(sc_p scp);
  147 static int mpu_waitack(sc_p scp);
  148 static int mpu_status(sc_p scp);
  149 static int mpu_command(sc_p scp, u_int8_t value);
  150 static int mpu_readdata(sc_p scp, u_int8_t *value);
  151 static int mpu_writedata(sc_p scp, u_int8_t value);
  152 static u_int mpu_readport(sc_p scp, int off);
  153 static void mpu_writeport(sc_p scp, int off, u_int8_t value);
  154 static int mpu_allocres(sc_p scp, device_t dev);
  155 static void mpu_releaseres(sc_p scp, device_t dev);
  156 
  157 /*
  158  * This is the device descriptor for the midi device.
  159  */
  160 static mididev_info mpu_op_desc = {
  161         "MPU401 midi",
  162 
  163         SNDCARD_MPU401,
  164 
  165         NULL,
  166         NULL,
  167         mpu_ioctl,
  168 
  169         mpu_callback,
  170 
  171         MIDI_BUFFSIZE, /* Queue Length */
  172 
  173         0, /* XXX This is not an *audio* device! */
  174 };
  175 
  176 /*
  177  * Here are the main functions to interact to the user process.
  178  */
  179 
  180 static int
  181 mpu_probe(device_t dev)
  182 {
  183         sc_p scp;
  184         int ret;
  185 
  186         /* Check isapnp ids */
  187         if (isa_get_logicalid(dev) != 0)
  188                 return (ISA_PNP_PROBE(device_get_parent(dev), dev, mpu_ids));
  189 
  190         scp = device_get_softc(dev);
  191 
  192         device_set_desc(dev, mpu_op_desc.name);
  193         bzero(scp, sizeof(*scp));
  194 
  195         scp->io_rid = 0;
  196         ret = mpu_probe1(dev);
  197         if (ret != 0)
  198                 return (ret);
  199         ret = mpu_probe2(dev);
  200         if (ret != 0)
  201                 return (ret);
  202 
  203         return (0);
  204 }
  205 
  206 /*
  207  * Make sure this is an MPU401, not an 16550 uart.
  208  * Called only for non-pnp devices.
  209  */
  210 static int
  211 mpu_probe1(device_t dev)
  212 {
  213         sc_p scp;
  214         int iir;
  215         struct resource *io;
  216 
  217         scp = device_get_softc(dev);
  218 
  219         /*
  220          * If an MPU401 is ready to both input and output,
  221          * the status register value is zero, which may
  222          * confuse an 16550 uart to probe as an MPU401.
  223          * We read the IIR (base + 2), which is not used
  224          * by an MPU401.
  225          */
  226         io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 3, RF_ACTIVE);
  227         iir = bus_space_read_1(rman_get_bustag(io), rman_get_bushandle(io), com_iir) & 0xff;
  228         bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, io);
  229         if ((iir & ~(IIR_IMASK | IIR_FIFO_MASK)) == 0)
  230                 /* Likely to be an 16550. */
  231                 return (ENXIO);
  232 
  233         return (0);
  234 }
  235 
  236 /* Look up the irq. */
  237 static int
  238 mpu_probe2(device_t dev)
  239 {
  240         sc_p scp;
  241         int unit, i;
  242         intrmask_t irqp0, irqp1;
  243 
  244         scp = device_get_softc(dev);
  245         unit = device_get_unit(dev);
  246 
  247         scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 2, RF_ACTIVE);
  248         if (scp->io == NULL)
  249                 return (ENXIO);
  250 
  251         MIDI_DEBUG(printf("mpu%d: probing.\n", unit));
  252 
  253         /* Reset the interface. */
  254         if (mpu_resetmode(scp) != 0 || mpu_waitack(scp) != 0) {
  255                 printf("mpu%d: reset failed.\n", unit);
  256                 mpu_releaseres(scp, dev);
  257                 return (ENXIO);
  258         }
  259 
  260         /*
  261          * At this point, we are likely to have an interface.
  262          *
  263          * Switching the interface to uart mode gives us an interrupt.
  264          * We can make use of it to determine the irq.
  265          * Idea-stolen-from: sys/isa/sio.c:sioprobe()
  266          */
  267 
  268         critical_enter();
  269 
  270         /*
  271          * See the initial irq. We have to do this now,
  272          * otherwise a midi module/instrument might send
  273          * an active sensing, to mess up the irq.
  274          */
  275         irqp0 = isa_irq_pending();
  276         irqp1 = 0;
  277 
  278         /* Switch to uart mode. */
  279         if (mpu_uartmode(scp) != 0) {
  280                 critical_exit();
  281                 printf("mpu%d: mode switching failed.\n", unit);
  282                 mpu_releaseres(scp, dev);
  283                 return (ENXIO);
  284         }
  285 
  286         if (device_get_flags(dev) & MPU_DF_NO_IRQ) {
  287                 irqp0 = irqp1 = 0;
  288                 goto no_irq;
  289         }
  290 
  291         /* See which irq we have now. */
  292         for (i = 0 ; i < MPU_TRYDATA ; i++) {
  293                 DELAY(MPU_DELAY);
  294                 irqp1 = isa_irq_pending();
  295                 if (irqp1 != irqp0)
  296                         break;
  297         }
  298         if (irqp1 == irqp0) {
  299                 critical_exit();
  300                 printf("mpu%d: switching the mode gave no interrupt.\n", unit);
  301                 mpu_releaseres(scp, dev);
  302                 return (ENXIO);
  303         }
  304 
  305 no_irq:
  306         /* Wait to see an ACK. */
  307         if (mpu_waitack(scp) != 0) {
  308                 critical_exit();
  309                 printf("mpu%d: not acked.\n", unit);
  310                 mpu_releaseres(scp, dev);
  311                 return (ENXIO);
  312         }
  313 
  314         critical_exit();
  315 
  316         if (device_get_flags(dev) & MPU_DF_NO_IRQ)
  317                 scp->irq_val = 0;
  318         else
  319                 /* We have found the irq. */
  320                 scp->irq_val = ffs(~irqp0 & irqp1) - 1;
  321 
  322         MIDI_DEBUG(printf("mpu%d: probed.\n", unit));
  323 
  324         return (0);
  325 }
  326 
  327 static int
  328 mpusbc_probe(device_t dev)
  329 {
  330         char *s;
  331         sc_p scp;
  332         struct sndcard_func *func;
  333 
  334         /* The parent device has already been probed. */
  335 
  336         func = device_get_ivars(dev);
  337         if (func == NULL || func->func != SCF_MIDI)
  338                 return (ENXIO);
  339 
  340         s = "SB Midi Interface";
  341 
  342         scp = device_get_softc(dev);
  343         bzero(scp, sizeof(*scp));
  344         scp->io_rid = 1;
  345         scp->irq_rid = 0;
  346         device_set_desc(dev, s);
  347         return (0);
  348 }
  349 
  350 static int
  351 mpu_attach(device_t dev)
  352 {
  353         sc_p scp;
  354         mididev_info *devinfo;
  355 
  356         scp = device_get_softc(dev);
  357 
  358         MIDI_DEBUG(printf("mpu: attaching.\n"));
  359 
  360         mtx_init(&scp->mtx, "mpumid", NULL, MTX_DEF);
  361 
  362         /* Allocate the resources, switch to uart mode. */
  363         if (mpu_allocres(scp, dev) || mpu_uartmode(scp)) {
  364                 mpu_releaseres(scp, dev);
  365                 mtx_destroy(&scp->mtx);
  366                 return (ENXIO);
  367         }
  368 
  369         /* mpu_probe() has put the interface to uart mode. */
  370 
  371         /* Fill the softc. */
  372         scp->dev = dev;
  373         scp->devinfo = devinfo = create_mididev_info_unit(MDT_MIDI, &mpu_op_desc, &midisynth_op_desc);
  374 
  375         /* Fill the midi info. */
  376         if (scp->irq != NULL)
  377                 snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x irq %d",
  378                          (u_int)rman_get_start(scp->io), (int)rman_get_start(scp->irq));
  379         else
  380                 snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x",
  381                          (u_int)rman_get_start(scp->io));
  382 
  383         midiinit(devinfo, dev);
  384 
  385         /* Now we can handle the interrupts. */
  386         if (scp->irq != NULL)
  387                 bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, mpu_intr, scp,
  388                                &scp->ih);
  389 
  390         MIDI_DEBUG(printf("mpu: attached.\n"));
  391 
  392         return (0);
  393 }
  394 
  395 static int
  396 mpusbc_attach(device_t dev)
  397 {
  398         sc_p scp;
  399         int unit;
  400 
  401         scp = device_get_softc(dev);
  402         unit = device_get_unit(dev);
  403 
  404         mpu_attach(dev);
  405 
  406         return (0);
  407 }
  408 
  409 static int
  410 mpu_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
  411 {
  412         sc_p scp;
  413         mididev_info *devinfo;
  414         int unit;
  415         struct synth_info *synthinfo;
  416         struct midi_info *midiinfo;
  417 
  418         unit = MIDIUNIT(i_dev);
  419 
  420         MIDI_DEBUG(printf("mpu_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
  421 
  422         devinfo = get_mididev_info(i_dev, &unit);
  423         if (devinfo == NULL) {
  424                 MIDI_DEBUG(printf("mpu_ioctl: unit %d is not configured.\n", unit));
  425                 return (ENXIO);
  426         }
  427         scp = devinfo->softc;
  428 
  429         switch (cmd) {
  430         case SNDCTL_SYNTH_INFO:
  431                 synthinfo = (struct synth_info *)arg;
  432                 if (synthinfo->device != unit)
  433                         return (ENXIO);
  434                 bcopy(&mpu_synthinfo, synthinfo, sizeof(mpu_synthinfo));
  435                 synthinfo->device = unit;
  436                 return (0);
  437                 break;
  438         case SNDCTL_MIDI_INFO:
  439                 midiinfo = (struct midi_info *)arg;
  440                 if (midiinfo->device != unit)
  441                         return (ENXIO);
  442                 bcopy(&mpu_midiinfo, midiinfo, sizeof(mpu_midiinfo));
  443                 midiinfo->device = unit;
  444                 return (0);
  445                 break;
  446         default:
  447                 return (ENOSYS);
  448         }
  449         /* NOTREACHED */
  450         return (EINVAL);
  451 }
  452 
  453 static void
  454 mpu_intr(void *arg)
  455 {
  456         sc_p scp;
  457         u_char c;
  458         mididev_info *devinfo;
  459         int leni;
  460 
  461         scp = (sc_p)arg;
  462         devinfo = scp->devinfo;
  463 
  464         mtx_lock(&devinfo->flagqueue_mtx);
  465         mtx_lock(&scp->mtx);
  466 
  467         /* Read the received data. */
  468         while ((mpu_status(scp) & MPU_INPUTBUSY) == 0) {
  469                 /* Receive the data. */
  470                 mpu_readdata(scp, &c);
  471                 mtx_unlock(&scp->mtx);
  472                 /* Queue into the passthru buffer and start transmitting if we can. */
  473                 if ((devinfo->flags & MIDI_F_PASSTHRU) != 0 && ((devinfo->flags & MIDI_F_BUSY) == 0 || (devinfo->fflags & FWRITE) == 0)) {
  474                         midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c, sizeof(c), &leni);
  475                         devinfo->callback(devinfo, MIDI_CB_START | MIDI_CB_WR);
  476                 }
  477                 /* Queue if we are reading. Discard an active sensing. */
  478                 if ((devinfo->flags & MIDI_F_READING) != 0 && c != 0xfe) {
  479                         midibuf_input_intr(&devinfo->midi_dbuf_in, &c, sizeof(c), &leni);
  480                 }
  481                 mtx_lock(&scp->mtx);
  482         }
  483         mtx_unlock(&scp->mtx);
  484         mtx_unlock(&devinfo->flagqueue_mtx);
  485 
  486         /* Invoke the upper layer. */
  487         midi_intr(devinfo);
  488 }
  489 
  490 static int
  491 mpu_callback(void *di, int reason)
  492 {
  493         int unit;
  494         sc_p scp;
  495         mididev_info *d;
  496 
  497         d = (mididev_info *)di;
  498 
  499         mtx_assert(&d->flagqueue_mtx, MA_OWNED);
  500 
  501         if (d == NULL) {
  502                 MIDI_DEBUG(printf("mpu_callback: device not configured.\n"));
  503                 return (ENXIO);
  504         }
  505 
  506         unit = d->unit;
  507         scp = d->softc;
  508 
  509         switch (reason & MIDI_CB_REASON_MASK) {
  510         case MIDI_CB_START:
  511                 if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) == 0)
  512                         /* Begin recording. */
  513                         d->flags |= MIDI_F_READING;
  514                 if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) == 0)
  515                         /* Start playing. */
  516                         mpu_startplay(scp);
  517                 break;
  518         case MIDI_CB_STOP:
  519         case MIDI_CB_ABORT:
  520                 if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) != 0)
  521                         /* Stop recording. */
  522                         d->flags &= ~MIDI_F_READING;
  523                 if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) != 0)
  524                         /* Stop Playing. */
  525                         d->flags &= ~MIDI_F_WRITING;
  526                 break;
  527         }
  528 
  529         return (0);
  530 }
  531 
  532 /*
  533  * The functions below here are the libraries for the above ones.
  534  */
  535 
  536 /*
  537  * Starts to play the data in the output queue.
  538  */
  539 static void
  540 mpu_startplay(sc_p scp)
  541 {
  542         mididev_info *devinfo;
  543 
  544         devinfo = scp->devinfo;
  545 
  546         mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
  547 
  548         /* Can we play now? */
  549         if (devinfo->midi_dbuf_out.rl == 0)
  550                 return;
  551 
  552         devinfo->flags |= MIDI_F_WRITING;
  553         mpu_xmit(scp);
  554 }
  555 
  556 static void
  557 mpu_xmit(sc_p scp)
  558 {
  559         register mididev_info *devinfo;
  560         register midi_dbuf *dbuf;
  561         u_char c;
  562         int leno;
  563 
  564         devinfo = scp->devinfo;
  565 
  566         mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
  567 
  568         /* See which source to use. */
  569         if ((devinfo->flags & MIDI_F_PASSTHRU) == 0 || ((devinfo->flags & MIDI_F_BUSY) != 0 && (devinfo->fflags & FWRITE) != 0))
  570                 dbuf = &devinfo->midi_dbuf_out;
  571         else
  572                 dbuf = &devinfo->midi_dbuf_passthru;
  573 
  574         /* Transmit the data in the queue. */
  575         while ((devinfo->flags & MIDI_F_WRITING) != 0) {
  576                 if (dbuf->rl == 0) 
  577                         break;
  578                 else {
  579                         mtx_lock(&scp->mtx);
  580                         /* XXX Wait until we can write the data. */
  581                         if ((mpu_status(scp) & MPU_OUTPUTBUSY) == 0) {
  582                                 /* Send the data. */
  583                                 midibuf_output_intr(dbuf, &c, sizeof(c), &leno);
  584                                 mpu_writedata(scp, c);
  585                                 /* We are playing now. */
  586                                 devinfo->flags |= MIDI_F_WRITING;
  587                         }
  588                         mtx_unlock(&scp->mtx);
  589                 }
  590         }
  591         /* Stop playing. */
  592         devinfo->flags &= ~MIDI_F_WRITING;
  593 }
  594 
  595 
  596 /* 
  597  * Reset mpu.
  598  * The caller must lock scp->mtx before calling this function if needed.
  599  */
  600 static int
  601 mpu_resetmode(sc_p scp)
  602 {
  603         int i, resp;
  604 
  605         /* Reset the mpu. */
  606         resp = 0;
  607         for (i = 0 ; i < MPU_TRYDATA ; i++) {
  608                 resp = mpu_command(scp, MPU_RESET);
  609                 if (resp == 0)
  610                         break;
  611         }
  612         if (resp != 0)
  613                 return (1);
  614 
  615         DELAY(MPU_DELAY);
  616         return (0);
  617 }
  618 
  619 /*
  620  * Switch to uart mode.
  621  * The caller must lock scp->mtx before calling this function if needed.
  622  */
  623 static int
  624 mpu_uartmode(sc_p scp)
  625 {
  626         int i, resp;
  627 
  628         /* Switch to uart mode. */
  629         resp = 0;
  630         for (i = 0 ; i < MPU_TRYDATA ; i++) {
  631                 resp = mpu_command(scp, MPU_UART);
  632                 if (resp == 0)
  633                         break;
  634         }
  635         if (resp != 0)
  636                 return (1);
  637 
  638         DELAY(MPU_DELAY);
  639         return (0);
  640 }
  641 
  642 /*
  643  * Wait to see an ACK.
  644  * The caller must lock scp->mtx before calling this function if needed.
  645  */
  646 static int
  647 mpu_waitack(sc_p scp)
  648 {
  649         int i;
  650         u_int8_t resp;
  651 
  652         resp = 0;
  653         for (i = 0 ; i < MPU_TRYDATA ; i++) {
  654                 if (mpu_readdata(scp, &resp) == 0)
  655                         break;
  656         }
  657         if (resp != MPU_ACK)
  658                 return (1);
  659 
  660         DELAY(MPU_DELAY);
  661         return (0);
  662 }
  663 
  664 /* Reads the status. */
  665 static int
  666 mpu_status(sc_p scp)
  667 {
  668         return mpu_readport(scp, MPU_STATPORT);
  669 }
  670 
  671 /* Writes a command. */
  672 static int
  673 mpu_command(sc_p scp, u_int8_t value)
  674 {
  675         u_int status;
  676 
  677         /* Is the interface ready to write? */
  678         status = mpu_status(scp);
  679         if ((status & MPU_OUTPUTBUSY) != 0)
  680                 /* The interface is busy. */
  681                 return (EAGAIN);
  682 
  683         mpu_writeport(scp, MPU_CMDPORT, value);
  684 
  685         return (0);
  686 }
  687 
  688 /* Reads a byte of data. */
  689 static int
  690 mpu_readdata(sc_p scp, u_int8_t *value)
  691 {
  692         u_int status;
  693 
  694         if (value == NULL)
  695                 return (EINVAL);
  696 
  697         /* Is the interface ready to write? */
  698         status = mpu_status(scp);
  699         if ((status & MPU_INPUTBUSY) != 0)
  700                 /* The interface is busy. */
  701                 return (EAGAIN);
  702 
  703         *value = (u_int8_t)(mpu_readport(scp, MPU_DATAPORT) & 0xff);
  704 
  705         return (0);
  706 }
  707 
  708 /* Writes a byte of data. */
  709 static int
  710 mpu_writedata(sc_p scp, u_int8_t value)
  711 {
  712         u_int status;
  713 
  714         /* Is the interface ready to write? */
  715         status = mpu_status(scp);
  716         if ((status & MPU_OUTPUTBUSY) != 0)
  717                 /* The interface is busy. */
  718                 return (EAGAIN);
  719 
  720         mpu_writeport(scp, MPU_DATAPORT, value);
  721 
  722         return (0);
  723 }
  724 
  725 /* Reads from a port. */
  726 static u_int
  727 mpu_readport(sc_p scp, int off)
  728 {
  729         return bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off) & 0xff;
  730 }
  731 
  732 /* Writes to a port. */
  733 static void
  734 mpu_writeport(sc_p scp, int off, u_int8_t value)
  735 {
  736         bus_space_write_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off, value);
  737 }
  738 
  739 /* Allocates resources. */
  740 static int
  741 mpu_allocres(sc_p scp, device_t dev)
  742 {
  743         if (scp->io == NULL) {
  744                 scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 2, RF_ACTIVE);
  745                 if (scp->io == NULL)
  746                         return (1);
  747         }
  748         if (scp->irq == NULL && !(device_get_flags(dev) & MPU_DF_NO_IRQ)) {
  749                 if (scp->irq_val == 0)
  750                         scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &scp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
  751                 else
  752                         scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &scp->irq_rid, scp->irq_val, scp->irq_val, 1, RF_ACTIVE | RF_SHAREABLE);
  753                 if (scp->irq == NULL)
  754                         return (1);
  755         }
  756 
  757         return (0);
  758 }
  759 
  760 /* Releases resources. */
  761 static void
  762 mpu_releaseres(sc_p scp, device_t dev)
  763 {
  764         if (scp->irq != NULL) {
  765                 bus_release_resource(dev, SYS_RES_IRQ, scp->irq_rid, scp->irq);
  766                 scp->irq = NULL;
  767         }
  768         if (scp->io != NULL) {
  769                 bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, scp->io);
  770                 scp->io = NULL;
  771         }
  772 }
  773 
  774 static device_method_t mpu_methods[] = {
  775         /* Device interface */
  776         DEVMETHOD(device_probe , mpu_probe ),
  777         DEVMETHOD(device_attach, mpu_attach),
  778 
  779         { 0, 0 },
  780 };
  781 
  782 static driver_t mpu_driver = {
  783         "midi",
  784         mpu_methods,
  785         sizeof(struct mpu_softc),
  786 };
  787 
  788 DRIVER_MODULE(mpu, isa, mpu_driver, midi_devclass, 0, 0);
  789 
  790 static device_method_t mpusbc_methods[] = {
  791         /* Device interface */
  792         DEVMETHOD(device_probe , mpusbc_probe ),
  793         DEVMETHOD(device_attach, mpusbc_attach),
  794 
  795         { 0, 0 },
  796 };
  797 
  798 static driver_t mpusbc_driver = {
  799         "midi",
  800         mpusbc_methods,
  801         sizeof(struct mpu_softc),
  802 };
  803 
  804 DRIVER_MODULE(mpusbc, sbc, mpusbc_driver, midi_devclass, 0, 0);

Cache object: 7d901c11521b38a72feebf23d074d7ea


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.