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

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

1.1     ! nbrk        1: /*     $OpenBSD: autri.c,v 1.20 2007/05/26 00:36:03 krw Exp $  */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2001 SOMEYA Yoshihiko and KUROSAWA Takahiro.
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  *
        !            16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            26:  */
        !            27:
        !            28: /*
        !            29:  * Trident 4DWAVE-DX/NX, SiS 7018, ALi M5451 Sound Driver
        !            30:  *
        !            31:  * The register information is taken from the ALSA driver.
        !            32:  *
        !            33:  * Documentation links:
        !            34:  * - ftp://ftp.alsa-project.org/pub/manuals/trident/
        !            35:  */
        !            36:
        !            37: #include "midi.h"
        !            38:
        !            39: #include <sys/param.h>
        !            40: #include <sys/systm.h>
        !            41: #include <sys/kernel.h>
        !            42: #include <sys/fcntl.h>
        !            43: #include <sys/malloc.h>
        !            44: #include <sys/device.h>
        !            45: #include <sys/proc.h>
        !            46:
        !            47: #include <dev/pci/pcidevs.h>
        !            48: #include <dev/pci/pcireg.h>
        !            49: #include <dev/pci/pcivar.h>
        !            50:
        !            51: #include <sys/audioio.h>
        !            52: #include <dev/audio_if.h>
        !            53: #include <dev/midi_if.h>
        !            54: #include <dev/mulaw.h>
        !            55: #include <dev/auconv.h>
        !            56: #include <dev/ic/ac97.h>
        !            57: #include <dev/ic/mpuvar.h>
        !            58:
        !            59: #include <machine/bus.h>
        !            60: #include <machine/intr.h>
        !            61:
        !            62: #include <dev/pci/autrireg.h>
        !            63: #include <dev/pci/autrivar.h>
        !            64:
        !            65: #ifdef AUDIO_DEBUG
        !            66: # define DPRINTF(x)    if (autridebug) printf x
        !            67: # define DPRINTFN(n,x) if (autridebug > (n)) printf x
        !            68: int autridebug = 0;
        !            69: #else
        !            70: # define DPRINTF(x)
        !            71: # define DPRINTFN(n,x)
        !            72: #endif
        !            73:
        !            74: int    autri_match(struct device *, void *, void *);
        !            75: void   autri_attach(struct device *, struct device *, void *);
        !            76: int    autri_intr(void *);
        !            77:
        !            78: #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
        !            79: #define KERNADDR(p) ((void *)((p)->addr))
        !            80:
        !            81: int autri_allocmem(struct autri_softc *, size_t, size_t, struct autri_dma *);
        !            82: int autri_freemem(struct autri_softc *, struct autri_dma *);
        !            83:
        !            84: #define TWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))
        !            85: #define TWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))
        !            86: #define TWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))
        !            87: #define TREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r))
        !            88: #define TREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r))
        !            89: #define TREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r))
        !            90:
        !            91: static __inline void autri_reg_set_1(struct autri_softc *, int, uint8_t);
        !            92: static __inline void autri_reg_clear_1(struct autri_softc *, int, uint8_t);
        !            93: static __inline void autri_reg_set_4(struct autri_softc *, int, uint32_t);
        !            94: static __inline void autri_reg_clear_4(struct autri_softc *, int, uint32_t);
        !            95:
        !            96: int    autri_attach_codec(void *sc, struct ac97_codec_if *);
        !            97: int    autri_read_codec(void *sc, u_int8_t a, u_int16_t *d);
        !            98: int    autri_write_codec(void *sc, u_int8_t a, u_int16_t d);
        !            99: void   autri_reset_codec(void *sc);
        !           100: enum ac97_host_flags   autri_flags_codec(void *);
        !           101:
        !           102: void autri_powerhook(int why,void *addr);
        !           103: int  autri_init(void *sc);
        !           104: struct autri_dma *autri_find_dma(struct autri_softc *, void *);
        !           105: void autri_setup_channel(struct autri_softc *sc,int mode,
        !           106:                                    struct audio_params *param);
        !           107: void autri_enable_interrupt(struct autri_softc *sc, int ch);
        !           108: void autri_disable_interrupt(struct autri_softc *sc, int ch);
        !           109: void autri_startch(struct autri_softc *sc, int ch, int ch_intr);
        !           110: void autri_stopch(struct autri_softc *sc, int ch, int ch_intr);
        !           111: void autri_enable_loop_interrupt(void *sc);
        !           112: #if 0
        !           113: void autri_disable_loop_interrupt(void *sc);
        !           114: #endif
        !           115:
        !           116: struct cfdriver autri_cd = {
        !           117:        NULL, "autri", DV_DULL
        !           118: };
        !           119:
        !           120: struct cfattach autri_ca = {
        !           121:        sizeof(struct autri_softc), autri_match, autri_attach
        !           122: };
        !           123:
        !           124: int    autri_open(void *, int);
        !           125: void   autri_close(void *);
        !           126: int    autri_query_encoding(void *, struct audio_encoding *);
        !           127: int    autri_set_params(void *, int, int, struct audio_params *,
        !           128:            struct audio_params *);
        !           129: int    autri_round_blocksize(void *, int);
        !           130: int    autri_trigger_output(void *, void *, void *, int, void (*)(void *),
        !           131:            void *, struct audio_params *);
        !           132: int    autri_trigger_input(void *, void *, void *, int, void (*)(void *),
        !           133:            void *, struct audio_params *);
        !           134: int    autri_halt_output(void *);
        !           135: int    autri_halt_input(void *);
        !           136: int    autri_getdev(void *, struct audio_device *);
        !           137: int    autri_mixer_set_port(void *, mixer_ctrl_t *);
        !           138: int    autri_mixer_get_port(void *, mixer_ctrl_t *);
        !           139: void   *autri_malloc(void *, int, size_t, int, int);
        !           140: void   autri_free(void *, void *, int);
        !           141: paddr_t        autri_mappage(void *, void *, off_t, int);
        !           142: int    autri_get_props(void *);
        !           143: int    autri_query_devinfo(void *addr, mixer_devinfo_t *dip);
        !           144:
        !           145: int    autri_get_portnum_by_name(struct autri_softc *, char *, char *, char *);
        !           146:
        !           147: struct audio_hw_if autri_hw_if = {
        !           148:        autri_open,
        !           149:        autri_close,
        !           150:        NULL,                   /* drain */
        !           151:        autri_query_encoding,
        !           152:        autri_set_params,
        !           153:        autri_round_blocksize,
        !           154:        NULL,                   /* commit_settings */
        !           155:        NULL,                   /* init_output */
        !           156:        NULL,                   /* init_input */
        !           157:        NULL,                   /* start_output */
        !           158:        NULL,                   /* start_input */
        !           159:        autri_halt_output,
        !           160:        autri_halt_input,
        !           161:        NULL,                   /* speaker_ctl */
        !           162:        autri_getdev,
        !           163:        NULL,                   /* setfd */
        !           164:        autri_mixer_set_port,
        !           165:        autri_mixer_get_port,
        !           166:        autri_query_devinfo,
        !           167:        autri_malloc,
        !           168:        autri_free,
        !           169:        NULL,
        !           170:        autri_mappage,
        !           171:        autri_get_props,
        !           172:        autri_trigger_output,
        !           173:        autri_trigger_input,
        !           174: };
        !           175:
        !           176: #if NMIDI > 0
        !           177: void   autri_midi_close(void *);
        !           178: void   autri_midi_getinfo(void *, struct midi_info *);
        !           179: int    autri_midi_open(void *, int, void (*)(void *, int),
        !           180:                           void (*)(void *), void *);
        !           181: int    autri_midi_output(void *, int);
        !           182:
        !           183: struct midi_hw_if autri_midi_hw_if = {
        !           184:        autri_midi_open,
        !           185:        autri_midi_close,
        !           186:        autri_midi_output,
        !           187:        NULL,                   /* flush */
        !           188:        autri_midi_getinfo,
        !           189:        NULL,                   /* ioctl */
        !           190: };
        !           191: #endif
        !           192:
        !           193: /*
        !           194:  * register set/clear bit
        !           195:  */
        !           196: static __inline void
        !           197: autri_reg_set_1(sc, no, mask)
        !           198:        struct autri_softc *sc;
        !           199:        int no;
        !           200:        uint8_t mask;
        !           201: {
        !           202:        bus_space_write_1(sc->memt, sc->memh, no,
        !           203:            (bus_space_read_1(sc->memt, sc->memh, no) | mask));
        !           204: }
        !           205:
        !           206: static __inline void
        !           207: autri_reg_clear_1(sc, no, mask)
        !           208:        struct autri_softc *sc;
        !           209:        int no;
        !           210:        uint8_t mask;
        !           211: {
        !           212:        bus_space_write_1(sc->memt, sc->memh, no,
        !           213:            (bus_space_read_1(sc->memt, sc->memh, no) & ~mask));
        !           214: }
        !           215:
        !           216: static __inline void
        !           217: autri_reg_set_4(sc, no, mask)
        !           218:        struct autri_softc *sc;
        !           219:        int no;
        !           220:        uint32_t mask;
        !           221: {
        !           222:        bus_space_write_4(sc->memt, sc->memh, no,
        !           223:            (bus_space_read_4(sc->memt, sc->memh, no) | mask));
        !           224: }
        !           225:
        !           226: static __inline void
        !           227: autri_reg_clear_4(sc, no, mask)
        !           228:        struct autri_softc *sc;
        !           229:        int no;
        !           230:        uint32_t mask;
        !           231: {
        !           232:        bus_space_write_4(sc->memt, sc->memh, no,
        !           233:            (bus_space_read_4(sc->memt, sc->memh, no) & ~mask));
        !           234: }
        !           235:
        !           236: /*
        !           237:  * AC97 codec
        !           238:  */
        !           239: int
        !           240: autri_attach_codec(sc_, codec_if)
        !           241:        void *sc_;
        !           242:        struct ac97_codec_if *codec_if;
        !           243: {
        !           244:        struct autri_codec_softc *sc = sc_;
        !           245:
        !           246:        DPRINTF(("autri_attach_codec()\n"));
        !           247:
        !           248:        sc->codec_if = codec_if;
        !           249:        return 0;
        !           250: }
        !           251:
        !           252: int
        !           253: autri_read_codec(sc_, index, data)
        !           254:        void *sc_;
        !           255:        u_int8_t index;
        !           256:        u_int16_t *data;
        !           257: {
        !           258:        struct autri_codec_softc *codec = sc_;
        !           259:        struct autri_softc *sc = codec->sc;
        !           260:        u_int32_t status, addr, cmd, busy;
        !           261:        u_int16_t count;
        !           262:
        !           263:        /*DPRINTF(("sc->sc->type : 0x%X",sc->sc->type));*/
        !           264:
        !           265:        switch (sc->sc_devid) {
        !           266:        case AUTRI_DEVICE_ID_4DWAVE_DX:
        !           267:                addr = AUTRI_DX_ACR1;
        !           268:                cmd  = AUTRI_DX_ACR1_CMD_READ;
        !           269:                busy = AUTRI_DX_ACR1_BUSY_READ;
        !           270:                break;
        !           271:        case AUTRI_DEVICE_ID_4DWAVE_NX:
        !           272:                addr = AUTRI_NX_ACR2;
        !           273:                cmd  = AUTRI_NX_ACR2_CMD_READ;
        !           274:                busy = AUTRI_NX_ACR2_BUSY_READ | AUTRI_NX_ACR2_RECV_WAIT;
        !           275:                break;
        !           276:        case AUTRI_DEVICE_ID_SIS_7018:
        !           277:                addr = AUTRI_SIS_ACRD;
        !           278:                cmd  = AUTRI_SIS_ACRD_CMD_READ;
        !           279:                busy = AUTRI_SIS_ACRD_BUSY_READ | AUTRI_SIS_ACRD_AUDIO_BUSY;
        !           280:                break;
        !           281:        case AUTRI_DEVICE_ID_ALI_M5451:
        !           282:                if (sc->sc_revision > 0x01)
        !           283:                        addr = AUTRI_ALI_ACWR;
        !           284:                else
        !           285:                        addr = AUTRI_ALI_ACRD;
        !           286:                cmd  = AUTRI_ALI_ACRD_CMD_READ;
        !           287:                busy = AUTRI_ALI_ACRD_BUSY_READ;
        !           288:                break;
        !           289:        default:
        !           290:                printf("%s: autri_read_codec : unknown device\n",
        !           291:                    sc->sc_dev.dv_xname);
        !           292:                return -1;
        !           293:        }
        !           294:
        !           295:        /* wait for 'Ready to Read' */
        !           296:        for (count=0; count < 0xffff; count++) {
        !           297:                if ((TREAD4(sc, addr) & busy) == 0)
        !           298:                        break;
        !           299:                DELAY(1);
        !           300:        }
        !           301:
        !           302:        if (count == 0xffff) {
        !           303:                printf("%s: Codec timeout. Busy reading AC97 codec.\n",
        !           304:                    sc->sc_dev.dv_xname);
        !           305:                return -1;
        !           306:        }
        !           307:
        !           308:        /* send Read Command to AC97 */
        !           309:        TWRITE4(sc, addr, (index & 0x7f) | cmd);
        !           310:
        !           311:        /* wait for 'Returned data is available' */
        !           312:        for (count=0; count < 0xffff; count++) {
        !           313:                status = TREAD4(sc, addr);
        !           314:                if ((status & busy) == 0)
        !           315:                        break;
        !           316:                DELAY(1);
        !           317:        }
        !           318:
        !           319:        if (count == 0xffff) {
        !           320:                printf("%s: Codec timeout. Busy reading AC97 codec.\n",
        !           321:                    sc->sc_dev.dv_xname);
        !           322:                return -1;
        !           323:        }
        !           324:
        !           325:        *data =  (status >> 16) & 0x0000ffff;
        !           326:        /*DPRINTF(("autri_read_codec(0x%X) return 0x%X\n",reg,*data));*/
        !           327:        return 0;
        !           328: }
        !           329:
        !           330: int
        !           331: autri_write_codec(sc_, index, data)
        !           332:        void *sc_;
        !           333:        u_int8_t index;
        !           334:        u_int16_t data;
        !           335: {
        !           336:        struct autri_codec_softc *codec = sc_;
        !           337:        struct autri_softc *sc = codec->sc;
        !           338:        u_int32_t addr, cmd, busy;
        !           339:        u_int16_t count;
        !           340:
        !           341:        /*DPRINTF(("autri_write_codec(0x%X,0x%X)\n",index,data));*/
        !           342:
        !           343:        switch (sc->sc_devid) {
        !           344:        case AUTRI_DEVICE_ID_4DWAVE_DX:
        !           345:                addr = AUTRI_DX_ACR0;
        !           346:                cmd  = AUTRI_DX_ACR0_CMD_WRITE;
        !           347:                busy = AUTRI_DX_ACR0_BUSY_WRITE;
        !           348:                break;
        !           349:        case AUTRI_DEVICE_ID_4DWAVE_NX:
        !           350:                addr = AUTRI_NX_ACR1;
        !           351:                cmd  = AUTRI_NX_ACR1_CMD_WRITE;
        !           352:                busy = AUTRI_NX_ACR1_BUSY_WRITE;
        !           353:                break;
        !           354:        case AUTRI_DEVICE_ID_SIS_7018:
        !           355:                addr = AUTRI_SIS_ACWR;
        !           356:                cmd  = AUTRI_SIS_ACWR_CMD_WRITE;
        !           357:                busy = AUTRI_SIS_ACWR_BUSY_WRITE | AUTRI_SIS_ACWR_AUDIO_BUSY;
        !           358:                break;
        !           359:        case AUTRI_DEVICE_ID_ALI_M5451:
        !           360:                addr = AUTRI_ALI_ACWR;
        !           361:                cmd  = AUTRI_ALI_ACWR_CMD_WRITE;
        !           362:                if (sc->sc_revision > 0x01)
        !           363:                        cmd  |= 0x0100;
        !           364:                busy = AUTRI_ALI_ACWR_BUSY_WRITE;
        !           365:                break;
        !           366:        default:
        !           367:                printf("%s: autri_write_codec : unknown device.\n",
        !           368:                    sc->sc_dev.dv_xname);
        !           369:                return -1;
        !           370:        }
        !           371:
        !           372:        /* wait for 'Ready to Write' */
        !           373:        for (count=0; count < 0xffff; count++) {
        !           374:                if ((TREAD4(sc, addr) & busy) == 0)
        !           375:                        break;
        !           376:                DELAY(1);
        !           377:        }
        !           378:
        !           379:        if (count == 0xffff) {
        !           380:                printf("%s: Codec timeout. Busy writing AC97 codec\n",
        !           381:                    sc->sc_dev.dv_xname);
        !           382:                return -1;
        !           383:        }
        !           384:
        !           385:        /* send Write Command to AC97 */
        !           386:        TWRITE4(sc, addr, (data << 16) | (index & 0x7f) | cmd);
        !           387:
        !           388:        return 0;
        !           389: }
        !           390:
        !           391: void
        !           392: autri_reset_codec(sc_)
        !           393:        void *sc_;
        !           394: {
        !           395:        struct autri_codec_softc *codec = sc_;
        !           396:        struct autri_softc *sc = codec->sc;
        !           397:        u_int32_t reg, ready;
        !           398:        int addr, count = 200;
        !           399:
        !           400:        DPRINTF(("autri_reset_codec(codec=%p,sc=%p)\n",codec,sc));
        !           401:        DPRINTF(("sc->sc_devid=%X\n",sc->sc_devid));
        !           402:
        !           403:        switch (sc->sc_devid) {
        !           404:        case AUTRI_DEVICE_ID_4DWAVE_DX:
        !           405:                /* warm reset AC97 codec */
        !           406:                autri_reg_set_4(sc, AUTRI_DX_ACR2, 1);
        !           407:                delay(100);
        !           408:                /* release reset */
        !           409:                autri_reg_clear_4(sc, AUTRI_DX_ACR2, 1);
        !           410:                delay(100);
        !           411:
        !           412:                addr = AUTRI_DX_ACR2;
        !           413:                ready = AUTRI_DX_ACR2_CODEC_READY;
        !           414:                break;
        !           415:        case AUTRI_DEVICE_ID_4DWAVE_NX:
        !           416:                /* warm reset AC97 codec */
        !           417:                autri_reg_set_4(sc, AUTRI_NX_ACR0, 1);
        !           418:                delay(100);
        !           419:                /* release reset */
        !           420:                autri_reg_clear_4(sc, AUTRI_NX_ACR0, 1);
        !           421:                delay(100);
        !           422:
        !           423:                addr = AUTRI_NX_ACR0;
        !           424:                ready = AUTRI_NX_ACR0_CODEC_READY;
        !           425:                break;
        !           426:        case AUTRI_DEVICE_ID_SIS_7018:
        !           427:                /* warm reset AC97 codec */
        !           428:                autri_reg_set_4(sc, AUTRI_SIS_SCTRL, 2);
        !           429:                delay(1000);
        !           430:                /* release reset (warm & cold) */
        !           431:                autri_reg_clear_4(sc, AUTRI_SIS_SCTRL, 3);
        !           432:                delay(2000);
        !           433:
        !           434:                addr = AUTRI_SIS_SCTRL;
        !           435:                ready = AUTRI_SIS_SCTRL_CODEC_READY;
        !           436:                break;
        !           437:        case AUTRI_DEVICE_ID_ALI_M5451:
        !           438:                /* warm reset AC97 codec */
        !           439:                autri_reg_set_4(sc, AUTRI_ALI_SCTRL, 1);
        !           440:                delay(100);
        !           441:                /* release reset (warm & cold) */
        !           442:                autri_reg_clear_4(sc, AUTRI_ALI_SCTRL, 3);
        !           443:                delay(100);
        !           444:
        !           445:                addr = AUTRI_ALI_SCTRL;
        !           446:                ready = AUTRI_ALI_SCTRL_CODEC_READY;
        !           447:                break;
        !           448:        }
        !           449:
        !           450:        /* wait for 'Codec Ready' */
        !           451:        while (count--) {
        !           452:                reg = TREAD4(sc, addr);
        !           453:                if (reg & ready)
        !           454:                        break;
        !           455:                delay(1000);
        !           456:        }
        !           457:
        !           458:        if (count == 0)
        !           459:                printf("%s: Codec timeout. AC97 is not ready for operation.\n",
        !           460:                    sc->sc_dev.dv_xname);
        !           461: }
        !           462:
        !           463: enum ac97_host_flags
        !           464: autri_flags_codec(void *v)
        !           465: {
        !           466:        struct autri_codec_softc *sc = v;
        !           467:
        !           468:        return (sc->flags);
        !           469: }
        !           470:
        !           471: /*
        !           472:  *
        !           473:  */
        !           474: const struct pci_matchid autri_devices[] = {
        !           475:        { PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_4DWAVE_NX },
        !           476:        { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7018 },
        !           477:        { PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5451 }
        !           478: };
        !           479:
        !           480: int
        !           481: autri_match(parent, match, aux)
        !           482:        struct device *parent;
        !           483:        void *match;
        !           484:        void *aux;
        !           485: {
        !           486:        struct pci_attach_args *pa = aux;
        !           487:
        !           488:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TRIDENT &&
        !           489:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TRIDENT_4DWAVE_DX) {
        !           490:                /*
        !           491:                 * IBM makes a pcn network card and improperly
        !           492:                 * sets the vendor and product ID's.  Avoid matching.
        !           493:                 */
        !           494:                if (PCI_CLASS(pa->pa_class) == PCI_CLASS_NETWORK)
        !           495:                        return (0);
        !           496:                else
        !           497:                        return (1);
        !           498:        }
        !           499:
        !           500:        return (pci_matchbyid((struct pci_attach_args *)aux, autri_devices,
        !           501:            sizeof(autri_devices)/sizeof(autri_devices[0])));
        !           502: }
        !           503:
        !           504: void
        !           505: autri_attach(parent, self, aux)
        !           506:        struct device *parent;
        !           507:        struct device *self;
        !           508:        void *aux;
        !           509: {
        !           510:        struct autri_softc *sc = (struct autri_softc *)self;
        !           511:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
        !           512:        pci_chipset_tag_t pc = pa->pa_pc;
        !           513:        struct autri_codec_softc *codec;
        !           514:        bus_size_t iosize;
        !           515:        pci_intr_handle_t ih;
        !           516:        char const *intrstr;
        !           517:        mixer_ctrl_t ctl;
        !           518:        int i, r;
        !           519:
        !           520:        sc->sc_devid = pa->pa_id;
        !           521:        sc->sc_class = pa->pa_class;
        !           522:        sc->sc_revision = PCI_REVISION(pa->pa_class);
        !           523:
        !           524:        /* map register to memory */
        !           525:        if (pci_mapreg_map(pa, AUTRI_PCI_MEMORY_BASE,
        !           526:            PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, &iosize, 0)) {
        !           527:                printf("%s: can't map memory space\n", sc->sc_dev.dv_xname);
        !           528:                return;
        !           529:        }
        !           530:
        !           531:        /* map and establish the interrupt */
        !           532:        if (pci_intr_map(pa, &ih)) {
        !           533:                printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
        !           534:                bus_space_unmap(sc->memt, sc->memh, iosize);
        !           535:                return;
        !           536:        }
        !           537:        intrstr = pci_intr_string(pc, ih);
        !           538:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, autri_intr, sc,
        !           539:            sc->sc_dev.dv_xname);
        !           540:        if (sc->sc_ih == NULL) {
        !           541:                printf("%s: couldn't establish interrupt",
        !           542:                    sc->sc_dev.dv_xname);
        !           543:                if (intrstr != NULL)
        !           544:                        printf(" at %s", intrstr);
        !           545:                printf("\n");
        !           546:                bus_space_unmap(sc->memt, sc->memh, iosize);
        !           547:                return;
        !           548:        }
        !           549:        printf(": %s\n", intrstr);
        !           550:
        !           551:        sc->sc_dmatag = pa->pa_dmat;
        !           552:        sc->sc_pc = pc;
        !           553:        sc->sc_pt = pa->pa_tag;
        !           554:
        !           555:        /* initialize the device */
        !           556:        autri_init(sc);
        !           557:
        !           558:        /* attach AC97 codec */
        !           559:        codec = &sc->sc_codec;
        !           560:        memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev));
        !           561:        codec->sc = sc;
        !           562:
        !           563:        codec->host_if.arg = codec;
        !           564:        codec->host_if.attach = autri_attach_codec;
        !           565:        codec->host_if.reset = autri_reset_codec;
        !           566:        codec->host_if.read = autri_read_codec;
        !           567:        codec->host_if.write = autri_write_codec;
        !           568:        codec->host_if.flags = autri_flags_codec;
        !           569:        codec->flags = AC97_HOST_DONT_READ | AC97_HOST_SWAPPED_CHANNELS;
        !           570:        if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001)
        !           571:                codec->flags &= ~AC97_HOST_SWAPPED_CHANNELS;
        !           572:
        !           573:        if ((r = ac97_attach(&codec->host_if)) != 0) {
        !           574:                printf("%s: can't attach codec (error 0x%X)\n",
        !           575:                    sc->sc_dev.dv_xname, r);
        !           576:                pci_intr_disestablish(pc, sc->sc_ih);
        !           577:                bus_space_unmap(sc->memt, sc->memh, iosize);
        !           578:                return;
        !           579:        }
        !           580:
        !           581:        /* disable mutes */
        !           582:        for (i = 0; i < 4; i++) {
        !           583:                static struct {
        !           584:                        char *class, *device;
        !           585:                } d[] = {
        !           586:                        { AudioCoutputs, AudioNmaster},
        !           587:                        { AudioCinputs, AudioNdac},
        !           588:                        { AudioCinputs, AudioNcd},
        !           589:                        { AudioCrecord, AudioNvolume},
        !           590:                };
        !           591:
        !           592:                ctl.type = AUDIO_MIXER_ENUM;
        !           593:                ctl.un.ord = 0;
        !           594:
        !           595: #if 0
        !           596:                ctl.dev = sc->sc_codec.codec_if->vtbl->get_portnum_by_name(sc->sc_codec.codec_if,
        !           597:                    d[i].class, d[i].device, AudioNmute);
        !           598: #endif
        !           599:                ctl.dev = autri_get_portnum_by_name(sc,d[i].class,
        !           600:                                                   d[i].device, AudioNmute);
        !           601:                autri_mixer_set_port(sc, &ctl);
        !           602:        }
        !           603:
        !           604:        /* set a reasonable default volume */
        !           605:        ctl.type = AUDIO_MIXER_VALUE;
        !           606:        ctl.un.value.num_channels = 2;
        !           607:        ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
        !           608:        ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
        !           609:
        !           610:        ctl.dev = autri_get_portnum_by_name(sc,AudioCoutputs,AudioNmaster,NULL);
        !           611:        autri_mixer_set_port(sc, &ctl);
        !           612:
        !           613:        audio_attach_mi(&autri_hw_if, sc, &sc->sc_dev);
        !           614:
        !           615: #if NMIDI > 0
        !           616:        midi_attach_mi(&autri_midi_hw_if, sc, &sc->sc_dev);
        !           617: #endif
        !           618:
        !           619:        sc->sc_old_power = PWR_RESUME;
        !           620:        powerhook_establish(autri_powerhook, sc);
        !           621: }
        !           622:
        !           623: void
        !           624: autri_powerhook(int why,void *addr)
        !           625: {
        !           626:        struct autri_softc *sc = addr;
        !           627:
        !           628:        if (why == PWR_RESUME && sc->sc_old_power == PWR_SUSPEND) {
        !           629:                DPRINTF(("PWR_RESUME\n"));
        !           630:                autri_init(sc);
        !           631:                /*autri_reset_codec(&sc->sc_codec);*/
        !           632:                (sc->sc_codec.codec_if->vtbl->restore_ports)(sc->sc_codec.codec_if);
        !           633:        }
        !           634:        sc->sc_old_power = why;
        !           635: }
        !           636:
        !           637: int
        !           638: autri_init(sc_)
        !           639:        void *sc_;
        !           640: {
        !           641:        struct autri_softc *sc = sc_;
        !           642:        pcireg_t reg;
        !           643:
        !           644:        pci_chipset_tag_t pc = sc->sc_pc;
        !           645:        pcitag_t pt = sc->sc_pt;
        !           646:
        !           647:        DPRINTF(("in autri_init()\n"));
        !           648:        DPRINTFN(5,("pci_conf_read(0x40) : 0x%X\n",pci_conf_read(pc,pt,0x40)));
        !           649:        DPRINTFN(5,("pci_conf_read(0x44) : 0x%X\n",pci_conf_read(pc,pt,0x44)));
        !           650:
        !           651:        switch (sc->sc_devid) {
        !           652:        case AUTRI_DEVICE_ID_4DWAVE_DX:
        !           653:                /* disable Legacy Control */
        !           654:                pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
        !           655:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           656:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
        !           657:                delay(100);
        !           658:                /* audio engine reset */
        !           659:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           660:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00040000);
        !           661:                delay(100);
        !           662:                /* release reset */
        !           663:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           664:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
        !           665:                delay(100);
        !           666:                /* DAC on */
        !           667:                autri_reg_set_4(sc,AUTRI_DX_ACR2,0x02);
        !           668:                break;
        !           669:        case AUTRI_DEVICE_ID_4DWAVE_NX:
        !           670:                /* disable Legacy Control */
        !           671:                pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
        !           672:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           673:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
        !           674:                delay(100);
        !           675:                /* audio engine reset */
        !           676:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           677:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00010000);
        !           678:                delay(100);
        !           679:                /* release reset */
        !           680:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           681:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00010000);
        !           682:                delay(100);
        !           683:                /* DAC on */
        !           684:                autri_reg_set_4(sc,AUTRI_NX_ACR0,0x02);
        !           685:                break;
        !           686:        case AUTRI_DEVICE_ID_SIS_7018:
        !           687:                /* disable Legacy Control */
        !           688:                pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
        !           689:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           690:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
        !           691:                delay(100);
        !           692:                /* reset Digital Controller */
        !           693:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           694:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
        !           695:                delay(100);
        !           696:                /* release reset */
        !           697:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           698:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
        !           699:                delay(100);
        !           700:                /* disable AC97 GPIO interrupt */
        !           701:                TWRITE1(sc, AUTRI_SIS_ACGPIO, 0);
        !           702:                /* enable 64 channel mode */
        !           703:                autri_reg_set_4(sc, AUTRI_LFO_GC_CIR, BANK_B_EN);
        !           704:                break;
        !           705:        case AUTRI_DEVICE_ID_ALI_M5451:
        !           706:                /* disable Legacy Control */
        !           707:                pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
        !           708:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           709:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
        !           710:                delay(100);
        !           711:                /* reset Digital Controller */
        !           712:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           713:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
        !           714:                delay(100);
        !           715:                /* release reset */
        !           716:                reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
        !           717:                pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
        !           718:                delay(100);
        !           719:                /* enable PCM input */
        !           720:                autri_reg_set_4(sc, AUTRI_ALI_GCONTROL, AUTRI_ALI_GCONTROL_PCM_IN);
        !           721:                break;
        !           722:        }
        !           723:
        !           724:        if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
        !           725:                sc->sc_play.ch      = 0;
        !           726:                sc->sc_play.ch_intr = 1;
        !           727:                sc->sc_rec.ch       = 31;
        !           728:                sc->sc_rec.ch_intr  = 2;
        !           729:        } else {
        !           730:                sc->sc_play.ch      = 0x20;
        !           731:                sc->sc_play.ch_intr = 0x21;
        !           732:                sc->sc_rec.ch       = 0x22;
        !           733:                sc->sc_rec.ch_intr  = 0x23;
        !           734:        }
        !           735:
        !           736:        /* clear channel status */
        !           737:        TWRITE4(sc, AUTRI_STOP_A, 0xffffffff);
        !           738:        TWRITE4(sc, AUTRI_STOP_B, 0xffffffff);
        !           739:
        !           740:        /* disable channel interrupt */
        !           741:        TWRITE4(sc, AUTRI_AINTEN_A, 0);
        !           742:        TWRITE4(sc, AUTRI_AINTEN_B, 0);
        !           743:
        !           744: #if 0
        !           745:        /* TLB */
        !           746:        if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
        !           747:                TWRITE4(sc,AUTRI_NX_TLBC,0);
        !           748:        }
        !           749: #endif
        !           750:
        !           751:        autri_enable_loop_interrupt(sc);
        !           752:
        !           753:        DPRINTF(("out autri_init()\n"));
        !           754:        return 0;
        !           755: }
        !           756:
        !           757: void
        !           758: autri_enable_loop_interrupt(sc_)
        !           759:        void *sc_;
        !           760: {
        !           761:        struct autri_softc *sc = sc_;
        !           762:        u_int32_t reg;
        !           763:
        !           764:        /*reg = (ENDLP_IE | MIDLP_IE);*/
        !           765:        reg = ENDLP_IE;
        !           766: #if 0
        !           767:        if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
        !           768:                reg |= BANK_B_EN;
        !           769: #endif
        !           770:        autri_reg_set_4(sc,AUTRI_LFO_GC_CIR,reg);
        !           771: }
        !           772:
        !           773: #if 0
        !           774: void
        !           775: autri_disable_loop_interrupt(sc_)
        !           776:        void *sc_;
        !           777: {
        !           778:        struct autri_softc *sc = sc_;
        !           779:        u_int32_t reg;
        !           780:
        !           781:        reg = (ENDLP_IE | MIDLP_IE);
        !           782:        autri_reg_clear_4(sc,AUTRI_LFO_GC_CIR,reg);
        !           783: }
        !           784: #endif
        !           785:
        !           786: int
        !           787: autri_intr(p)
        !           788:        void *p;
        !           789: {
        !           790:        struct autri_softc *sc = p;
        !           791:        u_int32_t intsrc;
        !           792:        u_int32_t mask, active[2];
        !           793:        int ch, endch;
        !           794: /*
        !           795:        u_int32_t reg;
        !           796:        u_int32_t cso,eso;
        !           797: */
        !           798:
        !           799:        intsrc = TREAD4(sc,AUTRI_MISCINT);
        !           800:        if ((intsrc & (ADDRESS_IRQ|MPU401_IRQ)) == 0)
        !           801:                return 0;
        !           802:
        !           803:        if (intsrc & ADDRESS_IRQ) {
        !           804:
        !           805:                active[0] = TREAD4(sc,AUTRI_AIN_A);
        !           806:                active[1] = TREAD4(sc,AUTRI_AIN_B);
        !           807:
        !           808:                if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
        !           809:                        endch = 32;
        !           810:                } else {
        !           811:                        endch = 64;
        !           812:                }
        !           813:
        !           814:                for (ch=0; ch<endch; ch++) {
        !           815:                        mask = 1 << (ch & 0x1f);
        !           816:                        if (active[(ch & 0x20) ? 1 : 0] & mask) {
        !           817:
        !           818:                                /* clear interrupt */
        !           819:                                TWRITE4(sc, (ch & 0x20) ? AUTRI_AIN_B : AUTRI_AIN_A, mask);
        !           820:                                /* disable interrupt */
        !           821:                                autri_reg_clear_4(sc,(ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
        !           822: #if 0
        !           823:                                reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
        !           824:                                TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | ch);
        !           825:
        !           826:                                if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
        !           827:                                  cso = TREAD4(sc, 0xe0) & 0x00ffffff;
        !           828:                                  eso = TREAD4(sc, 0xe8) & 0x00ffffff;
        !           829:                                } else {
        !           830:                                  cso = (TREAD4(sc, 0xe0) >> 16) & 0x0000ffff;
        !           831:                                  eso = (TREAD4(sc, 0xe8) >> 16) & 0x0000ffff;
        !           832:                                }
        !           833:                                /*printf("cso=%d, eso=%d\n",cso,eso);*/
        !           834: #endif
        !           835:                                if (ch == sc->sc_play.ch_intr) {
        !           836:                                        if (sc->sc_play.intr)
        !           837:                                                sc->sc_play.intr(sc->sc_play.intr_arg);
        !           838:                                }
        !           839:
        !           840:                                if (ch == sc->sc_rec.ch_intr) {
        !           841:                                        if (sc->sc_rec.intr)
        !           842:                                                sc->sc_rec.intr(sc->sc_rec.intr_arg);
        !           843:                                }
        !           844:
        !           845:                                /* enable interrupt */
        !           846:                                autri_reg_set_4(sc, (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
        !           847:                        }
        !           848:                }
        !           849:        }
        !           850:
        !           851:        if (intsrc & MPU401_IRQ) {
        !           852:                /* XXX */
        !           853:        }
        !           854:
        !           855:        autri_reg_set_4(sc,AUTRI_MISCINT,
        !           856:                ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW);
        !           857:
        !           858:        return 1;
        !           859: }
        !           860:
        !           861: /*
        !           862:  *
        !           863:  */
        !           864:
        !           865: int
        !           866: autri_allocmem(sc, size, align, p)
        !           867:        struct autri_softc *sc;
        !           868:        size_t size;
        !           869:        size_t align;
        !           870:        struct autri_dma *p;
        !           871: {
        !           872:        int error;
        !           873:
        !           874:        p->size = size;
        !           875:        error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
        !           876:            p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
        !           877:            &p->nsegs, BUS_DMA_NOWAIT);
        !           878:        if (error)
        !           879:                return (error);
        !           880:
        !           881:        error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
        !           882:            &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
        !           883:        if (error)
        !           884:                goto free;
        !           885:
        !           886:        error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
        !           887:            0, BUS_DMA_NOWAIT, &p->map);
        !           888:        if (error)
        !           889:                goto unmap;
        !           890:
        !           891:        error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
        !           892:            BUS_DMA_NOWAIT);
        !           893:        if (error)
        !           894:                goto destroy;
        !           895:        return (0);
        !           896:
        !           897: destroy:
        !           898:        bus_dmamap_destroy(sc->sc_dmatag, p->map);
        !           899: unmap:
        !           900:        bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
        !           901: free:
        !           902:        bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
        !           903:        return (error);
        !           904: }
        !           905:
        !           906: int
        !           907: autri_freemem(sc, p)
        !           908:        struct autri_softc *sc;
        !           909:        struct autri_dma *p;
        !           910: {
        !           911:        bus_dmamap_unload(sc->sc_dmatag, p->map);
        !           912:        bus_dmamap_destroy(sc->sc_dmatag, p->map);
        !           913:        bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
        !           914:        bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
        !           915:        return 0;
        !           916: }
        !           917:
        !           918: int
        !           919: autri_open(addr, flags)
        !           920:        void *addr;
        !           921:        int flags;
        !           922: {
        !           923:        DPRINTF(("autri_open()\n"));
        !           924:        DPRINTFN(5,("MISCINT    : 0x%08X\n",
        !           925:            TREAD4((struct autri_softc *)addr, AUTRI_MISCINT)));
        !           926:        DPRINTFN(5,("LFO_GC_CIR : 0x%08X\n",
        !           927:            TREAD4((struct autri_softc *)addr, AUTRI_LFO_GC_CIR)));
        !           928:        return 0;
        !           929: }
        !           930:
        !           931: void
        !           932: autri_close(addr)
        !           933:        void *addr;
        !           934: {
        !           935:        DPRINTF(("autri_close()\n"));
        !           936: }
        !           937:
        !           938: int
        !           939: autri_query_encoding(addr, fp)
        !           940:        void *addr;
        !           941:        struct audio_encoding *fp;
        !           942: {
        !           943:        switch (fp->index) {
        !           944:        case 0:
        !           945:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
        !           946:                fp->encoding = AUDIO_ENCODING_ULINEAR;
        !           947:                fp->precision = 8;
        !           948:                fp->flags = 0;
        !           949:                break;
        !           950:        case 1:
        !           951:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
        !           952:                fp->encoding = AUDIO_ENCODING_ULAW;
        !           953:                fp->precision = 8;
        !           954:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           955:                break;
        !           956:        case 2:
        !           957:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
        !           958:                fp->encoding = AUDIO_ENCODING_ALAW;
        !           959:                fp->precision = 8;
        !           960:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           961:                break;
        !           962:        case 3:
        !           963:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
        !           964:                fp->encoding = AUDIO_ENCODING_SLINEAR;
        !           965:                fp->precision = 8;
        !           966:                fp->flags = 0;
        !           967:                break;
        !           968:        case 4:
        !           969:                strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
        !           970:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
        !           971:                fp->precision = 16;
        !           972:                fp->flags = 0;
        !           973:                break;
        !           974:        case 5:
        !           975:                strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
        !           976:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
        !           977:                fp->precision = 16;
        !           978:                fp->flags = 0;
        !           979:                break;
        !           980:        case 6:
        !           981:                strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
        !           982:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
        !           983:                fp->precision = 16;
        !           984:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           985:                break;
        !           986:        case 7:
        !           987:                strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
        !           988:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
        !           989:                fp->precision = 16;
        !           990:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
        !           991:                break;
        !           992:        default:
        !           993:                return (EINVAL);
        !           994:        }
        !           995:
        !           996:        return 0;
        !           997: }
        !           998:
        !           999: int
        !          1000: autri_set_params(addr, setmode, usemode, play, rec)
        !          1001:        void *addr;
        !          1002:        int setmode, usemode;
        !          1003:        struct audio_params *play, *rec;
        !          1004: {
        !          1005:        struct audio_params *p;
        !          1006:        int mode;
        !          1007:
        !          1008:        for (mode = AUMODE_RECORD; mode != -1;
        !          1009:            mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
        !          1010:                if ((setmode & mode) == 0)
        !          1011:                        continue;
        !          1012:
        !          1013:                p = mode == AUMODE_PLAY ? play : rec;
        !          1014:
        !          1015:                if (p->sample_rate < 4000 || p->sample_rate > 48000 ||
        !          1016:                    (p->precision != 8 && p->precision != 16) ||
        !          1017:                    (p->channels != 1 && p->channels != 2))
        !          1018:                        return (EINVAL);
        !          1019:
        !          1020:                p->factor = 1;
        !          1021:                p->sw_code = 0;
        !          1022:                switch (p->encoding) {
        !          1023:                case AUDIO_ENCODING_SLINEAR_BE:
        !          1024:                case AUDIO_ENCODING_ULINEAR_BE:
        !          1025:                        if (p->precision == 16)
        !          1026:                                p->sw_code = swap_bytes;
        !          1027:                        break;
        !          1028:                case AUDIO_ENCODING_SLINEAR_LE:
        !          1029:                case AUDIO_ENCODING_ULINEAR_LE:
        !          1030:                        break;
        !          1031:                case AUDIO_ENCODING_ULAW:
        !          1032:                        if (mode == AUMODE_PLAY)
        !          1033:                                p->sw_code = mulaw_to_ulinear8;
        !          1034:                        else
        !          1035:                                p->sw_code = ulinear8_to_mulaw;
        !          1036:
        !          1037:                        break;
        !          1038:                case AUDIO_ENCODING_ALAW:
        !          1039:                        if (mode == AUMODE_PLAY)
        !          1040:                                p->sw_code = alaw_to_ulinear8;
        !          1041:                        else
        !          1042:                                p->sw_code = ulinear8_to_alaw;
        !          1043:
        !          1044:                        break;
        !          1045:                default:
        !          1046:                        return (EINVAL);
        !          1047:                }
        !          1048:        }
        !          1049:
        !          1050:        return 0;
        !          1051: }
        !          1052:
        !          1053: int
        !          1054: autri_round_blocksize(addr, block)
        !          1055:        void *addr;
        !          1056:        int block;
        !          1057: {
        !          1058:        return ((block + 3) & -4);
        !          1059: }
        !          1060:
        !          1061: int
        !          1062: autri_halt_output(addr)
        !          1063:        void *addr;
        !          1064: {
        !          1065:        struct autri_softc *sc = addr;
        !          1066:
        !          1067:        DPRINTF(("autri_halt_output()\n"));
        !          1068:
        !          1069:        sc->sc_play.intr = NULL;
        !          1070:        autri_stopch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
        !          1071:        autri_disable_interrupt(sc, sc->sc_play.ch_intr);
        !          1072:
        !          1073:        return 0;
        !          1074: }
        !          1075:
        !          1076: int
        !          1077: autri_halt_input(addr)
        !          1078:        void *addr;
        !          1079: {
        !          1080:        struct autri_softc *sc = addr;
        !          1081:
        !          1082:        DPRINTF(("autri_halt_input()\n"));
        !          1083:
        !          1084:        sc->sc_rec.intr = NULL;
        !          1085:        autri_stopch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
        !          1086:        autri_disable_interrupt(sc, sc->sc_rec.ch_intr);
        !          1087:
        !          1088:        return 0;
        !          1089: }
        !          1090:
        !          1091: int
        !          1092: autri_getdev(addr, retp)
        !          1093:        void *addr;
        !          1094:        struct audio_device *retp;
        !          1095: {
        !          1096:        struct autri_softc *sc = addr;
        !          1097:
        !          1098:        DPRINTF(("autri_getdev().\n"));
        !          1099:
        !          1100:        strncpy(retp->name, "Trident 4DWAVE", sizeof(retp->name));
        !          1101:        snprintf(retp->version, sizeof(retp->version), "0x%02x",
        !          1102:            PCI_REVISION(sc->sc_class));
        !          1103:
        !          1104:        switch (sc->sc_devid) {
        !          1105:        case AUTRI_DEVICE_ID_4DWAVE_DX:
        !          1106:                strncpy(retp->config, "4DWAVE-DX", sizeof(retp->config));
        !          1107:                break;
        !          1108:        case AUTRI_DEVICE_ID_4DWAVE_NX:
        !          1109:                strncpy(retp->config, "4DWAVE-NX", sizeof(retp->config));
        !          1110:                break;
        !          1111:        case AUTRI_DEVICE_ID_SIS_7018:
        !          1112:                strncpy(retp->config, "SiS 7018", sizeof(retp->config));
        !          1113:                break;
        !          1114:        case AUTRI_DEVICE_ID_ALI_M5451:
        !          1115:                strncpy(retp->config, "ALi M5451", sizeof(retp->config));
        !          1116:                break;
        !          1117:        default:
        !          1118:                strncpy(retp->config, "unknown", sizeof(retp->config));
        !          1119:        }
        !          1120:
        !          1121:        return 0;
        !          1122: }
        !          1123:
        !          1124: int
        !          1125: autri_mixer_set_port(addr, cp)
        !          1126:        void *addr;
        !          1127:        mixer_ctrl_t *cp;
        !          1128: {
        !          1129:        struct autri_softc *sc = addr;
        !          1130:
        !          1131:        return (sc->sc_codec.codec_if->vtbl->mixer_set_port(
        !          1132:            sc->sc_codec.codec_if, cp));
        !          1133: }
        !          1134:
        !          1135: int
        !          1136: autri_mixer_get_port(addr, cp)
        !          1137:        void *addr;
        !          1138:        mixer_ctrl_t *cp;
        !          1139: {
        !          1140:        struct autri_softc *sc = addr;
        !          1141:
        !          1142:        return (sc->sc_codec.codec_if->vtbl->mixer_get_port(
        !          1143:            sc->sc_codec.codec_if, cp));
        !          1144: }
        !          1145:
        !          1146: int
        !          1147: autri_query_devinfo(addr, dip)
        !          1148:        void *addr;
        !          1149:        mixer_devinfo_t *dip;
        !          1150: {
        !          1151:        struct autri_softc *sc = addr;
        !          1152:
        !          1153:        return (sc->sc_codec.codec_if->vtbl->query_devinfo(
        !          1154:            sc->sc_codec.codec_if, dip));
        !          1155: }
        !          1156:
        !          1157: int
        !          1158: autri_get_portnum_by_name(sc, class, device, qualifier)
        !          1159:        struct autri_softc *sc;
        !          1160:        char *class, *device, *qualifier;
        !          1161: {
        !          1162:        return (sc->sc_codec.codec_if->vtbl->get_portnum_by_name(
        !          1163:            sc->sc_codec.codec_if, class, device, qualifier));
        !          1164: }
        !          1165:
        !          1166: void *
        !          1167: autri_malloc(addr, direction, size, pool, flags)
        !          1168:        void *addr;
        !          1169:        int direction;
        !          1170:        size_t size;
        !          1171:        int pool, flags;
        !          1172: {
        !          1173:        struct autri_softc *sc = addr;
        !          1174:        struct autri_dma *p;
        !          1175:        int error;
        !          1176:
        !          1177:        p = malloc(sizeof(*p), pool, flags);
        !          1178:        if (!p)
        !          1179:                return NULL;
        !          1180:
        !          1181: #if 0
        !          1182:        error = autri_allocmem(sc, size, 16, p);
        !          1183: #endif
        !          1184:        error = autri_allocmem(sc, size, 0x10000, p);
        !          1185:        if (error) {
        !          1186:                free(p, pool);
        !          1187:                return NULL;
        !          1188:        }
        !          1189:
        !          1190:        p->next = sc->sc_dmas;
        !          1191:        sc->sc_dmas = p;
        !          1192:        return KERNADDR(p);
        !          1193: }
        !          1194:
        !          1195: void
        !          1196: autri_free(addr, ptr, pool)
        !          1197:        void *addr;
        !          1198:        void *ptr;
        !          1199:        int pool;
        !          1200: {
        !          1201:        struct autri_softc *sc = addr;
        !          1202:        struct autri_dma **pp, *p;
        !          1203:
        !          1204:        for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
        !          1205:                if (KERNADDR(p) == ptr) {
        !          1206:                        autri_freemem(sc, p);
        !          1207:                        *pp = p->next;
        !          1208:                        free(p, pool);
        !          1209:                        return;
        !          1210:                }
        !          1211:        }
        !          1212: }
        !          1213:
        !          1214: struct autri_dma *
        !          1215: autri_find_dma(sc, addr)
        !          1216:        struct autri_softc *sc;
        !          1217:        void *addr;
        !          1218: {
        !          1219:        struct autri_dma *p;
        !          1220:
        !          1221:        for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next)
        !          1222:                ;
        !          1223:
        !          1224:        return p;
        !          1225: }
        !          1226:
        !          1227: paddr_t
        !          1228: autri_mappage(addr, mem, off, prot)
        !          1229:        void *addr;
        !          1230:        void *mem;
        !          1231:        off_t off;
        !          1232:        int prot;
        !          1233: {
        !          1234:        struct autri_softc *sc = addr;
        !          1235:        struct autri_dma *p;
        !          1236:
        !          1237:        if (off < 0)
        !          1238:                return (-1);
        !          1239:
        !          1240:        p = autri_find_dma(sc, mem);
        !          1241:        if (!p)
        !          1242:                return (-1);
        !          1243:
        !          1244:        return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs,
        !          1245:            off, prot, BUS_DMA_WAITOK));
        !          1246: }
        !          1247:
        !          1248: int
        !          1249: autri_get_props(addr)
        !          1250:        void *addr;
        !          1251: {
        !          1252:        return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
        !          1253:                AUDIO_PROP_FULLDUPLEX);
        !          1254: }
        !          1255:
        !          1256: void
        !          1257: autri_setup_channel(sc, mode, param)
        !          1258:        struct autri_softc *sc;
        !          1259:        int mode;
        !          1260:        struct audio_params *param;
        !          1261: {
        !          1262:        int i, ch, channel;
        !          1263:        u_int32_t reg, cr[5];
        !          1264:        u_int32_t cso, eso;
        !          1265:        u_int32_t delta, dch[2], ctrl;
        !          1266:        u_int32_t alpha_fms, fm_vol, attribute;
        !          1267:
        !          1268:        u_int32_t dmaaddr, dmalen;
        !          1269:        int factor, rvol, cvol;
        !          1270:        struct autri_chstatus *chst;
        !          1271:
        !          1272:        ctrl = AUTRI_CTRL_LOOPMODE;
        !          1273:        switch (param->encoding) {
        !          1274:        case AUDIO_ENCODING_SLINEAR_BE:
        !          1275:        case AUDIO_ENCODING_SLINEAR_LE:
        !          1276:                ctrl |= AUTRI_CTRL_SIGNED;
        !          1277:                break;
        !          1278:        }
        !          1279:
        !          1280:        factor = 0;
        !          1281:        if (param->precision == 16) {
        !          1282:                ctrl |= AUTRI_CTRL_16BIT;
        !          1283:                factor++;
        !          1284:        }
        !          1285:
        !          1286:        if (param->channels == 2) {
        !          1287:                ctrl |= AUTRI_CTRL_STEREO;
        !          1288:                factor++;
        !          1289:        }
        !          1290:
        !          1291:        delta = (u_int32_t)param->sample_rate;
        !          1292:        if (delta < 4000)
        !          1293:                delta = 4000;
        !          1294:        if (delta > 48000)
        !          1295:                delta = 48000;
        !          1296:
        !          1297:        attribute = 0;
        !          1298:
        !          1299:        dch[1] = ((delta << 12) / 48000) & 0x0000ffff;
        !          1300:        if (mode == AUMODE_PLAY) {
        !          1301:                chst = &sc->sc_play;
        !          1302:                dch[0] = ((delta << 12) / 48000) & 0x0000ffff;
        !          1303:                ctrl |= AUTRI_CTRL_WAVEVOL;
        !          1304: /*
        !          1305:                if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451)
        !          1306:                        ctrl |= 0x80000000;
        !          1307: */
        !          1308:        } else {
        !          1309:                chst = &sc->sc_rec;
        !          1310:                dch[0] = ((48000 << 12) / delta) & 0x0000ffff;
        !          1311:                if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) {
        !          1312:                        ctrl |= AUTRI_CTRL_MUTE_SIS;
        !          1313:                        attribute = AUTRI_ATTR_PCMREC_SIS;
        !          1314:                        if (delta != 48000)
        !          1315:                                attribute |= AUTRI_ATTR_ENASRC_SIS;
        !          1316:                }
        !          1317:                ctrl |= AUTRI_CTRL_MUTE;
        !          1318:        }
        !          1319:
        !          1320:        dmaaddr = DMAADDR(chst->dma);
        !          1321:        cso = alpha_fms = 0;
        !          1322:        rvol = cvol = 0x7f;
        !          1323:        fm_vol = 0x0 | ((rvol & 0x7f) << 7) | (cvol & 0x7f);
        !          1324:
        !          1325:        for (ch=0; ch<2; ch++) {
        !          1326:
        !          1327:                if (ch == 0)
        !          1328:                        dmalen = (chst->length >> factor);
        !          1329:                else {
        !          1330:                        /* channel for interrupt */
        !          1331:                        dmalen = (chst->blksize >> factor);
        !          1332:                        if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
        !          1333:                                ctrl |= AUTRI_CTRL_MUTE_SIS;
        !          1334:                        else
        !          1335:                                ctrl |= AUTRI_CTRL_MUTE;
        !          1336:                        attribute = 0;
        !          1337:                }
        !          1338:
        !          1339:                eso = dmalen - 1;
        !          1340:
        !          1341:                switch (sc->sc_devid) {
        !          1342:                case AUTRI_DEVICE_ID_4DWAVE_DX:
        !          1343:                        cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
        !          1344:                        cr[1] = dmaaddr;
        !          1345:                        cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
        !          1346:                        cr[3] = fm_vol;
        !          1347:                        cr[4] = ctrl;
        !          1348:                        break;
        !          1349:                case AUTRI_DEVICE_ID_4DWAVE_NX:
        !          1350:                        cr[0] = (dch[ch] << 24) | (cso & 0x00ffffff);
        !          1351:                        cr[1] = dmaaddr;
        !          1352:                        cr[2] = ((dch[ch] << 16) & 0xff000000) | (eso & 0x00ffffff);
        !          1353:                        cr[3] = (alpha_fms << 16) | (fm_vol & 0x0000ffff);
        !          1354:                        cr[4] = ctrl;
        !          1355:                        break;
        !          1356:                case AUTRI_DEVICE_ID_SIS_7018:
        !          1357:                        cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
        !          1358:                        cr[1] = dmaaddr;
        !          1359:                        cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
        !          1360:                        cr[3] = attribute;
        !          1361:                        cr[4] = ctrl;
        !          1362:                        break;
        !          1363:                case AUTRI_DEVICE_ID_ALI_M5451:
        !          1364:                        cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
        !          1365:                        cr[1] = dmaaddr;
        !          1366:                        cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
        !          1367:                        cr[3] = 0;
        !          1368:                        cr[4] = ctrl;
        !          1369:                        break;
        !          1370:                }
        !          1371:
        !          1372:                /* write channel data */
        !          1373:                channel = (ch == 0) ? chst->ch : chst->ch_intr;
        !          1374:
        !          1375:                reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
        !          1376:                TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | channel);
        !          1377:
        !          1378:                for (i=0; i<5; i++) {
        !          1379:                        TWRITE4(sc, AUTRI_ARAM_CR + i*sizeof(cr[0]), cr[i]);
        !          1380:                        DPRINTFN(5,("cr[%d] : 0x%08X\n", i, cr[i]));
        !          1381:                }
        !          1382:
        !          1383:                /* Bank A only */
        !          1384:                if (channel < 0x20) {
        !          1385:                        TWRITE4(sc, AUTRI_EBUF1, AUTRI_EMOD_STILL);
        !          1386:                        TWRITE4(sc, AUTRI_EBUF2, AUTRI_EMOD_STILL);
        !          1387:                }
        !          1388:        }
        !          1389:
        !          1390: }
        !          1391:
        !          1392: int
        !          1393: autri_trigger_output(addr, start, end, blksize, intr, arg, param)
        !          1394:        void *addr;
        !          1395:        void *start, *end;
        !          1396:        int blksize;
        !          1397:        void (*intr)(void *);
        !          1398:        void *arg;
        !          1399:        struct audio_params *param;
        !          1400: {
        !          1401:        struct autri_softc *sc = addr;
        !          1402:        struct autri_dma *p;
        !          1403:
        !          1404:        DPRINTFN(5,("autri_trigger_output: sc=%p start=%p end=%p "
        !          1405:            "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
        !          1406:
        !          1407:        sc->sc_play.intr = intr;
        !          1408:        sc->sc_play.intr_arg = arg;
        !          1409:        sc->sc_play.offset = 0;
        !          1410:        sc->sc_play.blksize = blksize;
        !          1411:        sc->sc_play.length = (char *)end - (char *)start;
        !          1412:
        !          1413:        p = autri_find_dma(sc, start);
        !          1414:        if (!p) {
        !          1415:                printf("autri_trigger_output: bad addr %p\n", start);
        !          1416:                return (EINVAL);
        !          1417:        }
        !          1418:
        !          1419:        sc->sc_play.dma = p;
        !          1420:
        !          1421:        /* */
        !          1422:        autri_setup_channel(sc, AUMODE_PLAY, param);
        !          1423:
        !          1424:        /* volume set to no attenuation */
        !          1425:        TWRITE4(sc, AUTRI_MUSICVOL_WAVEVOL, 0);
        !          1426:
        !          1427:        /* enable interrupt */
        !          1428:        autri_enable_interrupt(sc, sc->sc_play.ch_intr);
        !          1429:
        !          1430:        /* start channel */
        !          1431:        autri_startch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
        !          1432:
        !          1433:        return 0;
        !          1434: }
        !          1435:
        !          1436: int
        !          1437: autri_trigger_input(addr, start, end, blksize, intr, arg, param)
        !          1438:        void *addr;
        !          1439:        void *start, *end;
        !          1440:        int blksize;
        !          1441:        void (*intr)(void *);
        !          1442:        void *arg;
        !          1443:        struct audio_params *param;
        !          1444: {
        !          1445:        struct autri_softc *sc = addr;
        !          1446:        struct autri_dma *p;
        !          1447:
        !          1448:        DPRINTFN(5,("autri_trigger_input: sc=%p start=%p end=%p "
        !          1449:            "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
        !          1450:
        !          1451:        sc->sc_rec.intr = intr;
        !          1452:        sc->sc_rec.intr_arg = arg;
        !          1453:        sc->sc_rec.offset = 0;
        !          1454:        sc->sc_rec.blksize = blksize;
        !          1455:        sc->sc_rec.length = (char *)end - (char *)start;
        !          1456:
        !          1457:        /* */
        !          1458:        p = autri_find_dma(sc, start);
        !          1459:        if (!p) {
        !          1460:                printf("autri_trigger_input: bad addr %p\n", start);
        !          1461:                return (EINVAL);
        !          1462:        }
        !          1463:
        !          1464:        sc->sc_rec.dma = p;
        !          1465:
        !          1466:        /* */
        !          1467:        if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
        !          1468:                autri_reg_set_4(sc, AUTRI_NX_ACR0, AUTRI_NX_ACR0_PSB_CAPTURE);
        !          1469:                TWRITE1(sc, AUTRI_NX_RCI3, AUTRI_NX_RCI3_ENABLE | sc->sc_rec.ch);
        !          1470:        }
        !          1471:
        !          1472: #if 0
        !          1473:        /* 4DWAVE only allows capturing at a 48KHz rate */
        !          1474:        if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_DX ||
        !          1475:            sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX)
        !          1476:                param->sample_rate = 48000;
        !          1477: #endif
        !          1478:
        !          1479:        autri_setup_channel(sc, AUMODE_RECORD, param);
        !          1480:
        !          1481:        /* enable interrupt */
        !          1482:        autri_enable_interrupt(sc, sc->sc_rec.ch_intr);
        !          1483:
        !          1484:        /* start channel */
        !          1485:        autri_startch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
        !          1486:
        !          1487:        return 0;
        !          1488: }
        !          1489:
        !          1490: #if 0
        !          1491: int
        !          1492: autri_halt(sc)
        !          1493:        struct autri_softc *sc;
        !          1494: {
        !          1495:        DPRINTF(("autri_halt().\n"));
        !          1496:        /*autri_stopch(sc);*/
        !          1497:        autri_disable_interrupt(sc, sc->sc_play.channel);
        !          1498:        autri_disable_interrupt(sc, sc->sc_rec.channel);
        !          1499:        return 0;
        !          1500: }
        !          1501: #endif
        !          1502:
        !          1503: void
        !          1504: autri_enable_interrupt(sc, ch)
        !          1505:        struct autri_softc *sc;
        !          1506:        int ch;
        !          1507: {
        !          1508:        int reg;
        !          1509:
        !          1510:        reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
        !          1511:        ch &= 0x1f;
        !          1512:
        !          1513:        autri_reg_set_4(sc, reg, 1 << ch);
        !          1514: }
        !          1515:
        !          1516: void
        !          1517: autri_disable_interrupt(sc, ch)
        !          1518:        struct autri_softc *sc;
        !          1519:        int ch;
        !          1520: {
        !          1521:        int reg;
        !          1522:
        !          1523:        reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
        !          1524:        ch &= 0x1f;
        !          1525:
        !          1526:        autri_reg_clear_4(sc, reg, 1 << ch);
        !          1527: }
        !          1528:
        !          1529: void
        !          1530: autri_startch(sc, ch, ch_intr)
        !          1531:        struct autri_softc *sc;
        !          1532:        int ch, ch_intr;
        !          1533: {
        !          1534:        int reg;
        !          1535:        u_int32_t chmask;
        !          1536:
        !          1537:        reg = (ch & 0x20) ? AUTRI_START_B : AUTRI_START_A;
        !          1538:        ch &= 0x1f;
        !          1539:        chmask = (1 << ch) | (1 << ch_intr);
        !          1540:
        !          1541:        autri_reg_set_4(sc, reg, chmask);
        !          1542: }
        !          1543:
        !          1544: void
        !          1545: autri_stopch(sc, ch, ch_intr)
        !          1546:        struct autri_softc *sc;
        !          1547:        int ch, ch_intr;
        !          1548: {
        !          1549:        int reg;
        !          1550:        u_int32_t chmask;
        !          1551:
        !          1552:        reg = (ch & 0x20) ? AUTRI_STOP_B : AUTRI_STOP_A;
        !          1553:        ch &= 0x1f;
        !          1554:        chmask = (1 << ch) | (1 << ch_intr);
        !          1555:
        !          1556:        autri_reg_set_4(sc, reg, chmask);
        !          1557: }
        !          1558:
        !          1559: #if NMIDI > 0
        !          1560: int
        !          1561: autri_midi_open(void *addr, int flags,
        !          1562:        void (*iintr)(void *, int),
        !          1563:        void (*ointr)(void *),
        !          1564:        void *arg)
        !          1565: {
        !          1566:        struct autri_softc *sc = addr;
        !          1567:
        !          1568:        DPRINTF(("autri_midi_open()\n"));
        !          1569:
        !          1570:        DPRINTFN(5,("MPUR1 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR1)));
        !          1571:        DPRINTFN(5,("MPUR2 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR2)));
        !          1572:
        !          1573:        sc->sc_iintr = iintr;
        !          1574:        sc->sc_ointr = ointr;
        !          1575:        sc->sc_arg = arg;
        !          1576:
        !          1577:        if (flags & FREAD)
        !          1578:                autri_reg_clear_1(sc, AUTRI_MPUR2, AUTRI_MIDIIN_ENABLE_INTR);
        !          1579:
        !          1580:        if (flags & FWRITE)
        !          1581:                autri_reg_set_1(sc, AUTRI_MPUR2, AUTRI_MIDIOUT_CONNECT);
        !          1582:
        !          1583:        return (0);
        !          1584: }
        !          1585:
        !          1586: void
        !          1587: autri_midi_close(void *addr)
        !          1588: {
        !          1589:        struct autri_softc *sc = addr;
        !          1590:
        !          1591:        DPRINTF(("autri_midi_close()\n"));
        !          1592:
        !          1593:        tsleep(sc, PWAIT, "autri", hz/10); /* give uart a chance to drain */
        !          1594:
        !          1595:        sc->sc_iintr = NULL;
        !          1596:        sc->sc_ointr = NULL;
        !          1597: }
        !          1598:
        !          1599: int
        !          1600: autri_midi_output(void *addr, int d)
        !          1601: {
        !          1602:        struct autri_softc *sc = addr;
        !          1603:        int x;
        !          1604:
        !          1605:        for (x = 0; x != MIDI_BUSY_WAIT; x++) {
        !          1606:                if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) == 0) {
        !          1607:                        TWRITE1(sc, AUTRI_MPUR0, d);
        !          1608:                        return (0);
        !          1609:                }
        !          1610:                delay(MIDI_BUSY_DELAY);
        !          1611:        }
        !          1612:        return (EIO);
        !          1613: }
        !          1614:
        !          1615: void
        !          1616: autri_midi_getinfo(void *addr, struct midi_info *mi)
        !          1617: {
        !          1618:        mi->name = "4DWAVE MIDI UART";
        !          1619:        mi->props = MIDI_PROP_CAN_INPUT;
        !          1620: }
        !          1621:
        !          1622: #endif

CVSweb