[BACK]Return to emuxki.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/emuxki.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: emuxki.c,v 1.24 2007/07/10 22:04:28 jakemsr Exp $     */
        !             2: /*     $NetBSD: emuxki.c,v 1.1 2001/10/17 18:39:41 jdolecek Exp $      */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 2001 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Yannick Montulet.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *     This product includes software developed by the NetBSD
        !            22:  *     Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: /*
        !            41:  * Driver for Creative Labs SBLive! series and probably PCI512.
        !            42:  *
        !            43:  * Known bugs:
        !            44:  * - inversed stereo at ac97 codec level
        !            45:  *   (XXX jdolecek - don't see the problem? maybe because auvia(4) has
        !            46:  *    it swapped too?)
        !            47:  * - bass disappear when you plug rear jack-in on Cambridge FPS2000 speakers
        !            48:  *   (and presumably all speakers that support front and rear jack-in)
        !            49:  *
        !            50:  * TODO:
        !            51:  * - Digital Outputs
        !            52:  * - (midi/mpu),joystick support
        !            53:  * - Multiple voices play (problem with /dev/audio architecture)
        !            54:  * - Multiple sources recording (Pb with audio(4))
        !            55:  * - Independent modification of each channel's parameters (via mixer ?)
        !            56:  * - DSP FX patches (to make fx like chipmunk)
        !            57:  */
        !            58:
        !            59: #include <sys/types.h>
        !            60: #include <sys/device.h>
        !            61: #include <sys/errno.h>
        !            62: #include <sys/malloc.h>
        !            63: #include <sys/systm.h>
        !            64: #include <sys/param.h>
        !            65: #include <sys/audioio.h>
        !            66: #include <sys/selinfo.h>
        !            67:
        !            68: #include <dev/pci/pcireg.h>
        !            69: #include <dev/pci/pcivar.h>
        !            70: #include <dev/pci/pcidevs.h>
        !            71:
        !            72: #include <dev/audio_if.h>
        !            73: #include <dev/audiovar.h>
        !            74: #include <dev/auconv.h>
        !            75: #include <dev/mulaw.h>
        !            76: #include <dev/ic/ac97.h>
        !            77:
        !            78: #include <dev/pci/emuxkireg.h>
        !            79: #include <dev/pci/emuxkivar.h>
        !            80:
        !            81: #define slinear16_to_ulinear8_le linear16_to_ulinear8_le;
        !            82:
        !            83: /* autconf goo */
        !            84: int  emuxki_match(struct device *, void *, void *);
        !            85: void emuxki_attach(struct device *, struct device *, void *);
        !            86: int  emuxki_detach(struct device *, int);
        !            87: int  emuxki_scinit(struct emuxki_softc *sc);
        !            88: void emuxki_pci_shutdown(struct emuxki_softc *sc);
        !            89:
        !            90: /* dma mem mgmt */
        !            91: struct dmamem *emuxki_dmamem_alloc(bus_dma_tag_t, size_t, bus_size_t,
        !            92:                                 int, int, int);
        !            93: void   emuxki_dmamem_free(struct dmamem *, int);
        !            94: void   emuxki_dmamem_delete(struct dmamem *mem, int type);
        !            95:
        !            96: struct emuxki_mem *emuxki_mem_new(struct emuxki_softc *sc, int ptbidx,
        !            97:        size_t size, int type, int flags);
        !            98: void emuxki_mem_delete(struct emuxki_mem *mem, int type);
        !            99:
        !           100: /* Emu10k1 init & shutdown */
        !           101: int  emuxki_init(struct emuxki_softc *);
        !           102: void emuxki_shutdown(struct emuxki_softc *);
        !           103:
        !           104: /* Emu10k1 mem mgmt */
        !           105: void   *emuxki_pmem_alloc(struct emuxki_softc *, size_t,int,int);
        !           106: void   *emuxki_rmem_alloc(struct emuxki_softc *, size_t,int,int);
        !           107:
        !           108: /*
        !           109:  * Emu10k1 channels funcs : There is no direct access to channels, everything
        !           110:  * is done through voices I will at least provide channel based fx params
        !           111:  * modification, later...
        !           112:  */
        !           113:
        !           114: /* Emu10k1 voice mgmt */
        !           115: struct emuxki_voice *emuxki_voice_new(struct emuxki_softc *, u_int8_t);
        !           116: void   emuxki_voice_delete(struct emuxki_voice *);
        !           117: int    emuxki_voice_set_audioparms(struct emuxki_voice *, u_int8_t, u_int8_t, u_int32_t);
        !           118: /* emuxki_voice_set_fxparms will come later, it'll need channel distinction */
        !           119: int emuxki_voice_set_bufparms(struct emuxki_voice *, void *, u_int32_t, u_int16_t);
        !           120: int emuxki_voice_set_stereo(struct emuxki_voice *voice, u_int8_t stereo);
        !           121: int emuxki_voice_dataloc_create(struct emuxki_voice *voice);
        !           122: void emuxki_voice_dataloc_destroy(struct emuxki_voice *voice);
        !           123: void emuxki_voice_commit_parms(struct emuxki_voice *);
        !           124: void emuxki_voice_recsrc_release(struct emuxki_softc *sc, emuxki_recsrc_t source);
        !           125: int emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source);
        !           126: int emuxki_voice_adc_rate(struct emuxki_voice *);
        !           127: u_int32_t emuxki_voice_curaddr(struct emuxki_voice *);
        !           128: int emuxki_set_vparms(struct emuxki_voice *voice, struct audio_params *p);
        !           129: int emuxki_voice_set_srate(struct emuxki_voice *voice, u_int32_t srate);
        !           130: void emuxki_voice_start(struct emuxki_voice *, void (*) (void *), void *);
        !           131: void emuxki_voice_halt(struct emuxki_voice *);
        !           132: int emuxki_voice_channel_create(struct emuxki_voice *voice);
        !           133: void emuxki_voice_channel_destroy(struct emuxki_voice *voice);
        !           134:
        !           135: struct emuxki_channel *emuxki_channel_new(struct emuxki_voice *voice, u_int8_t num);
        !           136: void emuxki_channel_delete(struct emuxki_channel *chan);
        !           137: void emuxki_channel_start(struct emuxki_channel *chan);
        !           138: void emuxki_channel_stop(struct emuxki_channel *chan);
        !           139: void emuxki_channel_commit_fx(struct emuxki_channel *chan);
        !           140: void emuxki_channel_commit_parms(struct emuxki_channel *chan);
        !           141: void emuxki_channel_set_bufparms(struct emuxki_channel *chan, u_int32_t start, u_int32_t end);
        !           142: void emuxki_channel_set_srate(struct emuxki_channel *chan, u_int32_t srate);
        !           143: void emuxki_channel_set_fxsend(struct emuxki_channel *chan,
        !           144:        struct emuxki_chanparms_fxsend *fxsend);
        !           145: void emuxki_chanparms_set_defaults(struct emuxki_channel *chan);
        !           146:
        !           147: void emuxki_resched_timer(struct emuxki_softc *sc);
        !           148:
        !           149: /*
        !           150:  * Emu10k1 stream mgmt : not done yet
        !           151:  */
        !           152: #if 0
        !           153: struct emuxki_stream *emuxki_stream_new(struct emu10k1 *);
        !           154: void   emuxki_stream_delete(struct emuxki_stream *);
        !           155: int    emuxki_stream_set_audio_params(struct emuxki_stream *, u_int8_t,
        !           156:                                            u_int8_t, u_int8_t, u_int16_t);
        !           157: void   emuxki_stream_start(struct emuxki_stream *);
        !           158: void   emuxki_stream_halt(struct emuxki_stream *);
        !           159: #endif
        !           160:
        !           161: /* fx interface */
        !           162: void emuxki_initfx(struct emuxki_softc *sc);
        !           163: void emuxki_dsp_addop(struct emuxki_softc *sc, u_int16_t *pc, u_int8_t op,
        !           164:        u_int16_t r, u_int16_t a, u_int16_t x, u_int16_t y);
        !           165: void emuxki_write_micro(struct emuxki_softc *sc, u_int32_t pc, u_int32_t data);
        !           166:
        !           167: /* audio interface callbacks */
        !           168:
        !           169: int    emuxki_open(void *, int);
        !           170: void   emuxki_close(void *);
        !           171:
        !           172: int    emuxki_query_encoding(void *, struct audio_encoding *);
        !           173: int    emuxki_set_params(void *, int, int,
        !           174:                                      struct audio_params *,
        !           175:                                      struct audio_params *);
        !           176:
        !           177: int    emuxki_round_blocksize(void *, int);
        !           178: size_t emuxki_round_buffersize(void *, int, size_t);
        !           179:
        !           180: int    emuxki_trigger_output(void *, void *, void *, int, void (*)(void *),
        !           181:            void *, struct audio_params *);
        !           182: int    emuxki_trigger_input(void *, void *, void *, int, void (*) (void *),
        !           183:            void *, struct audio_params *);
        !           184: int    emuxki_halt_output(void *);
        !           185: int    emuxki_halt_input(void *);
        !           186:
        !           187: int    emuxki_getdev(void *, struct audio_device *);
        !           188: int    emuxki_set_port(void *, mixer_ctrl_t *);
        !           189: int    emuxki_get_port(void *, mixer_ctrl_t *);
        !           190: int    emuxki_query_devinfo(void *, mixer_devinfo_t *);
        !           191:
        !           192: void   *emuxki_allocm(void *, int, size_t, int, int);
        !           193: void   emuxki_freem(void *, void *, int);
        !           194:
        !           195: paddr_t        emuxki_mappage(void *, void *, off_t, int);
        !           196: int    emuxki_get_props(void *);
        !           197:
        !           198: /* Interrupt handler */
        !           199: int  emuxki_intr(void *);
        !           200:
        !           201: /* Emu10k1 AC97 interface callbacks */
        !           202: int  emuxki_ac97_init(struct emuxki_softc *sc);
        !           203: int  emuxki_ac97_attach(void *, struct ac97_codec_if *);
        !           204: int  emuxki_ac97_read(void *, u_int8_t, u_int16_t *);
        !           205: int  emuxki_ac97_write(void *, u_int8_t, u_int16_t);
        !           206: void emuxki_ac97_reset(void *);
        !           207:
        !           208: const struct pci_matchid emuxki_devices[] = {
        !           209:        { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_SBLIVE },
        !           210:        { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_SBLIVE2 },
        !           211:        { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_AUDIGY },
        !           212:        { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_AUDIGY2 },
        !           213: };
        !           214:
        !           215: /*
        !           216:  * Autoconfig goo.
        !           217:  */
        !           218: struct cfdriver emu_cd = {
        !           219:        NULL, "emu", DV_DULL
        !           220: };
        !           221:
        !           222: struct cfattach emu_ca = {
        !           223:         sizeof(struct emuxki_softc),
        !           224:         emuxki_match,
        !           225:         emuxki_attach,
        !           226:        emuxki_detach,
        !           227:        NULL              /* config activate */
        !           228: };
        !           229:
        !           230: struct audio_hw_if emuxki_hw_if = {
        !           231:        emuxki_open,
        !           232:        emuxki_close,
        !           233:        NULL,                   /* drain */
        !           234:        emuxki_query_encoding,
        !           235:        emuxki_set_params,
        !           236:        emuxki_round_blocksize,
        !           237:        NULL,                   /* commit settings */
        !           238:        NULL,                   /* init_output */
        !           239:        NULL,                   /* init_input */
        !           240:        NULL,                   /* start_output */
        !           241:        NULL,                   /* start_input */
        !           242:        emuxki_halt_output,
        !           243:        emuxki_halt_input,
        !           244:        NULL,                   /* speaker_ctl */
        !           245:        emuxki_getdev,
        !           246:        NULL,                   /* setfd */
        !           247:        emuxki_set_port,
        !           248:        emuxki_get_port,
        !           249:        emuxki_query_devinfo,
        !           250:        emuxki_allocm,
        !           251:        emuxki_freem,
        !           252:        emuxki_round_buffersize,
        !           253:        emuxki_mappage,
        !           254:        emuxki_get_props,
        !           255:        emuxki_trigger_output,
        !           256:        emuxki_trigger_input,
        !           257: };
        !           258:
        !           259: #if 0
        !           260: static const int emuxki_recsrc_intrmasks[EMU_NUMRECSRCS] =
        !           261:     { EMU_INTE_MICBUFENABLE, EMU_INTE_ADCBUFENABLE, EMU_INTE_EFXBUFENABLE };
        !           262: #endif
        !           263: static const u_int32_t emuxki_recsrc_bufaddrreg[EMU_NUMRECSRCS] =
        !           264:     { EMU_MICBA, EMU_ADCBA, EMU_FXBA };
        !           265: static const u_int32_t emuxki_recsrc_szreg[EMU_NUMRECSRCS] =
        !           266:     { EMU_MICBS, EMU_ADCBS, EMU_FXBS };
        !           267: static const int emuxki_recbuf_sz[] = {
        !           268:        0, 384, 448, 512, 640, 768, 896, 1024, 1280, 1536, 1792,
        !           269:        2048, 2560, 3072, 3584, 4096, 5120, 6144, 7168, 8192, 10240,
        !           270:        12288, 14366, 16384, 20480, 24576, 28672, 32768, 40960, 49152,
        !           271:        57344, 65536
        !           272: };
        !           273:
        !           274: /*
        !           275:  * DMA memory mgmt
        !           276:  */
        !           277:
        !           278: void
        !           279: emuxki_dmamem_delete(struct dmamem *mem, int type)
        !           280: {
        !           281:        free(mem->segs, type);
        !           282:        free(mem, type);
        !           283: }
        !           284:
        !           285: struct dmamem *
        !           286: emuxki_dmamem_alloc(bus_dma_tag_t dmat, size_t size, bus_size_t align,
        !           287:             int nsegs, int type, int flags)
        !           288: {
        !           289:        struct dmamem   *mem;
        !           290:        int             bus_dma_flags;
        !           291:
        !           292:        /* Allocate memory for structure */
        !           293:        if ((mem = malloc(sizeof(*mem), type, flags)) == NULL)
        !           294:                return (NULL);
        !           295:        mem->dmat = dmat;
        !           296:        mem->size = size;
        !           297:        mem->align = align;
        !           298:        mem->nsegs = nsegs;
        !           299:        mem->bound = 0;
        !           300:
        !           301:        mem->segs = malloc(mem->nsegs * sizeof(*(mem->segs)), type, flags);
        !           302:        if (mem->segs == NULL) {
        !           303:                free(mem, type);
        !           304:                return (NULL);
        !           305:        }
        !           306:
        !           307:        bus_dma_flags = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
        !           308:        if (bus_dmamem_alloc(dmat, mem->size, mem->align, mem->bound,
        !           309:                             mem->segs, mem->nsegs, &(mem->rsegs),
        !           310:                             bus_dma_flags)) {
        !           311:                emuxki_dmamem_delete(mem, type);
        !           312:                return (NULL);
        !           313:        }
        !           314:
        !           315:        if (bus_dmamem_map(dmat, mem->segs, mem->nsegs, mem->size,
        !           316:                           &(mem->kaddr), bus_dma_flags | BUS_DMA_COHERENT)) {
        !           317:                bus_dmamem_free(dmat, mem->segs, mem->nsegs);
        !           318:                emuxki_dmamem_delete(mem, type);
        !           319:                return (NULL);
        !           320:        }
        !           321:
        !           322:        if (bus_dmamap_create(dmat, mem->size, mem->nsegs, mem->size,
        !           323:                              mem->bound, bus_dma_flags, &(mem->map))) {
        !           324:                bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
        !           325:                bus_dmamem_free(dmat, mem->segs, mem->nsegs);
        !           326:                emuxki_dmamem_delete(mem, type);
        !           327:                return (NULL);
        !           328:        }
        !           329:
        !           330:        if (bus_dmamap_load(dmat, mem->map, mem->kaddr,
        !           331:                            mem->size, NULL, bus_dma_flags)) {
        !           332:                bus_dmamap_destroy(dmat, mem->map);
        !           333:                bus_dmamem_unmap(dmat, mem->kaddr, mem->size);
        !           334:                bus_dmamem_free(dmat, mem->segs, mem->nsegs);
        !           335:                emuxki_dmamem_delete(mem, type);
        !           336:                return (NULL);
        !           337:        }
        !           338:
        !           339:        return (mem);
        !           340: }
        !           341:
        !           342: void
        !           343: emuxki_dmamem_free(struct dmamem *mem, int type)
        !           344: {
        !           345:        bus_dmamap_unload(mem->dmat, mem->map);
        !           346:        bus_dmamap_destroy(mem->dmat, mem->map);
        !           347:        bus_dmamem_unmap(mem->dmat, mem->kaddr, mem->size);
        !           348:        bus_dmamem_free(mem->dmat, mem->segs, mem->nsegs);
        !           349:        emuxki_dmamem_delete(mem, type);
        !           350: }
        !           351:
        !           352:
        !           353: /*
        !           354:  * Autoconf device callbacks : attach and detach
        !           355:  */
        !           356:
        !           357: void
        !           358: emuxki_pci_shutdown(struct emuxki_softc *sc)
        !           359: {
        !           360:        if (sc->sc_ih != NULL)
        !           361:                pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
        !           362:        if (sc->sc_ios)
        !           363:                bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
        !           364: }
        !           365:
        !           366: int
        !           367: emuxki_scinit(struct emuxki_softc *sc)
        !           368: {
        !           369:        int             err;
        !           370:
        !           371:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
        !           372:                /* enable spdif(?) output on non-APS */
        !           373:                (sc->sc_type == EMUXKI_APS? 0 : EMU_HCFG_GPOUTPUT0) |
        !           374:                EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
        !           375:                EMU_HCFG_MUTEBUTTONENABLE);
        !           376:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
        !           377:                EMU_INTE_SAMPLERATER | EMU_INTE_PCIERRENABLE);
        !           378:
        !           379:        if ((err = emuxki_init(sc)))
        !           380:                return (err);
        !           381:
        !           382:        if (sc->sc_type & EMUXKI_AUDIGY2) {
        !           383:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
        !           384:                        EMU_HCFG_AUDIOENABLE | EMU_HCFG_AC3ENABLE_CDSPDIF |
        !           385:                        EMU_HCFG_AC3ENABLE_GPSPDIF | EMU_HCFG_AUTOMUTE);
        !           386:        } else if (sc->sc_type & EMUXKI_AUDIGY) {
        !           387:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
        !           388:                        EMU_HCFG_AUDIOENABLE | EMU_HCFG_AUTOMUTE);
        !           389:        } else {
        !           390:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
        !           391:                        EMU_HCFG_AUDIOENABLE | EMU_HCFG_JOYENABLE |
        !           392:                        EMU_HCFG_LOCKTANKCACHE_MASK | EMU_HCFG_AUTOMUTE);
        !           393:        }
        !           394:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
        !           395:                bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
        !           396:                EMU_INTE_VOLINCRENABLE | EMU_INTE_VOLDECRENABLE |
        !           397:                EMU_INTE_MUTEENABLE);
        !           398:
        !           399:        if (sc->sc_type & EMUXKI_AUDIGY2) {
        !           400:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG,
        !           401:                        EMU_A_IOCFG_GPOUT0 |
        !           402:                        bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_A_IOCFG));
        !           403:        }
        !           404:
        !           405:        /* No multiple voice support for now */
        !           406:        sc->pvoice = sc->rvoice = NULL;
        !           407:
        !           408:        return (0);
        !           409: }
        !           410:
        !           411: int
        !           412: emuxki_ac97_init(struct emuxki_softc *sc)
        !           413: {
        !           414:        sc->hostif.arg = sc;
        !           415:        sc->hostif.attach = emuxki_ac97_attach;
        !           416:        sc->hostif.read = emuxki_ac97_read;
        !           417:        sc->hostif.write = emuxki_ac97_write;
        !           418:        sc->hostif.reset = emuxki_ac97_reset;
        !           419:        sc->hostif.flags = NULL;
        !           420:        return (ac97_attach(&(sc->hostif)));
        !           421: }
        !           422:
        !           423: int
        !           424: emuxki_match(struct device *parent, void *match, void *aux)
        !           425: {
        !           426:        return (pci_matchbyid((struct pci_attach_args *)aux, emuxki_devices,
        !           427:            sizeof(emuxki_devices)/sizeof(emuxki_devices[0])));
        !           428: }
        !           429:
        !           430: void
        !           431: emuxki_attach(struct device *parent, struct device *self, void *aux)
        !           432: {
        !           433:        struct emuxki_softc *sc = (struct emuxki_softc *) self;
        !           434:        struct pci_attach_args *pa = aux;
        !           435:        pci_intr_handle_t ih;
        !           436:        const char     *intrstr;
        !           437:
        !           438:        if (pci_mapreg_map(pa, EMU_PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
        !           439:            &(sc->sc_iot), &(sc->sc_ioh), &(sc->sc_iob), &(sc->sc_ios), 0)) {
        !           440:                printf(": can't map iospace\n");
        !           441:                return;
        !           442:        }
        !           443:
        !           444:        sc->sc_pc   = pa->pa_pc;
        !           445:        sc->sc_dmat = pa->pa_dmat;
        !           446:
        !           447:        if (pci_intr_map(pa, &ih)) {
        !           448:                printf(": couldn't map interrupt\n");
        !           449:                bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
        !           450:                return;
        !           451:        }
        !           452:
        !           453:        intrstr = pci_intr_string(pa->pa_pc, ih);
        !           454:        sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, emuxki_intr,
        !           455:                sc, sc->sc_dev.dv_xname);
        !           456:        if (sc->sc_ih == NULL) {
        !           457:                printf(": couldn't establish interrupt");
        !           458:                if (intrstr != NULL)
        !           459:                        printf(" at %s", intrstr);
        !           460:                printf("\n");
        !           461:                bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
        !           462:                return;
        !           463:        }
        !           464:        printf(": %s\n", intrstr);
        !           465:
        !           466:        /* XXX it's unknown whether APS is made from Audigy as well */
        !           467:        if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CREATIVELABS_AUDIGY) {
        !           468:                sc->sc_type = EMUXKI_AUDIGY;
        !           469:                 if (PCI_REVISION(pa->pa_class) == 0x04 ||
        !           470:                    PCI_REVISION(pa->pa_class) == 0x08) {
        !           471:                        sc->sc_type |= EMUXKI_AUDIGY2;
        !           472:                        strlcpy(sc->sc_audv.name, "Audigy2", sizeof sc->sc_audv.name);
        !           473:                } else {
        !           474:                        strlcpy(sc->sc_audv.name, "Audigy", sizeof sc->sc_audv.name);
        !           475:                }
        !           476:        } else if (pci_conf_read(pa->pa_pc, pa->pa_tag,
        !           477:            PCI_SUBSYS_ID_REG) == EMU_SUBSYS_APS) {
        !           478:                sc->sc_type = EMUXKI_APS;
        !           479:                strlcpy(sc->sc_audv.name, "E-mu APS", sizeof sc->sc_audv.name);
        !           480:        } else {
        !           481:                sc->sc_type = EMUXKI_SBLIVE;
        !           482:                strlcpy(sc->sc_audv.name, "SB Live!", sizeof sc->sc_audv.name);
        !           483:        }
        !           484:        snprintf(sc->sc_audv.version, sizeof sc->sc_audv.version, "0x%02x",
        !           485:                 PCI_REVISION(pa->pa_class));
        !           486:        strlcpy(sc->sc_audv.config, "emuxki", sizeof sc->sc_audv.config);
        !           487:
        !           488:        if (emuxki_scinit(sc) ||
        !           489:            /* APS has no ac97 XXX */
        !           490:            (sc->sc_type == EMUXKI_APS || emuxki_ac97_init(sc)) ||
        !           491:            (sc->sc_audev = audio_attach_mi(&emuxki_hw_if, sc, self)) == NULL) {
        !           492:                emuxki_pci_shutdown(sc);
        !           493:                return;
        !           494:        }
        !           495: }
        !           496:
        !           497: int
        !           498: emuxki_detach(struct device *self, int flags)
        !           499: {
        !           500:        struct emuxki_softc *sc = (struct emuxki_softc *) self;
        !           501:
        !           502:         if (sc->sc_audev != NULL) /* Test in case audio didn't attach */
        !           503:                config_detach(sc->sc_audev, 0);
        !           504:
        !           505:        /* All voices should be stopped now but add some code here if not */
        !           506:
        !           507:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_HCFG,
        !           508:                EMU_HCFG_LOCKSOUNDCACHE | EMU_HCFG_LOCKTANKCACHE_MASK |
        !           509:                EMU_HCFG_MUTEBUTTONENABLE);
        !           510:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE, 0);
        !           511:
        !           512:        emuxki_shutdown(sc);
        !           513:
        !           514:        emuxki_pci_shutdown(sc);
        !           515:
        !           516:        return (0);
        !           517: }
        !           518:
        !           519:
        !           520: /* Misc stuff relative to emu10k1 */
        !           521:
        !           522: static __inline u_int32_t
        !           523: emuxki_rate_to_pitch(u_int32_t rate)
        !           524: {
        !           525:        static const u_int32_t logMagTable[128] = {
        !           526:                0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3,
        !           527:                0x13aa2, 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a,
        !           528:                0x2655d, 0x28ed5, 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb,
        !           529:                0x381b6, 0x3a93d, 0x3d081, 0x3f782, 0x41e42, 0x444c1, 0x46b01,
        !           530:                0x49101, 0x4b6c4, 0x4dc49, 0x50191, 0x5269e, 0x54b6f, 0x57006,
        !           531:                0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7, 0x646ee, 0x66a00,
        !           532:                0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829, 0x759d4,
        !           533:                0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
        !           534:                0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20,
        !           535:                0x93d26, 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec,
        !           536:                0xa11d8, 0xa2f9d, 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241,
        !           537:                0xadf26, 0xafbe7, 0xb1885, 0xb3500, 0xb5157, 0xb6d8c, 0xb899f,
        !           538:                0xba58f, 0xbc15e, 0xbdd0c, 0xbf899, 0xc1404, 0xc2f50, 0xc4a7b,
        !           539:                0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c, 0xceaec, 0xd053f,
        !           540:                0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3, 0xdba4a,
        !           541:                0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
        !           542:                0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a,
        !           543:                0xf2c83, 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57,
        !           544:                0xfd1a7, 0xfe8df
        !           545:        };
        !           546:        static const u_int8_t logSlopeTable[128] = {
        !           547:                0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
        !           548:                0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
        !           549:                0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
        !           550:                0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
        !           551:                0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
        !           552:                0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
        !           553:                0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
        !           554:                0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
        !           555:                0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
        !           556:                0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
        !           557:                0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
        !           558:                0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
        !           559:                0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
        !           560:                0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
        !           561:                0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
        !           562:                0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
        !           563:        };
        !           564:        int8_t          i;
        !           565:
        !           566:        if (rate == 0)
        !           567:                return 0;       /* Bail out if no leading "1" */
        !           568:        rate *= 11185;          /* Scale 48000 to 0x20002380 */
        !           569:        for (i = 31; i > 0; i--) {
        !           570:                if (rate & 0x80000000) {        /* Detect leading "1" */
        !           571:                        return (((u_int32_t) (i - 15) << 20) +
        !           572:                                logMagTable[0x7f & (rate >> 24)] +
        !           573:                                (0x7f & (rate >> 17)) *
        !           574:                                logSlopeTable[0x7f & (rate >> 24)]);
        !           575:                }
        !           576:                rate <<= 1;
        !           577:        }
        !           578:
        !           579:        return 0;               /* Should never reach this point */
        !           580: }
        !           581:
        !           582: /* Emu10k1 Low level */
        !           583:
        !           584: static __inline u_int32_t
        !           585: emuxki_read(struct emuxki_softc *sc, u_int16_t chano, u_int32_t reg)
        !           586: {
        !           587:        u_int32_t       ptr, mask = 0xffffffff;
        !           588:        u_int8_t        size, offset = 0;
        !           589:        int             s;
        !           590:
        !           591:        ptr = ((((u_int32_t) reg) << 16) &
        !           592:                (sc->sc_type & EMUXKI_AUDIGY ?
        !           593:                        EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
        !           594:                (chano & EMU_PTR_CHNO_MASK);
        !           595:        if (reg & 0xff000000) {
        !           596:                size = (reg >> 24) & 0x3f;
        !           597:                offset = (reg >> 16) & 0x1f;
        !           598:                mask = ((1 << size) - 1) << offset;
        !           599:        }
        !           600:
        !           601:        s = splaudio();
        !           602:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
        !           603:        ptr = (bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_DATA) & mask)
        !           604:                >> offset;
        !           605:        splx(s);
        !           606:
        !           607:        return (ptr);
        !           608: }
        !           609:
        !           610: static __inline void
        !           611: emuxki_write(struct emuxki_softc *sc, u_int16_t chano,
        !           612:              u_int32_t reg, u_int32_t data)
        !           613: {
        !           614:        u_int32_t       ptr, mask;
        !           615:        u_int8_t        size, offset;
        !           616:        int             s;
        !           617:
        !           618:        ptr = ((((u_int32_t) reg) << 16) &
        !           619:                (sc->sc_type & EMUXKI_AUDIGY ?
        !           620:                        EMU_A_PTR_ADDR_MASK : EMU_PTR_ADDR_MASK)) |
        !           621:                (chano & EMU_PTR_CHNO_MASK);
        !           622:
        !           623:        /* BE CAREFUL WITH THAT AXE, EUGENE */
        !           624:        if (ptr == 0x52 || ptr == 0x53)
        !           625:                return;
        !           626:
        !           627:        if (reg & 0xff000000) {
        !           628:                size = (reg >> 24) & 0x3f;
        !           629:                offset = (reg >> 16) & 0x1f;
        !           630:                mask = ((1 << size) - 1) << offset;
        !           631:                data = ((data << offset) & mask) |
        !           632:                        (emuxki_read(sc, chano, reg & 0xffff) & ~mask);
        !           633:        }
        !           634:
        !           635:        s = splaudio();
        !           636:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_PTR, ptr);
        !           637:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_DATA, data);
        !           638:        splx(s);
        !           639: }
        !           640:
        !           641: /* Microcode should this go in /sys/dev/microcode ? */
        !           642:
        !           643: void
        !           644: emuxki_write_micro(struct emuxki_softc *sc, u_int32_t pc, u_int32_t data)
        !           645: {
        !           646:        emuxki_write(sc, 0,
        !           647:                (sc->sc_type & EMUXKI_AUDIGY ?
        !           648:                        EMU_A_MICROCODEBASE : EMU_MICROCODEBASE) + pc,
        !           649:                 data);
        !           650: }
        !           651:
        !           652: void
        !           653: emuxki_dsp_addop(struct emuxki_softc *sc, u_int16_t *pc, u_int8_t op,
        !           654:                  u_int16_t r, u_int16_t a, u_int16_t x, u_int16_t y)
        !           655: {
        !           656:        if (sc->sc_type & EMUXKI_AUDIGY) {
        !           657:                emuxki_write_micro(sc, *pc << 1,
        !           658:                        ((x << 12) & EMU_A_DSP_LOWORD_OPX_MASK) |
        !           659:                        (y & EMU_A_DSP_LOWORD_OPY_MASK));
        !           660:                emuxki_write_micro(sc, (*pc << 1) + 1,
        !           661:                        ((op << 24) & EMU_A_DSP_HIWORD_OPCODE_MASK) |
        !           662:                        ((r << 12) & EMU_A_DSP_HIWORD_RESULT_MASK) |
        !           663:                        (a & EMU_A_DSP_HIWORD_OPA_MASK));
        !           664:        } else {
        !           665:                emuxki_write_micro(sc, *pc << 1,
        !           666:                        ((x << 10) & EMU_DSP_LOWORD_OPX_MASK) |
        !           667:                        (y & EMU_DSP_LOWORD_OPY_MASK));
        !           668:                emuxki_write_micro(sc, (*pc << 1) + 1,
        !           669:                        ((op << 20) & EMU_DSP_HIWORD_OPCODE_MASK) |
        !           670:                        ((r << 10) & EMU_DSP_HIWORD_RESULT_MASK) |
        !           671:                        (a & EMU_DSP_HIWORD_OPA_MASK));
        !           672:        }
        !           673:        (*pc)++;
        !           674: }
        !           675:
        !           676: /* init and shutdown */
        !           677:
        !           678: void
        !           679: emuxki_initfx(struct emuxki_softc *sc)
        !           680: {
        !           681:        u_int16_t       pc;
        !           682:
        !           683:        /* Set all GPRs to 0 */
        !           684:        for (pc = 0; pc < 256; pc++)
        !           685:                emuxki_write(sc, 0, EMU_DSP_GPR(pc), 0);
        !           686:        for (pc = 0; pc < 160; pc++) {
        !           687:                emuxki_write(sc, 0, EMU_TANKMEMDATAREGBASE + pc, 0);
        !           688:                emuxki_write(sc, 0, EMU_TANKMEMADDRREGBASE + pc, 0);
        !           689:        }
        !           690:        pc = 0;
        !           691:
        !           692:        if (sc->sc_type & EMUXKI_AUDIGY) {
        !           693:                /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
        !           694:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
        !           695:                                  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
        !           696:                                  EMU_A_DSP_CST(0),
        !           697:                                  EMU_DSP_FX(0), EMU_A_DSP_CST(4));
        !           698:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
        !           699:                                  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
        !           700:                                  EMU_A_DSP_CST(0),
        !           701:                                  EMU_DSP_FX(1), EMU_A_DSP_CST(4));
        !           702:
        !           703:                /* Rear channel OUT (l/r) = FX[2/3] * 4 */
        !           704: #if 0
        !           705:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
        !           706:                                  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_REAR),
        !           707:                                  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_A_FRONT),
        !           708:                                  EMU_DSP_FX(0), EMU_A_DSP_CST(4));
        !           709:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
        !           710:                                  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_REAR),
        !           711:                                  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_A_FRONT),
        !           712:                                  EMU_DSP_FX(1), EMU_A_DSP_CST(4));
        !           713: #endif
        !           714:                /* ADC recording (l/r) = AC97 In (l/r) */
        !           715:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
        !           716:                                  EMU_A_DSP_OUTL(EMU_A_DSP_OUT_ADC),
        !           717:                                  EMU_A_DSP_INL(EMU_DSP_IN_AC97),
        !           718:                                  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
        !           719:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
        !           720:                                  EMU_A_DSP_OUTR(EMU_A_DSP_OUT_ADC),
        !           721:                                  EMU_A_DSP_INR(EMU_DSP_IN_AC97),
        !           722:                                  EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
        !           723:
        !           724:                /* zero out the rest of the microcode */
        !           725:                while (pc < 512)
        !           726:                        emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
        !           727:                                          EMU_A_DSP_CST(0), EMU_A_DSP_CST(0),
        !           728:                                          EMU_A_DSP_CST(0), EMU_A_DSP_CST(0));
        !           729:
        !           730:                emuxki_write(sc, 0, EMU_A_DBG, 0);      /* Is it really necessary ? */
        !           731:        } else {
        !           732:                /* AC97 Out (l/r) = AC97 In (l/r) + FX[0/1] * 4 */
        !           733:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
        !           734:                                  EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
        !           735:                                  EMU_DSP_CST(0),
        !           736:                                  EMU_DSP_FX(0), EMU_DSP_CST(4));
        !           737:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
        !           738:                                  EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
        !           739:                                  EMU_DSP_CST(0),
        !           740:                                  EMU_DSP_FX(1), EMU_DSP_CST(4));
        !           741:
        !           742:                /* Rear channel OUT (l/r) = FX[2/3] * 4 */
        !           743: #if 0
        !           744:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
        !           745:                                  EMU_DSP_OUTL(EMU_DSP_OUT_AD_REAR),
        !           746:                                  EMU_DSP_OUTL(EMU_DSP_OUT_A_FRONT),
        !           747:                                  EMU_DSP_FX(0), EMU_DSP_CST(4));
        !           748:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_MACINTS,
        !           749:                                  EMU_DSP_OUTR(EMU_DSP_OUT_AD_REAR),
        !           750:                                  EMU_DSP_OUTR(EMU_DSP_OUT_A_FRONT),
        !           751:                                  EMU_DSP_FX(1), EMU_DSP_CST(4));
        !           752: #endif
        !           753:                /* ADC recording (l/r) = AC97 In (l/r) */
        !           754:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
        !           755:                                  EMU_DSP_OUTL(EMU_DSP_OUT_ADC),
        !           756:                                  EMU_DSP_INL(EMU_DSP_IN_AC97),
        !           757:                                  EMU_DSP_CST(0), EMU_DSP_CST(0));
        !           758:                emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
        !           759:                                  EMU_DSP_OUTR(EMU_DSP_OUT_ADC),
        !           760:                                  EMU_DSP_INR(EMU_DSP_IN_AC97),
        !           761:                                  EMU_DSP_CST(0), EMU_DSP_CST(0));
        !           762:
        !           763:                /* zero out the rest of the microcode */
        !           764:                while (pc < 512)
        !           765:                        emuxki_dsp_addop(sc, &pc, EMU_DSP_OP_ACC3,
        !           766:                                          EMU_DSP_CST(0), EMU_DSP_CST(0),
        !           767:                                          EMU_DSP_CST(0), EMU_DSP_CST(0));
        !           768:
        !           769:                emuxki_write(sc, 0, EMU_DBG, 0);        /* Is it really necessary ? */
        !           770:        }
        !           771: }
        !           772:
        !           773: int
        !           774: emuxki_init(struct emuxki_softc *sc)
        !           775: {
        !           776:        u_int16_t       i;
        !           777:        u_int32_t       spcs, *ptb;
        !           778:        bus_addr_t      silentpage;
        !           779:
        !           780:        /* disable any channel interrupt */
        !           781:        emuxki_write(sc, 0, EMU_CLIEL, 0);
        !           782:        emuxki_write(sc, 0, EMU_CLIEH, 0);
        !           783:        emuxki_write(sc, 0, EMU_SOLEL, 0);
        !           784:        emuxki_write(sc, 0, EMU_SOLEH, 0);
        !           785:
        !           786:        /* Set recording buffers sizes to zero */
        !           787:        emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
        !           788:        emuxki_write(sc, 0, EMU_MICBA, 0);
        !           789:        emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
        !           790:        emuxki_write(sc, 0, EMU_FXBA, 0);
        !           791:        emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
        !           792:        emuxki_write(sc, 0, EMU_ADCBA, 0);
        !           793:
        !           794:         if(sc->sc_type & EMUXKI_AUDIGY) {
        !           795:                 emuxki_write(sc, 0, EMU_SPBYPASS, EMU_SPBYPASS_24_BITS);
        !           796:                 emuxki_write(sc, 0, EMU_AC97SLOT, EMU_AC97SLOT_CENTER | EMU_AC97SLOT_LFE);
        !           797:         }
        !           798:
        !           799:        /* Initialize all channels to stopped and no effects */
        !           800:        for (i = 0; i < EMU_NUMCHAN; i++) {
        !           801:                emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
        !           802:                emuxki_write(sc, i, EMU_CHAN_IP, 0);
        !           803:                emuxki_write(sc, i, EMU_CHAN_VTFT, 0xffff);
        !           804:                emuxki_write(sc, i, EMU_CHAN_CVCF, 0xffff);
        !           805:                emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
        !           806:                emuxki_write(sc, i, EMU_CHAN_CPF, 0);
        !           807:                emuxki_write(sc, i, EMU_CHAN_CCR, 0);
        !           808:                emuxki_write(sc, i, EMU_CHAN_PSST, 0);
        !           809:                emuxki_write(sc, i, EMU_CHAN_DSL, 0x10);        /* Why 16 ? */
        !           810:                emuxki_write(sc, i, EMU_CHAN_CCCA, 0);
        !           811:                emuxki_write(sc, i, EMU_CHAN_Z1, 0);
        !           812:                emuxki_write(sc, i, EMU_CHAN_Z2, 0);
        !           813:                emuxki_write(sc, i, EMU_CHAN_FXRT, 0x32100000);
        !           814:                emuxki_write(sc, i, EMU_CHAN_ATKHLDM, 0);
        !           815:                emuxki_write(sc, i, EMU_CHAN_DCYSUSM, 0);
        !           816:                emuxki_write(sc, i, EMU_CHAN_IFATN, 0xffff);
        !           817:                emuxki_write(sc, i, EMU_CHAN_PEFE, 0);
        !           818:                emuxki_write(sc, i, EMU_CHAN_FMMOD, 0);
        !           819:                emuxki_write(sc, i, EMU_CHAN_TREMFRQ, 24);
        !           820:                emuxki_write(sc, i, EMU_CHAN_FM2FRQ2, 24);
        !           821:                emuxki_write(sc, i, EMU_CHAN_TEMPENV, 0);
        !           822:
        !           823:                /* these are last so OFF prevents writing */
        !           824:                emuxki_write(sc, i, EMU_CHAN_LFOVAL2, 0);
        !           825:                emuxki_write(sc, i, EMU_CHAN_LFOVAL1, 0);
        !           826:                emuxki_write(sc, i, EMU_CHAN_ATKHLDV, 0);
        !           827:                emuxki_write(sc, i, EMU_CHAN_ENVVOL, 0);
        !           828:                emuxki_write(sc, i, EMU_CHAN_ENVVAL, 0);
        !           829:        }
        !           830:
        !           831:        /* set digital outputs format */
        !           832:        spcs = (EMU_SPCS_CLKACCY_1000PPM | EMU_SPCS_SAMPLERATE_48 |
        !           833:              EMU_SPCS_CHANNELNUM_LEFT | EMU_SPCS_SOURCENUM_UNSPEC |
        !           834:                EMU_SPCS_GENERATIONSTATUS | 0x00001200 /* Cat code. */ |
        !           835:                0x00000000 /* IEC-958 Mode */ | EMU_SPCS_EMPHASIS_NONE |
        !           836:                EMU_SPCS_COPYRIGHT);
        !           837:        emuxki_write(sc, 0, EMU_SPCS0, spcs);
        !           838:        emuxki_write(sc, 0, EMU_SPCS1, spcs);
        !           839:        emuxki_write(sc, 0, EMU_SPCS2, spcs);
        !           840:
        !           841:         if(sc->sc_type & EMUXKI_AUDIGY2) {
        !           842:                 emuxki_write(sc, 0, EMU_A2_SPDIF_SAMPLERATE, EMU_A2_SPDIF_UNKNOWN);
        !           843:
        !           844:                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCSEL);
        !           845:                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA,
        !           846:                         EMU_A2_SRCSEL_ENABLE_SPDIF | EMU_A2_SRCSEL_ENABLE_SRCMULTI);
        !           847:
        !           848:                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_PTR, EMU_A2_SRCMULTI);
        !           849:                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_A2_DATA, EMU_A2_SRCMULTI_ENABLE_INPUT);
        !           850:         }
        !           851:
        !           852:
        !           853:        /* Let's play with sound processor */
        !           854:        emuxki_initfx(sc);
        !           855:
        !           856:        /* Here is our Page Table */
        !           857:        if ((sc->ptb = emuxki_dmamem_alloc(sc->sc_dmat,
        !           858:            EMU_MAXPTE * sizeof(u_int32_t),
        !           859:            EMU_DMA_ALIGN, EMU_DMAMEM_NSEG,
        !           860:            M_DEVBUF, M_WAITOK)) == NULL)
        !           861:                return (ENOMEM);
        !           862:
        !           863:        /* This is necessary unless you like Metallic noise... */
        !           864:        if ((sc->silentpage = emuxki_dmamem_alloc(sc->sc_dmat, EMU_PTESIZE,
        !           865:            EMU_DMA_ALIGN, EMU_DMAMEM_NSEG, M_DEVBUF, M_WAITOK))==NULL){
        !           866:                emuxki_dmamem_free(sc->ptb, M_DEVBUF);
        !           867:                return (ENOMEM);
        !           868:        }
        !           869:
        !           870:        /* Zero out the silent page */
        !           871:        /* This might not be always true, it might be 128 for 8bit channels */
        !           872:        memset(KERNADDR(sc->silentpage), 0, DMASIZE(sc->silentpage));
        !           873:
        !           874:        /*
        !           875:         * Set all the PTB Entries to the silent page We shift the physical
        !           876:         * address by one and OR it with the page number. I don't know what
        !           877:         * the ORed index is for, might be a very useful unused feature...
        !           878:         */
        !           879:        silentpage = DMAADDR(sc->silentpage) << 1;
        !           880:        ptb = KERNADDR(sc->ptb);
        !           881:        for (i = 0; i < EMU_MAXPTE; i++)
        !           882:                ptb[i] = htole32(silentpage | i);
        !           883:
        !           884:        /* Write PTB address and set TCB to none */
        !           885:        emuxki_write(sc, 0, EMU_PTB, DMAADDR(sc->ptb));
        !           886:        emuxki_write(sc, 0, EMU_TCBS, 0);       /* This means 16K TCB */
        !           887:        emuxki_write(sc, 0, EMU_TCB, 0);        /* No TCB use for now */
        !           888:
        !           889:        /*
        !           890:         * Set channels MAPs to the silent page.
        !           891:         * I don't know what MAPs are for.
        !           892:         */
        !           893:        silentpage |= EMU_CHAN_MAP_PTI_MASK;
        !           894:        for (i = 0; i < EMU_NUMCHAN; i++) {
        !           895:                emuxki_write(sc, i, EMU_CHAN_MAPA, silentpage);
        !           896:                emuxki_write(sc, i, EMU_CHAN_MAPB, silentpage);
        !           897:                sc->channel[i] = NULL;
        !           898:        }
        !           899:
        !           900:        /* Init voices list */
        !           901:        LIST_INIT(&(sc->voices));
        !           902:
        !           903:        /* Timer is stopped */
        !           904:        sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
        !           905:        return (0);
        !           906: }
        !           907:
        !           908: void
        !           909: emuxki_shutdown(struct emuxki_softc *sc)
        !           910: {
        !           911:        u_int32_t       i;
        !           912:
        !           913:        /* Disable any Channels interrupts */
        !           914:        emuxki_write(sc, 0, EMU_CLIEL, 0);
        !           915:        emuxki_write(sc, 0, EMU_CLIEH, 0);
        !           916:        emuxki_write(sc, 0, EMU_SOLEL, 0);
        !           917:        emuxki_write(sc, 0, EMU_SOLEH, 0);
        !           918:
        !           919:        /*
        !           920:         * Should do some voice(stream) stopping stuff here, that's what will
        !           921:         * stop and deallocate all channels.
        !           922:         */
        !           923:
        !           924:        /* Stop all channels */
        !           925:        /* XXX This shouldn't be necessary, I'll remove once everything works */
        !           926:        for (i = 0; i < EMU_NUMCHAN; i++)
        !           927:                emuxki_write(sc, i, EMU_CHAN_DCYSUSV, 0);
        !           928:        for (i = 0; i < EMU_NUMCHAN; i++) {
        !           929:                emuxki_write(sc, i, EMU_CHAN_VTFT, 0);
        !           930:                emuxki_write(sc, i, EMU_CHAN_CVCF, 0);
        !           931:                emuxki_write(sc, i, EMU_CHAN_PTRX, 0);
        !           932:                emuxki_write(sc, i, EMU_CHAN_CPF, 0);
        !           933:        }
        !           934:
        !           935:        /*
        !           936:         * Deallocate Emu10k1 caches and recording buffers. Again it will be
        !           937:         * removed because it will be done in voice shutdown.
        !           938:         */
        !           939:        emuxki_write(sc, 0, EMU_MICBS, EMU_RECBS_BUFSIZE_NONE);
        !           940:        emuxki_write(sc, 0, EMU_MICBA, 0);
        !           941:        emuxki_write(sc, 0, EMU_FXBS, EMU_RECBS_BUFSIZE_NONE);
        !           942:        emuxki_write(sc, 0, EMU_FXBA, 0);
        !           943:         if(sc->sc_type & EMUXKI_AUDIGY) {
        !           944:                 emuxki_write(sc, 0, EMU_A_FXWC1, 0);
        !           945:                 emuxki_write(sc, 0, EMU_A_FXWC2, 0);
        !           946:         } else {
        !           947:                 emuxki_write(sc, 0, EMU_FXWC, 0);
        !           948:         }
        !           949:        emuxki_write(sc, 0, EMU_ADCBS, EMU_RECBS_BUFSIZE_NONE);
        !           950:        emuxki_write(sc, 0, EMU_ADCBA, 0);
        !           951:
        !           952:        /*
        !           953:         * XXX I don't know yet how I will handle tank cache buffer,
        !           954:         * I don't even clearly  know what it is for.
        !           955:         */
        !           956:        emuxki_write(sc, 0, EMU_TCB, 0);        /* 16K again */
        !           957:        emuxki_write(sc, 0, EMU_TCBS, 0);
        !           958:
        !           959:        emuxki_write(sc, 0, EMU_DBG, 0x8000);   /* necessary ? */
        !           960:
        !           961:        emuxki_dmamem_free(sc->silentpage, M_DEVBUF);
        !           962:        emuxki_dmamem_free(sc->ptb, M_DEVBUF);
        !           963: }
        !           964:
        !           965: /* Emu10k1 Memory management */
        !           966:
        !           967: struct emuxki_mem *
        !           968: emuxki_mem_new(struct emuxki_softc *sc, int ptbidx,
        !           969:                size_t size, int type, int flags)
        !           970: {
        !           971:        struct emuxki_mem *mem;
        !           972:
        !           973:        if ((mem = malloc(sizeof(*mem), type, flags)) == NULL)
        !           974:                return (NULL);
        !           975:
        !           976:        mem->ptbidx = ptbidx;
        !           977:        if ((mem->dmamem = emuxki_dmamem_alloc(sc->sc_dmat, size,
        !           978:            EMU_DMA_ALIGN, EMU_DMAMEM_NSEG, type, flags)) == NULL) {
        !           979:                free(mem, type);
        !           980:                return (NULL);
        !           981:        }
        !           982:        return (mem);
        !           983: }
        !           984:
        !           985: void
        !           986: emuxki_mem_delete(struct emuxki_mem *mem, int type)
        !           987: {
        !           988:        emuxki_dmamem_free(mem->dmamem, type);
        !           989:        free(mem, type);
        !           990: }
        !           991:
        !           992: void *
        !           993: emuxki_pmem_alloc(struct emuxki_softc *sc, size_t size, int type, int flags)
        !           994: {
        !           995:        int             i, j, s;
        !           996:        size_t          numblocks;
        !           997:        struct emuxki_mem *mem;
        !           998:        u_int32_t      *ptb, silentpage;
        !           999:
        !          1000:        ptb = KERNADDR(sc->ptb);
        !          1001:        silentpage = DMAADDR(sc->silentpage) << 1;
        !          1002:        numblocks = size / EMU_PTESIZE;
        !          1003:        if (size % EMU_PTESIZE)
        !          1004:                numblocks++;
        !          1005:
        !          1006:        for (i = 0; i < EMU_MAXPTE; i++)
        !          1007:                if ((letoh32(ptb[i]) & EMU_CHAN_MAP_PTE_MASK) == silentpage) {
        !          1008:                        /* We look for a free PTE */
        !          1009:                        s = splaudio();
        !          1010:                        for (j = 0; j < numblocks; j++)
        !          1011:                                if ((letoh32(ptb[i + j])
        !          1012:                                    & EMU_CHAN_MAP_PTE_MASK)
        !          1013:                                    != silentpage)
        !          1014:                                        break;
        !          1015:                        if (j == numblocks) {
        !          1016:                                if ((mem = emuxki_mem_new(sc, i,
        !          1017:                                                size, type, flags)) == NULL) {
        !          1018:                                        splx(s);
        !          1019:                                        return (NULL);
        !          1020:                                }
        !          1021:                                for (j = 0; j < numblocks; j++)
        !          1022:                                        ptb[i + j] =
        !          1023:                                            htole32((((DMAADDR(mem->dmamem) +
        !          1024:                                            j * EMU_PTESIZE)) << 1) | (i + j));
        !          1025:                                LIST_INSERT_HEAD(&(sc->mem), mem, next);
        !          1026:                                splx(s);
        !          1027:                                return (KERNADDR(mem->dmamem));
        !          1028:                        } else
        !          1029:                                i += j;
        !          1030:                        splx(s);
        !          1031:                }
        !          1032:        return (NULL);
        !          1033: }
        !          1034:
        !          1035: void *
        !          1036: emuxki_rmem_alloc(struct emuxki_softc *sc, size_t size, int type, int flags)
        !          1037: {
        !          1038:        struct emuxki_mem *mem;
        !          1039:        int             s;
        !          1040:
        !          1041:        mem = emuxki_mem_new(sc, EMU_RMEM, size, type, flags);
        !          1042:        if (mem == NULL)
        !          1043:                return (NULL);
        !          1044:
        !          1045:        s = splaudio();
        !          1046:        LIST_INSERT_HEAD(&(sc->mem), mem, next);
        !          1047:        splx(s);
        !          1048:
        !          1049:        return (KERNADDR(mem->dmamem));
        !          1050: }
        !          1051:
        !          1052: /*
        !          1053:  * emuxki_channel_* : Channel management functions
        !          1054:  * emuxki_chanparms_* : Channel parameters modification functions
        !          1055:  */
        !          1056:
        !          1057: /*
        !          1058:  * is splaudio necessary here, can the same voice be manipulated by two
        !          1059:  * different threads at a time ?
        !          1060:  */
        !          1061: void
        !          1062: emuxki_chanparms_set_defaults(struct emuxki_channel *chan)
        !          1063: {
        !          1064:        chan->fxsend.a.level = chan->fxsend.b.level =
        !          1065:        chan->fxsend.c.level = chan->fxsend.d.level =
        !          1066:        /* for audigy */
        !          1067:        chan->fxsend.e.level = chan->fxsend.f.level =
        !          1068:        chan->fxsend.g.level = chan->fxsend.h.level =
        !          1069:                chan->voice->sc->sc_type & EMUXKI_AUDIGY ?
        !          1070:                        0xc0 : 0xff;    /* not max */
        !          1071:
        !          1072:        chan->fxsend.a.dest = 0x0;
        !          1073:        chan->fxsend.b.dest = 0x1;
        !          1074:        chan->fxsend.c.dest = 0x2;
        !          1075:        chan->fxsend.d.dest = 0x3;
        !          1076:        /* for audigy */
        !          1077:        chan->fxsend.e.dest = 0x4;
        !          1078:        chan->fxsend.f.dest = 0x5;
        !          1079:        chan->fxsend.g.dest = 0x6;
        !          1080:        chan->fxsend.h.dest = 0x7;
        !          1081:
        !          1082:        chan->pitch.initial = 0x0000;   /* shouldn't it be 0xE000 ? */
        !          1083:        chan->pitch.current = 0x0000;   /* should it be 0x0400 */
        !          1084:        chan->pitch.target = 0x0000;    /* the unity pitch shift ? */
        !          1085:        chan->pitch.envelope_amount = 0x00;     /* none */
        !          1086:
        !          1087:        chan->initial_attenuation = 0x00;       /* no attenuation */
        !          1088:        chan->volume.current = 0x0000;  /* no volume */
        !          1089:        chan->volume.target = 0xffff;
        !          1090:        chan->volume.envelope.current_state = 0x8000;   /* 0 msec delay */
        !          1091:        chan->volume.envelope.hold_time = 0x7f; /* 0 msec */
        !          1092:        chan->volume.envelope.attack_time = 0x7F;       /* 5.5msec */
        !          1093:        chan->volume.envelope.sustain_level = 0x7F;     /* full  */
        !          1094:        chan->volume.envelope.decay_time = 0x7F;        /* 22msec  */
        !          1095:
        !          1096:        chan->filter.initial_cutoff_frequency = 0xff;   /* no filter */
        !          1097:        chan->filter.current_cutoff_frequency = 0xffff; /* no filtering */
        !          1098:        chan->filter.target_cutoff_frequency = 0xffff;  /* no filtering */
        !          1099:        chan->filter.lowpass_resonance_height = 0x0;
        !          1100:        chan->filter.interpolation_ROM = 0x1;   /* full band */
        !          1101:        chan->filter.envelope_amount = 0x7f;    /* none */
        !          1102:        chan->filter.LFO_modulation_depth = 0x00;       /* none */
        !          1103:
        !          1104:        chan->loop.start = 0x000000;
        !          1105:        chan->loop.end = 0x000010;      /* Why ? */
        !          1106:
        !          1107:        chan->modulation.envelope.current_state = 0x8000;
        !          1108:        chan->modulation.envelope.hold_time = 0x00;     /* 127 better ? */
        !          1109:        chan->modulation.envelope.attack_time = 0x00;   /* infinite */
        !          1110:        chan->modulation.envelope.sustain_level = 0x00; /* off */
        !          1111:        chan->modulation.envelope.decay_time = 0x7f;    /* 22 msec */
        !          1112:        chan->modulation.LFO_state = 0x8000;
        !          1113:
        !          1114:        chan->vibrato_LFO.state = 0x8000;
        !          1115:        chan->vibrato_LFO.modulation_depth = 0x00;      /* none */
        !          1116:        chan->vibrato_LFO.vibrato_depth = 0x00;
        !          1117:        chan->vibrato_LFO.frequency = 0x00;     /* Why set to 24 when
        !          1118:                                                 * initialized ? */
        !          1119:
        !          1120:        chan->tremolo_depth = 0x00;
        !          1121: }
        !          1122:
        !          1123: /* only call it at splaudio */
        !          1124: struct emuxki_channel *
        !          1125: emuxki_channel_new(struct emuxki_voice *voice, u_int8_t num)
        !          1126: {
        !          1127:        struct emuxki_channel *chan;
        !          1128:
        !          1129:        chan = malloc(sizeof(struct emuxki_channel), M_DEVBUF, M_WAITOK);
        !          1130:        if (chan == NULL)
        !          1131:                return (NULL);
        !          1132:
        !          1133:        chan->voice = voice;
        !          1134:        chan->num = num;
        !          1135:        emuxki_chanparms_set_defaults(chan);
        !          1136:        chan->voice->sc->channel[num] = chan;
        !          1137:        return (chan);
        !          1138: }
        !          1139:
        !          1140: /* only call it at splaudio */
        !          1141: void
        !          1142: emuxki_channel_delete(struct emuxki_channel *chan)
        !          1143: {
        !          1144:        chan->voice->sc->channel[chan->num] = NULL;
        !          1145:        free(chan, M_DEVBUF);
        !          1146: }
        !          1147:
        !          1148: void
        !          1149: emuxki_channel_set_fxsend(struct emuxki_channel *chan,
        !          1150:                           struct emuxki_chanparms_fxsend *fxsend)
        !          1151: {
        !          1152:        /* Could do a memcpy ...*/
        !          1153:        chan->fxsend.a.level = fxsend->a.level;
        !          1154:        chan->fxsend.b.level = fxsend->b.level;
        !          1155:        chan->fxsend.c.level = fxsend->c.level;
        !          1156:        chan->fxsend.d.level = fxsend->d.level;
        !          1157:        chan->fxsend.a.dest = fxsend->a.dest;
        !          1158:        chan->fxsend.b.dest = fxsend->b.dest;
        !          1159:        chan->fxsend.c.dest = fxsend->c.dest;
        !          1160:        chan->fxsend.d.dest = fxsend->d.dest;
        !          1161:
        !          1162:        /* for audigy */
        !          1163:        chan->fxsend.e.level = fxsend->e.level;
        !          1164:        chan->fxsend.f.level = fxsend->f.level;
        !          1165:        chan->fxsend.g.level = fxsend->g.level;
        !          1166:        chan->fxsend.h.level = fxsend->h.level;
        !          1167:        chan->fxsend.e.dest = fxsend->e.dest;
        !          1168:        chan->fxsend.f.dest = fxsend->f.dest;
        !          1169:        chan->fxsend.g.dest = fxsend->g.dest;
        !          1170:        chan->fxsend.h.dest = fxsend->h.dest;
        !          1171: }
        !          1172:
        !          1173: void
        !          1174: emuxki_channel_set_srate(struct emuxki_channel *chan, u_int32_t srate)
        !          1175: {
        !          1176:        chan->pitch.target = (srate << 8) / 375;
        !          1177:        chan->pitch.target = (chan->pitch.target >> 1) +
        !          1178:                (chan->pitch.target & 1);
        !          1179:        chan->pitch.target &= 0xffff;
        !          1180:        chan->pitch.current = chan->pitch.target;
        !          1181:        chan->pitch.initial =
        !          1182:                (emuxki_rate_to_pitch(srate) >> 8) & EMU_CHAN_IP_MASK;
        !          1183: }
        !          1184:
        !          1185: /* voice params must be set before calling this */
        !          1186: void
        !          1187: emuxki_channel_set_bufparms(struct emuxki_channel *chan,
        !          1188:                             u_int32_t start, u_int32_t end)
        !          1189: {
        !          1190:        chan->loop.start = start & EMU_CHAN_PSST_LOOPSTARTADDR_MASK;
        !          1191:        chan->loop.end = end & EMU_CHAN_DSL_LOOPENDADDR_MASK;
        !          1192: }
        !          1193:
        !          1194: void
        !          1195: emuxki_channel_commit_fx(struct emuxki_channel *chan)
        !          1196: {
        !          1197:        struct emuxki_softc *sc = chan->voice->sc;
        !          1198:         u_int8_t       chano = chan->num;
        !          1199:
        !          1200:         if(sc->sc_type & EMUXKI_AUDIGY) {
        !          1201:                 emuxki_write(sc, chano, EMU_A_CHAN_FXRT1,
        !          1202:                               (chan->fxsend.d.dest << 24) |
        !          1203:                               (chan->fxsend.c.dest << 16) |
        !          1204:                               (chan->fxsend.b.dest << 8) |
        !          1205:                               (chan->fxsend.a.dest));
        !          1206:                 emuxki_write(sc, chano, EMU_A_CHAN_FXRT2,
        !          1207:                               (chan->fxsend.h.dest << 24) |
        !          1208:                               (chan->fxsend.g.dest << 16) |
        !          1209:                               (chan->fxsend.f.dest << 8) |
        !          1210:                               (chan->fxsend.e.dest));
        !          1211:                 emuxki_write(sc, chano, EMU_A_CHAN_SENDAMOUNTS,
        !          1212:                               (chan->fxsend.e.level << 24) |
        !          1213:                               (chan->fxsend.f.level << 16) |
        !          1214:                               (chan->fxsend.g.level << 8) |
        !          1215:                               (chan->fxsend.h.level));
        !          1216:         } else {
        !          1217:                 emuxki_write(sc, chano, EMU_CHAN_FXRT,
        !          1218:                               (chan->fxsend.d.dest << 28) |
        !          1219:                               (chan->fxsend.c.dest << 24) |
        !          1220:                               (chan->fxsend.b.dest << 20) |
        !          1221:                               (chan->fxsend.a.dest << 16));
        !          1222:         }
        !          1223:
        !          1224:         emuxki_write(sc, chano, 0x10000000 | EMU_CHAN_PTRX,
        !          1225:                       (chan->fxsend.a.level << 8) | chan->fxsend.b.level);
        !          1226:         emuxki_write(sc, chano, EMU_CHAN_DSL,
        !          1227:                       (chan->fxsend.d.level << 24) | chan->loop.end);
        !          1228:         emuxki_write(sc, chano, EMU_CHAN_PSST,
        !          1229:                       (chan->fxsend.c.level << 24) | chan->loop.start);
        !          1230: }
        !          1231:
        !          1232: void
        !          1233: emuxki_channel_commit_parms(struct emuxki_channel *chan)
        !          1234: {
        !          1235:        struct emuxki_voice *voice = chan->voice;
        !          1236:        struct emuxki_softc *sc = voice->sc;
        !          1237:        u_int32_t start, mapval;
        !          1238:        u_int8_t chano = chan->num;
        !          1239:        int s;
        !          1240:
        !          1241:        start = chan->loop.start +
        !          1242:                (voice->stereo ? 28 : 30) * (voice->b16 + 1);
        !          1243:        mapval = DMAADDR(sc->silentpage) << 1 | EMU_CHAN_MAP_PTI_MASK;
        !          1244:
        !          1245:        s = splaudio();
        !          1246:        emuxki_write(sc, chano, EMU_CHAN_CPF_STEREO, voice->stereo);
        !          1247:
        !          1248:        emuxki_channel_commit_fx(chan);
        !          1249:
        !          1250:        emuxki_write(sc, chano, EMU_CHAN_CCCA,
        !          1251:                (chan->filter.lowpass_resonance_height << 28) |
        !          1252:                (chan->filter.interpolation_ROM << 25) |
        !          1253:                (voice->b16 ? 0 : EMU_CHAN_CCCA_8BITSELECT) | start);
        !          1254:        emuxki_write(sc, chano, EMU_CHAN_Z1, 0);
        !          1255:        emuxki_write(sc, chano, EMU_CHAN_Z2, 0);
        !          1256:        emuxki_write(sc, chano, EMU_CHAN_MAPA, mapval);
        !          1257:        emuxki_write(sc, chano, EMU_CHAN_MAPB, mapval);
        !          1258:        emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRFILTER,
        !          1259:                chan->filter.current_cutoff_frequency);
        !          1260:        emuxki_write(sc, chano, EMU_CHAN_VTFT_FILTERTARGET,
        !          1261:                chan->filter.target_cutoff_frequency);
        !          1262:        emuxki_write(sc, chano, EMU_CHAN_ATKHLDM,
        !          1263:                (chan->modulation.envelope.hold_time << 8) |
        !          1264:                chan->modulation.envelope.attack_time);
        !          1265:        emuxki_write(sc, chano, EMU_CHAN_DCYSUSM,
        !          1266:                (chan->modulation.envelope.sustain_level << 8) |
        !          1267:                chan->modulation.envelope.decay_time);
        !          1268:        emuxki_write(sc, chano, EMU_CHAN_LFOVAL1,
        !          1269:                chan->modulation.LFO_state);
        !          1270:        emuxki_write(sc, chano, EMU_CHAN_LFOVAL2,
        !          1271:                chan->vibrato_LFO.state);
        !          1272:        emuxki_write(sc, chano, EMU_CHAN_FMMOD,
        !          1273:                (chan->vibrato_LFO.modulation_depth << 8) |
        !          1274:                chan->filter.LFO_modulation_depth);
        !          1275:        emuxki_write(sc, chano, EMU_CHAN_TREMFRQ,
        !          1276:                (chan->tremolo_depth << 8));
        !          1277:        emuxki_write(sc, chano, EMU_CHAN_FM2FRQ2,
        !          1278:                (chan->vibrato_LFO.vibrato_depth << 8) |
        !          1279:                chan->vibrato_LFO.frequency);
        !          1280:        emuxki_write(sc, chano, EMU_CHAN_ENVVAL,
        !          1281:                chan->modulation.envelope.current_state);
        !          1282:        emuxki_write(sc, chano, EMU_CHAN_ATKHLDV,
        !          1283:                (chan->volume.envelope.hold_time << 8) |
        !          1284:                chan->volume.envelope.attack_time);
        !          1285:        emuxki_write(sc, chano, EMU_CHAN_ENVVOL,
        !          1286:                chan->volume.envelope.current_state);
        !          1287:        emuxki_write(sc, chano, EMU_CHAN_PEFE,
        !          1288:                (chan->pitch.envelope_amount << 8) |
        !          1289:                chan->filter.envelope_amount);
        !          1290:        splx(s);
        !          1291: }
        !          1292:
        !          1293: void
        !          1294: emuxki_channel_start(struct emuxki_channel *chan)
        !          1295: {
        !          1296:        struct emuxki_voice *voice = chan->voice;
        !          1297:        struct emuxki_softc *sc = voice->sc;
        !          1298:        u_int8_t        cache_sample, cache_invalid_size, chano = chan->num;
        !          1299:        u_int32_t       sample;
        !          1300:        int             s;
        !          1301:
        !          1302:        cache_sample = voice->stereo ? 4 : 2;
        !          1303:        sample = voice->b16 ? 0x00000000 : 0x80808080;
        !          1304:        cache_invalid_size = (voice->stereo ? 28 : 30) * (voice->b16 + 1);
        !          1305:
        !          1306:        s = splaudio();
        !          1307:        while (cache_sample--) {
        !          1308:                emuxki_write(sc, chano, EMU_CHAN_CD0 + cache_sample,
        !          1309:                        sample);
        !          1310:        }
        !          1311:        emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE, 0);
        !          1312:        emuxki_write(sc, chano, EMU_CHAN_CCR_READADDRESS, 64);
        !          1313:        emuxki_write(sc, chano, EMU_CHAN_CCR_CACHEINVALIDSIZE,
        !          1314:                cache_invalid_size);
        !          1315:        emuxki_write(sc, chano, EMU_CHAN_IFATN,
        !          1316:                (chan->filter.target_cutoff_frequency << 8) |
        !          1317:                chan->initial_attenuation);
        !          1318:        emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET,
        !          1319:                chan->volume.target);
        !          1320:        emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL,
        !          1321:                chan->volume.current);
        !          1322:        emuxki_write(sc, 0,
        !          1323:                EMU_MKSUBREG(1, chano, EMU_SOLEL + (chano >> 5)),
        !          1324:                0);     /* Clear stop on loop */
        !          1325:        emuxki_write(sc, 0,
        !          1326:                EMU_MKSUBREG(1, chano, EMU_CLIEL + (chano >> 5)),
        !          1327:                0);     /* Clear loop interrupt */
        !          1328:        emuxki_write(sc, chano, EMU_CHAN_DCYSUSV,
        !          1329:                (chan->volume.envelope.sustain_level << 8) |
        !          1330:                chan->volume.envelope.decay_time);
        !          1331:        emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET,
        !          1332:                chan->pitch.target);
        !          1333:        emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH,
        !          1334:                chan->pitch.current);
        !          1335:        emuxki_write(sc, chano, EMU_CHAN_IP, chan->pitch.initial);
        !          1336:
        !          1337:        splx(s);
        !          1338: }
        !          1339:
        !          1340: void
        !          1341: emuxki_channel_stop(struct emuxki_channel *chan)
        !          1342: {
        !          1343:        int s;
        !          1344:        u_int8_t chano = chan->num;
        !          1345:        struct emuxki_softc *sc = chan->voice->sc;
        !          1346:
        !          1347:        s = splaudio();
        !          1348:        emuxki_write(sc, chano, EMU_CHAN_PTRX_PITCHTARGET, 0);
        !          1349:        emuxki_write(sc, chano, EMU_CHAN_CPF_PITCH, 0);
        !          1350:        emuxki_write(sc, chano, EMU_CHAN_IFATN_ATTENUATION, 0xff);
        !          1351:        emuxki_write(sc, chano, EMU_CHAN_VTFT_VOLUMETARGET, 0);
        !          1352:        emuxki_write(sc, chano, EMU_CHAN_CVCF_CURRVOL, 0);
        !          1353:        emuxki_write(sc, chano, EMU_CHAN_IP, 0);
        !          1354:        splx(s);
        !          1355: }
        !          1356:
        !          1357: /*
        !          1358:  * Voices management
        !          1359:  * emuxki_voice_dataloc : use(play or rec) independent dataloc union helpers
        !          1360:  * emuxki_voice_channel_* : play part of dataloc union helpers
        !          1361:  * emuxki_voice_recsrc_* : rec part of dataloc union helpers
        !          1362:  */
        !          1363:
        !          1364: /* Allocate channels for voice in case of play voice */
        !          1365: int
        !          1366: emuxki_voice_channel_create(struct emuxki_voice *voice)
        !          1367: {
        !          1368:        struct emuxki_channel **channel = voice->sc->channel;
        !          1369:        u_int8_t i, stereo = voice->stereo;
        !          1370:        int s;
        !          1371:
        !          1372:        for (i = 0; i < EMU_NUMCHAN; i += stereo + 1) {
        !          1373:                if ((stereo && (channel[i + 1] != NULL)) ||
        !          1374:                    (channel[i] != NULL))       /* Looking for free channels */
        !          1375:                        continue;
        !          1376:                s = splaudio();
        !          1377:                if (stereo) {
        !          1378:                        voice->dataloc.chan[1] =
        !          1379:                                emuxki_channel_new(voice, i + 1);
        !          1380:                        if (voice->dataloc.chan[1] == NULL) {
        !          1381:                                splx(s);
        !          1382:                                return (ENOMEM);
        !          1383:                        }
        !          1384:                }
        !          1385:                voice->dataloc.chan[0] = emuxki_channel_new(voice, i);
        !          1386:                if (voice->dataloc.chan[0] == NULL) {
        !          1387:                        if (stereo) {
        !          1388:                                emuxki_channel_delete(voice->dataloc.chan[1]);
        !          1389:                                voice->dataloc.chan[1] = NULL;
        !          1390:                        }
        !          1391:                        splx(s);
        !          1392:                        return (ENOMEM);
        !          1393:                }
        !          1394:                splx(s);
        !          1395:                return (0);
        !          1396:        }
        !          1397:        return (EAGAIN);
        !          1398: }
        !          1399:
        !          1400: /* When calling this function we assume no one can access the voice */
        !          1401: void
        !          1402: emuxki_voice_channel_destroy(struct emuxki_voice *voice)
        !          1403: {
        !          1404:        emuxki_channel_delete(voice->dataloc.chan[0]);
        !          1405:        voice->dataloc.chan[0] = NULL;
        !          1406:        if (voice->stereo)
        !          1407:                emuxki_channel_delete(voice->dataloc.chan[1]);
        !          1408:        voice->dataloc.chan[1] = NULL;
        !          1409: }
        !          1410:
        !          1411: /*
        !          1412:  * Will come back when used in voice_dataloc_create
        !          1413:  */
        !          1414: int
        !          1415: emuxki_recsrc_reserve(struct emuxki_voice *voice, emuxki_recsrc_t source)
        !          1416: {
        !          1417:        if (source < 0 || source >= EMU_NUMRECSRCS) {
        !          1418: #ifdef EMUXKI_DEBUG
        !          1419:                printf("Tried to reserve invalid source: %d\n", source);
        !          1420: #endif
        !          1421:                return (EINVAL);
        !          1422:        }
        !          1423:        if (voice->sc->recsrc[source] == voice)
        !          1424:                return (0);                     /* XXX */
        !          1425:        if (voice->sc->recsrc[source] != NULL)
        !          1426:                return (EBUSY);
        !          1427:        voice->sc->recsrc[source] = voice;
        !          1428:        return (0);
        !          1429: }
        !          1430:
        !          1431: /* When calling this function we assume the voice is stopped */
        !          1432: void
        !          1433: emuxki_voice_recsrc_release(struct emuxki_softc *sc, emuxki_recsrc_t source)
        !          1434: {
        !          1435:        sc->recsrc[source] = NULL;
        !          1436: }
        !          1437:
        !          1438: int
        !          1439: emuxki_voice_dataloc_create(struct emuxki_voice *voice)
        !          1440: {
        !          1441:        int             error;
        !          1442:
        !          1443:        if (voice->use & EMU_VOICE_USE_PLAY) {
        !          1444:                if ((error = emuxki_voice_channel_create(voice)))
        !          1445:                        return (error);
        !          1446:        } else {
        !          1447:                if ((error =
        !          1448:                    emuxki_recsrc_reserve(voice, voice->dataloc.source)))
        !          1449:                        return (error);
        !          1450:        }
        !          1451:        return (0);
        !          1452: }
        !          1453:
        !          1454: void
        !          1455: emuxki_voice_dataloc_destroy(struct emuxki_voice *voice)
        !          1456: {
        !          1457:        if (voice->use & EMU_VOICE_USE_PLAY) {
        !          1458:                if (voice->dataloc.chan[0] != NULL)
        !          1459:                        emuxki_voice_channel_destroy(voice);
        !          1460:        } else {
        !          1461:                if (voice->dataloc.source != EMU_RECSRC_NOTSET) {
        !          1462:                        emuxki_voice_recsrc_release(voice->sc,
        !          1463:                                                     voice->dataloc.source);
        !          1464:                        voice->dataloc.source = EMU_RECSRC_NOTSET;
        !          1465:                }
        !          1466:        }
        !          1467: }
        !          1468:
        !          1469: struct emuxki_voice *
        !          1470: emuxki_voice_new(struct emuxki_softc *sc, u_int8_t use)
        !          1471: {
        !          1472:        struct emuxki_voice *voice;
        !          1473:        int             s;
        !          1474:
        !          1475:        s = splaudio();
        !          1476:        voice = sc->lvoice;
        !          1477:        sc->lvoice = NULL;
        !          1478:        splx(s);
        !          1479:
        !          1480:        if (!voice) {
        !          1481:                if (!(voice = malloc(sizeof(*voice), M_DEVBUF, M_WAITOK)))
        !          1482:                        return (NULL);
        !          1483:        } else if (voice->use != use)
        !          1484:                emuxki_voice_dataloc_destroy(voice);
        !          1485:        else
        !          1486:                goto skip_initialize;
        !          1487:
        !          1488:        voice->sc = sc;
        !          1489:        voice->state = !EMU_VOICE_STATE_STARTED;
        !          1490:        voice->stereo = EMU_VOICE_STEREO_NOTSET;
        !          1491:        voice->b16 = 0;
        !          1492:        voice->sample_rate = 0;
        !          1493:        if (use & EMU_VOICE_USE_PLAY)
        !          1494:                voice->dataloc.chan[0] = voice->dataloc.chan[1] = NULL;
        !          1495:        else
        !          1496:                voice->dataloc.source = EMU_RECSRC_NOTSET;
        !          1497:        voice->buffer = NULL;
        !          1498:        voice->blksize = 0;
        !          1499:        voice->trigblk = 0;
        !          1500:        voice->blkmod = 0;
        !          1501:        voice->inth = NULL;
        !          1502:        voice->inthparam = NULL;
        !          1503:        voice->use = use;
        !          1504:
        !          1505: skip_initialize:
        !          1506:        s = splaudio();
        !          1507:        LIST_INSERT_HEAD((&sc->voices), voice, next);
        !          1508:        splx(s);
        !          1509:
        !          1510:        return (voice);
        !          1511: }
        !          1512:
        !          1513: void
        !          1514: emuxki_voice_delete(struct emuxki_voice *voice)
        !          1515: {
        !          1516:        struct emuxki_softc *sc = voice->sc;
        !          1517:        struct emuxki_voice *lvoice;
        !          1518:        int s;
        !          1519:
        !          1520:        if (voice->state & EMU_VOICE_STATE_STARTED)
        !          1521:                emuxki_voice_halt(voice);
        !          1522:
        !          1523:        s = splaudio();
        !          1524:        LIST_REMOVE(voice, next);
        !          1525:        lvoice = sc->lvoice;
        !          1526:        sc->lvoice = voice;
        !          1527:        splx(s);
        !          1528:
        !          1529:        if (lvoice) {
        !          1530:                emuxki_voice_dataloc_destroy(lvoice);
        !          1531:                free(lvoice, M_DEVBUF);
        !          1532:        }
        !          1533: }
        !          1534:
        !          1535: int
        !          1536: emuxki_voice_set_stereo(struct emuxki_voice *voice, u_int8_t stereo)
        !          1537: {
        !          1538:        int     error;
        !          1539:        emuxki_recsrc_t source = 0; /* XXX: gcc */
        !          1540:        struct emuxki_chanparms_fxsend fxsend;
        !          1541:
        !          1542:        if (! (voice->use & EMU_VOICE_USE_PLAY))
        !          1543:                source = voice->dataloc.source;
        !          1544:        emuxki_voice_dataloc_destroy(voice);
        !          1545:        if (! (voice->use & EMU_VOICE_USE_PLAY))
        !          1546:                voice->dataloc.source = source;
        !          1547:        voice->stereo = stereo;
        !          1548:        if ((error = emuxki_voice_dataloc_create(voice)))
        !          1549:          return (error);
        !          1550:        if (voice->use & EMU_VOICE_USE_PLAY) {
        !          1551:                fxsend.a.dest = 0x0;
        !          1552:                fxsend.b.dest = 0x1;
        !          1553:                fxsend.c.dest = 0x2;
        !          1554:                fxsend.d.dest = 0x3;
        !          1555:                /* for audigy */
        !          1556:                fxsend.e.dest = 0x4;
        !          1557:                fxsend.f.dest = 0x5;
        !          1558:                fxsend.g.dest = 0x6;
        !          1559:                fxsend.h.dest = 0x7;
        !          1560:                if (voice->stereo) {
        !          1561:                        fxsend.a.level = fxsend.c.level = 0xc0;
        !          1562:                        fxsend.b.level = fxsend.d.level = 0x00;
        !          1563:                        fxsend.e.level = fxsend.g.level = 0xc0;
        !          1564:                        fxsend.f.level = fxsend.h.level = 0x00;
        !          1565:                        emuxki_channel_set_fxsend(voice->dataloc.chan[0],
        !          1566:                                                   &fxsend);
        !          1567:                        fxsend.a.level = fxsend.c.level = 0x00;
        !          1568:                        fxsend.b.level = fxsend.d.level = 0xc0;
        !          1569:                        fxsend.e.level = fxsend.g.level = 0x00;
        !          1570:                        fxsend.f.level = fxsend.h.level = 0xc0;
        !          1571:                        emuxki_channel_set_fxsend(voice->dataloc.chan[1],
        !          1572:                                                   &fxsend);
        !          1573:                } /* No else : default is good for mono */
        !          1574:        }
        !          1575:        return (0);
        !          1576: }
        !          1577:
        !          1578: int
        !          1579: emuxki_voice_set_srate(struct emuxki_voice *voice, u_int32_t srate)
        !          1580: {
        !          1581:        if (voice->use & EMU_VOICE_USE_PLAY) {
        !          1582:                if ((srate < 4000) || (srate > 48000))
        !          1583:                        return (EINVAL);
        !          1584:                voice->sample_rate = srate;
        !          1585:                emuxki_channel_set_srate(voice->dataloc.chan[0], srate);
        !          1586:                if (voice->stereo)
        !          1587:                        emuxki_channel_set_srate(voice->dataloc.chan[1],
        !          1588:                                                  srate);
        !          1589:        } else {
        !          1590:                if ((srate < 8000) || (srate > 48000))
        !          1591:                        return (EINVAL);
        !          1592:                voice->sample_rate = srate;
        !          1593:                if (emuxki_voice_adc_rate(voice) < 0) {
        !          1594:                        voice->sample_rate = 0;
        !          1595:                        return (EINVAL);
        !          1596:                }
        !          1597:        }
        !          1598:        return (0);
        !          1599: }
        !          1600:
        !          1601: int
        !          1602: emuxki_voice_set_audioparms(struct emuxki_voice *voice, u_int8_t stereo,
        !          1603:                             u_int8_t b16, u_int32_t srate)
        !          1604: {
        !          1605:        int             error = 0;
        !          1606:
        !          1607:        /*
        !          1608:         * Audio driver tried to set recording AND playing params even if
        !          1609:         * device opened in play or record only mode ==>
        !          1610:         * modified emuxki_set_params.
        !          1611:         * Stays here for now just in case ...
        !          1612:         */
        !          1613:        if (voice == NULL) {
        !          1614: #ifdef EMUXKI_DEBUG
        !          1615:                printf("warning: tried to set unallocated voice params !!\n");
        !          1616: #endif
        !          1617:                return (0);
        !          1618:        }
        !          1619:
        !          1620:        if (voice->stereo == stereo && voice->b16 == b16 &&
        !          1621:            voice->sample_rate == srate)
        !          1622:                return (0);
        !          1623:
        !          1624: #ifdef EMUXKI_DEBUG
        !          1625:        printf("Setting %s voice params : %s, %u bits, %u hz\n",
        !          1626:               (voice->use & EMU_VOICE_USE_PLAY) ? "play" : "record",
        !          1627:               stereo ? "stereo" : "mono", (b16 + 1) * 8, srate);
        !          1628: #endif
        !          1629:
        !          1630:        if (voice->stereo != stereo) {
        !          1631:                if ((error = emuxki_voice_set_stereo(voice, stereo)))
        !          1632:                        return (error);
        !          1633:         }
        !          1634:        voice->b16 = b16;
        !          1635:        if (voice->sample_rate != srate)
        !          1636:                error = emuxki_voice_set_srate(voice, srate);
        !          1637:        return error;
        !          1638: }
        !          1639:
        !          1640: /* voice audio parms (see just before) must be set prior to this */
        !          1641: int
        !          1642: emuxki_voice_set_bufparms(struct emuxki_voice *voice, void *ptr,
        !          1643:                           u_int32_t bufsize, u_int16_t blksize)
        !          1644: {
        !          1645:        struct emuxki_mem *mem;
        !          1646:        struct emuxki_channel **chan;
        !          1647:        u_int32_t start, end;
        !          1648:        u_int8_t sample_size;
        !          1649:        int idx;
        !          1650:        int error = EFAULT;
        !          1651:
        !          1652:        LIST_FOREACH(mem, &voice->sc->mem, next) {
        !          1653:                if (KERNADDR(mem->dmamem) != ptr)
        !          1654:                        continue;
        !          1655:
        !          1656:                voice->buffer = mem;
        !          1657:                sample_size = (voice->b16 + 1) * (voice->stereo + 1);
        !          1658:                voice->trigblk = 0;     /* This shouldn't be needed */
        !          1659:                voice->blkmod = bufsize / blksize;
        !          1660:                if (bufsize % blksize)    /* This should not happen */
        !          1661:                        voice->blkmod++;
        !          1662:                error = 0;
        !          1663:
        !          1664:                if (voice->use & EMU_VOICE_USE_PLAY) {
        !          1665:                        voice->blksize = blksize / sample_size;
        !          1666:                        chan = voice->dataloc.chan;
        !          1667:                        start = (mem->ptbidx << 12) / sample_size;
        !          1668:                        end = start + bufsize / sample_size;
        !          1669:                        emuxki_channel_set_bufparms(chan[0],
        !          1670:                                                     start, end);
        !          1671:                        if (voice->stereo)
        !          1672:                                emuxki_channel_set_bufparms(chan[1],
        !          1673:                                     start, end);
        !          1674:                        voice->timerate = (u_int32_t) 48000 *
        !          1675:                                        voice->blksize / voice->sample_rate;
        !          1676:                        if (voice->timerate < 5)
        !          1677:                                error = EINVAL;
        !          1678:                } else {
        !          1679:                        voice->blksize = blksize;
        !          1680:                        for(idx = sizeof(emuxki_recbuf_sz) /
        !          1681:                            sizeof(emuxki_recbuf_sz[0]); --idx >= 0;)
        !          1682:                                if (emuxki_recbuf_sz[idx] == bufsize)
        !          1683:                                        break;
        !          1684:                        if (idx < 0) {
        !          1685: #ifdef EMUXKI_DEBUG
        !          1686:                                printf("Invalid bufsize: %d\n", bufsize);
        !          1687: #endif
        !          1688:                                return (EINVAL);
        !          1689:                        }
        !          1690:                        emuxki_write(voice->sc, 0,
        !          1691:                            emuxki_recsrc_szreg[voice->dataloc.source], idx);
        !          1692:                        emuxki_write(voice->sc, 0,
        !          1693:                            emuxki_recsrc_bufaddrreg[voice->dataloc.source],
        !          1694:                            DMAADDR(mem->dmamem));
        !          1695:
        !          1696:                        /* Use timer to emulate DMA completion interrupt */
        !          1697:                        voice->timerate = (u_int32_t) 48000 * blksize /
        !          1698:                            (voice->sample_rate * sample_size);
        !          1699:                        if (voice->timerate < 5) {
        !          1700: #ifdef EMUXKI_DEBUG
        !          1701:                                printf("Invalid timerate: %d, blksize %d\n",
        !          1702:                                    voice->timerate, blksize);
        !          1703: #endif
        !          1704:                                error = EINVAL;
        !          1705:                        }
        !          1706:                }
        !          1707:
        !          1708:                break;
        !          1709:        }
        !          1710:
        !          1711:        return (error);
        !          1712: }
        !          1713:
        !          1714: void
        !          1715: emuxki_voice_commit_parms(struct emuxki_voice *voice)
        !          1716: {
        !          1717:        if (voice->use & EMU_VOICE_USE_PLAY) {
        !          1718:                emuxki_channel_commit_parms(voice->dataloc.chan[0]);
        !          1719:                if (voice->stereo)
        !          1720:                        emuxki_channel_commit_parms(voice->dataloc.chan[1]);
        !          1721:        }
        !          1722: }
        !          1723:
        !          1724: u_int32_t
        !          1725: emuxki_voice_curaddr(struct emuxki_voice *voice)
        !          1726: {
        !          1727:        int idxreg = 0;
        !          1728:
        !          1729:        /* XXX different semantics in these cases */
        !          1730:        if (voice->use & EMU_VOICE_USE_PLAY) {
        !          1731:                /* returns number of samples (an l/r pair counts 1) */
        !          1732:                return (emuxki_read(voice->sc,
        !          1733:                                     voice->dataloc.chan[0]->num,
        !          1734:                                     EMU_CHAN_CCCA_CURRADDR) -
        !          1735:                        voice->dataloc.chan[0]->loop.start);
        !          1736:        } else {
        !          1737:                /* returns number of bytes */
        !          1738:                switch (voice->dataloc.source) {
        !          1739:                        case EMU_RECSRC_MIC:
        !          1740:                                idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ?
        !          1741:                                        EMU_A_MICIDX : EMU_MICIDX;
        !          1742:                                break;
        !          1743:                        case EMU_RECSRC_ADC:
        !          1744:                                idxreg = (voice->sc->sc_type & EMUXKI_AUDIGY) ?
        !          1745:                                        EMU_A_ADCIDX : EMU_ADCIDX;
        !          1746:                                break;
        !          1747:                        case EMU_RECSRC_FX:
        !          1748:                                idxreg = EMU_FXIDX;
        !          1749:                                break;
        !          1750:                        default:
        !          1751: #ifdef EMUXKI_DEBUG
        !          1752:                                printf("emu: bad recording source!\n");
        !          1753: #endif
        !          1754:                                break;
        !          1755:                }
        !          1756:                return (emuxki_read(voice->sc, 0, EMU_RECIDX(idxreg))
        !          1757:                                & EMU_RECIDX_MASK);
        !          1758:        }
        !          1759:        return (0);
        !          1760: }
        !          1761:
        !          1762: void
        !          1763: emuxki_resched_timer(struct emuxki_softc *sc)
        !          1764: {
        !          1765:        struct emuxki_voice *voice;
        !          1766:        u_int16_t       timerate = 1024;
        !          1767:        u_int8_t        active = 0;
        !          1768:        int s;
        !          1769:
        !          1770:        s = splaudio();
        !          1771:        LIST_FOREACH(voice, &sc->voices, next) {
        !          1772:                if ((voice->state & EMU_VOICE_STATE_STARTED) == 0)
        !          1773:                        continue;
        !          1774:                active = 1;
        !          1775:                if (voice->timerate < timerate)
        !          1776:                        timerate = voice->timerate;
        !          1777:        }
        !          1778:
        !          1779:        if (timerate & ~EMU_TIMER_RATE_MASK)
        !          1780:                timerate = 0;
        !          1781:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_TIMER, timerate);
        !          1782:        if (!active && (sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
        !          1783:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
        !          1784:                        bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) &
        !          1785:                        ~EMU_INTE_INTERTIMERENB);
        !          1786:                sc->timerstate &= ~EMU_TIMER_STATE_ENABLED;
        !          1787:        } else if (active && !(sc->timerstate & EMU_TIMER_STATE_ENABLED)) {
        !          1788:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_INTE,
        !          1789:                        bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_INTE) |
        !          1790:                        EMU_INTE_INTERTIMERENB);
        !          1791:                sc->timerstate |= EMU_TIMER_STATE_ENABLED;
        !          1792:        }
        !          1793:        splx(s);
        !          1794: }
        !          1795:
        !          1796: int
        !          1797: emuxki_voice_adc_rate(struct emuxki_voice *voice)
        !          1798: {
        !          1799:        switch(voice->sample_rate) {
        !          1800:                case 48000:
        !          1801:                        return EMU_ADCCR_SAMPLERATE_48;
        !          1802:                        break;
        !          1803:                case 44100:
        !          1804:                        return EMU_ADCCR_SAMPLERATE_44;
        !          1805:                        break;
        !          1806:                case 32000:
        !          1807:                        return EMU_ADCCR_SAMPLERATE_32;
        !          1808:                        break;
        !          1809:                case 24000:
        !          1810:                        return EMU_ADCCR_SAMPLERATE_24;
        !          1811:                        break;
        !          1812:                case 22050:
        !          1813:                        return EMU_ADCCR_SAMPLERATE_22;
        !          1814:                        break;
        !          1815:                case 16000:
        !          1816:                        return EMU_ADCCR_SAMPLERATE_16;
        !          1817:                        break;
        !          1818:                case 12000:
        !          1819:                        if(voice->sc->sc_type & EMUXKI_AUDIGY)
        !          1820:                                return EMU_A_ADCCR_SAMPLERATE_12;
        !          1821:                        else {
        !          1822: #ifdef EMUXKI_DEBUG
        !          1823:                                printf("recording sample_rate not supported : %u\n", voice->sample_rate);
        !          1824: #endif
        !          1825:                                return (-1);
        !          1826:                        }
        !          1827:                        break;
        !          1828:                case 11000:
        !          1829:                        if(voice->sc->sc_type & EMUXKI_AUDIGY)
        !          1830:                                return EMU_A_ADCCR_SAMPLERATE_11;
        !          1831:                        else
        !          1832:                                return EMU_ADCCR_SAMPLERATE_11;
        !          1833:                        break;
        !          1834:                case 8000:
        !          1835:                        if(voice->sc->sc_type & EMUXKI_AUDIGY)
        !          1836:                                return EMU_A_ADCCR_SAMPLERATE_8;
        !          1837:                        else
        !          1838:                                return EMU_ADCCR_SAMPLERATE_8;
        !          1839:                        break;
        !          1840:                default:
        !          1841: #ifdef EMUXKI_DEBUG
        !          1842:                                printf("recording sample_rate not supported : %u\n", voice->sample_rate);
        !          1843: #endif
        !          1844:                                return (-1);
        !          1845:        }
        !          1846:        return (-1);  /* shouldn't get here */
        !          1847: }
        !          1848:
        !          1849: void
        !          1850: emuxki_voice_start(struct emuxki_voice *voice,
        !          1851:                    void (*inth) (void *), void *inthparam)
        !          1852: {
        !          1853:        u_int32_t val;
        !          1854:
        !          1855:        voice->inth = inth;
        !          1856:        voice->inthparam = inthparam;
        !          1857:        if (voice->use & EMU_VOICE_USE_PLAY) {
        !          1858:                voice->trigblk = 1;
        !          1859:                emuxki_channel_start(voice->dataloc.chan[0]);
        !          1860:                if (voice->stereo)
        !          1861:                        emuxki_channel_start(voice->dataloc.chan[1]);
        !          1862:        } else {
        !          1863:                voice->trigblk = 1;
        !          1864:                switch (voice->dataloc.source) {
        !          1865:                case EMU_RECSRC_ADC:
        !          1866:                        /* XXX need to program DSP to output L+R
        !          1867:                         * XXX in monaural case? */
        !          1868:                        if (voice->sc->sc_type & EMUXKI_AUDIGY) {
        !          1869:                                val = EMU_A_ADCCR_LCHANENABLE;
        !          1870:                                if (voice->stereo)
        !          1871:                                        val |= EMU_A_ADCCR_RCHANENABLE;
        !          1872:                        } else {
        !          1873:                                val = EMU_ADCCR_LCHANENABLE;
        !          1874:                                if (voice->stereo)
        !          1875:                                        val |= EMU_ADCCR_RCHANENABLE;
        !          1876:                        }
        !          1877:                        val |= emuxki_voice_adc_rate(voice);
        !          1878:                        emuxki_write(voice->sc, 0, EMU_ADCCR, 0);
        !          1879:                        emuxki_write(voice->sc, 0, EMU_ADCCR, val);
        !          1880:                        break;
        !          1881:                case EMU_RECSRC_MIC:
        !          1882:                case EMU_RECSRC_FX:
        !          1883:                        printf("unimplemented\n");
        !          1884:                        break;
        !          1885:                case EMU_RECSRC_NOTSET:
        !          1886:                default:
        !          1887:                        break;
        !          1888:                }
        !          1889: #if 0
        !          1890:                /* DMA completion interrupt is useless; use timer */
        !          1891:                int s;
        !          1892:                s = splaudio();
        !          1893:                val = emu_rd(sc, INTE, 4);
        !          1894:                val |= emuxki_recsrc_intrmasks[voice->dataloc.source];
        !          1895:                emu_wr(sc, INTE, val, 4);
        !          1896:                splx(s);
        !          1897: #endif
        !          1898:        }
        !          1899:        voice->state |= EMU_VOICE_STATE_STARTED;
        !          1900:        emuxki_resched_timer(voice->sc);
        !          1901: }
        !          1902:
        !          1903: void
        !          1904: emuxki_voice_halt(struct emuxki_voice *voice)
        !          1905: {
        !          1906:        if (voice->use & EMU_VOICE_USE_PLAY) {
        !          1907:                emuxki_channel_stop(voice->dataloc.chan[0]);
        !          1908:                if (voice->stereo)
        !          1909:                        emuxki_channel_stop(voice->dataloc.chan[1]);
        !          1910:        } else {
        !          1911:                switch (voice->dataloc.source) {
        !          1912:                case EMU_RECSRC_ADC:
        !          1913:                        emuxki_write(voice->sc, 0, EMU_ADCCR, 0);
        !          1914:                        break;
        !          1915:                case EMU_RECSRC_FX:
        !          1916:                case EMU_RECSRC_MIC:
        !          1917:                        printf("unimplemented\n");
        !          1918:                        break;
        !          1919:                case EMU_RECSRC_NOTSET:
        !          1920:                        printf("Bad dataloc.source\n");
        !          1921:                }
        !          1922:                /* This should reset buffer pointer */
        !          1923:                emuxki_write(voice->sc, 0,
        !          1924:                    emuxki_recsrc_szreg[voice->dataloc.source],
        !          1925:                    EMU_RECBS_BUFSIZE_NONE);
        !          1926: #if 0
        !          1927:                int s;
        !          1928:                s = splaudio();
        !          1929:                val = emu_rd(sc, INTE, 4);
        !          1930:                val &= ~emuxki_recsrc_intrmasks[voice->dataloc.source];
        !          1931:                emu_wr(sc, INTE, val, 4);
        !          1932:                splx(s);
        !          1933: #endif
        !          1934:        }
        !          1935:        voice->state &= ~EMU_VOICE_STATE_STARTED;
        !          1936:        emuxki_resched_timer(voice->sc);
        !          1937: }
        !          1938:
        !          1939: /*
        !          1940:  * The interrupt handler
        !          1941:  */
        !          1942: int
        !          1943: emuxki_intr(void *arg)
        !          1944: {
        !          1945:        struct emuxki_softc *sc = arg;
        !          1946:        u_int32_t       ipr, curblk, us = 0;
        !          1947:        struct emuxki_voice *voice;
        !          1948:
        !          1949:        while ((ipr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, EMU_IPR))) {
        !          1950:                if (ipr & EMU_IPR_INTERVALTIMER) {
        !          1951:                        LIST_FOREACH(voice, &sc->voices, next) {
        !          1952:                                if ((voice->state &
        !          1953:                                      EMU_VOICE_STATE_STARTED) == 0)
        !          1954:                                        continue;
        !          1955:
        !          1956:                                curblk = emuxki_voice_curaddr(voice) /
        !          1957:                                       voice->blksize;
        !          1958: #if 0
        !          1959:                                if (curblk == voice->trigblk) {
        !          1960:                                        voice->inth(voice->inthparam);
        !          1961:                                        voice->trigblk++;
        !          1962:                                        voice->trigblk %= voice->blkmod;
        !          1963:                                }
        !          1964: #else
        !          1965:                                while ((curblk >= voice->trigblk &&
        !          1966:                                    curblk < (voice->trigblk + voice->blkmod / 2)) ||
        !          1967:                                    ((int)voice->trigblk - (int)curblk) >
        !          1968:                                    (voice->blkmod / 2 + 1)) {
        !          1969:                                        voice->inth(voice->inthparam);
        !          1970:                                        voice->trigblk++;
        !          1971:                                        voice->trigblk %= voice->blkmod;
        !          1972:                                }
        !          1973: #endif
        !          1974:                        }
        !          1975:                        us = 1;
        !          1976:                }
        !          1977:
        !          1978:                /* Got interrupt */
        !          1979:                bus_space_write_4(sc->sc_iot, sc->sc_ioh, EMU_IPR, ipr);
        !          1980:        }
        !          1981:
        !          1982:        return (us);
        !          1983: }
        !          1984:
        !          1985:
        !          1986: /*
        !          1987:  * Audio Architecture callbacks
        !          1988:  */
        !          1989:
        !          1990: int
        !          1991: emuxki_open(void *addr, int flags)
        !          1992: {
        !          1993:        struct emuxki_softc *sc = addr;
        !          1994:
        !          1995: #ifdef EMUXKI_DEBUG
        !          1996:        printf("%s: emuxki_open called\n", sc->sc_dev.dv_xname);
        !          1997: #endif
        !          1998:
        !          1999:        /*
        !          2000:         * Multiple voice support would be added as soon as I find a way to
        !          2001:         * trick the audio arch into supporting multiple voices.
        !          2002:         * Or I might integrate a modified audio arch supporting
        !          2003:         * multiple voices.
        !          2004:         */
        !          2005:
        !          2006:        /*
        !          2007:         * I did this because i have problems identifying the selected
        !          2008:         * recording source(s) which is necessary when setting recording
        !          2009:         * params. This will be addressed very soon.
        !          2010:         */
        !          2011:        if (flags & AUOPEN_READ) {
        !          2012:                sc->rvoice = emuxki_voice_new(sc, 0 /* EMU_VOICE_USE_RECORD */);
        !          2013:                if (sc->rvoice == NULL)
        !          2014:                        return (EBUSY);
        !          2015:
        !          2016:                /* XXX Hardcode RECSRC_ADC for now */
        !          2017:                sc->rvoice->dataloc.source = EMU_RECSRC_ADC;
        !          2018:        }
        !          2019:
        !          2020:        if (flags & AUOPEN_WRITE) {
        !          2021:                sc->pvoice = emuxki_voice_new(sc, EMU_VOICE_USE_PLAY);
        !          2022:                if (sc->pvoice == NULL) {
        !          2023:                        if (flags & AUOPEN_READ)
        !          2024:                                emuxki_voice_delete(sc->rvoice);
        !          2025:                        return (EBUSY);
        !          2026:                }
        !          2027:        }
        !          2028:
        !          2029:        return (0);
        !          2030: }
        !          2031:
        !          2032: void
        !          2033: emuxki_close(void *addr)
        !          2034: {
        !          2035:        struct emuxki_softc *sc = addr;
        !          2036:
        !          2037: #ifdef EMUXKI_DEBUG
        !          2038:        printf("%s: emu10K1_close called\n", sc->sc_dev.dv_xname);
        !          2039: #endif
        !          2040:
        !          2041:        /* No multiple voice support for now */
        !          2042:        if (sc->rvoice != NULL)
        !          2043:                emuxki_voice_delete(sc->rvoice);
        !          2044:        sc->rvoice = NULL;
        !          2045:        if (sc->pvoice != NULL)
        !          2046:                emuxki_voice_delete(sc->pvoice);
        !          2047:        sc->pvoice = NULL;
        !          2048: }
        !          2049:
        !          2050: int
        !          2051: emuxki_query_encoding(void *addr, struct audio_encoding *fp)
        !          2052: {
        !          2053: #ifdef EMUXKI_DEBUG
        !          2054:        struct emuxki_softc *sc = addr;
        !          2055:
        !          2056:        printf("%s: emuxki_query_encoding called\n", sc->sc_dev.dv_xname);
        !          2057: #endif
        !          2058:
        !          2059:        switch (fp->index) {
        !          2060:        case 0:
        !          2061:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
        !          2062:                fp->encoding = AUDIO_ENCODING_ULINEAR;
        !          2063:                fp->precision = 8;
        !          2064:                fp->flags = 0;
        !          2065:                break;
        !          2066:        case 1:
        !          2067:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
        !          2068:                fp->encoding = AUDIO_ENCODING_ULAW;
        !          2069:                fp->precision = 8;
        !          2070:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          2071:                break;
        !          2072:        case 2:
        !          2073:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
        !          2074:                fp->encoding = AUDIO_ENCODING_ALAW;
        !          2075:                fp->precision = 8;
        !          2076:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          2077:                break;
        !          2078:        case 3:
        !          2079:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
        !          2080:                fp->encoding = AUDIO_ENCODING_SLINEAR;
        !          2081:                fp->precision = 8;
        !          2082:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          2083:                break;
        !          2084:        case 4:
        !          2085:                strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
        !          2086:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
        !          2087:                fp->precision = 16;
        !          2088:                fp->flags = 0;
        !          2089:                break;
        !          2090:        case 5:
        !          2091:                strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
        !          2092:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
        !          2093:                fp->precision = 16;
        !          2094:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          2095:                break;
        !          2096:        case 6:
        !          2097:                strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
        !          2098:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
        !          2099:                fp->precision = 16;
        !          2100:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          2101:                break;
        !          2102:        case 7:
        !          2103:                strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
        !          2104:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
        !          2105:                fp->precision = 16;
        !          2106:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !          2107:                break;
        !          2108:        default:
        !          2109:                return (EINVAL);
        !          2110:        }
        !          2111:        return (0);
        !          2112: }
        !          2113:
        !          2114: int
        !          2115: emuxki_set_vparms(struct emuxki_voice *voice, struct audio_params *p)
        !          2116: {
        !          2117:        u_int8_t        b16, mode;
        !          2118:
        !          2119:        mode = (voice->use & EMU_VOICE_USE_PLAY) ?
        !          2120:                AUMODE_PLAY : AUMODE_RECORD;
        !          2121:        p->factor = 1;
        !          2122:        p->sw_code = NULL;
        !          2123:        if (p->channels != 1 && p->channels != 2)
        !          2124:                return (EINVAL);/* Will change when streams come in use */
        !          2125:
        !          2126:        /*
        !          2127:         * Always use slinear_le for recording, as how to set otherwise
        !          2128:         * isn't known.
        !          2129:         */
        !          2130:        if (mode == AUMODE_PLAY)
        !          2131:                b16 = (p->precision == 16);
        !          2132:        else {
        !          2133:                b16 = 1;
        !          2134:                if (p->precision == 8)
        !          2135:                        p->factor *= 2;
        !          2136:        }
        !          2137:
        !          2138:        switch (p->encoding) {
        !          2139:        case AUDIO_ENCODING_ULAW:
        !          2140:                if (mode == AUMODE_PLAY) {
        !          2141:                        p->factor = 2;
        !          2142:                        p->sw_code = mulaw_to_slinear16_le;
        !          2143:                        b16 = 1;
        !          2144:                } else
        !          2145:                        p->sw_code = slinear16_to_mulaw_le;
        !          2146:                break;
        !          2147:
        !          2148:        case AUDIO_ENCODING_ALAW:
        !          2149:                if (mode == AUMODE_PLAY) {
        !          2150:                        p->factor = 2;
        !          2151:                        p->sw_code = alaw_to_slinear16_le;
        !          2152:                        b16 = 1;
        !          2153:                } else
        !          2154:                        p->sw_code = slinear16_to_alaw_le;
        !          2155:                break;
        !          2156:
        !          2157:        case AUDIO_ENCODING_SLINEAR_LE:
        !          2158:                if (p->precision == 8) {
        !          2159:                        if (mode == AUMODE_PLAY)
        !          2160:                                p->sw_code = change_sign8;
        !          2161:                        else
        !          2162:                                p->sw_code = linear16_to_linear8_le;
        !          2163:                }
        !          2164:                break;
        !          2165:
        !          2166:        case AUDIO_ENCODING_ULINEAR_LE:
        !          2167:                if (p->precision == 16)
        !          2168:                        p->sw_code = change_sign16_le;
        !          2169:                else if (mode == AUMODE_RECORD)
        !          2170:                        p->sw_code = slinear16_to_ulinear8_le;
        !          2171:                break;
        !          2172:
        !          2173:        case AUDIO_ENCODING_SLINEAR_BE:
        !          2174:                if (p->precision == 16)
        !          2175:                        p->sw_code = swap_bytes;
        !          2176:                else {
        !          2177:                        if (mode == AUMODE_PLAY)
        !          2178:                                p->sw_code = change_sign8;
        !          2179:                        else
        !          2180:                                p->sw_code = linear16_to_linear8_le;
        !          2181:                }
        !          2182:                break;
        !          2183:
        !          2184:        case AUDIO_ENCODING_ULINEAR_BE:
        !          2185:                if (p->precision == 16) {
        !          2186:                        if (mode == AUMODE_PLAY)
        !          2187:                                p->sw_code = swap_bytes_change_sign16_le;
        !          2188:                        else
        !          2189:                                p->sw_code = change_sign16_swap_bytes_le;
        !          2190:                } else if (mode == AUMODE_RECORD)
        !          2191:                        p->sw_code = slinear16_to_ulinear8_le;
        !          2192:                break;
        !          2193:
        !          2194:        default:
        !          2195:                return (EINVAL);
        !          2196:        }
        !          2197:
        !          2198:        return (emuxki_voice_set_audioparms(voice, p->channels == 2,
        !          2199:                                     b16, p->sample_rate));
        !          2200: }
        !          2201:
        !          2202: int
        !          2203: emuxki_set_params(void *addr, int setmode, int usemode,
        !          2204:                   struct audio_params *play, struct audio_params *rec)
        !          2205: {
        !          2206:        struct emuxki_softc *sc = addr;
        !          2207:        int          mode, error;
        !          2208:        struct audio_params *p;
        !          2209:
        !          2210:        for (mode = AUMODE_RECORD; mode != -1;
        !          2211:             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
        !          2212:                if ((usemode & setmode & mode) == 0)
        !          2213:                        continue;
        !          2214:
        !          2215:                p = (mode == AUMODE_PLAY) ? play : rec;
        !          2216:
        !          2217:                /* No multiple voice support for now */
        !          2218:                if ((error = emuxki_set_vparms((mode == AUMODE_PLAY) ?
        !          2219:                                                sc->pvoice : sc->rvoice, p)))
        !          2220:                        return (error);
        !          2221:        }
        !          2222:
        !          2223:        return (0);
        !          2224: }
        !          2225:
        !          2226: int
        !          2227: emuxki_halt_output(void *addr)
        !          2228: {
        !          2229:        struct emuxki_softc *sc = addr;
        !          2230:
        !          2231:        /* No multiple voice support for now */
        !          2232:        if (sc->pvoice == NULL)
        !          2233:                return (ENXIO);
        !          2234:
        !          2235:        emuxki_voice_halt(sc->pvoice);
        !          2236:        return (0);
        !          2237: }
        !          2238:
        !          2239: int
        !          2240: emuxki_halt_input(void *addr)
        !          2241: {
        !          2242:        struct emuxki_softc *sc = addr;
        !          2243:
        !          2244: #ifdef EMUXKI_DEBUG
        !          2245:        printf("%s: emuxki_halt_input called\n", sc->sc_dev.dv_xname);
        !          2246: #endif
        !          2247:
        !          2248:        /* No multiple voice support for now */
        !          2249:        if (sc->rvoice == NULL)
        !          2250:                return (ENXIO);
        !          2251:        emuxki_voice_halt(sc->rvoice);
        !          2252:        return (0);
        !          2253: }
        !          2254:
        !          2255: int
        !          2256: emuxki_getdev(void *v, struct audio_device *adp)
        !          2257: {
        !          2258:        struct emuxki_softc *sc = v;
        !          2259:        *adp = sc->sc_audv;
        !          2260:        return 0;
        !          2261: }
        !          2262:
        !          2263: int
        !          2264: emuxki_set_port(void *addr, mixer_ctrl_t *mctl)
        !          2265: {
        !          2266:        struct emuxki_softc *sc = addr;
        !          2267:
        !          2268:        return sc->codecif->vtbl->mixer_set_port(sc->codecif, mctl);
        !          2269: }
        !          2270:
        !          2271: int
        !          2272: emuxki_get_port(void *addr, mixer_ctrl_t *mctl)
        !          2273: {
        !          2274:        struct emuxki_softc *sc = addr;
        !          2275:
        !          2276:        return sc->codecif->vtbl->mixer_get_port(sc->codecif, mctl);
        !          2277: }
        !          2278:
        !          2279: int
        !          2280: emuxki_query_devinfo(void *addr, mixer_devinfo_t *minfo)
        !          2281: {
        !          2282:        struct emuxki_softc *sc = addr;
        !          2283:
        !          2284:        return sc->codecif->vtbl->query_devinfo(sc->codecif, minfo);
        !          2285: }
        !          2286:
        !          2287: void *
        !          2288: emuxki_allocm(void *addr, int direction, size_t size, int type, int flags)
        !          2289: {
        !          2290:        struct emuxki_softc *sc = addr;
        !          2291:
        !          2292:        if (direction == AUMODE_PLAY)
        !          2293:                return emuxki_pmem_alloc(sc, size, type, flags);
        !          2294:        else
        !          2295:                return emuxki_rmem_alloc(sc, size, type, flags);
        !          2296: }
        !          2297:
        !          2298: void
        !          2299: emuxki_freem(void *addr, void *ptr, int type)
        !          2300: {
        !          2301:        struct emuxki_softc *sc = addr;
        !          2302:        int          i, s;
        !          2303:        struct emuxki_mem *mem;
        !          2304:        size_t    numblocks;
        !          2305:        u_int32_t      *ptb, silentpage;
        !          2306:
        !          2307:        ptb = KERNADDR(sc->ptb);
        !          2308:        silentpage = DMAADDR(sc->silentpage) << 1;
        !          2309:        LIST_FOREACH(mem, &sc->mem, next) {
        !          2310:                if (KERNADDR(mem->dmamem) != ptr)
        !          2311:                        continue;
        !          2312:
        !          2313:                s = splaudio();
        !          2314:                if (mem->ptbidx != EMU_RMEM) {
        !          2315:                        numblocks = DMASIZE(mem->dmamem) / EMU_PTESIZE;
        !          2316:                        if (DMASIZE(mem->dmamem) % EMU_PTESIZE)
        !          2317:                                numblocks++;
        !          2318:                        for (i = 0; i < numblocks; i++)
        !          2319:                                ptb[mem->ptbidx + i] =
        !          2320:                                    htole32(silentpage | (mem->ptbidx + i));
        !          2321:                }
        !          2322:                LIST_REMOVE(mem, next);
        !          2323:                splx(s);
        !          2324:
        !          2325:                emuxki_mem_delete(mem, type);
        !          2326:                break;
        !          2327:        }
        !          2328: }
        !          2329:
        !          2330: /* blocksize should be a divisor of allowable buffersize */
        !          2331: /* XXX probably this could be done better */
        !          2332: int
        !          2333: emuxki_round_blocksize(void *addr, int blksize)
        !          2334: {
        !          2335:        int bufsize = 65536;
        !          2336:
        !          2337:        while (bufsize > blksize)
        !          2338:                bufsize /= 2;
        !          2339:
        !          2340:        return bufsize;
        !          2341: }
        !          2342:
        !          2343: size_t
        !          2344: emuxki_round_buffersize(void *addr, int direction, size_t bsize)
        !          2345: {
        !          2346:
        !          2347:        if (direction == AUMODE_PLAY) {
        !          2348:                if (bsize < EMU_PTESIZE)
        !          2349:                        bsize = EMU_PTESIZE;
        !          2350:                else if (bsize > (EMU_PTESIZE * EMU_MAXPTE))
        !          2351:                        bsize = EMU_PTESIZE * EMU_MAXPTE;
        !          2352:                /* Would be better if set to max available */
        !          2353:                else if (bsize % EMU_PTESIZE)
        !          2354:                        bsize = bsize -
        !          2355:                                (bsize % EMU_PTESIZE) +
        !          2356:                                EMU_PTESIZE;
        !          2357:        } else {
        !          2358:                int idx;
        !          2359:
        !          2360:                /* find nearest lower recbuf size */
        !          2361:                for(idx = sizeof(emuxki_recbuf_sz) /
        !          2362:                    sizeof(emuxki_recbuf_sz[0]); --idx >= 0; ) {
        !          2363:                        if (bsize >= emuxki_recbuf_sz[idx]) {
        !          2364:                                bsize = emuxki_recbuf_sz[idx];
        !          2365:                                break;
        !          2366:                        }
        !          2367:                }
        !          2368:
        !          2369:                if (bsize == 0)
        !          2370:                        bsize = 384;
        !          2371:        }
        !          2372:
        !          2373:        return (bsize);
        !          2374: }
        !          2375:
        !          2376: paddr_t
        !          2377: emuxki_mappage(void *addr, void *ptr, off_t off, int prot)
        !          2378: {
        !          2379:        struct emuxki_softc *sc = addr;
        !          2380:        struct emuxki_mem *mem;
        !          2381:
        !          2382:        LIST_FOREACH(mem, &sc->mem, next) {
        !          2383:                if (KERNADDR(mem->dmamem) == ptr) {
        !          2384:                        struct dmamem *dm = mem->dmamem;
        !          2385:
        !          2386:                        return bus_dmamem_mmap(dm->dmat, dm->segs, dm->nsegs,
        !          2387:                               off, prot, BUS_DMA_WAITOK);
        !          2388:                }
        !          2389:        }
        !          2390:
        !          2391:        return (-1);
        !          2392: }
        !          2393:
        !          2394: int
        !          2395: emuxki_get_props(void *addr)
        !          2396: {
        !          2397:        return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
        !          2398:                AUDIO_PROP_FULLDUPLEX);
        !          2399: }
        !          2400:
        !          2401: int
        !          2402: emuxki_trigger_output(void *addr, void *start, void *end, int blksize,
        !          2403:                       void (*inth) (void *), void *inthparam,
        !          2404:                       struct audio_params *params)
        !          2405: {
        !          2406:        struct emuxki_softc *sc = addr;
        !          2407:        /* No multiple voice support for now */
        !          2408:        struct emuxki_voice *voice = sc->pvoice;
        !          2409:        int          error;
        !          2410:
        !          2411:        if (voice == NULL)
        !          2412:                return (ENXIO);
        !          2413:        if ((error = emuxki_set_vparms(voice, params)))
        !          2414:                return (error);
        !          2415:        if ((error = emuxki_voice_set_bufparms(voice, start,
        !          2416:                                (caddr_t)end - (caddr_t)start, blksize)))
        !          2417:                return (error);
        !          2418:        emuxki_voice_commit_parms(voice);
        !          2419:        emuxki_voice_start(voice, inth, inthparam);
        !          2420:
        !          2421:        return (0);
        !          2422: }
        !          2423:
        !          2424: int
        !          2425: emuxki_trigger_input(void *addr, void *start, void *end, int blksize,
        !          2426:                      void (*inth) (void *), void *inthparam,
        !          2427:                      struct audio_params *params)
        !          2428: {
        !          2429:        struct emuxki_softc *sc = addr;
        !          2430:        /* No multiple voice support for now */
        !          2431:        struct emuxki_voice *voice = sc->rvoice;
        !          2432:        int     error;
        !          2433:
        !          2434:        if (voice == NULL)
        !          2435:                return (ENXIO);
        !          2436:        if ((error = emuxki_set_vparms(voice, params)))
        !          2437:                return (error);
        !          2438:        if ((error = emuxki_voice_set_bufparms(voice, start,
        !          2439:                                                (caddr_t)end - (caddr_t)start,
        !          2440:                                                blksize)))
        !          2441:                return (error);
        !          2442:        emuxki_voice_start(voice, inth, inthparam);
        !          2443:
        !          2444:        return (0);
        !          2445: }
        !          2446:
        !          2447:
        !          2448: /*
        !          2449:  * AC97 callbacks
        !          2450:  */
        !          2451:
        !          2452: int
        !          2453: emuxki_ac97_attach(void *arg, struct ac97_codec_if *codecif)
        !          2454: {
        !          2455:        struct emuxki_softc *sc = arg;
        !          2456:
        !          2457:        sc->codecif = codecif;
        !          2458:        return (0);
        !          2459: }
        !          2460:
        !          2461: int
        !          2462: emuxki_ac97_read(void *arg, u_int8_t reg, u_int16_t *val)
        !          2463: {
        !          2464:        struct emuxki_softc *sc = arg;
        !          2465:        int s;
        !          2466:
        !          2467:        s = splaudio();
        !          2468:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
        !          2469:        *val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA);
        !          2470:        splx(s);
        !          2471:
        !          2472:        return (0);
        !          2473: }
        !          2474:
        !          2475: int
        !          2476: emuxki_ac97_write(void *arg, u_int8_t reg, u_int16_t val)
        !          2477: {
        !          2478:        struct emuxki_softc *sc = arg;
        !          2479:        int s;
        !          2480:
        !          2481:        s = splaudio();
        !          2482:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, EMU_AC97ADDR, reg);
        !          2483:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, EMU_AC97DATA, val);
        !          2484:        splx(s);
        !          2485:
        !          2486:        return (0);
        !          2487: }
        !          2488:
        !          2489: void
        !          2490: emuxki_ac97_reset(void *arg)
        !          2491: {
        !          2492: }

CVSweb