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/pcm/buffer.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER 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 
   27 #include <dev/sound/pcm/sound.h>
   28 
   29 #include "feeder_if.h"
   30 
   31 SND_DECLARE_FILE("$FreeBSD: releng/5.2/sys/dev/sound/pcm/buffer.c 123013 2003-11-27 19:51:44Z matk $");
   32 
   33 struct snd_dbuf *
   34 sndbuf_create(device_t dev, char *drv, char *desc)
   35 {
   36         struct snd_dbuf *b;
   37 
   38         b = malloc(sizeof(*b), M_DEVBUF, M_WAITOK | M_ZERO);
   39         snprintf(b->name, SNDBUF_NAMELEN, "%s:%s", drv, desc);
   40         b->dev = dev;
   41 
   42         return b;
   43 }
   44 
   45 void
   46 sndbuf_destroy(struct snd_dbuf *b)
   47 {
   48         free(b, M_DEVBUF);
   49 }
   50 
   51 bus_addr_t
   52 sndbuf_getbufaddr(struct snd_dbuf *buf)
   53 {
   54         return (buf->buf_addr);
   55 }
   56 
   57 static void
   58 sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
   59 {
   60         struct snd_dbuf *b = (struct snd_dbuf *)arg;
   61 
   62         if (bootverbose) {
   63                 device_printf(b->dev, "sndbuf_setmap %lx, %lx; ", (unsigned long)segs->ds_addr,
   64                        (unsigned long)segs->ds_len);
   65                 printf("%p -> %lx\n", b->buf, (unsigned long)vtophys(b->buf));
   66         }
   67         b->buf_addr = segs->ds_addr;
   68 }
   69 
   70 /*
   71  * Allocate memory for DMA buffer. If the device does not use DMA transfers,
   72  * the driver can call malloc(9) and sndbuf_setup() itself.
   73  */
   74 
   75 int
   76 sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, unsigned int size)
   77 {
   78         b->dmatag = dmatag;
   79         b->maxsize = size;
   80         b->bufsize = b->maxsize;
   81         if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, BUS_DMA_NOWAIT, &b->dmamap))
   82                 return ENOSPC;
   83         if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize, sndbuf_setmap, b, 0))
   84                 return ENOSPC;
   85         return sndbuf_resize(b, 2, b->maxsize / 2);
   86 }
   87 
   88 int
   89 sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size)
   90 {
   91         b->buf = buf;
   92         b->maxsize = size;
   93         b->bufsize = b->maxsize;
   94         return sndbuf_resize(b, 2, b->maxsize / 2);
   95 }
   96 
   97 void
   98 sndbuf_free(struct snd_dbuf *b)
   99 {
  100         if (b->tmpbuf)
  101                 free(b->tmpbuf, M_DEVBUF);
  102         b->tmpbuf = NULL;
  103 
  104         if (b->dmamap)
  105                 bus_dmamap_unload(b->dmatag, b->dmamap);
  106 
  107         if (b->dmamap && b->buf)
  108                 bus_dmamem_free(b->dmatag, b->buf, b->dmamap);
  109         b->dmamap = NULL;
  110         b->buf = NULL;
  111 }
  112 
  113 int
  114 sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
  115 {
  116         u_int8_t *tmpbuf;
  117         if (b->maxsize == 0)
  118                 return 0;
  119         if (blkcnt == 0)
  120                 blkcnt = b->blkcnt;
  121         if (blksz == 0)
  122                 blksz = b->blksz;
  123         if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz > b->maxsize))
  124                 return EINVAL;
  125         if (blkcnt == b->blkcnt && blksz == b->blksz)
  126                 return 0;
  127         b->blkcnt = blkcnt;
  128         b->blksz = blksz;
  129         b->bufsize = blkcnt * blksz;
  130 
  131         tmpbuf = malloc(b->bufsize, M_DEVBUF, M_NOWAIT);
  132         if (tmpbuf == NULL)
  133                 return ENOMEM;
  134         free(b->tmpbuf, M_DEVBUF);
  135         b->tmpbuf = tmpbuf;
  136         sndbuf_reset(b);
  137         return 0;
  138 }
  139 
  140 int
  141 sndbuf_remalloc(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz)
  142 {
  143         u_int8_t *buf, *tmpbuf, *f1, *f2;
  144         unsigned int bufsize;
  145 
  146         if (blkcnt < 2 || blksz < 16)
  147                 return EINVAL;
  148 
  149         bufsize = blksz * blkcnt;
  150 
  151         buf = malloc(bufsize, M_DEVBUF, M_NOWAIT);
  152         if (buf == NULL)
  153                 return ENOMEM;
  154 
  155         tmpbuf = malloc(bufsize, M_DEVBUF, M_NOWAIT);
  156         if (tmpbuf == NULL) {
  157                 free(buf, M_DEVBUF);
  158                 return ENOMEM;
  159         }
  160 
  161         b->blkcnt = blkcnt;
  162         b->blksz = blksz;
  163         b->bufsize = bufsize;
  164         b->maxsize = bufsize;
  165         f1 = b->buf;
  166         f2 = b->tmpbuf;
  167         b->buf = buf;
  168         b->tmpbuf = tmpbuf;
  169 
  170         if (f1)
  171                 free(f1, M_DEVBUF);
  172         if (f2)
  173                 free(f2, M_DEVBUF);
  174 
  175         sndbuf_reset(b);
  176         return 0;
  177 }
  178 
  179 void
  180 sndbuf_clear(struct snd_dbuf *b, unsigned int length)
  181 {
  182         int i;
  183         u_char data, *p;
  184 
  185         if (length == 0)
  186                 return;
  187         if (length > b->bufsize)
  188                 length = b->bufsize;
  189 
  190         if (b->fmt & AFMT_SIGNED)
  191                 data = 0x00;
  192         else
  193                 data = 0x80;
  194 
  195         i = sndbuf_getfreeptr(b);
  196         p = sndbuf_getbuf(b);
  197         while (length > 0) {
  198                 p[i] = data;
  199                 length--;
  200                 i++;
  201                 if (i >= b->bufsize)
  202                         i = 0;
  203         }
  204 }
  205 
  206 void
  207 sndbuf_fillsilence(struct snd_dbuf *b)
  208 {
  209         int i;
  210         u_char data, *p;
  211 
  212         if (b->fmt & AFMT_SIGNED)
  213                 data = 0x00;
  214         else
  215                 data = 0x80;
  216 
  217         i = 0;
  218         p = sndbuf_getbuf(b);
  219         while (i < b->bufsize)
  220                 p[i++] = data;
  221         b->rp = 0;
  222         b->rl = b->bufsize;
  223 }
  224 
  225 void
  226 sndbuf_reset(struct snd_dbuf *b)
  227 {
  228         b->hp = 0;
  229         b->rp = 0;
  230         b->rl = 0;
  231         b->dl = 0;
  232         b->prev_total = 0;
  233         b->total = 0;
  234         b->xrun = 0;
  235         if (b->buf && b->bufsize > 0)
  236                 sndbuf_clear(b, b->bufsize);
  237 }
  238 
  239 u_int32_t
  240 sndbuf_getfmt(struct snd_dbuf *b)
  241 {
  242         return b->fmt;
  243 }
  244 
  245 int
  246 sndbuf_setfmt(struct snd_dbuf *b, u_int32_t fmt)
  247 {
  248         b->fmt = fmt;
  249         b->bps = 1;
  250         b->bps <<= (b->fmt & AFMT_STEREO)? 1 : 0;
  251         b->bps <<= (b->fmt & AFMT_16BIT)? 1 : 0;
  252         b->bps <<= (b->fmt & AFMT_32BIT)? 2 : 0;
  253         return 0;
  254 }
  255 
  256 unsigned int
  257 sndbuf_getspd(struct snd_dbuf *b)
  258 {
  259         return b->spd;
  260 }
  261 
  262 void
  263 sndbuf_setspd(struct snd_dbuf *b, unsigned int spd)
  264 {
  265         b->spd = spd;
  266 }
  267 
  268 unsigned int
  269 sndbuf_getalign(struct snd_dbuf *b)
  270 {
  271         static int align[] = {0, 1, 1, 2, 2, 2, 2, 3};
  272 
  273         return align[b->bps - 1];
  274 }
  275 
  276 unsigned int
  277 sndbuf_getblkcnt(struct snd_dbuf *b)
  278 {
  279         return b->blkcnt;
  280 }
  281 
  282 void
  283 sndbuf_setblkcnt(struct snd_dbuf *b, unsigned int blkcnt)
  284 {
  285         b->blkcnt = blkcnt;
  286 }
  287 
  288 unsigned int
  289 sndbuf_getblksz(struct snd_dbuf *b)
  290 {
  291         return b->blksz;
  292 }
  293 
  294 void
  295 sndbuf_setblksz(struct snd_dbuf *b, unsigned int blksz)
  296 {
  297         b->blksz = blksz;
  298 }
  299 
  300 unsigned int
  301 sndbuf_getbps(struct snd_dbuf *b)
  302 {
  303         return b->bps;
  304 }
  305 
  306 void *
  307 sndbuf_getbuf(struct snd_dbuf *b)
  308 {
  309         return b->buf;
  310 }
  311 
  312 void *
  313 sndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs)
  314 {
  315         KASSERT(ofs < b->bufsize, ("%s: ofs invalid %d", __func__, ofs));
  316 
  317         return b->buf + ofs;
  318 }
  319 
  320 unsigned int
  321 sndbuf_getsize(struct snd_dbuf *b)
  322 {
  323         return b->bufsize;
  324 }
  325 
  326 unsigned int
  327 sndbuf_getmaxsize(struct snd_dbuf *b)
  328 {
  329         return b->maxsize;
  330 }
  331 
  332 unsigned int
  333 sndbuf_runsz(struct snd_dbuf *b)
  334 {
  335         return b->dl;
  336 }
  337 
  338 void
  339 sndbuf_setrun(struct snd_dbuf *b, int go)
  340 {
  341         b->dl = go? b->blksz : 0;
  342 }
  343 
  344 struct selinfo *
  345 sndbuf_getsel(struct snd_dbuf *b)
  346 {
  347         return &b->sel;
  348 }
  349 
  350 /************************************************************/
  351 unsigned int
  352 sndbuf_getxrun(struct snd_dbuf *b)
  353 {
  354         SNDBUF_LOCKASSERT(b);
  355 
  356         return b->xrun;
  357 }
  358 
  359 void
  360 sndbuf_setxrun(struct snd_dbuf *b, unsigned int cnt)
  361 {
  362         SNDBUF_LOCKASSERT(b);
  363 
  364         b->xrun = cnt;
  365 }
  366 
  367 unsigned int
  368 sndbuf_gethwptr(struct snd_dbuf *b)
  369 {
  370         SNDBUF_LOCKASSERT(b);
  371 
  372         return b->hp;
  373 }
  374 
  375 void
  376 sndbuf_sethwptr(struct snd_dbuf *b, unsigned int ptr)
  377 {
  378         SNDBUF_LOCKASSERT(b);
  379 
  380         b->hp = ptr;
  381 }
  382 
  383 unsigned int
  384 sndbuf_getready(struct snd_dbuf *b)
  385 {
  386         SNDBUF_LOCKASSERT(b);
  387         KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
  388 
  389         return b->rl;
  390 }
  391 
  392 unsigned int
  393 sndbuf_getreadyptr(struct snd_dbuf *b)
  394 {
  395         SNDBUF_LOCKASSERT(b);
  396         KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp));
  397 
  398         return b->rp;
  399 }
  400 
  401 unsigned int
  402 sndbuf_getfree(struct snd_dbuf *b)
  403 {
  404         SNDBUF_LOCKASSERT(b);
  405         KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
  406 
  407         return b->bufsize - b->rl;
  408 }
  409 
  410 unsigned int
  411 sndbuf_getfreeptr(struct snd_dbuf *b)
  412 {
  413         SNDBUF_LOCKASSERT(b);
  414         KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp));
  415         KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
  416 
  417         return (b->rp + b->rl) % b->bufsize;
  418 }
  419 
  420 unsigned int
  421 sndbuf_getblocks(struct snd_dbuf *b)
  422 {
  423         SNDBUF_LOCKASSERT(b);
  424 
  425         return b->total / b->blksz;
  426 }
  427 
  428 unsigned int
  429 sndbuf_getprevblocks(struct snd_dbuf *b)
  430 {
  431         SNDBUF_LOCKASSERT(b);
  432 
  433         return b->prev_total / b->blksz;
  434 }
  435 
  436 unsigned int
  437 sndbuf_gettotal(struct snd_dbuf *b)
  438 {
  439         SNDBUF_LOCKASSERT(b);
  440 
  441         return b->total;
  442 }
  443 
  444 void
  445 sndbuf_updateprevtotal(struct snd_dbuf *b)
  446 {
  447         SNDBUF_LOCKASSERT(b);
  448 
  449         b->prev_total = b->total;
  450 }
  451 
  452 /************************************************************/
  453 
  454 int
  455 sndbuf_acquire(struct snd_dbuf *b, u_int8_t *from, unsigned int count)
  456 {
  457         int l;
  458 
  459         KASSERT(count <= sndbuf_getfree(b), ("%s: count %d > free %d", __func__, count, sndbuf_getfree(b)));
  460         KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
  461         b->total += count;
  462         if (from != NULL) {
  463                 while (count > 0) {
  464                         l = MIN(count, sndbuf_getsize(b) - sndbuf_getfreeptr(b));
  465                         bcopy(from, sndbuf_getbufofs(b, sndbuf_getfreeptr(b)), l);
  466                         from += l;
  467                         b->rl += l;
  468                         count -= l;
  469                 }
  470         } else
  471                 b->rl += count;
  472         KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count));
  473 
  474         return 0;
  475 }
  476 
  477 int
  478 sndbuf_dispose(struct snd_dbuf *b, u_int8_t *to, unsigned int count)
  479 {
  480         int l;
  481 
  482         KASSERT(count <= sndbuf_getready(b), ("%s: count %d > ready %d", __func__, count, sndbuf_getready(b)));
  483         KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl));
  484         if (to != NULL) {
  485                 while (count > 0) {
  486                         l = MIN(count, sndbuf_getsize(b) - sndbuf_getreadyptr(b));
  487                         bcopy(sndbuf_getbufofs(b, sndbuf_getreadyptr(b)), to, l);
  488                         to += l;
  489                         b->rl -= l;
  490                         b->rp = (b->rp + l) % b->bufsize;
  491                         count -= l;
  492                 }
  493         } else {
  494                 b->rl -= count;
  495                 b->rp = (b->rp + count) % b->bufsize;
  496         }
  497         KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count));
  498 
  499         return 0;
  500 }
  501 
  502 /* count is number of bytes we want added to destination buffer */
  503 int
  504 sndbuf_feed(struct snd_dbuf *from, struct snd_dbuf *to, struct pcm_channel *channel, struct pcm_feeder *feeder, unsigned int count)
  505 {
  506         KASSERT(count > 0, ("can't feed 0 bytes"));
  507 
  508         if (sndbuf_getfree(to) < count)
  509                 return EINVAL;
  510 
  511         count = FEEDER_FEED(feeder, channel, to->tmpbuf, count, from);
  512         if (count)
  513                 sndbuf_acquire(to, to->tmpbuf, count);
  514         /* the root feeder has called sndbuf_dispose(from, , bytes fetched) */
  515 
  516         return 0;
  517 }
  518 
  519 /************************************************************/
  520 
  521 void
  522 sndbuf_dump(struct snd_dbuf *b, char *s, u_int32_t what)
  523 {
  524         printf("%s: [", s);
  525         if (what & 0x01)
  526                 printf(" bufsize: %d, maxsize: %d", b->bufsize, b->maxsize);
  527         if (what & 0x02)
  528                 printf(" dl: %d, rp: %d, rl: %d, hp: %d", b->dl, b->rp, b->rl, b->hp);
  529         if (what & 0x04)
  530                 printf(" total: %d, prev_total: %d, xrun: %d", b->total, b->prev_total, b->xrun);
  531         if (what & 0x08)
  532                 printf(" fmt: 0x%x, spd: %d", b->fmt, b->spd);
  533         if (what & 0x10)
  534                 printf(" blksz: %d, blkcnt: %d, flags: 0x%x", b->blksz, b->blkcnt, b->flags);
  535         printf(" ]\n");
  536 }
  537 
  538 /************************************************************/
  539 u_int32_t
  540 sndbuf_getflags(struct snd_dbuf *b)
  541 {
  542         return b->flags;
  543 }
  544 
  545 void
  546 sndbuf_setflags(struct snd_dbuf *b, u_int32_t flags, int on)
  547 {
  548         b->flags &= ~flags;
  549         if (on)
  550                 b->flags |= flags;
  551 }
  552 

Cache object: eef579940727eefb1d357e67f1820907


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