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/tc/bba.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 /* $NetBSD: bba.c,v 1.20 2003/05/03 18:11:41 wiz Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *        This product includes software developed by the NetBSD
   18  *        Foundation, Inc. and its contributors.
   19  * 4. Neither the name of The NetBSD Foundation nor the names of its
   20  *    contributors may be used to endorse or promote products derived
   21  *    from this software without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   33  * POSSIBILITY OF SUCH DAMAGE.
   34  */
   35 
   36 /* maxine/alpha baseboard audio (bba) */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: bba.c,v 1.20 2003/05/03 18:11:41 wiz Exp $");
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/device.h>
   45 #include <sys/malloc.h>
   46 
   47 #include <machine/bus.h>
   48 #include <machine/autoconf.h>
   49 #include <machine/cpu.h>
   50 
   51 #include <sys/audioio.h>
   52 #include <dev/audio_if.h>
   53 
   54 #include <dev/ic/am7930reg.h>
   55 #include <dev/ic/am7930var.h>
   56 
   57 #include <dev/tc/tcvar.h>
   58 #include <dev/tc/ioasicreg.h>
   59 #include <dev/tc/ioasicvar.h>
   60 
   61 #ifdef AUDIO_DEBUG
   62 #define DPRINTF(x)      if (am7930debug) printf x
   63 #else
   64 #define DPRINTF(x)
   65 #endif  /* AUDIO_DEBUG */
   66 
   67 #define BBA_MAX_DMA_SEGMENTS    16
   68 #define BBA_DMABUF_SIZE         (BBA_MAX_DMA_SEGMENTS*IOASIC_DMA_BLOCKSIZE)
   69 #define BBA_DMABUF_ALIGN        IOASIC_DMA_BLOCKSIZE
   70 #define BBA_DMABUF_BOUNDARY     0
   71 
   72 struct bba_mem {
   73         struct bba_mem *next;
   74         bus_addr_t addr;
   75         bus_size_t size;
   76         caddr_t kva;
   77 };
   78 
   79 struct bba_dma_state {
   80         bus_dmamap_t dmam;              /* DMA map */
   81         int active;
   82         int curseg;                     /* current segment in DMA buffer */
   83         void (*intr)__P((void *));      /* higher-level audio handler */
   84         void *intr_arg;
   85 };
   86 
   87 struct bba_softc {
   88         struct am7930_softc sc_am7930;          /* glue to MI code */
   89 
   90         bus_space_tag_t sc_bst;                 /* IOASIC bus tag/handle */
   91         bus_space_handle_t sc_bsh;
   92         bus_dma_tag_t sc_dmat;
   93         bus_space_handle_t sc_codec_bsh;        /* codec bus space handle */
   94 
   95         struct bba_mem *sc_mem_head;            /* list of buffers */
   96 
   97         struct bba_dma_state sc_tx_dma_state;
   98         struct bba_dma_state sc_rx_dma_state;
   99 };
  100 
  101 int     bba_match __P((struct device *, struct cfdata *, void *));
  102 void    bba_attach __P((struct device *, struct device *, void *));
  103 
  104 CFATTACH_DECL(bba, sizeof(struct bba_softc),
  105     bba_match, bba_attach, NULL, NULL);
  106 
  107 /*
  108  * Define our interface into the am7930 MI driver.
  109  */
  110 
  111 u_int8_t        bba_codec_iread __P((struct am7930_softc *, int));
  112 u_int16_t       bba_codec_iread16 __P((struct am7930_softc *, int));
  113 void    bba_codec_iwrite __P((struct am7930_softc *, int, u_int8_t));
  114 void    bba_codec_iwrite16 __P((struct am7930_softc *, int, u_int16_t));
  115 void    bba_onopen __P((struct am7930_softc *sc));
  116 void    bba_onclose __P((struct am7930_softc *sc));
  117 void    bba_output_conv __P((void *, u_int8_t *, int));
  118 void    bba_input_conv __P((void *, u_int8_t *, int));
  119 
  120 struct am7930_glue bba_glue = {
  121         bba_codec_iread,
  122         bba_codec_iwrite,
  123         bba_codec_iread16,
  124         bba_codec_iwrite16,
  125         bba_onopen,
  126         bba_onclose,
  127         4,
  128         bba_input_conv,
  129         bba_output_conv,
  130 };
  131 
  132 /*
  133  * Define our interface to the higher level audio driver.
  134  */
  135 
  136 int     bba_round_blocksize __P((void *, int));
  137 int     bba_halt_output __P((void *));
  138 int     bba_halt_input __P((void *));
  139 int     bba_getdev __P((void *, struct audio_device *));
  140 void    *bba_allocm __P((void *, int, size_t, struct malloc_type *, int));
  141 void    bba_freem __P((void *, void *, struct malloc_type *));
  142 size_t  bba_round_buffersize __P((void *, int, size_t));
  143 int     bba_get_props __P((void *));
  144 paddr_t bba_mappage __P((void *, void *, off_t, int));
  145 int     bba_trigger_output __P((void *, void *, void *, int,
  146             void (*)(void *), void *, struct audio_params *));
  147 int     bba_trigger_input __P((void *, void *, void *, int,
  148             void (*)(void *), void *, struct audio_params *));
  149 
  150 struct audio_hw_if sa_hw_if = {
  151         am7930_open,
  152         am7930_close,
  153         0,
  154         am7930_query_encoding,
  155         am7930_set_params,
  156         bba_round_blocksize,            /* md */
  157         am7930_commit_settings,
  158         0,
  159         0,
  160         0,
  161         0,
  162         bba_halt_output,                /* md */
  163         bba_halt_input,                 /* md */
  164         0,
  165         bba_getdev,
  166         0,
  167         am7930_set_port,
  168         am7930_get_port,
  169         am7930_query_devinfo,
  170         bba_allocm,                     /* md */
  171         bba_freem,                      /* md */
  172         bba_round_buffersize,           /* md */
  173         bba_mappage,
  174         bba_get_props,
  175         bba_trigger_output,             /* md */
  176         bba_trigger_input,              /* md */
  177         0,
  178 };
  179 
  180 struct audio_device bba_device = {
  181         "am7930",
  182         "x",
  183         "bba"
  184 };
  185 
  186 int     bba_intr __P((void *));
  187 void    bba_reset __P((struct bba_softc *, int));
  188 void    bba_codec_dwrite __P((struct am7930_softc *, int, u_int8_t));
  189 u_int8_t        bba_codec_dread __P((struct am7930_softc *, int));
  190 
  191 int bba_match(parent, cf, aux)
  192         struct device *parent;
  193         struct cfdata *cf;
  194         void *aux;
  195 {
  196         struct ioasicdev_attach_args *ia = aux;
  197 
  198         if (strcmp(ia->iada_modname, "isdn") != 0 &&
  199             strcmp(ia->iada_modname, "AMD79c30") != 0)
  200                 return 0;
  201 
  202         return 1;
  203 }
  204 
  205 
  206 void
  207 bba_attach(parent, self, aux)
  208         struct device *parent;
  209         struct device *self;
  210         void *aux;
  211 {
  212         struct ioasicdev_attach_args *ia = aux;
  213         struct bba_softc *sc = (struct bba_softc *)self;
  214         struct am7930_softc *asc = &sc->sc_am7930;
  215 
  216         sc->sc_bst = ((struct ioasic_softc *)parent)->sc_bst;
  217         sc->sc_bsh = ((struct ioasic_softc *)parent)->sc_bsh;
  218         sc->sc_dmat = ((struct ioasic_softc *)parent)->sc_dmat;
  219 
  220         /* get the bus space handle for codec */
  221         if (bus_space_subregion(sc->sc_bst, sc->sc_bsh,
  222             ia->iada_offset, 0, &sc->sc_codec_bsh)) {
  223                 printf("%s: unable to map device\n", asc->sc_dev.dv_xname);
  224                 return;
  225         }
  226 
  227         printf("\n");
  228 
  229         bba_reset(sc,1);
  230 
  231         /*
  232          * Set up glue for MI code early; we use some of it here.
  233          */
  234         asc->sc_glue = &bba_glue;
  235 
  236         /*
  237          *  MI initialisation.  We will be doing DMA.
  238          */
  239         am7930_init(asc, AUDIOAMD_DMA_MODE);
  240 
  241         ioasic_intr_establish(parent, ia->iada_cookie, TC_IPL_NONE,
  242             bba_intr, sc);
  243 
  244         audio_attach_mi(&sa_hw_if, asc, &asc->sc_dev);
  245 }
  246 
  247 
  248 void
  249 bba_onopen(sc)
  250         struct am7930_softc *sc;
  251 {
  252         bba_reset((struct bba_softc *)sc, 0);
  253 }
  254 
  255 
  256 void
  257 bba_onclose(sc)
  258         struct am7930_softc *sc;
  259 {
  260         bba_halt_input((struct bba_softc *)sc);
  261         bba_halt_output((struct bba_softc *)sc);
  262 }
  263 
  264 
  265 void
  266 bba_reset(sc, reset)
  267         struct bba_softc *sc;
  268         int reset;
  269 {
  270         u_int32_t ssr;
  271 
  272         /* disable any DMA and reset the codec */
  273         ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
  274         ssr &= ~(IOASIC_CSR_DMAEN_ISDN_T | IOASIC_CSR_DMAEN_ISDN_R);
  275         if (reset)
  276                 ssr &= ~IOASIC_CSR_ISDN_ENABLE;
  277         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
  278         DELAY(10);      /* 400ns required for codec to reset */
  279 
  280         /* initialise DMA pointers */
  281         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1);
  282         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1);
  283         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1);
  284         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1);
  285 
  286         /* take out of reset state */
  287         if (reset) {
  288                 ssr |= IOASIC_CSR_ISDN_ENABLE;
  289                 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
  290         }
  291 
  292 }
  293 
  294 
  295 void *
  296 bba_allocm(addr, direction, size, pool, flags)
  297         void *addr;
  298         int direction;
  299         size_t size;
  300         struct malloc_type *pool;
  301         int flags;
  302 {
  303         struct am7930_softc *asc = addr;
  304         struct bba_softc *sc = addr;
  305         bus_dma_segment_t seg;
  306         int rseg;
  307         caddr_t kva;
  308         struct bba_mem *m;
  309         int w;
  310         int state = 0;
  311 
  312         DPRINTF(("bba_allocm: size = %d\n",size));
  313 
  314         w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
  315 
  316         if (bus_dmamem_alloc(sc->sc_dmat, size, BBA_DMABUF_ALIGN,
  317             BBA_DMABUF_BOUNDARY, &seg, 1, &rseg, w)) {
  318                 printf("%s: can't allocate DMA buffer\n",
  319                     asc->sc_dev.dv_xname);
  320                 goto bad;
  321         }
  322         state |= 1;
  323 
  324         if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, size,
  325             &kva, w | BUS_DMA_COHERENT)) {
  326                 printf("%s: can't map DMA buffer\n", asc->sc_dev.dv_xname);
  327                 goto bad;
  328         }
  329         state |= 2;
  330 
  331         m = malloc(sizeof(struct bba_mem), pool, flags);
  332         if (m == NULL)
  333                 goto bad;
  334         m->addr = seg.ds_addr;
  335         m->size = seg.ds_len;
  336         m->kva = kva;
  337         m->next = sc->sc_mem_head;
  338         sc->sc_mem_head = m;
  339 
  340         return (void *)kva;
  341 
  342 bad:
  343         if (state & 2)
  344                 bus_dmamem_unmap(sc->sc_dmat, kva, size);
  345         if (state & 1)
  346                 bus_dmamem_free(sc->sc_dmat, &seg, 1);
  347         return NULL;
  348 }
  349 
  350 
  351 void
  352 bba_freem(addr, ptr, pool)
  353         void *addr;
  354         void *ptr;
  355         struct malloc_type *pool;
  356 {
  357         struct bba_softc *sc = addr;
  358         struct bba_mem **mp, *m;
  359         bus_dma_segment_t seg;
  360         caddr_t kva = (caddr_t)addr;
  361 
  362         for (mp = &sc->sc_mem_head; *mp && (*mp)->kva != kva;
  363             mp = &(*mp)->next)
  364                 /* nothing */ ;
  365         m = *mp;
  366         if (m == NULL) {
  367                 printf("bba_freem: freeing unallocated memory\n");
  368                 return;
  369         }
  370         *mp = m->next;
  371         bus_dmamem_unmap(sc->sc_dmat, kva, m->size);
  372 
  373         seg.ds_addr = m->addr;
  374         seg.ds_len = m->size;
  375         bus_dmamem_free(sc->sc_dmat, &seg, 1);
  376         free(m, pool);
  377 }
  378 
  379 
  380 size_t
  381 bba_round_buffersize(addr, direction, size)
  382         void *addr;
  383         int direction;
  384         size_t size;
  385 {
  386         DPRINTF(("bba_round_buffersize: size=%d\n", size));
  387 
  388         return (size > BBA_DMABUF_SIZE ? BBA_DMABUF_SIZE :
  389             roundup(size, IOASIC_DMA_BLOCKSIZE));
  390 }
  391 
  392 
  393 int
  394 bba_halt_output(addr)
  395         void *addr;
  396 {
  397         struct bba_softc *sc = addr;
  398         struct bba_dma_state *d = &sc->sc_tx_dma_state;
  399         u_int32_t ssr;
  400 
  401         /* disable any DMA */
  402         ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
  403         ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
  404         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
  405         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR, -1);
  406         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR, -1);
  407 
  408         if (d->active) {
  409                 bus_dmamap_unload(sc->sc_dmat, d->dmam);
  410                 bus_dmamap_destroy(sc->sc_dmat, d->dmam);
  411                 d->active = 0;
  412         }
  413 
  414         return 0;
  415 }
  416 
  417 
  418 int
  419 bba_halt_input(addr)
  420         void *addr;
  421 {
  422         struct bba_softc *sc = addr;
  423         struct bba_dma_state *d = &sc->sc_rx_dma_state;
  424         u_int32_t ssr;
  425 
  426         /* disable any DMA */
  427         ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
  428         ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
  429         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
  430         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR, -1);
  431         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR, -1);
  432 
  433         if (d->active) {
  434                 bus_dmamap_unload(sc->sc_dmat, d->dmam);
  435                 bus_dmamap_destroy(sc->sc_dmat, d->dmam);
  436                 d->active = 0;
  437         }
  438 
  439         return 0;
  440 }
  441 
  442 
  443 int
  444 bba_getdev(addr, retp)
  445         void *addr;
  446         struct audio_device *retp;
  447 {
  448         *retp = bba_device;
  449         return 0;
  450 }
  451 
  452 
  453 int
  454 bba_trigger_output(addr, start, end, blksize, intr, arg, param)
  455         void *addr;
  456         void *start, *end;
  457         int blksize;
  458         void (*intr) __P((void *));
  459         void *arg;
  460         struct audio_params *param;
  461 {
  462         struct bba_softc *sc = addr;
  463         struct bba_dma_state *d = &sc->sc_tx_dma_state;
  464         u_int32_t ssr;
  465         tc_addr_t phys, nphys;
  466         int state = 0;
  467 
  468         DPRINTF(("bba_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
  469             addr, start, end, blksize, intr, arg));
  470 
  471         /* disable any DMA */
  472         ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
  473         ssr &= ~IOASIC_CSR_DMAEN_ISDN_T;
  474         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
  475 
  476         if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start,
  477             BBA_MAX_DMA_SEGMENTS, IOASIC_DMA_BLOCKSIZE,
  478             BBA_DMABUF_BOUNDARY, BUS_DMA_NOWAIT, &d->dmam)) {
  479                 printf("bba_trigger_output: can't create DMA map\n");
  480                 goto bad;
  481         }
  482         state |= 1;
  483 
  484         if (bus_dmamap_load(sc->sc_dmat, d->dmam, start,
  485             (char *)end - (char *)start, NULL, BUS_DMA_WRITE|BUS_DMA_NOWAIT)) {
  486             printf("bba_trigger_output: can't load DMA map\n");
  487                 goto bad;
  488         }
  489         state |= 2;
  490 
  491         d->intr = intr;
  492         d->intr_arg = arg;
  493         d->curseg = 1;
  494 
  495         /* get physical address of buffer start */
  496         phys = (tc_addr_t)d->dmam->dm_segs[0].ds_addr;
  497         nphys = (tc_addr_t)d->dmam->dm_segs[1].ds_addr;
  498 
  499         /* setup DMA pointer */
  500         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_DMAPTR,
  501             IOASIC_DMA_ADDR(phys));
  502         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_X_NEXTPTR,
  503             IOASIC_DMA_ADDR(nphys));
  504 
  505         /* kick off DMA */
  506         ssr |= IOASIC_CSR_DMAEN_ISDN_T;
  507         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
  508 
  509         d->active = 1;
  510 
  511         return 0;
  512 
  513 bad:
  514         if (state & 2)
  515                 bus_dmamap_unload(sc->sc_dmat, d->dmam);
  516         if (state & 1)
  517                 bus_dmamap_destroy(sc->sc_dmat, d->dmam);
  518         return 1;
  519 }
  520 
  521 
  522 int
  523 bba_trigger_input(addr, start, end, blksize, intr, arg, param)
  524         void *addr;
  525         void *start, *end;
  526         int blksize;
  527         void (*intr) __P((void *));
  528         void *arg;
  529         struct audio_params *param;
  530 {
  531         struct bba_softc *sc = (struct bba_softc *)addr;
  532         struct bba_dma_state *d = &sc->sc_rx_dma_state;
  533         tc_addr_t phys, nphys;
  534         u_int32_t ssr;
  535         int state = 0;
  536 
  537         DPRINTF(("bba_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
  538             addr, start, end, blksize, intr, arg));
  539 
  540         /* disable any DMA */
  541         ssr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
  542         ssr &= ~IOASIC_CSR_DMAEN_ISDN_R;
  543         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
  544 
  545         if (bus_dmamap_create(sc->sc_dmat, (char *)end - (char *)start,
  546             BBA_MAX_DMA_SEGMENTS, IOASIC_DMA_BLOCKSIZE,
  547             BBA_DMABUF_BOUNDARY, BUS_DMA_NOWAIT, &d->dmam)) {
  548                 printf("bba_trigger_input: can't create DMA map\n");
  549                 goto bad;
  550         }
  551         state |= 1;
  552 
  553         if (bus_dmamap_load(sc->sc_dmat, d->dmam, start,
  554             (char *)end - (char *)start, NULL, BUS_DMA_READ|BUS_DMA_NOWAIT)) {
  555                 printf("bba_trigger_input: can't load DMA map\n");
  556                 goto bad;
  557         }
  558         state |= 2;
  559 
  560         d->intr = intr;
  561         d->intr_arg = arg;
  562         d->curseg = 1;
  563 
  564         /* get physical address of buffer start */
  565         phys = (tc_addr_t)d->dmam->dm_segs[0].ds_addr;
  566         nphys = (tc_addr_t)d->dmam->dm_segs[1].ds_addr;
  567 
  568         /* setup DMA pointer */
  569         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_DMAPTR,
  570             IOASIC_DMA_ADDR(phys));
  571         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_ISDN_R_NEXTPTR,
  572             IOASIC_DMA_ADDR(nphys));
  573 
  574         /* kick off DMA */
  575         ssr |= IOASIC_CSR_DMAEN_ISDN_R;
  576         bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, ssr);
  577 
  578         d->active = 1;
  579 
  580         return 0;
  581 
  582 bad:
  583         if (state & 2)
  584                 bus_dmamap_unload(sc->sc_dmat, d->dmam);
  585         if (state & 1)
  586                 bus_dmamap_destroy(sc->sc_dmat, d->dmam);
  587         return 1;
  588 }
  589 
  590 int 
  591 bba_intr(addr)
  592         void *addr;
  593 {
  594         struct bba_softc *sc = addr;
  595         struct bba_dma_state *d;
  596         tc_addr_t nphys;
  597         int s, mask;
  598 
  599         s = splaudio();
  600 
  601         mask = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_INTR);
  602 
  603         if (mask & IOASIC_INTR_ISDN_TXLOAD) {
  604                 d = &sc->sc_tx_dma_state;
  605                 d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
  606                 nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
  607                 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
  608                     IOASIC_ISDN_X_NEXTPTR, IOASIC_DMA_ADDR(nphys));
  609                 if (d->intr != NULL)
  610                         (*d->intr)(d->intr_arg);
  611         }
  612         if (mask & IOASIC_INTR_ISDN_RXLOAD) {
  613                 d = &sc->sc_rx_dma_state;
  614                 d->curseg = (d->curseg+1) % d->dmam->dm_nsegs;
  615                 nphys = (tc_addr_t)d->dmam->dm_segs[d->curseg].ds_addr;
  616                 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
  617                     IOASIC_ISDN_R_NEXTPTR, IOASIC_DMA_ADDR(nphys));
  618                 if (d->intr != NULL)
  619                         (*d->intr)(d->intr_arg);
  620         }
  621 
  622         splx(s);
  623 
  624         return 0;
  625 }
  626 
  627 int
  628 bba_get_props(addr)
  629         void *addr;
  630 {
  631         return (AUDIO_PROP_MMAP | am7930_get_props(addr));
  632 }
  633 
  634 paddr_t
  635 bba_mappage(addr, mem, offset, prot)
  636         void *addr;
  637         void *mem;
  638         off_t offset;
  639         int prot;
  640 {
  641         struct bba_softc *sc = addr;
  642         struct bba_mem **mp;
  643         bus_dma_segment_t seg;
  644         caddr_t kva = (caddr_t)mem;
  645 
  646         for (mp = &sc->sc_mem_head; *mp && (*mp)->kva != kva;
  647             mp = &(*mp)->next)
  648                 /* nothing */ ;
  649         if (*mp == NULL || offset < 0) {
  650                 return -1;
  651         }
  652 
  653         seg.ds_addr = (*mp)->addr;
  654         seg.ds_len = (*mp)->size;
  655 
  656         return bus_dmamem_mmap(sc->sc_dmat, &seg, 1, offset,
  657             prot, BUS_DMA_WAITOK);
  658 }
  659 
  660 
  661 void
  662 bba_input_conv(v, p, cc)
  663         void *v;
  664         u_int8_t *p;
  665         int cc;
  666 {
  667         u_int8_t *q = p;
  668 
  669         DPRINTF(("bba_input_conv(): v=%p p=%p cc=%d\n", v, p, cc));
  670 
  671         /*
  672          * p points start of buffer
  673          * cc is the number of bytes in the destination buffer
  674          */
  675 
  676         while (--cc >= 0) {
  677                 *p = ((*(u_int32_t *)q)>>16)&0xff;
  678                 q += 4;
  679                 p++;
  680         }
  681 }
  682 
  683 
  684 void
  685 bba_output_conv(v, p, cc)
  686         void *v;
  687         u_int8_t *p;
  688         int cc;
  689 {
  690         u_int8_t *q = p;
  691 
  692         DPRINTF(("bba_output_conv(): v=%p p=%p cc=%d\n", v, p, cc));
  693 
  694         /*
  695          * p points start of buffer
  696          * cc is the number of bytes in the source buffer
  697          */
  698 
  699         p += cc;
  700         q += cc * 4;
  701         while (--cc >= 0) {
  702                 q -= 4;
  703                 p -= 1;
  704                 *(u_int32_t *)q = (*p<<16);
  705         }
  706 }
  707 
  708 
  709 int
  710 bba_round_blocksize(addr, blk)
  711         void *addr;
  712         int blk;
  713 {
  714         return (IOASIC_DMA_BLOCKSIZE);
  715 }
  716 
  717 
  718 /* indirect write */
  719 void
  720 bba_codec_iwrite(sc, reg, val)
  721         struct am7930_softc *sc;
  722         int reg;
  723         u_int8_t val;
  724 {
  725         DPRINTF(("bba_codec_iwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
  726 
  727         bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
  728         bba_codec_dwrite(sc, AM7930_DREG_DR, val);
  729 }
  730 
  731 
  732 void
  733 bba_codec_iwrite16(sc, reg, val)
  734         struct am7930_softc *sc;
  735         int reg;
  736         u_int16_t val;
  737 {
  738         DPRINTF(("bba_codec_iwrite16(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
  739 
  740         bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
  741         bba_codec_dwrite(sc, AM7930_DREG_DR, val);
  742         bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8);
  743 }
  744 
  745 
  746 u_int16_t
  747 bba_codec_iread16(sc, reg)
  748         struct am7930_softc *sc;
  749         int reg;
  750 {
  751         u_int16_t val;
  752         DPRINTF(("bba_codec_iread16(): sc=%p, reg=%d\n",sc,reg));
  753 
  754         bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
  755         val = bba_codec_dread(sc, AM7930_DREG_DR) << 8;
  756         val |= bba_codec_dread(sc, AM7930_DREG_DR);
  757 
  758         return val;
  759 }
  760 
  761 
  762 /* indirect read */
  763 u_int8_t
  764 bba_codec_iread(sc, reg)
  765         struct am7930_softc *sc;
  766         int reg;
  767 {
  768         u_int8_t val;
  769 
  770         DPRINTF(("bba_codec_iread(): sc=%p, reg=%d\n",sc,reg));
  771 
  772         bba_codec_dwrite(sc, AM7930_DREG_CR, reg);
  773         val = bba_codec_dread(sc, AM7930_DREG_DR);
  774 
  775         DPRINTF(("read 0x%x (%d)\n", val, val));
  776 
  777         return val;
  778 }
  779 
  780 /* direct write */
  781 void
  782 bba_codec_dwrite(asc, reg, val)
  783         struct am7930_softc *asc;
  784         int reg;
  785         u_int8_t val;
  786 {
  787         struct bba_softc *sc = (struct bba_softc *)asc;
  788 
  789         DPRINTF(("bba_codec_dwrite(): sc=%p, reg=%d, val=%d\n",sc,reg,val));
  790 
  791 #if defined(__alpha__)
  792         bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh,
  793             reg << 2, val << 8);
  794 #else
  795         bus_space_write_4(sc->sc_bst, sc->sc_codec_bsh,
  796             reg << 6, val);
  797 #endif
  798 }
  799 
  800 /* direct read */
  801 u_int8_t
  802 bba_codec_dread(asc, reg)
  803         struct am7930_softc *asc;
  804         int reg;
  805 {
  806         struct bba_softc *sc = (struct bba_softc *)asc;
  807 
  808         DPRINTF(("bba_codec_dread(): sc=%p, reg=%d\n",sc,reg));
  809 
  810 #if defined(__alpha__)
  811         return ((bus_space_read_4(sc->sc_bst, sc->sc_codec_bsh,
  812                 reg << 2) >> 8) & 0xff);
  813 #else
  814         return (bus_space_read_4(sc->sc_bst, sc->sc_codec_bsh,
  815                 reg << 6) & 0xff);
  816 #endif
  817 }

Cache object: 0306777d168d8ced7de2d22b19ca389e


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