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

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

1.1     ! nbrk        1: /*     $OpenBSD: cmpci.c,v 1.14 2006/07/27 00:45:59 brad Exp $ */
        !             2: /*     $NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $       */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Takuya SHIOZAKI <tshiozak@NetBSD.org> .
        !            10:  *
        !            11:  * This code is derived from software contributed to The NetBSD Foundation
        !            12:  * by ITOH Yasufumi.
        !            13:  *
        !            14:  * Redistribution and use in source and binary forms, with or without
        !            15:  * modification, are permitted provided that the following conditions
        !            16:  * are met:
        !            17:  * 1. Redistributions of source code must retain the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer.
        !            19:  * 2. Redistributions in binary form must reproduce the above copyright
        !            20:  *    notice, this list of conditions and the following disclaimer in the
        !            21:  *    documentation and/or other materials provided with the distribution.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  *
        !            35:  */
        !            36:
        !            37: /*
        !            38:  * C-Media CMI8x38 Audio Chip Support.
        !            39:  *
        !            40:  * TODO:
        !            41:  *   - 4ch / 6ch support.
        !            42:  *   - Joystick support.
        !            43:  *
        !            44:  */
        !            45:
        !            46: #if 0
        !            47: #include <sys/cdefs.h>
        !            48: __KERNEL_RCSID(0, "$NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $");
        !            49: #endif
        !            50:
        !            51: #if defined(AUDIO_DEBUG) || defined(DEBUG)
        !            52: #define DPRINTF(x) if (cmpcidebug) printf x
        !            53: int cmpcidebug = 0;
        !            54: #else
        !            55: #define DPRINTF(x)
        !            56: #endif
        !            57:
        !            58: #include <sys/param.h>
        !            59: #include <sys/systm.h>
        !            60: #include <sys/kernel.h>
        !            61: #include <sys/malloc.h>
        !            62: #include <sys/device.h>
        !            63: #include <sys/proc.h>
        !            64:
        !            65: #include <dev/pci/pcidevs.h>
        !            66: #include <dev/pci/pcivar.h>
        !            67:
        !            68: #include <sys/audioio.h>
        !            69: #include <dev/audio_if.h>
        !            70: #include <dev/midi_if.h>
        !            71:
        !            72: #include <dev/mulaw.h>
        !            73: #include <dev/auconv.h>
        !            74: #include <dev/pci/cmpcireg.h>
        !            75: #include <dev/pci/cmpcivar.h>
        !            76:
        !            77: #include <dev/ic/mpuvar.h>
        !            78: #include <machine/bus.h>
        !            79: #include <machine/intr.h>
        !            80:
        !            81: /*
        !            82:  * Low-level HW interface
        !            83:  */
        !            84: __inline uint8_t cmpci_mixerreg_read(struct cmpci_softc *,
        !            85:                                                 uint8_t);
        !            86: __inline void cmpci_mixerreg_write(struct cmpci_softc *,
        !            87:                                               uint8_t, uint8_t);
        !            88: __inline void cmpci_reg_partial_write_1(struct cmpci_softc *,
        !            89:                                                    int, int,
        !            90:                                                    unsigned, unsigned);
        !            91: __inline void cmpci_reg_partial_write_4(struct cmpci_softc *,
        !            92:                                                    int, int,
        !            93:                                                    uint32_t, uint32_t);
        !            94: __inline void cmpci_reg_set_1(struct cmpci_softc *,
        !            95:                                          int, uint8_t);
        !            96: __inline void cmpci_reg_clear_1(struct cmpci_softc *,
        !            97:                                            int, uint8_t);
        !            98: __inline void cmpci_reg_set_4(struct cmpci_softc *,
        !            99:                                          int, uint32_t);
        !           100: __inline void cmpci_reg_clear_4(struct cmpci_softc *,
        !           101:                                            int, uint32_t);
        !           102: __inline void cmpci_reg_set_reg_misc(struct cmpci_softc *,
        !           103:                                                 uint32_t);
        !           104: __inline void cmpci_reg_clear_reg_misc(struct cmpci_softc *,
        !           105:                                                   uint32_t);
        !           106: int cmpci_rate_to_index(int);
        !           107: __inline int cmpci_index_to_rate(int);
        !           108: __inline int cmpci_index_to_divider(int);
        !           109:
        !           110: int cmpci_adjust(int, int);
        !           111: void cmpci_set_mixer_gain(struct cmpci_softc *, int);
        !           112: void cmpci_set_out_ports(struct cmpci_softc *);
        !           113: int cmpci_set_in_ports(struct cmpci_softc *);
        !           114:
        !           115: /*
        !           116:  * autoconf interface
        !           117:  */
        !           118: int cmpci_match(struct device *, void *, void *);
        !           119: void cmpci_attach(struct device *, struct device *, void *);
        !           120:
        !           121: struct cfdriver cmpci_cd = {
        !           122:        NULL, "cmpci", DV_DULL
        !           123: };
        !           124:
        !           125: struct cfattach cmpci_ca = {
        !           126:        sizeof (struct cmpci_softc), cmpci_match, cmpci_attach
        !           127: };
        !           128:
        !           129: /* interrupt */
        !           130: int cmpci_intr(void *);
        !           131:
        !           132: /*
        !           133:  * DMA stuff
        !           134:  */
        !           135: int cmpci_alloc_dmamem(struct cmpci_softc *,
        !           136:                                   size_t, int,
        !           137:                                   int, caddr_t *);
        !           138: int cmpci_free_dmamem(struct cmpci_softc *, caddr_t,
        !           139:                                  int);
        !           140: struct cmpci_dmanode * cmpci_find_dmamem(struct cmpci_softc *,
        !           141:                                                     caddr_t);
        !           142:
        !           143: /*
        !           144:  * Interface to machine independent layer
        !           145:  */
        !           146: int cmpci_open(void *, int);
        !           147: void cmpci_close(void *);
        !           148: int cmpci_query_encoding(void *, struct audio_encoding *);
        !           149: int cmpci_set_params(void *, int, int,
        !           150:                                 struct audio_params *,
        !           151:                                 struct audio_params *);
        !           152: int cmpci_round_blocksize(void *, int);
        !           153: int cmpci_halt_output(void *);
        !           154: int cmpci_halt_input(void *);
        !           155: int cmpci_getdev(void *, struct audio_device *);
        !           156: int cmpci_set_port(void *, mixer_ctrl_t *);
        !           157: int cmpci_get_port(void *, mixer_ctrl_t *);
        !           158: int cmpci_query_devinfo(void *, mixer_devinfo_t *);
        !           159: void *cmpci_malloc(void *, int, size_t, int, int);
        !           160: void cmpci_free(void *, void *, int);
        !           161: size_t cmpci_round_buffersize(void *, int, size_t);
        !           162: paddr_t cmpci_mappage(void *, void *, off_t, int);
        !           163: int cmpci_get_props(void *);
        !           164: int cmpci_trigger_output(void *, void *, void *, int,
        !           165:                                     void (*)(void *), void *,
        !           166:                                     struct audio_params *);
        !           167: int cmpci_trigger_input(void *, void *, void *, int,
        !           168:                                    void (*)(void *), void *,
        !           169:                                    struct audio_params *);
        !           170:
        !           171: struct audio_hw_if cmpci_hw_if = {
        !           172:        cmpci_open,             /* open */
        !           173:        cmpci_close,            /* close */
        !           174:        NULL,                   /* drain */
        !           175:        cmpci_query_encoding,   /* query_encoding */
        !           176:        cmpci_set_params,       /* set_params */
        !           177:        cmpci_round_blocksize,  /* round_blocksize */
        !           178:        NULL,                   /* commit_settings */
        !           179:        NULL,                   /* init_output */
        !           180:        NULL,                   /* init_input */
        !           181:        NULL,                   /* start_output */
        !           182:        NULL,                   /* start_input */
        !           183:        cmpci_halt_output,      /* halt_output */
        !           184:        cmpci_halt_input,       /* halt_input */
        !           185:        NULL,                   /* speaker_ctl */
        !           186:        cmpci_getdev,           /* getdev */
        !           187:        NULL,                   /* setfd */
        !           188:        cmpci_set_port,         /* set_port */
        !           189:        cmpci_get_port,         /* get_port */
        !           190:        cmpci_query_devinfo,    /* query_devinfo */
        !           191:        cmpci_malloc,           /* malloc */
        !           192:        cmpci_free,             /* free */
        !           193:        cmpci_round_buffersize,/* round_buffersize */
        !           194:        cmpci_mappage,          /* mappage */
        !           195:        cmpci_get_props,        /* get_props */
        !           196:        cmpci_trigger_output,   /* trigger_output */
        !           197:        cmpci_trigger_input,    /* trigger_input */
        !           198: };
        !           199:
        !           200: /*
        !           201:  * Low-level HW interface
        !           202:  */
        !           203:
        !           204: /* mixer register read/write */
        !           205: __inline uint8_t
        !           206: cmpci_mixerreg_read(struct cmpci_softc *sc, uint8_t no)
        !           207: {
        !           208:        uint8_t ret;
        !           209:
        !           210:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
        !           211:        delay(10);
        !           212:        ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA);
        !           213:        delay(10);
        !           214:        return ret;
        !           215: }
        !           216:
        !           217: __inline void
        !           218: cmpci_mixerreg_write(struct cmpci_softc *sc, uint8_t no, uint8_t val)
        !           219: {
        !           220:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
        !           221:        delay(10);
        !           222:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val);
        !           223:        delay(10);
        !           224: }
        !           225:
        !           226: /* register partial write */
        !           227: __inline void
        !           228: cmpci_reg_partial_write_1(struct cmpci_softc *sc, int no, int shift,
        !           229:     unsigned mask, unsigned val)
        !           230: {
        !           231:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
        !           232:            (val<<shift) |
        !           233:            (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
        !           234:        delay(10);
        !           235: }
        !           236:
        !           237: __inline void
        !           238: cmpci_reg_partial_write_4(struct cmpci_softc *sc, int no, int shift,
        !           239:     uint32_t mask, uint32_t val)
        !           240: {
        !           241:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
        !           242:            (val<<shift) |
        !           243:            (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
        !           244:        delay(10);
        !           245: }
        !           246:
        !           247: /* register set/clear bit */
        !           248: __inline void
        !           249: cmpci_reg_set_1(struct cmpci_softc *sc, int no, uint8_t mask)
        !           250: {
        !           251:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
        !           252:            (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) | mask));
        !           253:        delay(10);
        !           254: }
        !           255:
        !           256: __inline void
        !           257: cmpci_reg_clear_1(struct cmpci_softc *sc, int no, uint8_t mask)
        !           258: {
        !           259:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
        !           260:            (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~mask));
        !           261:        delay(10);
        !           262: }
        !           263:
        !           264: __inline void
        !           265: cmpci_reg_set_4(struct cmpci_softc *sc, int no, uint32_t mask)
        !           266: {
        !           267:        /* use cmpci_reg_set_reg_misc() for CMPCI_REG_MISC */
        !           268:        KDASSERT(no != CMPCI_REG_MISC);
        !           269:
        !           270:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
        !           271:            (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
        !           272:        delay(10);
        !           273: }
        !           274:
        !           275: __inline void
        !           276: cmpci_reg_clear_4(struct cmpci_softc *sc, int no, uint32_t mask)
        !           277: {
        !           278:        /* use cmpci_reg_clear_reg_misc() for CMPCI_REG_MISC */
        !           279:        KDASSERT(no != CMPCI_REG_MISC);
        !           280:
        !           281:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
        !           282:            (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
        !           283:        delay(10);
        !           284: }
        !           285:
        !           286: /*
        !           287:  * The CMPCI_REG_MISC register needs special handling, since one of
        !           288:  * its bits has different read/write values.
        !           289:  */
        !           290: __inline void
        !           291: cmpci_reg_set_reg_misc(struct cmpci_softc *sc, uint32_t mask)
        !           292: {
        !           293:        sc->sc_reg_misc |= mask;
        !           294:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
        !           295:            sc->sc_reg_misc);
        !           296:        delay(10);
        !           297: }
        !           298:
        !           299: __inline void
        !           300: cmpci_reg_clear_reg_misc(struct cmpci_softc *sc, uint32_t mask)
        !           301: {
        !           302:        sc->sc_reg_misc &= ~mask;
        !           303:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
        !           304:            sc->sc_reg_misc);
        !           305:        delay(10);
        !           306: }
        !           307:
        !           308: /* rate */
        !           309: static const struct {
        !           310:        int rate;
        !           311:        int divider;
        !           312: } cmpci_rate_table[CMPCI_REG_NUMRATE] = {
        !           313: #define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
        !           314:        _RATE(5512),
        !           315:        _RATE(8000),
        !           316:        _RATE(11025),
        !           317:        _RATE(16000),
        !           318:        _RATE(22050),
        !           319:        _RATE(32000),
        !           320:        _RATE(44100),
        !           321:        _RATE(48000)
        !           322: #undef _RATE
        !           323: };
        !           324:
        !           325: int
        !           326: cmpci_rate_to_index(int rate)
        !           327: {
        !           328:        int i;
        !           329:
        !           330:        for (i = 0; i < CMPCI_REG_NUMRATE - 1; i++)
        !           331:                if (rate <=
        !           332:                    (cmpci_rate_table[i].rate + cmpci_rate_table[i+1].rate) / 2)
        !           333:                        return i;
        !           334:        return i;  /* 48000 */
        !           335: }
        !           336:
        !           337: __inline int
        !           338: cmpci_index_to_rate(int index)
        !           339: {
        !           340:        return cmpci_rate_table[index].rate;
        !           341: }
        !           342:
        !           343: __inline int
        !           344: cmpci_index_to_divider(int index)
        !           345: {
        !           346:        return cmpci_rate_table[index].divider;
        !           347: }
        !           348:
        !           349: const struct pci_matchid cmpci_devices[] = {
        !           350:        { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338A },
        !           351:        { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338B },
        !           352:        { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738 },
        !           353:        { PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738B }
        !           354: };
        !           355:
        !           356: /*
        !           357:  * interface to configure the device.
        !           358:  */
        !           359:
        !           360: int
        !           361: cmpci_match(struct device *parent, void *match, void *aux)
        !           362: {
        !           363:        return (pci_matchbyid((struct pci_attach_args *)aux, cmpci_devices,
        !           364:            sizeof(cmpci_devices)/sizeof(cmpci_devices[0])));
        !           365: }
        !           366:
        !           367: void
        !           368: cmpci_attach(struct device *parent, struct device *self, void *aux)
        !           369: {
        !           370:        struct cmpci_softc *sc = (struct cmpci_softc *)self;
        !           371:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
        !           372:        struct audio_attach_args aa;
        !           373:        pci_intr_handle_t ih;
        !           374:        char const *intrstr;
        !           375:        int i, v;
        !           376:
        !           377:        sc->sc_id = pa->pa_id;
        !           378:        sc->sc_class = pa->pa_class;
        !           379:        switch (PCI_PRODUCT(sc->sc_id)) {
        !           380:        case PCI_PRODUCT_CMI_CMI8338A:
        !           381:                /*FALLTHROUGH*/
        !           382:        case PCI_PRODUCT_CMI_CMI8338B:
        !           383:                sc->sc_capable = CMPCI_CAP_CMI8338;
        !           384:                break;
        !           385:        case PCI_PRODUCT_CMI_CMI8738:
        !           386:                /*FALLTHROUGH*/
        !           387:        case PCI_PRODUCT_CMI_CMI8738B:
        !           388:                sc->sc_capable = CMPCI_CAP_CMI8738;
        !           389:                break;
        !           390:        }
        !           391:
        !           392:        /* map I/O space */
        !           393:        if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
        !           394:                           &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) {
        !           395:                printf(": failed to map I/O space\n");
        !           396:                return;
        !           397:        }
        !           398:
        !           399:        /* interrupt */
        !           400:        if (pci_intr_map(pa, &ih)) {
        !           401:                printf(": failed to map interrupt\n");
        !           402:                return;
        !           403:        }
        !           404:        intrstr = pci_intr_string(pa->pa_pc, ih);
        !           405:        sc->sc_ih=pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, cmpci_intr, sc,
        !           406:            sc->sc_dev.dv_xname);
        !           407:        if (sc->sc_ih == NULL) {
        !           408:                printf(": failed to establish interrupt");
        !           409:                if (intrstr != NULL)
        !           410:                        printf(" at %s", intrstr);
        !           411:                printf("\n");
        !           412:                return;
        !           413:        }
        !           414:        printf(": %s\n", intrstr);
        !           415:
        !           416:        sc->sc_dmat = pa->pa_dmat;
        !           417:
        !           418:        audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev);
        !           419:
        !           420:        /* attach OPL device */
        !           421:        aa.type = AUDIODEV_TYPE_OPL;
        !           422:        aa.hwif = NULL;
        !           423:        aa.hdl = NULL;
        !           424:        (void)config_found(&sc->sc_dev, &aa, audioprint);
        !           425:
        !           426:        /* attach MPU-401 device */
        !           427:        aa.type = AUDIODEV_TYPE_MPU;
        !           428:        aa.hwif = NULL;
        !           429:        aa.hdl = NULL;
        !           430:        if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
        !           431:            CMPCI_REG_MPU_BASE, CMPCI_REG_MPU_SIZE, &sc->sc_mpu_ioh) == 0)
        !           432:                sc->sc_mpudev = config_found(&sc->sc_dev, &aa, audioprint);
        !           433:
        !           434:        /* get initial value (this is 0 and may be omitted but just in case) */
        !           435:        sc->sc_reg_misc = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
        !           436:            CMPCI_REG_MISC) & ~CMPCI_REG_SPDIF48K;
        !           437:
        !           438:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
        !           439:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
        !           440:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
        !           441:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX,
        !           442:            CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC|CMPCI_SB16_SW_LINE);
        !           443:        for (i = 0; i < CMPCI_NDEVS; i++) {
        !           444:                switch(i) {
        !           445:                /*
        !           446:                 * CMI8738 defaults are
        !           447:                 *  master:     0xe0    (0x00 - 0xf8)
        !           448:                 *  FM, DAC:    0xc0    (0x00 - 0xf8)
        !           449:                 *  PC speaker: 0x80    (0x00 - 0xc0)
        !           450:                 *  others:     0
        !           451:                 */
        !           452:                /* volume */
        !           453:                case CMPCI_MASTER_VOL:
        !           454:                        v = 128;        /* 224 */
        !           455:                        break;
        !           456:                case CMPCI_FM_VOL:
        !           457:                case CMPCI_DAC_VOL:
        !           458:                        v = 192;
        !           459:                        break;
        !           460:                case CMPCI_PCSPEAKER:
        !           461:                        v = 128;
        !           462:                        break;
        !           463:
        !           464:                /* booleans, set to true */
        !           465:                case CMPCI_CD_MUTE:
        !           466:                case CMPCI_MIC_MUTE:
        !           467:                case CMPCI_LINE_IN_MUTE:
        !           468:                case CMPCI_AUX_IN_MUTE:
        !           469:                        v = 1;
        !           470:                        break;
        !           471:
        !           472:                /* volume with inital value 0 */
        !           473:                case CMPCI_CD_VOL:
        !           474:                case CMPCI_LINE_IN_VOL:
        !           475:                case CMPCI_AUX_IN_VOL:
        !           476:                case CMPCI_MIC_VOL:
        !           477:                case CMPCI_MIC_RECVOL:
        !           478:                        /* FALLTHROUGH */
        !           479:
        !           480:                /* others are cleared */
        !           481:                case CMPCI_MIC_PREAMP:
        !           482:                case CMPCI_RECORD_SOURCE:
        !           483:                case CMPCI_PLAYBACK_MODE:
        !           484:                case CMPCI_SPDIF_IN_SELECT:
        !           485:                case CMPCI_SPDIF_IN_PHASE:
        !           486:                case CMPCI_SPDIF_LOOP:
        !           487:                case CMPCI_SPDIF_OUT_PLAYBACK:
        !           488:                case CMPCI_SPDIF_OUT_VOLTAGE:
        !           489:                case CMPCI_MONITOR_DAC:
        !           490:                case CMPCI_REAR:
        !           491:                case CMPCI_INDIVIDUAL:
        !           492:                case CMPCI_REVERSE:
        !           493:                case CMPCI_SURROUND:
        !           494:                default:
        !           495:                        v = 0;
        !           496:                        break;
        !           497:                }
        !           498:                sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v;
        !           499:                cmpci_set_mixer_gain(sc, i);
        !           500:        }
        !           501: }
        !           502:
        !           503: int
        !           504: cmpci_intr(void *handle)
        !           505: {
        !           506:        struct cmpci_softc *sc = handle;
        !           507:        uint32_t intrstat;
        !           508:
        !           509:        intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
        !           510:            CMPCI_REG_INTR_STATUS);
        !           511:
        !           512:        if (!(intrstat & CMPCI_REG_ANY_INTR))
        !           513:                return 0;
        !           514:
        !           515:        delay(10);
        !           516:
        !           517:        /* disable and reset intr */
        !           518:        if (intrstat & CMPCI_REG_CH0_INTR)
        !           519:                cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
        !           520:                   CMPCI_REG_CH0_INTR_ENABLE);
        !           521:        if (intrstat & CMPCI_REG_CH1_INTR)
        !           522:                cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
        !           523:                    CMPCI_REG_CH1_INTR_ENABLE);
        !           524:
        !           525:        if (intrstat & CMPCI_REG_CH0_INTR) {
        !           526:                if (sc->sc_play.intr != NULL)
        !           527:                        (*sc->sc_play.intr)(sc->sc_play.intr_arg);
        !           528:        }
        !           529:        if (intrstat & CMPCI_REG_CH1_INTR) {
        !           530:                if (sc->sc_rec.intr != NULL)
        !           531:                        (*sc->sc_rec.intr)(sc->sc_rec.intr_arg);
        !           532:        }
        !           533:
        !           534:        /* enable intr */
        !           535:        if (intrstat & CMPCI_REG_CH0_INTR)
        !           536:                cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
        !           537:                    CMPCI_REG_CH0_INTR_ENABLE);
        !           538:        if (intrstat & CMPCI_REG_CH1_INTR)
        !           539:                cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
        !           540:                    CMPCI_REG_CH1_INTR_ENABLE);
        !           541:
        !           542: #if 0
        !           543:        if (intrstat & CMPCI_REG_UART_INTR && sc->sc_mpudev != NULL)
        !           544:                mpu_intr(sc->sc_mpudev);
        !           545: #endif
        !           546:
        !           547:        return 1;
        !           548: }
        !           549:
        !           550: /* open/close */
        !           551: int
        !           552: cmpci_open(void *handle, int flags)
        !           553: {
        !           554:        return 0;
        !           555: }
        !           556:
        !           557: void
        !           558: cmpci_close(void *handle)
        !           559: {
        !           560: }
        !           561:
        !           562: int
        !           563: cmpci_query_encoding(void *handle, struct audio_encoding *fp)
        !           564: {
        !           565:        switch (fp->index) {
        !           566:        case 0:
        !           567:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
        !           568:                fp->encoding = AUDIO_ENCODING_ULINEAR;
        !           569:                fp->precision = 8;
        !           570:                fp->flags = 0;
        !           571:                break;
        !           572:        case 1:
        !           573:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
        !           574:                fp->encoding = AUDIO_ENCODING_ULAW;
        !           575:                fp->precision = 8;
        !           576:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           577:                break;
        !           578:        case 2:
        !           579:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
        !           580:                fp->encoding = AUDIO_ENCODING_ALAW;
        !           581:                fp->precision = 8;
        !           582:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           583:                break;
        !           584:        case 3:
        !           585:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
        !           586:                fp->encoding = AUDIO_ENCODING_SLINEAR;
        !           587:                fp->precision = 8;
        !           588:                fp->flags = 0;
        !           589:                break;
        !           590:        case 4:
        !           591:                strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
        !           592:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
        !           593:                fp->precision = 16;
        !           594:                fp->flags = 0;
        !           595:                break;
        !           596:        case 5:
        !           597:                strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
        !           598:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
        !           599:                fp->precision = 16;
        !           600:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           601:                break;
        !           602:        case 6:
        !           603:                strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
        !           604:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
        !           605:                fp->precision = 16;
        !           606:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           607:                break;
        !           608:        case 7:
        !           609:                strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
        !           610:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
        !           611:                fp->precision = 16;
        !           612:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           613:                break;
        !           614:        default:
        !           615:                return EINVAL;
        !           616:        }
        !           617:        return 0;
        !           618: }
        !           619:
        !           620: int
        !           621: cmpci_set_params(void *handle, int setmode, int usemode,
        !           622:     struct audio_params *play, struct audio_params *rec)
        !           623: {
        !           624:        int i;
        !           625:        struct cmpci_softc *sc = handle;
        !           626:
        !           627:        for (i = 0; i < 2; i++) {
        !           628:                int md_format;
        !           629:                int md_divide;
        !           630:                int md_index;
        !           631:                int mode;
        !           632:                struct audio_params *p;
        !           633:
        !           634:                switch (i) {
        !           635:                case 0:
        !           636:                        mode = AUMODE_PLAY;
        !           637:                        p = play;
        !           638:                        break;
        !           639:                case 1:
        !           640:                        mode = AUMODE_RECORD;
        !           641:                        p = rec;
        !           642:                        break;
        !           643:                default:
        !           644:                        return EINVAL;
        !           645:                }
        !           646:
        !           647:                if (!(setmode & mode))
        !           648:                        continue;
        !           649:
        !           650:                /* format */
        !           651:                p->sw_code = NULL;
        !           652:                switch (p->channels) {
        !           653:                case 1:
        !           654:                        md_format = CMPCI_REG_FORMAT_MONO;
        !           655:                        break;
        !           656:                case 2:
        !           657:                        md_format = CMPCI_REG_FORMAT_STEREO;
        !           658:                        break;
        !           659:                default:
        !           660:                        return (EINVAL);
        !           661:                }
        !           662:                switch (p->encoding) {
        !           663:                case AUDIO_ENCODING_ULAW:
        !           664:                        if (p->precision != 8)
        !           665:                                return (EINVAL);
        !           666:                        if (mode & AUMODE_PLAY) {
        !           667:                                p->factor = 2;
        !           668:                                p->sw_code = mulaw_to_slinear16_le;
        !           669:                                md_format |= CMPCI_REG_FORMAT_16BIT;
        !           670:                        } else {
        !           671:                                p->sw_code = ulinear8_to_mulaw;
        !           672:                                md_format |= CMPCI_REG_FORMAT_8BIT;
        !           673:                        }
        !           674:                        break;
        !           675:                case AUDIO_ENCODING_ALAW:
        !           676:                        if (p->precision != 8)
        !           677:                                return (EINVAL);
        !           678:                        if (mode & AUMODE_PLAY) {
        !           679:                                p->factor = 2;
        !           680:                                p->sw_code = alaw_to_slinear16_le;
        !           681:                                md_format |= CMPCI_REG_FORMAT_16BIT;
        !           682:                        } else {
        !           683:                                p->sw_code = ulinear8_to_alaw;
        !           684:                                md_format |= CMPCI_REG_FORMAT_8BIT;
        !           685:                        }
        !           686:                        break;
        !           687:                case AUDIO_ENCODING_SLINEAR_LE:
        !           688:                        switch (p->precision) {
        !           689:                        case 8:
        !           690:                                p->sw_code = change_sign8;
        !           691:                                md_format |= CMPCI_REG_FORMAT_8BIT;
        !           692:                                break;
        !           693:                        case 16:
        !           694:                                md_format |= CMPCI_REG_FORMAT_16BIT;
        !           695:                                break;
        !           696:                        default:
        !           697:                                return (EINVAL);
        !           698:                        }
        !           699:                        break;
        !           700:                case AUDIO_ENCODING_SLINEAR_BE:
        !           701:                        switch (p->precision) {
        !           702:                        case 8:
        !           703:                                md_format |= CMPCI_REG_FORMAT_8BIT;
        !           704:                                p->sw_code = change_sign8;
        !           705:                                break;
        !           706:                        case 16:
        !           707:                                md_format |= CMPCI_REG_FORMAT_16BIT;
        !           708:                                p->sw_code = swap_bytes;
        !           709:                                break;
        !           710:                        default:
        !           711:                                return (EINVAL);
        !           712:                        }
        !           713:                        break;
        !           714:                case AUDIO_ENCODING_ULINEAR_LE:
        !           715:                        switch (p->precision) {
        !           716:                        case 8:
        !           717:                                md_format |= CMPCI_REG_FORMAT_8BIT;
        !           718:                                break;
        !           719:                        case 16:
        !           720:                                md_format |= CMPCI_REG_FORMAT_16BIT;
        !           721:                                p->sw_code = change_sign16_le;
        !           722:                                break;
        !           723:                        default:
        !           724:                                return (EINVAL);
        !           725:                        }
        !           726:                        break;
        !           727:                case AUDIO_ENCODING_ULINEAR_BE:
        !           728:                        switch (p->precision) {
        !           729:                        case 8:
        !           730:                                md_format |= CMPCI_REG_FORMAT_8BIT;
        !           731:                                break;
        !           732:                        case 16:
        !           733:                                md_format |= CMPCI_REG_FORMAT_16BIT;
        !           734:                                if (mode & AUMODE_PLAY)
        !           735:                                        p->sw_code =
        !           736:                                            swap_bytes_change_sign16_le;
        !           737:                                else
        !           738:                                        p->sw_code =
        !           739:                                            change_sign16_swap_bytes_le;
        !           740:                                break;
        !           741:                        default:
        !           742:                                return (EINVAL);
        !           743:                        }
        !           744:                        break;
        !           745:                default:
        !           746:                        return (EINVAL);
        !           747:                }
        !           748:                if (mode & AUMODE_PLAY)
        !           749:                        cmpci_reg_partial_write_4(sc,
        !           750:                           CMPCI_REG_CHANNEL_FORMAT,
        !           751:                           CMPCI_REG_CH0_FORMAT_SHIFT,
        !           752:                           CMPCI_REG_CH0_FORMAT_MASK, md_format);
        !           753:                else
        !           754:                        cmpci_reg_partial_write_4(sc,
        !           755:                           CMPCI_REG_CHANNEL_FORMAT,
        !           756:                           CMPCI_REG_CH1_FORMAT_SHIFT,
        !           757:                           CMPCI_REG_CH1_FORMAT_MASK, md_format);
        !           758:                /* sample rate */
        !           759:                md_index = cmpci_rate_to_index(p->sample_rate);
        !           760:                md_divide = cmpci_index_to_divider(md_index);
        !           761:                p->sample_rate = cmpci_index_to_rate(md_index);
        !           762:                DPRINTF(("%s: sample:%d, divider=%d\n",
        !           763:                         sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
        !           764:                if (mode & AUMODE_PLAY) {
        !           765:                        cmpci_reg_partial_write_4(sc,
        !           766:                            CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT,
        !           767:                            CMPCI_REG_DAC_FS_MASK, md_divide);
        !           768:                        sc->sc_play.md_divide = md_divide;
        !           769:                } else {
        !           770:                        cmpci_reg_partial_write_4(sc,
        !           771:                            CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
        !           772:                            CMPCI_REG_ADC_FS_MASK, md_divide);
        !           773:                        sc->sc_rec.md_divide = md_divide;
        !           774:                }
        !           775:                cmpci_set_out_ports(sc);
        !           776:                cmpci_set_in_ports(sc);
        !           777:        }
        !           778:        return 0;
        !           779: }
        !           780:
        !           781: /* ARGSUSED */
        !           782: int
        !           783: cmpci_round_blocksize(void *handle, int block)
        !           784: {
        !           785:        return ((block + 3) & -4);
        !           786: }
        !           787:
        !           788: int
        !           789: cmpci_halt_output(void *handle)
        !           790: {
        !           791:        struct cmpci_softc *sc = handle;
        !           792:        int s;
        !           793:
        !           794:        s = splaudio();
        !           795:        sc->sc_play.intr = NULL;
        !           796:        cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
        !           797:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
        !           798:        /* wait for reset DMA */
        !           799:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
        !           800:        delay(10);
        !           801:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
        !           802:        splx(s);
        !           803:
        !           804:        return 0;
        !           805: }
        !           806:
        !           807: int
        !           808: cmpci_halt_input(void *handle)
        !           809: {
        !           810:        struct cmpci_softc *sc = handle;
        !           811:        int s;
        !           812:
        !           813:        s = splaudio();
        !           814:        sc->sc_rec.intr = NULL;
        !           815:        cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
        !           816:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
        !           817:        /* wait for reset DMA */
        !           818:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
        !           819:        delay(10);
        !           820:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
        !           821:        splx(s);
        !           822:
        !           823:        return 0;
        !           824: }
        !           825:
        !           826: /* get audio device information */
        !           827: int
        !           828: cmpci_getdev(void *handle, struct audio_device *ad)
        !           829: {
        !           830:        struct cmpci_softc *sc = handle;
        !           831:
        !           832:        strncpy(ad->name, "CMI PCI Audio", sizeof(ad->name));
        !           833:        snprintf(ad->version, sizeof(ad->version), "0x%02x",
        !           834:                 PCI_REVISION(sc->sc_class));
        !           835:        switch (PCI_PRODUCT(sc->sc_id)) {
        !           836:        case PCI_PRODUCT_CMI_CMI8338A:
        !           837:                strncpy(ad->config, "CMI8338A", sizeof(ad->config));
        !           838:                break;
        !           839:        case PCI_PRODUCT_CMI_CMI8338B:
        !           840:                strncpy(ad->config, "CMI8338B", sizeof(ad->config));
        !           841:                break;
        !           842:        case PCI_PRODUCT_CMI_CMI8738:
        !           843:                strncpy(ad->config, "CMI8738", sizeof(ad->config));
        !           844:                break;
        !           845:        case PCI_PRODUCT_CMI_CMI8738B:
        !           846:                strncpy(ad->config, "CMI8738B", sizeof(ad->config));
        !           847:                break;
        !           848:        default:
        !           849:                strncpy(ad->config, "unknown", sizeof(ad->config));
        !           850:        }
        !           851:
        !           852:        return 0;
        !           853: }
        !           854:
        !           855: /* mixer device information */
        !           856: int
        !           857: cmpci_query_devinfo(void *handle, mixer_devinfo_t *dip)
        !           858: {
        !           859:        static const char *const mixer_port_names[] = {
        !           860:                AudioNdac, AudioNfmsynth, AudioNcd, AudioNline, AudioNaux,
        !           861:                AudioNmicrophone
        !           862:        };
        !           863:        static const char *const mixer_classes[] = {
        !           864:                AudioCinputs, AudioCoutputs, AudioCrecord, CmpciCplayback,
        !           865:                CmpciCspdif
        !           866:        };
        !           867:        struct cmpci_softc *sc = handle;
        !           868:        int i;
        !           869:
        !           870:        dip->prev = dip->next = AUDIO_MIXER_LAST;
        !           871:
        !           872:        switch (dip->index) {
        !           873:        case CMPCI_INPUT_CLASS:
        !           874:        case CMPCI_OUTPUT_CLASS:
        !           875:        case CMPCI_RECORD_CLASS:
        !           876:        case CMPCI_PLAYBACK_CLASS:
        !           877:        case CMPCI_SPDIF_CLASS:
        !           878:                dip->type = AUDIO_MIXER_CLASS;
        !           879:                dip->mixer_class = dip->index;
        !           880:                strlcpy(dip->label.name,
        !           881:                    mixer_classes[dip->index - CMPCI_INPUT_CLASS],
        !           882:                    sizeof dip->label.name);
        !           883:                return 0;
        !           884:
        !           885:        case CMPCI_AUX_IN_VOL:
        !           886:                dip->un.v.delta = 1 << (8 - CMPCI_REG_AUX_VALBITS);
        !           887:                goto vol1;
        !           888:        case CMPCI_DAC_VOL:
        !           889:        case CMPCI_FM_VOL:
        !           890:        case CMPCI_CD_VOL:
        !           891:        case CMPCI_LINE_IN_VOL:
        !           892:        case CMPCI_MIC_VOL:
        !           893:                dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
        !           894:        vol1:   dip->mixer_class = CMPCI_INPUT_CLASS;
        !           895:                dip->next = dip->index + 6;     /* CMPCI_xxx_MUTE */
        !           896:                strlcpy(dip->label.name, mixer_port_names[dip->index],
        !           897:                    sizeof dip->label.name);
        !           898:                dip->un.v.num_channels = (dip->index == CMPCI_MIC_VOL ? 1 : 2);
        !           899:        vol:
        !           900:                dip->type = AUDIO_MIXER_VALUE;
        !           901:                strlcpy(dip->un.v.units.name, AudioNvolume,
        !           902:                    sizeof dip->un.v.units.name);
        !           903:                return 0;
        !           904:
        !           905:        case CMPCI_MIC_MUTE:
        !           906:                dip->next = CMPCI_MIC_PREAMP;
        !           907:                /* FALLTHROUGH */
        !           908:        case CMPCI_DAC_MUTE:
        !           909:        case CMPCI_FM_MUTE:
        !           910:        case CMPCI_CD_MUTE:
        !           911:        case CMPCI_LINE_IN_MUTE:
        !           912:        case CMPCI_AUX_IN_MUTE:
        !           913:                dip->prev = dip->index - 6;     /* CMPCI_xxx_VOL */
        !           914:                dip->mixer_class = CMPCI_INPUT_CLASS;
        !           915:                strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
        !           916:                goto on_off;
        !           917:        on_off:
        !           918:                dip->type = AUDIO_MIXER_ENUM;
        !           919:                dip->un.e.num_mem = 2;
        !           920:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
        !           921:                    sizeof dip->un.e.member[0].label.name);
        !           922:                dip->un.e.member[0].ord = 0;
        !           923:                strlcpy(dip->un.e.member[1].label.name, AudioNon,
        !           924:                    sizeof dip->un.e.member[1].label.name);
        !           925:                dip->un.e.member[1].ord = 1;
        !           926:                return 0;
        !           927:
        !           928:        case CMPCI_MIC_PREAMP:
        !           929:                dip->mixer_class = CMPCI_INPUT_CLASS;
        !           930:                dip->prev = CMPCI_MIC_MUTE;
        !           931:                strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name);
        !           932:                goto on_off;
        !           933:        case CMPCI_PCSPEAKER:
        !           934:                dip->mixer_class = CMPCI_INPUT_CLASS;
        !           935:                strlcpy(dip->label.name, AudioNspeaker, sizeof dip->label.name);
        !           936:                dip->un.v.num_channels = 1;
        !           937:                dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_SPEAKER_VALBITS);
        !           938:                goto vol;
        !           939:        case CMPCI_RECORD_SOURCE:
        !           940:                dip->mixer_class = CMPCI_RECORD_CLASS;
        !           941:                strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
        !           942:                dip->type = AUDIO_MIXER_SET;
        !           943:                dip->un.s.num_mem = 7;
        !           944:                strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone,
        !           945:                    sizeof dip->un.s.member[0].label.name);
        !           946:                dip->un.s.member[0].mask = CMPCI_RECORD_SOURCE_MIC;
        !           947:                strlcpy(dip->un.s.member[1].label.name, AudioNcd,
        !           948:                    sizeof dip->un.s.member[1].label.name);
        !           949:                dip->un.s.member[1].mask = CMPCI_RECORD_SOURCE_CD;
        !           950:                strlcpy(dip->un.s.member[2].label.name, AudioNline,
        !           951:                    sizeof dip->un.s.member[2].label.name);
        !           952:                dip->un.s.member[2].mask = CMPCI_RECORD_SOURCE_LINE_IN;
        !           953:                strlcpy(dip->un.s.member[3].label.name, AudioNaux,
        !           954:                    sizeof dip->un.s.member[3].label.name);
        !           955:                dip->un.s.member[3].mask = CMPCI_RECORD_SOURCE_AUX_IN;
        !           956:                strlcpy(dip->un.s.member[4].label.name, AudioNwave,
        !           957:                    sizeof dip->un.s.member[4].label.name);
        !           958:                dip->un.s.member[4].mask = CMPCI_RECORD_SOURCE_WAVE;
        !           959:                strlcpy(dip->un.s.member[5].label.name, AudioNfmsynth,
        !           960:                    sizeof dip->un.s.member[5].label.name);
        !           961:                dip->un.s.member[5].mask = CMPCI_RECORD_SOURCE_FM;
        !           962:                strlcpy(dip->un.s.member[6].label.name, CmpciNspdif,
        !           963:                    sizeof dip->un.s.member[6].label.name);
        !           964:                dip->un.s.member[6].mask = CMPCI_RECORD_SOURCE_SPDIF;
        !           965:                return 0;
        !           966:        case CMPCI_MIC_RECVOL:
        !           967:                dip->mixer_class = CMPCI_RECORD_CLASS;
        !           968:                strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
        !           969:                dip->un.v.num_channels = 1;
        !           970:                dip->un.v.delta = 1 << (8 - CMPCI_REG_ADMIC_VALBITS);
        !           971:                goto vol;
        !           972:
        !           973:        case CMPCI_PLAYBACK_MODE:
        !           974:                dip->mixer_class = CMPCI_PLAYBACK_CLASS;
        !           975:                dip->type = AUDIO_MIXER_ENUM;
        !           976:                strlcpy(dip->label.name, AudioNmode, sizeof dip->label.name);
        !           977:                dip->un.e.num_mem = 2;
        !           978:                strlcpy(dip->un.e.member[0].label.name, AudioNdac,
        !           979:                    sizeof dip->un.e.member[0].label.name);
        !           980:                dip->un.e.member[0].ord = CMPCI_PLAYBACK_MODE_WAVE;
        !           981:                strlcpy(dip->un.e.member[1].label.name, CmpciNspdif,
        !           982:                    sizeof dip->un.e.member[1].label.name);
        !           983:                dip->un.e.member[1].ord = CMPCI_PLAYBACK_MODE_SPDIF;
        !           984:                return 0;
        !           985:        case CMPCI_SPDIF_IN_SELECT:
        !           986:                dip->mixer_class = CMPCI_SPDIF_CLASS;
        !           987:                dip->type = AUDIO_MIXER_ENUM;
        !           988:                dip->next = CMPCI_SPDIF_IN_PHASE;
        !           989:                strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
        !           990:                i = 0;
        !           991:                strlcpy(dip->un.e.member[i].label.name, CmpciNspdin1,
        !           992:                    sizeof dip->un.e.member[i].label.name);
        !           993:                dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN1;
        !           994:                if (CMPCI_ISCAP(sc, 2ND_SPDIN)) {
        !           995:                        strlcpy(dip->un.e.member[i].label.name, CmpciNspdin2,
        !           996:                            sizeof dip->un.e.member[i].label.name);
        !           997:                        dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN2;
        !           998:                }
        !           999:                strlcpy(dip->un.e.member[i].label.name, CmpciNspdout,
        !          1000:                    sizeof dip->un.e.member[i].label.name);
        !          1001:                dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDOUT;
        !          1002:                dip->un.e.num_mem = i;
        !          1003:                return 0;
        !          1004:        case CMPCI_SPDIF_IN_PHASE:
        !          1005:                dip->mixer_class = CMPCI_SPDIF_CLASS;
        !          1006:                dip->prev = CMPCI_SPDIF_IN_SELECT;
        !          1007:                strlcpy(dip->label.name, CmpciNphase, sizeof dip->label.name);
        !          1008:                dip->type = AUDIO_MIXER_ENUM;
        !          1009:                dip->un.e.num_mem = 2;
        !          1010:                strlcpy(dip->un.e.member[0].label.name, CmpciNpositive,
        !          1011:                    sizeof dip->un.e.member[0].label.name);
        !          1012:                dip->un.e.member[0].ord = CMPCI_SPDIF_IN_PHASE_POSITIVE;
        !          1013:                strlcpy(dip->un.e.member[1].label.name, CmpciNnegative,
        !          1014:                    sizeof dip->un.e.member[1].label.name);
        !          1015:                dip->un.e.member[1].ord = CMPCI_SPDIF_IN_PHASE_NEGATIVE;
        !          1016:                return 0;
        !          1017:        case CMPCI_SPDIF_LOOP:
        !          1018:                dip->mixer_class = CMPCI_SPDIF_CLASS;
        !          1019:                dip->next = CMPCI_SPDIF_OUT_PLAYBACK;
        !          1020:                strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
        !          1021:                dip->type = AUDIO_MIXER_ENUM;
        !          1022:                dip->un.e.num_mem = 2;
        !          1023:                strlcpy(dip->un.e.member[0].label.name, CmpciNplayback,
        !          1024:                    sizeof dip->un.e.member[0].label.name);
        !          1025:                dip->un.e.member[0].ord = CMPCI_SPDIF_LOOP_OFF;
        !          1026:                strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
        !          1027:                    sizeof dip->un.e.member[1].label.name);
        !          1028:                dip->un.e.member[1].ord = CMPCI_SPDIF_LOOP_ON;
        !          1029:                return 0;
        !          1030:        case CMPCI_SPDIF_OUT_PLAYBACK:
        !          1031:                dip->mixer_class = CMPCI_SPDIF_CLASS;
        !          1032:                dip->prev = CMPCI_SPDIF_LOOP;
        !          1033:                dip->next = CMPCI_SPDIF_OUT_VOLTAGE;
        !          1034:                strlcpy(dip->label.name, CmpciNplayback, sizeof dip->label.name);
        !          1035:                dip->type = AUDIO_MIXER_ENUM;
        !          1036:                dip->un.e.num_mem = 2;
        !          1037:                strlcpy(dip->un.e.member[0].label.name, AudioNwave,
        !          1038:                    sizeof dip->un.e.member[0].label.name);
        !          1039:                dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_PLAYBACK_WAVE;
        !          1040:                strlcpy(dip->un.e.member[1].label.name, CmpciNlegacy,
        !          1041:                    sizeof dip->un.e.member[1].label.name);
        !          1042:                dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_PLAYBACK_LEGACY;
        !          1043:                return 0;
        !          1044:        case CMPCI_SPDIF_OUT_VOLTAGE:
        !          1045:                dip->mixer_class = CMPCI_SPDIF_CLASS;
        !          1046:                dip->prev = CMPCI_SPDIF_OUT_PLAYBACK;
        !          1047:                strlcpy(dip->label.name, CmpciNvoltage, sizeof dip->label.name);
        !          1048:                dip->type = AUDIO_MIXER_ENUM;
        !          1049:                dip->un.e.num_mem = 2;
        !          1050:                strlcpy(dip->un.e.member[0].label.name, CmpciNhigh_v,
        !          1051:                    sizeof dip->un.e.member[0].label.name);
        !          1052:                dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_VOLTAGE_HIGH;
        !          1053:                strlcpy(dip->un.e.member[1].label.name, CmpciNlow_v,
        !          1054:                    sizeof dip->un.e.member[1].label.name);
        !          1055:                dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_VOLTAGE_LOW;
        !          1056:                return 0;
        !          1057:        case CMPCI_MONITOR_DAC:
        !          1058:                dip->mixer_class = CMPCI_SPDIF_CLASS;
        !          1059:                strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
        !          1060:                dip->type = AUDIO_MIXER_ENUM;
        !          1061:                dip->un.e.num_mem = 3;
        !          1062:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
        !          1063:                    sizeof dip->un.e.member[0].label.name);
        !          1064:                dip->un.e.member[0].ord = CMPCI_MONITOR_DAC_OFF;
        !          1065:                strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
        !          1066:                    sizeof dip->un.e.member[1].label.name);
        !          1067:                dip->un.e.member[1].ord = CMPCI_MONITOR_DAC_SPDIN;
        !          1068:                strlcpy(dip->un.e.member[2].label.name, CmpciNspdout,
        !          1069:                    sizeof dip->un.e.member[2].label.name);
        !          1070:                dip->un.e.member[2].ord = CMPCI_MONITOR_DAC_SPDOUT;
        !          1071:                return 0;
        !          1072:
        !          1073:        case CMPCI_MASTER_VOL:
        !          1074:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
        !          1075:                strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
        !          1076:                dip->un.v.num_channels = 2;
        !          1077:                dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
        !          1078:                goto vol;
        !          1079:        case CMPCI_REAR:
        !          1080:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
        !          1081:                dip->next = CMPCI_INDIVIDUAL;
        !          1082:                strlcpy(dip->label.name, CmpciNrear, sizeof dip->label.name);
        !          1083:                goto on_off;
        !          1084:        case CMPCI_INDIVIDUAL:
        !          1085:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
        !          1086:                dip->prev = CMPCI_REAR;
        !          1087:                dip->next = CMPCI_REVERSE;
        !          1088:                strlcpy(dip->label.name, CmpciNindividual, sizeof dip->label.name);
        !          1089:                goto on_off;
        !          1090:        case CMPCI_REVERSE:
        !          1091:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
        !          1092:                dip->prev = CMPCI_INDIVIDUAL;
        !          1093:                strlcpy(dip->label.name, CmpciNreverse, sizeof dip->label.name);
        !          1094:                goto on_off;
        !          1095:        case CMPCI_SURROUND:
        !          1096:                dip->mixer_class = CMPCI_OUTPUT_CLASS;
        !          1097:                strlcpy(dip->label.name, CmpciNsurround, sizeof dip->label.name);
        !          1098:                goto on_off;
        !          1099:        }
        !          1100:
        !          1101:        return ENXIO;
        !          1102: }
        !          1103:
        !          1104: int
        !          1105: cmpci_alloc_dmamem(struct cmpci_softc *sc, size_t size, int type, int flags,
        !          1106:     caddr_t *r_addr)
        !          1107: {
        !          1108:        int error = 0;
        !          1109:        struct cmpci_dmanode *n;
        !          1110:        int w;
        !          1111:
        !          1112:        n = malloc(sizeof(struct cmpci_dmanode), type, flags);
        !          1113:        if (n == NULL) {
        !          1114:                error = ENOMEM;
        !          1115:                goto quit;
        !          1116:        }
        !          1117:
        !          1118:        w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
        !          1119: #define CMPCI_DMABUF_ALIGN    0x4
        !          1120: #define CMPCI_DMABUF_BOUNDARY 0x0
        !          1121:        n->cd_tag = sc->sc_dmat;
        !          1122:        n->cd_size = size;
        !          1123:        error = bus_dmamem_alloc(n->cd_tag, n->cd_size,
        !          1124:            CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs,
        !          1125:            sizeof(n->cd_segs)/sizeof(n->cd_segs[0]), &n->cd_nsegs, w);
        !          1126:        if (error)
        !          1127:                goto mfree;
        !          1128:        error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
        !          1129:            &n->cd_addr, w | BUS_DMA_COHERENT);
        !          1130:        if (error)
        !          1131:                goto dmafree;
        !          1132:        error = bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0,
        !          1133:            w, &n->cd_map);
        !          1134:        if (error)
        !          1135:                goto unmap;
        !          1136:        error = bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size,
        !          1137:            NULL, w);
        !          1138:        if (error)
        !          1139:                goto destroy;
        !          1140:
        !          1141:        n->cd_next = sc->sc_dmap;
        !          1142:        sc->sc_dmap = n;
        !          1143:        *r_addr = KVADDR(n);
        !          1144:        return 0;
        !          1145:
        !          1146:  destroy:
        !          1147:        bus_dmamap_destroy(n->cd_tag, n->cd_map);
        !          1148:  unmap:
        !          1149:        bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
        !          1150:  dmafree:
        !          1151:        bus_dmamem_free(n->cd_tag,
        !          1152:                        n->cd_segs, sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
        !          1153:  mfree:
        !          1154:        free(n, type);
        !          1155:  quit:
        !          1156:        return error;
        !          1157: }
        !          1158:
        !          1159: int
        !          1160: cmpci_free_dmamem(struct cmpci_softc *sc, caddr_t addr, int type)
        !          1161: {
        !          1162:        struct cmpci_dmanode **nnp;
        !          1163:
        !          1164:        for (nnp = &sc->sc_dmap; *nnp; nnp = &(*nnp)->cd_next) {
        !          1165:                if ((*nnp)->cd_addr == addr) {
        !          1166:                        struct cmpci_dmanode *n = *nnp;
        !          1167:                        bus_dmamap_unload(n->cd_tag, n->cd_map);
        !          1168:                        bus_dmamap_destroy(n->cd_tag, n->cd_map);
        !          1169:                        bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
        !          1170:                        bus_dmamem_free(n->cd_tag, n->cd_segs,
        !          1171:                            sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
        !          1172:                        free(n, type);
        !          1173:                        return 0;
        !          1174:                }
        !          1175:        }
        !          1176:        return -1;
        !          1177: }
        !          1178:
        !          1179: struct cmpci_dmanode *
        !          1180: cmpci_find_dmamem(struct cmpci_softc *sc, caddr_t addr)
        !          1181: {
        !          1182:        struct cmpci_dmanode *p;
        !          1183:
        !          1184:        for (p = sc->sc_dmap; p; p = p->cd_next) {
        !          1185:                if (KVADDR(p) == (void *)addr)
        !          1186:                        break;
        !          1187:        }
        !          1188:        return p;
        !          1189: }
        !          1190:
        !          1191: #if 0
        !          1192: void cmpci_print_dmamem(struct cmpci_dmanode *p);
        !          1193:
        !          1194: void
        !          1195: cmpci_print_dmamem(struct cmpci_dmanode *p)
        !          1196: {
        !          1197:        DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
        !          1198:                 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr,
        !          1199:                 (void *)DMAADDR(p), (void *)p->cd_size));
        !          1200: }
        !          1201: #endif /* DEBUG */
        !          1202:
        !          1203: void *
        !          1204: cmpci_malloc(void *handle, int direction, size_t size, int type,
        !          1205:     int flags)
        !          1206: {
        !          1207:        caddr_t addr;
        !          1208:
        !          1209:        if (cmpci_alloc_dmamem(handle, size, type, flags, &addr))
        !          1210:                return NULL;
        !          1211:        return addr;
        !          1212: }
        !          1213:
        !          1214: void
        !          1215: cmpci_free(void *handle, void *addr, int type)
        !          1216: {
        !          1217:        cmpci_free_dmamem(handle, addr, type);
        !          1218: }
        !          1219:
        !          1220: #define MAXVAL 256
        !          1221: int
        !          1222: cmpci_adjust(int val, int mask)
        !          1223: {
        !          1224:        val += (MAXVAL - mask) >> 1;
        !          1225:        if (val >= MAXVAL)
        !          1226:                val = MAXVAL-1;
        !          1227:        return val & mask;
        !          1228: }
        !          1229:
        !          1230: void
        !          1231: cmpci_set_mixer_gain(struct cmpci_softc *sc, int port)
        !          1232: {
        !          1233:        int src;
        !          1234:        int bits, mask;
        !          1235:
        !          1236:        switch (port) {
        !          1237:        case CMPCI_MIC_VOL:
        !          1238:                cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_MIC,
        !          1239:                    CMPCI_ADJUST_MIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
        !          1240:                return;
        !          1241:        case CMPCI_MASTER_VOL:
        !          1242:                src = CMPCI_SB16_MIXER_MASTER_L;
        !          1243:                break;
        !          1244:        case CMPCI_LINE_IN_VOL:
        !          1245:                src = CMPCI_SB16_MIXER_LINE_L;
        !          1246:                break;
        !          1247:        case CMPCI_AUX_IN_VOL:
        !          1248:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MIXER_AUX,
        !          1249:                    CMPCI_ADJUST_AUX_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT],
        !          1250:                                              sc->sc_gain[port][CMPCI_RIGHT]));
        !          1251:                return;
        !          1252:        case CMPCI_MIC_RECVOL:
        !          1253:                cmpci_reg_partial_write_1(sc, CMPCI_REG_MIXER25,
        !          1254:                    CMPCI_REG_ADMIC_SHIFT, CMPCI_REG_ADMIC_MASK,
        !          1255:                    CMPCI_ADJUST_ADMIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
        !          1256:                return;
        !          1257:        case CMPCI_DAC_VOL:
        !          1258:                src = CMPCI_SB16_MIXER_VOICE_L;
        !          1259:                break;
        !          1260:        case CMPCI_FM_VOL:
        !          1261:                src = CMPCI_SB16_MIXER_FM_L;
        !          1262:                break;
        !          1263:        case CMPCI_CD_VOL:
        !          1264:                src = CMPCI_SB16_MIXER_CDDA_L;
        !          1265:                break;
        !          1266:        case CMPCI_PCSPEAKER:
        !          1267:                cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
        !          1268:                    CMPCI_ADJUST_2_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
        !          1269:                return;
        !          1270:        case CMPCI_MIC_PREAMP:
        !          1271:                if (sc->sc_gain[port][CMPCI_LR])
        !          1272:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
        !          1273:                            CMPCI_REG_MICGAINZ);
        !          1274:                else
        !          1275:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
        !          1276:                            CMPCI_REG_MICGAINZ);
        !          1277:                return;
        !          1278:
        !          1279:        case CMPCI_DAC_MUTE:
        !          1280:                if (sc->sc_gain[port][CMPCI_LR])
        !          1281:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
        !          1282:                            CMPCI_REG_WSMUTE);
        !          1283:                else
        !          1284:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
        !          1285:                            CMPCI_REG_WSMUTE);
        !          1286:                return;
        !          1287:        case CMPCI_FM_MUTE:
        !          1288:                if (sc->sc_gain[port][CMPCI_LR])
        !          1289:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
        !          1290:                            CMPCI_REG_FMMUTE);
        !          1291:                else
        !          1292:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
        !          1293:                            CMPCI_REG_FMMUTE);
        !          1294:                return;
        !          1295:        case CMPCI_AUX_IN_MUTE:
        !          1296:                if (sc->sc_gain[port][CMPCI_LR])
        !          1297:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
        !          1298:                            CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
        !          1299:                else
        !          1300:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
        !          1301:                            CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
        !          1302:                return;
        !          1303:        case CMPCI_CD_MUTE:
        !          1304:                mask = CMPCI_SB16_SW_CD;
        !          1305:                goto sbmute;
        !          1306:        case CMPCI_MIC_MUTE:
        !          1307:                mask = CMPCI_SB16_SW_MIC;
        !          1308:                goto sbmute;
        !          1309:        case CMPCI_LINE_IN_MUTE:
        !          1310:                mask = CMPCI_SB16_SW_LINE;
        !          1311:        sbmute:
        !          1312:                bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
        !          1313:                if (sc->sc_gain[port][CMPCI_LR])
        !          1314:                        bits = bits & ~mask;
        !          1315:                else
        !          1316:                        bits = bits | mask;
        !          1317:                cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits);
        !          1318:                return;
        !          1319:
        !          1320:        case CMPCI_SPDIF_IN_SELECT:
        !          1321:        case CMPCI_MONITOR_DAC:
        !          1322:        case CMPCI_PLAYBACK_MODE:
        !          1323:        case CMPCI_SPDIF_LOOP:
        !          1324:        case CMPCI_SPDIF_OUT_PLAYBACK:
        !          1325:                cmpci_set_out_ports(sc);
        !          1326:                return;
        !          1327:        case CMPCI_SPDIF_OUT_VOLTAGE:
        !          1328:                if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) {
        !          1329:                        if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR]
        !          1330:                            == CMPCI_SPDIF_OUT_VOLTAGE_HIGH)
        !          1331:                                cmpci_reg_clear_reg_misc(sc, CMPCI_REG_5V);
        !          1332:                        else
        !          1333:                                cmpci_reg_set_reg_misc(sc, CMPCI_REG_5V);
        !          1334:                }
        !          1335:                return;
        !          1336:        case CMPCI_SURROUND:
        !          1337:                if (CMPCI_ISCAP(sc, SURROUND)) {
        !          1338:                        if (sc->sc_gain[CMPCI_SURROUND][CMPCI_LR])
        !          1339:                                cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
        !          1340:                                                CMPCI_REG_SURROUND);
        !          1341:                        else
        !          1342:                                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
        !          1343:                                                  CMPCI_REG_SURROUND);
        !          1344:                }
        !          1345:                return;
        !          1346:        case CMPCI_REAR:
        !          1347:                if (CMPCI_ISCAP(sc, REAR)) {
        !          1348:                        if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
        !          1349:                                cmpci_reg_set_reg_misc(sc, CMPCI_REG_N4SPK3D);
        !          1350:                        else
        !          1351:                                cmpci_reg_clear_reg_misc(sc, CMPCI_REG_N4SPK3D);
        !          1352:                }
        !          1353:                return;
        !          1354:        case CMPCI_INDIVIDUAL:
        !          1355:                if (CMPCI_ISCAP(sc, INDIVIDUAL_REAR)) {
        !          1356:                        if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
        !          1357:                                cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
        !          1358:                                                CMPCI_REG_INDIVIDUAL);
        !          1359:                        else
        !          1360:                                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
        !          1361:                                                  CMPCI_REG_INDIVIDUAL);
        !          1362:                }
        !          1363:                return;
        !          1364:        case CMPCI_REVERSE:
        !          1365:                if (CMPCI_ISCAP(sc, REVERSE_FR)) {
        !          1366:                        if (sc->sc_gain[CMPCI_REVERSE][CMPCI_LR])
        !          1367:                                cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
        !          1368:                                                CMPCI_REG_REVERSE_FR);
        !          1369:                        else
        !          1370:                                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
        !          1371:                                                  CMPCI_REG_REVERSE_FR);
        !          1372:                }
        !          1373:                return;
        !          1374:        case CMPCI_SPDIF_IN_PHASE:
        !          1375:                if (CMPCI_ISCAP(sc, SPDIN_PHASE)) {
        !          1376:                        if (sc->sc_gain[CMPCI_SPDIF_IN_PHASE][CMPCI_LR]
        !          1377:                            == CMPCI_SPDIF_IN_PHASE_POSITIVE)
        !          1378:                                cmpci_reg_clear_1(sc, CMPCI_REG_CHANNEL_FORMAT,
        !          1379:                                                  CMPCI_REG_SPDIN_PHASE);
        !          1380:                        else
        !          1381:                                cmpci_reg_set_1(sc, CMPCI_REG_CHANNEL_FORMAT,
        !          1382:                                                CMPCI_REG_SPDIN_PHASE);
        !          1383:                }
        !          1384:                return;
        !          1385:        default:
        !          1386:                return;
        !          1387:        }
        !          1388:
        !          1389:        cmpci_mixerreg_write(sc, src,
        !          1390:            CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT]));
        !          1391:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
        !          1392:            CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_RIGHT]));
        !          1393: }
        !          1394:
        !          1395: void
        !          1396: cmpci_set_out_ports(struct cmpci_softc *sc)
        !          1397: {
        !          1398:        u_int8_t v;
        !          1399:        int enspdout = 0;
        !          1400:
        !          1401:        if (!CMPCI_ISCAP(sc, SPDLOOP))
        !          1402:                return;
        !          1403:
        !          1404:        /* SPDIF/out select */
        !          1405:        if (sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR] == CMPCI_SPDIF_LOOP_OFF) {
        !          1406:                /* playback */
        !          1407:                cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
        !          1408:        } else {
        !          1409:                /* monitor SPDIF/in */
        !          1410:                cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
        !          1411:        }
        !          1412:
        !          1413:        /* SPDIF in select */
        !          1414:        v = sc->sc_gain[CMPCI_SPDIF_IN_SELECT][CMPCI_LR];
        !          1415:        if (v & CMPCI_SPDIFIN_SPDIFIN2)
        !          1416:                cmpci_reg_set_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
        !          1417:        else
        !          1418:                cmpci_reg_clear_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
        !          1419:        if (v & CMPCI_SPDIFIN_SPDIFOUT)
        !          1420:                cmpci_reg_set_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
        !          1421:        else
        !          1422:                cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
        !          1423:
        !          1424:        /* playback to ... */
        !          1425:        if (CMPCI_ISCAP(sc, SPDOUT) &&
        !          1426:            sc->sc_gain[CMPCI_PLAYBACK_MODE][CMPCI_LR]
        !          1427:                == CMPCI_PLAYBACK_MODE_SPDIF &&
        !          1428:            (sc->sc_play.md_divide == CMPCI_REG_RATE_44100 ||
        !          1429:                (CMPCI_ISCAP(sc, SPDOUT_48K) &&
        !          1430:                    sc->sc_play.md_divide==CMPCI_REG_RATE_48000))) {
        !          1431:                /* playback to SPDIF */
        !          1432:                cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF0_ENABLE);
        !          1433:                enspdout = 1;
        !          1434:                if (sc->sc_play.md_divide==CMPCI_REG_RATE_48000)
        !          1435:                        cmpci_reg_set_reg_misc(sc,
        !          1436:                                CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
        !          1437:                else
        !          1438:                        cmpci_reg_clear_reg_misc(sc,
        !          1439:                                CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
        !          1440:        } else {
        !          1441:                /* playback to DAC */
        !          1442:                cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
        !          1443:                                  CMPCI_REG_SPDIF0_ENABLE);
        !          1444:                if (CMPCI_ISCAP(sc, SPDOUT_48K))
        !          1445:                        cmpci_reg_clear_reg_misc(sc,
        !          1446:                                CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
        !          1447:        }
        !          1448:
        !          1449:        /* legacy to SPDIF/out or not */
        !          1450:        if (CMPCI_ISCAP(sc, SPDLEGACY)) {
        !          1451:                if (sc->sc_gain[CMPCI_SPDIF_OUT_PLAYBACK][CMPCI_LR]
        !          1452:                    == CMPCI_SPDIF_OUT_PLAYBACK_WAVE)
        !          1453:                        cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
        !          1454:                                        CMPCI_REG_LEGACY_SPDIF_ENABLE);
        !          1455:                else {
        !          1456:                        cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
        !          1457:                                        CMPCI_REG_LEGACY_SPDIF_ENABLE);
        !          1458:                        enspdout = 1;
        !          1459:                }
        !          1460:        }
        !          1461:
        !          1462:        /* enable/disable SPDIF/out */
        !          1463:        if (CMPCI_ISCAP(sc, XSPDOUT) && enspdout)
        !          1464:                cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
        !          1465:                                CMPCI_REG_XSPDIF_ENABLE);
        !          1466:        else
        !          1467:                cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
        !          1468:                                CMPCI_REG_XSPDIF_ENABLE);
        !          1469:
        !          1470:        /* SPDIF monitor (digital to analog output) */
        !          1471:        if (CMPCI_ISCAP(sc, SPDIN_MONITOR)) {
        !          1472:                v = sc->sc_gain[CMPCI_MONITOR_DAC][CMPCI_LR];
        !          1473:                if (!(v & CMPCI_MONDAC_ENABLE))
        !          1474:                        cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
        !          1475:                                        CMPCI_REG_SPDIN_MONITOR);
        !          1476:                if (v & CMPCI_MONDAC_SPDOUT)
        !          1477:                        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
        !          1478:                                        CMPCI_REG_SPDIFOUT_DAC);
        !          1479:                else
        !          1480:                        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
        !          1481:                                        CMPCI_REG_SPDIFOUT_DAC);
        !          1482:                if (v & CMPCI_MONDAC_ENABLE)
        !          1483:                        cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
        !          1484:                                        CMPCI_REG_SPDIN_MONITOR);
        !          1485:        }
        !          1486: }
        !          1487:
        !          1488: int
        !          1489: cmpci_set_in_ports(struct cmpci_softc *sc)
        !          1490: {
        !          1491:        int mask;
        !          1492:        int bitsl, bitsr;
        !          1493:
        !          1494:        mask = sc->sc_in_mask;
        !          1495:
        !          1496:        /*
        !          1497:         * Note CMPCI_RECORD_SOURCE_CD, CMPCI_RECORD_SOURCE_LINE_IN and
        !          1498:         * CMPCI_RECORD_SOURCE_FM are defined to the corresponding bit
        !          1499:         * of the mixer register.
        !          1500:         */
        !          1501:        bitsr = mask & (CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
        !          1502:            CMPCI_RECORD_SOURCE_FM);
        !          1503:
        !          1504:        bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
        !          1505:        if (mask & CMPCI_RECORD_SOURCE_MIC) {
        !          1506:                bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
        !          1507:                bitsr |= CMPCI_SB16_MIXER_MIC_SRC;
        !          1508:        }
        !          1509:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
        !          1510:        cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
        !          1511:
        !          1512:        if (mask & CMPCI_RECORD_SOURCE_AUX_IN)
        !          1513:                cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
        !          1514:                    CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
        !          1515:        else
        !          1516:                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
        !          1517:                    CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
        !          1518:
        !          1519:        if (mask & CMPCI_RECORD_SOURCE_WAVE)
        !          1520:                cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
        !          1521:                    CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
        !          1522:        else
        !          1523:                cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
        !          1524:                    CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
        !          1525:
        !          1526:        if (CMPCI_ISCAP(sc, SPDIN) &&
        !          1527:            (sc->sc_rec.md_divide == CMPCI_REG_RATE_44100 ||
        !          1528:                (CMPCI_ISCAP(sc, SPDOUT_48K) &&
        !          1529:                    sc->sc_rec.md_divide == CMPCI_REG_RATE_48000/* XXX? */))) {
        !          1530:                if (mask & CMPCI_RECORD_SOURCE_SPDIF) {
        !          1531:                        /* enable SPDIF/in */
        !          1532:                        cmpci_reg_set_4(sc,
        !          1533:                                        CMPCI_REG_FUNC_1,
        !          1534:                                        CMPCI_REG_SPDIF1_ENABLE);
        !          1535:                } else {
        !          1536:                        cmpci_reg_clear_4(sc,
        !          1537:                                        CMPCI_REG_FUNC_1,
        !          1538:                                        CMPCI_REG_SPDIF1_ENABLE);
        !          1539:                }
        !          1540:        }
        !          1541:
        !          1542:        return 0;
        !          1543: }
        !          1544:
        !          1545: int
        !          1546: cmpci_set_port(void *handle, mixer_ctrl_t *cp)
        !          1547: {
        !          1548:        struct cmpci_softc *sc = handle;
        !          1549:        int lgain, rgain;
        !          1550:
        !          1551:        switch (cp->dev) {
        !          1552:        case CMPCI_MIC_VOL:
        !          1553:        case CMPCI_PCSPEAKER:
        !          1554:        case CMPCI_MIC_RECVOL:
        !          1555:                if (cp->un.value.num_channels != 1)
        !          1556:                        return EINVAL;
        !          1557:                /* FALLTHROUGH */
        !          1558:        case CMPCI_DAC_VOL:
        !          1559:        case CMPCI_FM_VOL:
        !          1560:        case CMPCI_CD_VOL:
        !          1561:        case CMPCI_LINE_IN_VOL:
        !          1562:        case CMPCI_AUX_IN_VOL:
        !          1563:        case CMPCI_MASTER_VOL:
        !          1564:                if (cp->type != AUDIO_MIXER_VALUE)
        !          1565:                        return EINVAL;
        !          1566:                switch (cp->un.value.num_channels) {
        !          1567:                case 1:
        !          1568:                        lgain = rgain =
        !          1569:                            cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
        !          1570:                        break;
        !          1571:                case 2:
        !          1572:                        lgain = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
        !          1573:                        rgain = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
        !          1574:                        break;
        !          1575:                default:
        !          1576:                        return EINVAL;
        !          1577:                }
        !          1578:                sc->sc_gain[cp->dev][CMPCI_LEFT]  = lgain;
        !          1579:                sc->sc_gain[cp->dev][CMPCI_RIGHT] = rgain;
        !          1580:
        !          1581:                cmpci_set_mixer_gain(sc, cp->dev);
        !          1582:                break;
        !          1583:
        !          1584:        case CMPCI_RECORD_SOURCE:
        !          1585:                if (cp->type != AUDIO_MIXER_SET)
        !          1586:                        return EINVAL;
        !          1587:
        !          1588:                if (cp->un.mask & ~(CMPCI_RECORD_SOURCE_MIC |
        !          1589:                    CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
        !          1590:                    CMPCI_RECORD_SOURCE_AUX_IN | CMPCI_RECORD_SOURCE_WAVE |
        !          1591:                    CMPCI_RECORD_SOURCE_FM | CMPCI_RECORD_SOURCE_SPDIF))
        !          1592:                        return EINVAL;
        !          1593:
        !          1594:                if (cp->un.mask & CMPCI_RECORD_SOURCE_SPDIF)
        !          1595:                        cp->un.mask = CMPCI_RECORD_SOURCE_SPDIF;
        !          1596:
        !          1597:                sc->sc_in_mask = cp->un.mask;
        !          1598:                return cmpci_set_in_ports(sc);
        !          1599:
        !          1600:        /* boolean */
        !          1601:        case CMPCI_DAC_MUTE:
        !          1602:        case CMPCI_FM_MUTE:
        !          1603:        case CMPCI_CD_MUTE:
        !          1604:        case CMPCI_LINE_IN_MUTE:
        !          1605:        case CMPCI_AUX_IN_MUTE:
        !          1606:        case CMPCI_MIC_MUTE:
        !          1607:        case CMPCI_MIC_PREAMP:
        !          1608:        case CMPCI_PLAYBACK_MODE:
        !          1609:        case CMPCI_SPDIF_IN_PHASE:
        !          1610:        case CMPCI_SPDIF_LOOP:
        !          1611:        case CMPCI_SPDIF_OUT_PLAYBACK:
        !          1612:        case CMPCI_SPDIF_OUT_VOLTAGE:
        !          1613:        case CMPCI_REAR:
        !          1614:        case CMPCI_INDIVIDUAL:
        !          1615:        case CMPCI_REVERSE:
        !          1616:        case CMPCI_SURROUND:
        !          1617:                if (cp->type != AUDIO_MIXER_ENUM)
        !          1618:                        return EINVAL;
        !          1619:                sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
        !          1620:                cmpci_set_mixer_gain(sc, cp->dev);
        !          1621:                break;
        !          1622:
        !          1623:        case CMPCI_SPDIF_IN_SELECT:
        !          1624:                switch (cp->un.ord) {
        !          1625:                case CMPCI_SPDIF_IN_SPDIN1:
        !          1626:                case CMPCI_SPDIF_IN_SPDIN2:
        !          1627:                case CMPCI_SPDIF_IN_SPDOUT:
        !          1628:                        break;
        !          1629:                default:
        !          1630:                        return EINVAL;
        !          1631:                }
        !          1632:                goto xenum;
        !          1633:        case CMPCI_MONITOR_DAC:
        !          1634:                switch (cp->un.ord) {
        !          1635:                case CMPCI_MONITOR_DAC_OFF:
        !          1636:                case CMPCI_MONITOR_DAC_SPDIN:
        !          1637:                case CMPCI_MONITOR_DAC_SPDOUT:
        !          1638:                        break;
        !          1639:                default:
        !          1640:                        return EINVAL;
        !          1641:                }
        !          1642:        xenum:
        !          1643:                if (cp->type != AUDIO_MIXER_ENUM)
        !          1644:                        return EINVAL;
        !          1645:                sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord;
        !          1646:                cmpci_set_mixer_gain(sc, cp->dev);
        !          1647:                break;
        !          1648:
        !          1649:        default:
        !          1650:            return EINVAL;
        !          1651:        }
        !          1652:
        !          1653:        return 0;
        !          1654: }
        !          1655:
        !          1656: int
        !          1657: cmpci_get_port(void *handle, mixer_ctrl_t *cp)
        !          1658: {
        !          1659:        struct cmpci_softc *sc = handle;
        !          1660:
        !          1661:        switch (cp->dev) {
        !          1662:        case CMPCI_MIC_VOL:
        !          1663:        case CMPCI_PCSPEAKER:
        !          1664:        case CMPCI_MIC_RECVOL:
        !          1665:                if (cp->un.value.num_channels != 1)
        !          1666:                        return EINVAL;
        !          1667:                /*FALLTHROUGH*/
        !          1668:        case CMPCI_DAC_VOL:
        !          1669:        case CMPCI_FM_VOL:
        !          1670:        case CMPCI_CD_VOL:
        !          1671:        case CMPCI_LINE_IN_VOL:
        !          1672:        case CMPCI_AUX_IN_VOL:
        !          1673:        case CMPCI_MASTER_VOL:
        !          1674:                switch (cp->un.value.num_channels) {
        !          1675:                case 1:
        !          1676:                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
        !          1677:                                sc->sc_gain[cp->dev][CMPCI_LEFT];
        !          1678:                        break;
        !          1679:                case 2:
        !          1680:                        cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
        !          1681:                                sc->sc_gain[cp->dev][CMPCI_LEFT];
        !          1682:                        cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
        !          1683:                                sc->sc_gain[cp->dev][CMPCI_RIGHT];
        !          1684:                        break;
        !          1685:                default:
        !          1686:                        return EINVAL;
        !          1687:                }
        !          1688:                break;
        !          1689:
        !          1690:        case CMPCI_RECORD_SOURCE:
        !          1691:                cp->un.mask = sc->sc_in_mask;
        !          1692:                break;
        !          1693:
        !          1694:        case CMPCI_DAC_MUTE:
        !          1695:        case CMPCI_FM_MUTE:
        !          1696:        case CMPCI_CD_MUTE:
        !          1697:        case CMPCI_LINE_IN_MUTE:
        !          1698:        case CMPCI_AUX_IN_MUTE:
        !          1699:        case CMPCI_MIC_MUTE:
        !          1700:        case CMPCI_MIC_PREAMP:
        !          1701:        case CMPCI_PLAYBACK_MODE:
        !          1702:        case CMPCI_SPDIF_IN_SELECT:
        !          1703:        case CMPCI_SPDIF_IN_PHASE:
        !          1704:        case CMPCI_SPDIF_LOOP:
        !          1705:        case CMPCI_SPDIF_OUT_PLAYBACK:
        !          1706:        case CMPCI_SPDIF_OUT_VOLTAGE:
        !          1707:        case CMPCI_MONITOR_DAC:
        !          1708:        case CMPCI_REAR:
        !          1709:        case CMPCI_INDIVIDUAL:
        !          1710:        case CMPCI_REVERSE:
        !          1711:        case CMPCI_SURROUND:
        !          1712:                cp->un.ord = sc->sc_gain[cp->dev][CMPCI_LR];
        !          1713:                break;
        !          1714:
        !          1715:        default:
        !          1716:                return EINVAL;
        !          1717:        }
        !          1718:
        !          1719:        return 0;
        !          1720: }
        !          1721:
        !          1722: /* ARGSUSED */
        !          1723: size_t
        !          1724: cmpci_round_buffersize(void *handle, int direction, size_t bufsize)
        !          1725: {
        !          1726:        if (bufsize > 0x10000)
        !          1727:                bufsize = 0x10000;
        !          1728:
        !          1729:        return bufsize;
        !          1730: }
        !          1731:
        !          1732: paddr_t
        !          1733: cmpci_mappage(void *handle, void *addr, off_t offset, int prot)
        !          1734: {
        !          1735:        struct cmpci_softc *sc = handle;
        !          1736:        struct cmpci_dmanode *p;
        !          1737:
        !          1738:        if (offset < 0 || NULL == (p = cmpci_find_dmamem(sc, addr)))
        !          1739:                return -1;
        !          1740:
        !          1741:        return bus_dmamem_mmap(p->cd_tag, p->cd_segs,
        !          1742:                   sizeof(p->cd_segs)/sizeof(p->cd_segs[0]),
        !          1743:                   offset, prot, BUS_DMA_WAITOK);
        !          1744: }
        !          1745:
        !          1746: /* ARGSUSED */
        !          1747: int
        !          1748: cmpci_get_props(void *handle)
        !          1749: {
        !          1750:        return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
        !          1751: }
        !          1752:
        !          1753: int
        !          1754: cmpci_trigger_output(void *handle, void *start, void *end, int blksize,
        !          1755:     void (*intr)(void *), void *arg, struct audio_params *param)
        !          1756: {
        !          1757:        struct cmpci_softc *sc = handle;
        !          1758:        struct cmpci_dmanode *p;
        !          1759:        int bps;
        !          1760:
        !          1761:        sc->sc_play.intr = intr;
        !          1762:        sc->sc_play.intr_arg = arg;
        !          1763:        bps = param->channels * param->precision * param->factor / 8;
        !          1764:        if (!bps)
        !          1765:                return EINVAL;
        !          1766:
        !          1767:        /* set DMA frame */
        !          1768:        if (!(p = cmpci_find_dmamem(sc, start)))
        !          1769:                return EINVAL;
        !          1770:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE,
        !          1771:            DMAADDR(p));
        !          1772:        delay(10);
        !          1773:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES,
        !          1774:            ((caddr_t)end - (caddr_t)start + 1) / bps - 1);
        !          1775:        delay(10);
        !          1776:
        !          1777:        /* set interrupt count */
        !          1778:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES,
        !          1779:                          (blksize + bps - 1) / bps - 1);
        !          1780:        delay(10);
        !          1781:
        !          1782:        /* start DMA */
        !          1783:        cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */
        !          1784:        cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
        !          1785:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
        !          1786:
        !          1787:        return 0;
        !          1788: }
        !          1789:
        !          1790: int
        !          1791: cmpci_trigger_input(void *handle, void *start, void *end, int blksize,
        !          1792:     void (*intr)(void *), void *arg, struct audio_params *param)
        !          1793: {
        !          1794:        struct cmpci_softc *sc = handle;
        !          1795:        struct cmpci_dmanode *p;
        !          1796:        int bps;
        !          1797:
        !          1798:        sc->sc_rec.intr = intr;
        !          1799:        sc->sc_rec.intr_arg = arg;
        !          1800:        bps = param->channels*param->precision*param->factor/8;
        !          1801:        if (!bps)
        !          1802:                return EINVAL;
        !          1803:
        !          1804:        /* set DMA frame */
        !          1805:        if (!(p = cmpci_find_dmamem(sc, start)))
        !          1806:                return EINVAL;
        !          1807:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE,
        !          1808:            DMAADDR(p));
        !          1809:        delay(10);
        !          1810:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
        !          1811:            ((caddr_t)end - (caddr_t)start + 1) / bps - 1);
        !          1812:        delay(10);
        !          1813:
        !          1814:        /* set interrupt count */
        !          1815:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
        !          1816:            (blksize + bps - 1) / bps - 1);
        !          1817:        delay(10);
        !          1818:
        !          1819:        /* start DMA */
        !          1820:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
        !          1821:        cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
        !          1822:        cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
        !          1823:
        !          1824:        return 0;
        !          1825: }
        !          1826:
        !          1827: /* end of file */

CVSweb