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/chips/audio.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  * Mach Operating System
    3  * Copyright (c) 1993 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        audio.c,v $
   29  * Revision 2.4  93/05/15  19:39:53  mrt
   30  *      machparam.h -> machspl.h
   31  * 
   32  * Revision 2.3  93/05/10  20:07:18  rvb
   33  *      GCC quiet.
   34  *      [93/05/06  09:53:58  af]
   35  * 
   36  * Revision 2.2  93/03/18  10:36:56  mrt
   37  *      Backward compat include of sys/types.h since busses.h
   38  *      not fixed yet in this release.
   39  *      [93/03/18  01:21:22  af]
   40  * 
   41  *      Started, from Berkeley's driver.
   42  *      [93/03/09            af]
   43  * 
   44 /*-
   45  * Copyright (c) 1991, 1992 The Regents of the University of California.
   46  * All rights reserved.
   47  *
   48  * Redistribution and use in source and binary forms, with or without
   49  * modification, are permitted provided that the following conditions
   50  * are met:
   51  * 1. Redistributions of source code must retain the above copyright
   52  *    notice, this list of conditions and the following disclaimer.
   53  * 2. Redistributions in binary form must reproduce the above copyright
   54  *    notice, this list of conditions and the following disclaimer in the
   55  *    documentation and/or other materials provided with the distribution.
   56  * 3. All advertising materials mentioning features or use of this software
   57  *    must display the following acknowledgement:
   58  *      This product includes software developed by the Computer Systems
   59  *      Engineering Group at Lawrence Berkeley Laboratory.
   60  * 4. The name of the Laboratory may not be used to endorse or promote 
   61  *    products derived from this software without specific prior written 
   62  *    permission.
   63  *
   64  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   65  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   66  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   67  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   68  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   69  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   70  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   71  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   72  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   73  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   74  * SUCH DAMAGE.
   75  *
   76  *      $Header: audio.c,v 2.4 93/05/15 19:39:53 mrt Exp $ (LBL)
   77  */
   78 
   79 #include <audio.h>
   80 #if NAUDIO > 0
   81 
   82 #include <platforms.h>
   83 
   84 #include <mach/std_types.h>
   85 #include <machine/machspl.h>
   86 #include <kern/kalloc.h>
   87 #include <chips/busses.h>
   88 
   89 #include <device/device_types.h>
   90 #include <device/io_req.h>
   91 #include <device/ds_routines.h>
   92 #include <device/audio_status.h>        /* user interface */
   93 #include <chips/audio_defs.h>           /* chip interface */
   94 #include <chips/audio_config.h>         /* machdep config */
   95 
   96 #define private static
   97 
   98 /*
   99  * Exported functions and data structures
  100  * [see header file for listing]
  101  */
  102 int audio_blocksize = DEFBLKSIZE;       /* patchable */
  103 int audio_backlog = 400;                /* 50ms in samples */
  104 
  105 /*
  106  * Software state, per AMD79C30 audio chip.
  107  */
  108 private
  109 struct audio_softc {
  110         void            *hw;            /* chip status */
  111         audio_switch_t  *ops;           /* chip operations */
  112         au_io_t         *sc_au;         /* recv and xmit buffers, etc */
  113 
  114 
  115         unsigned int    sc_wseek;               /* timestamp of last frame written */
  116         unsigned int    sc_rseek;               /* timestamp of last frame read */
  117 #if 0
  118         struct  selinfo sc_wsel;        /* write selector */
  119         struct  selinfo sc_rsel;        /* read selector */
  120 #endif
  121 
  122 } audio_softc_data[NAUDIO];
  123 
  124 #define unit_to_softc(u)        &audio_softc_data[u]
  125 
  126 
  127 /* forward declarations */
  128 private int     audio_sleep (au_cb_t *cb, int thresh);
  129 private void    audio_swintr (struct audio_softc *sc);
  130 
  131 /*
  132  * Audio chip found.
  133  */
  134 void
  135 audio_attach(
  136         void            *hw,            /* IN, chip status */
  137         audio_switch_t  *ops,
  138         void            **audio_status) /* OUT, audio status */
  139 {
  140         register struct audio_softc *sc;
  141         static int      next = 0;
  142 
  143         if (next >= NAUDIO)
  144                 panic("Please configure more than %d audio devices\n", NAUDIO);
  145         sc = &audio_softc_data[next++];
  146 
  147         printf(" audio");
  148 
  149         sc->hw  = hw;
  150         sc->ops = ops;
  151 
  152         *audio_status   = (void *)sc;
  153 }
  154 
  155 
  156 private int audio_setinfo (struct audio_softc *, audio_info_t *);
  157 private int audio_getinfo (struct audio_softc *, audio_info_t *);
  158 
  159 io_return_t
  160 audio_open(
  161         int             unit,
  162         int             mode,
  163         io_req_t        req)
  164 {
  165         register struct audio_softc *sc;
  166         register au_io_t *au;
  167 
  168         sc = unit_to_softc(unit);
  169         if (unit > NAUDIO || (!sc->hw))
  170                 return (D_NO_SUCH_DEVICE);
  171 
  172         if (!sc->sc_au) {
  173                 sc->sc_au = (au_io_t *) kalloc(sizeof(au_io_t));
  174                 bzero(sc->sc_au, sizeof(au_io_t));
  175         }
  176         au = sc->sc_au;
  177 
  178         au->au_lowat = audio_blocksize;
  179         au->au_hiwat = AUCB_SIZE - au->au_lowat;
  180         au->au_blksize = audio_blocksize;
  181         au->au_backlog = audio_backlog;
  182 
  183         /* set up read and write blocks and `dead sound' zero value. */
  184         AUCB_INIT(&au->au_rb);
  185         au->au_rb.cb_thresh = AUCB_SIZE;
  186         AUCB_INIT(&au->au_wb);
  187         au->au_wb.cb_thresh = -1;
  188 
  189         /* nothing read or written yet */
  190         sc->sc_rseek = 0;
  191         sc->sc_wseek = 0;
  192 
  193         (*sc->ops->init)(sc->hw);
  194 
  195         return (0);
  196 }
  197 
  198 private int
  199 audio_drain(
  200         register au_io_t *au)
  201 {
  202         register int error;
  203 
  204         while (!AUCB_EMPTY(&au->au_wb))
  205                 if ((error = audio_sleep(&au->au_wb, 0)) != 0)
  206                         return (error);
  207         return (0);
  208 }
  209 
  210 /*
  211  * Close an audio chip.
  212  */
  213 /* ARGSUSED */
  214 io_return_t
  215 audio_close(
  216         int             unit)
  217 {
  218         register struct audio_softc *sc = unit_to_softc(unit);
  219         register au_cb_t *cb;
  220         register spl_t s;
  221 
  222         /*
  223          * Block until output drains, but allow ^C interrupt.
  224          */
  225         sc->sc_au->au_lowat = 0;        /* avoid excessive wakeups */
  226 
  227         /*
  228          * If there is pending output, let it drain (unless
  229          * the output is paused).
  230          */
  231         cb = &sc->sc_au->au_wb;
  232         s = splaudio();
  233         if (!AUCB_EMPTY(cb) && !cb->cb_pause)
  234                 (void)audio_drain(sc->sc_au);
  235         /*
  236          * Disable interrupts, and done.
  237          */
  238         (*sc->ops->close)(sc->hw);
  239         splx(s);
  240         return (D_SUCCESS);
  241 }
  242 
  243 private int
  244 audio_sleep(cb, thresh)
  245         register au_cb_t *cb;
  246         register int thresh;
  247 {
  248         register int error;
  249         register spl_t s = splaudio();
  250 
  251         cb->cb_thresh = thresh;
  252         assert_wait((event_t)cb, TRUE);
  253         splx(s);
  254         thread_block((void (*)()) 0);
  255         return (0);     /* XXXX */
  256 }
  257 
  258 io_return_t
  259 audio_read(
  260         int             unit,
  261         io_req_t        ior)
  262 {
  263         register struct audio_softc *sc = unit_to_softc(unit);
  264         register au_cb_t *cb;
  265         register int n, head, taildata;
  266         register int blocksize = sc->sc_au->au_blksize;
  267         io_return_t     rc;
  268         unsigned char   *data;
  269 
  270         /*
  271          * Allocate read buffer
  272          */
  273         rc = device_read_alloc(ior, (vm_size_t)ior->io_count);
  274         if (rc != KERN_SUCCESS)
  275             return rc;
  276         data = (unsigned char *) ior->io_data;
  277         ior->io_residual = ior->io_count;
  278 
  279         cb = &sc->sc_au->au_rb;
  280         cb->cb_drops = 0;
  281         sc->sc_rseek = sc->sc_au->au_stamp - AUCB_LEN(cb);
  282         do {
  283                 while (AUCB_LEN(cb) < blocksize) {
  284 
  285                         if (ior->io_mode & D_NODELAY)
  286                                 return (D_WOULD_BLOCK);
  287 
  288                         if ((rc = audio_sleep(cb, blocksize)) != 0)
  289                                 return(rc);
  290                 }
  291                 /*
  292                  * The space calculation can only err on the short
  293                  * side if an interrupt occurs during processing:
  294                  * only cb_tail is altered in the interrupt code.
  295                  */
  296                 head = cb->cb_head;
  297                 if ((n = AUCB_LEN(cb)) > ior->io_residual)
  298                         n = ior->io_residual;
  299                 taildata = AUCB_SIZE - head;
  300 
  301                 if (n > taildata) {
  302                         bcopy(cb->cb_data + head, data, taildata);
  303                         bcopy(cb->cb_data, data + taildata, n - taildata);
  304                 } else
  305                         bcopy(cb->cb_data + head, data, n);
  306                 data += n;
  307                 ior->io_residual -= n;
  308 
  309                 head = AUCB_MOD(head + n);
  310                 cb->cb_head = head;
  311         } while (ior->io_residual >= blocksize);
  312 
  313         return (rc);
  314 }
  315 
  316 io_return_t
  317 audio_write(
  318         int             unit,
  319         io_req_t        ior)
  320 {
  321         register struct audio_softc *sc = unit_to_softc(unit);
  322         register au_io_t *au = sc->sc_au;
  323         register au_cb_t *cb = &au->au_wb;
  324         register int n, tail, tailspace, first, watermark, drops;
  325         io_return_t rc;
  326         unsigned char *data;
  327         vm_offset_t addr = 0;
  328 
  329         if (!(ior->io_op & IO_INBAND)) {
  330             /*
  331              * Copy out-of-line data into kernel address space.
  332              * Since data is copied as page list, it will be
  333              * accessible.
  334              */
  335             vm_map_copy_t copy = (vm_map_copy_t) ior->io_data;
  336             kern_return_t kr;
  337 
  338             kr = vm_map_copyout(device_io_map, &addr, copy);
  339             if (kr != KERN_SUCCESS)
  340                 return kr;
  341             data = (unsigned char *) addr;
  342         } else
  343             data = (unsigned char *) ior->io_data;
  344         ior->io_residual = ior->io_count;
  345 
  346         rc = D_SUCCESS;
  347         first = 1;
  348         while (ior->io_residual > 0) {
  349                 watermark = au->au_hiwat;
  350                 while (AUCB_LEN(cb) > watermark) {
  351 
  352                         if (ior->io_mode & D_NODELAY) {
  353                                 rc = D_WOULD_BLOCK;
  354                                 goto out;
  355                         }
  356 
  357                         if ((rc = audio_sleep(cb, watermark)) != 0)
  358                                 goto out;
  359 
  360                         watermark = au->au_lowat;
  361                 }
  362                 /*
  363                  * The only value that can change on an interrupt is
  364                  * cb->cb_head.  We only pull that out once to decide
  365                  * how much to write into cb_data; if we lose a race
  366                  * and cb_head changes, we will merely be overly
  367                  * conservative.  For a legitimate time stamp,
  368                  * however, we need to synchronize the accesses to
  369                  * au_stamp and cb_head at a high ipl below.
  370                  */
  371                 tail = cb->cb_tail;
  372                 if ((n = (AUCB_SIZE - 1) - AUCB_LEN(cb)) > ior->io_residual) {
  373                         n = ior->io_residual;
  374                         if (cb->cb_head == tail &&
  375                             n <= au->au_blksize &&
  376                             au->au_stamp - sc->sc_wseek > 400) {
  377                                 /*
  378                                  * the write is 'small', the buffer is empty
  379                                  * and we have been silent for at least 50ms
  380                                  * so we might be dealing with an application
  381                                  * that writes frames synchronously with
  382                                  * reading them.  If so, we need an output
  383                                  * backlog to cover scheduling delays or
  384                                  * there will be gaps in the sound output.
  385                                  * Also take this opportunity to reset the
  386                                  * buffer pointers in case we ended up on
  387                                  * a bad boundary (odd byte, blksize bytes
  388                                  * from end, etc.).
  389                                  */
  390                                 register unsigned long *ip;
  391                                 register unsigned long muzero;
  392                                 spl_t s;
  393                                 register int i;
  394 
  395                                 s = splaudio();
  396                                 cb->cb_head = cb->cb_tail = 0;
  397                                 splx(s);
  398 
  399                                 tail = au->au_backlog;
  400                                 ip = (unsigned long *)cb->cb_data;
  401                                 muzero = sample_rpt_long(0x7fL);
  402                                 for (i = tail / sizeof muzero; --i >= 0; )
  403                                         *ip++ = muzero;
  404                         }
  405                 }
  406                 tailspace = AUCB_SIZE - tail;
  407                 if (n > tailspace) {
  408                         /* write first part at tail and rest at head */
  409                         bcopy(data, cb->cb_data + tail, tailspace);
  410                         bcopy(data + tailspace, cb->cb_data,
  411                                          n - tailspace);
  412                 } else
  413                         bcopy(data, cb->cb_data + tail, n);
  414                 data += n;
  415                 ior->io_residual -= n;
  416 
  417                 tail = AUCB_MOD(tail + n);
  418                 if (first) {
  419                         register spl_t s = splaudio();
  420                         sc->sc_wseek = AUCB_LEN(cb) + au->au_stamp + 1;
  421                         /* 
  422                          * To guarantee that a write is contiguous in the
  423                          * sample space, we clear the drop count the first
  424                          * time through.  If we later get drops, we will
  425                          * break out of the loop below, before writing
  426                          * a new frame.
  427                          */
  428                         cb->cb_drops = 0;
  429                         cb->cb_tail = tail;
  430                         splx(s);
  431                         first = 0;
  432                 } else {
  433                         if (cb->cb_drops != 0)
  434                                 break;
  435                         cb->cb_tail = tail;
  436                 }
  437         }
  438 out:
  439         if (!(ior->io_op & IO_INBAND))
  440             (void) vm_deallocate(device_io_map, addr, ior->io_count);
  441         return (rc);
  442 }
  443 
  444 #include <sys/ioctl.h>
  445 
  446 io_return_t
  447 audio_get_status(
  448         int             unit,
  449         dev_flavor_t    flavor,
  450         dev_status_t    status,
  451         natural_t       *status_count)
  452 {
  453         register struct audio_softc *sc = unit_to_softc(unit);
  454         register au_io_t *au = sc->sc_au;
  455         io_return_t rc = D_SUCCESS;
  456         int i;
  457         spl_t   s;
  458 
  459         switch (flavor) {
  460 
  461         case AUDIO_GETMAP:
  462         case AUDIOGETREG:
  463                 rc = (*sc->ops->getstate)(sc->hw, flavor,
  464                                 (void *)status, status_count);
  465                 break;
  466 
  467         /*
  468          * Number of read samples dropped.  We don't know where or
  469          * when they were dropped.
  470          */
  471         case AUDIO_RERROR:
  472                 *(int *)status = au->au_rb.cb_drops;
  473                 *status_count = 1;
  474                 break;
  475 
  476         case AUDIO_WERROR:
  477                 *(int *)status = au->au_wb.cb_drops;
  478                 *status_count = 1;
  479                 break;
  480 
  481         /*
  482          * How many samples will elapse until mike hears the first
  483          * sample of what we last wrote?
  484          */
  485         case AUDIO_WSEEK:
  486                 s = splaudio();
  487                 *(unsigned int *)status = sc->sc_wseek - au->au_stamp
  488                                   + AUCB_LEN(&au->au_rb);
  489                 splx(s);
  490                 *status_count = 1;
  491                 break;
  492 
  493         case AUDIO_GETINFO:
  494                 rc = audio_getinfo(sc, (audio_info_t *)status);
  495                 *status_count = sizeof(audio_info_t) / sizeof(int);
  496                 break;
  497 
  498         default:
  499                 rc = D_INVALID_OPERATION;
  500                 break;
  501         }
  502         return (rc);
  503 }
  504 
  505 io_return_t
  506 audio_set_status(
  507         int             unit,
  508         dev_flavor_t    flavor,
  509         dev_status_t    status,
  510         natural_t       status_count)
  511 {
  512         register struct audio_softc *sc = unit_to_softc(unit);
  513         register au_io_t *au = sc->sc_au;
  514         int i;
  515         io_return_t rc = D_SUCCESS;
  516         spl_t   s;
  517 
  518         switch (flavor) {
  519 
  520         case AUDIO_SETMAP:
  521         case AUDIOSETREG:
  522                 rc = (*sc->ops->setstate)(sc->hw, flavor,
  523                                 (void *)status, status_count);
  524                 break;
  525 
  526         case AUDIO_FLUSH:
  527                 s = splaudio();
  528                 AUCB_INIT(&au->au_rb);
  529                 AUCB_INIT(&au->au_wb);
  530                 au->au_stamp = 0;
  531                 splx(s);
  532                 sc->sc_wseek = 0;
  533                 sc->sc_rseek = 0;
  534                 break;
  535 
  536         case AUDIO_SETINFO:
  537                 rc = audio_setinfo(sc, (audio_info_t *)status);
  538                 break;
  539 
  540         case AUDIO_DRAIN:
  541                 rc = audio_drain(au);
  542                 break;
  543 
  544         default:
  545                 rc = D_INVALID_OPERATION;
  546                 break;
  547         }
  548         return (rc);
  549 }
  550 
  551 
  552 /*
  553  * Interrupt routine
  554  */
  555 boolean_t
  556 audio_hwintr(
  557         void                    *status,
  558         unsigned int            s_in,
  559         unsigned int            *s_out)
  560 {
  561         register au_io_t *au = ((struct audio_softc *) status)->sc_au;
  562         register au_cb_t *cb;
  563         register int h, t, k;
  564         register boolean_t      wakeit = FALSE;
  565 
  566         ++au->au_stamp;
  567 
  568         /* receive incoming data */
  569         cb = &au->au_rb;
  570         h = cb->cb_head;
  571         t = cb->cb_tail;
  572         k = AUCB_MOD(t + 1);
  573         if (h == k)
  574                 cb->cb_drops++;
  575         else if  (cb->cb_pause != 0)
  576                 cb->cb_pdrops++;
  577         else {
  578                 cb->cb_data[t] = s_in;
  579                 cb->cb_tail = t = k;
  580         }
  581         if (AUCB_MOD(t - h) >= cb->cb_thresh) {
  582                 cb->cb_thresh = AUCB_SIZE;
  583                 cb->cb_waking = 1;
  584                 wakeit = TRUE;
  585         }
  586         /* send outgoing data */
  587         cb = &au->au_wb;
  588         h = cb->cb_head;
  589         t = cb->cb_tail;
  590         k = 0;
  591         if (h == t)
  592                 cb->cb_drops++;
  593         else if (cb->cb_pause != 0)
  594                 cb->cb_pdrops++;
  595         else {
  596                 cb->cb_head = h = AUCB_MOD(h + 1);
  597                 *s_out = cb->cb_data[h];
  598                 k = 1;
  599         }
  600         if (AUCB_MOD(t - h) <= cb->cb_thresh) {
  601                 cb->cb_thresh = -1;
  602                 cb->cb_waking = 1;
  603                 wakeit = TRUE;
  604         }
  605         if (wakeit)
  606                 audio_swintr((struct audio_softc *) status);
  607         return (k == 1);
  608 }
  609 
  610 private void
  611 audio_swintr(
  612         register struct audio_softc *sc)
  613 {
  614         register au_io_t *au = sc->sc_au;
  615 
  616         if (au->au_rb.cb_waking != 0) {
  617                 au->au_rb.cb_waking = 0;
  618                 wakeup(&au->au_rb);
  619         }
  620         if (au->au_wb.cb_waking != 0) {
  621                 au->au_wb.cb_waking = 0;
  622                 wakeup(&au->au_wb);
  623         }
  624 }
  625 
  626 private int
  627 audio_setinfo(sc, ai)
  628         struct audio_softc *sc;
  629         audio_info_t *ai;
  630 {
  631         struct audio_prinfo *r = &ai->record, *p = &ai->play;
  632         register int bsize;
  633         register au_io_t        *au = sc->sc_au;
  634         spl_t s;
  635 
  636         (*sc->ops->setgains)(sc->hw, p->gain, r->gain, ai->monitor_gain );
  637 
  638         if (p->pause != (unsigned char)~0)
  639                 au->au_wb.cb_pause = p->pause;
  640         if (r->pause != (unsigned char)~0)
  641                 au->au_rb.cb_pause = r->pause;
  642 
  643         if (p->port != ~0)
  644                 (*sc->ops->setport)(sc->hw, p->port);
  645 
  646         if (ai->blocksize != ~0) {
  647                 if (ai->blocksize == 0)
  648                         bsize = ai->blocksize = DEFBLKSIZE;
  649                 else if (ai->blocksize > MAXBLKSIZE)
  650                         bsize = ai->blocksize = MAXBLKSIZE;
  651                 else
  652                         bsize = ai->blocksize;
  653 
  654                 s = splaudio();
  655                 au->au_blksize = bsize;
  656                 /* AUDIO_FLUSH */
  657                 AUCB_INIT(&au->au_rb);
  658                 AUCB_INIT(&au->au_wb);
  659                 splx(s);
  660 
  661         }
  662         if (ai->hiwat != ~0 && (unsigned)ai->hiwat < AUCB_SIZE)
  663                 au->au_hiwat = ai->hiwat;
  664         if (ai->lowat != ~0 && ai->lowat < AUCB_SIZE)
  665                 au->au_lowat = ai->lowat;
  666         if (ai->backlog != ~0 && ai->backlog < (AUCB_SIZE/2))
  667                 au->au_backlog = ai->backlog;
  668 
  669         return (0);
  670 }
  671 
  672 private int
  673 audio_getinfo(sc, ai)
  674         struct audio_softc *sc;
  675         audio_info_t *ai;
  676 {
  677         struct audio_prinfo *r = &ai->record, *p = &ai->play;
  678         register au_io_t        *au = sc->sc_au;
  679 
  680         p->sample_rate = r->sample_rate = 8000;
  681         p->channels = r->channels = 1;
  682         p->precision = r->precision = 8;
  683         p->encoding = r->encoding = AUDIO_ENCODING_ULAW;
  684 
  685         (*sc->ops->getgains)(sc->hw, &p->gain, &r->gain, &ai->monitor_gain );
  686 
  687         r->port = AUDIO_MIKE;
  688         p->port = (*sc->ops->getport)(sc->hw);
  689 
  690         p->pause = au->au_wb.cb_pause;
  691         r->pause = au->au_rb.cb_pause;
  692         p->error = au->au_wb.cb_drops != 0;
  693         r->error = au->au_rb.cb_drops != 0;
  694 
  695         /* Now this is funny. If you got here it means you must have
  696            opened the device, so how could it possibly be closed ?
  697            Unless we upgrade the berkeley code to check if the chip
  698            is currently playing and/or recording... Later. */
  699         p->open = TRUE;
  700         r->open = TRUE;
  701 
  702         p->samples = au->au_stamp - au->au_wb.cb_pdrops;
  703         r->samples = au->au_stamp - au->au_rb.cb_pdrops;
  704 
  705         p->seek = sc->sc_wseek;
  706         r->seek = sc->sc_rseek;
  707 
  708         ai->blocksize = au->au_blksize;
  709         ai->hiwat = au->au_hiwat;
  710         ai->lowat = au->au_lowat;
  711         ai->backlog = au->au_backlog;
  712 
  713         return (0);
  714 }
  715 
  716 #if 1
  717 audio_status(int unit)
  718 {
  719         struct audio_softc *sc = unit_to_softc(unit);
  720         au_io_t *au;
  721 
  722         if (!sc) {
  723                 db_printf("No such thing\n");
  724                 return 0;
  725         }
  726         db_printf("@%lx: wseek %d rseek %d, au @%lx\n",
  727                 sc, sc->sc_wseek, sc->sc_rseek, sc->sc_au);
  728         if (!(au = sc->sc_au)) return 0;
  729 
  730         db_printf("au: stamp %x lo %x hi %x blk %x blg %x\n",
  731                 au->au_stamp, au->au_lowat, au->au_hiwat,
  732                 au->au_blksize, au->au_backlog);
  733         audio_queue_status(&au->au_rb, "read");
  734         audio_queue_status(&au->au_wb, "write");
  735         return 0;
  736 }
  737 audio_queue_status( au_cb_t *cb, char *logo)
  738 {
  739         db_printf("%s ring status:\n", logo);
  740         db_printf("   h %x t %x sh %x w %d p %d d %x pd %x\n",
  741                   cb->cb_head, cb->cb_tail, cb->cb_thresh,
  742                   cb->cb_waking, cb->cb_pause, (long)cb->cb_drops,
  743                   (long)cb->cb_pdrops);
  744 }
  745 
  746 #endif
  747 
  748 #endif  /* NAUDIO > 0 */
  749 

Cache object: a8ab65fffcd0387b0669c5805eebe5d1


[ 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.