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

Cache object: 7e5024c6f3f6c0e7e8f05f1f09337dad


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