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

Annotation of sys/dev/isa/pss.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: pss.c,v 1.22 2003/04/27 11:22:53 ho Exp $ */
                      2: /*     $NetBSD: pss.c,v 1.38 1998/01/12 09:43:44 thorpej Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1994 John Brezak
                      6:  * Copyright (c) 1991-1993 Regents of the University of California.
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *     This product includes software developed by the Computer Systems
                     20:  *     Engineering Group at Lawrence Berkeley Laboratory.
                     21:  * 4. Neither the name of the University nor of the Laboratory may be used
                     22:  *    to endorse or promote products derived from this software without
                     23:  *    specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     35:  * SUCH DAMAGE.
                     36:  *
                     37:  */
                     38:
                     39: /*
                     40:  * Copyright (c) 1993 Analog Devices Inc. All rights reserved
                     41:  *
                     42:  * Portions provided by Marc.Hoffman@analog.com and
                     43:  * Greg.Yukna@analog.com .
                     44:  *
                     45:  */
                     46:
                     47: /*
                     48:  * Todo:
                     49:  *     - Provide PSS driver to access DSP
                     50:  *     - Provide MIDI driver to access MPU
                     51:  *     - Finish support for CD drive (Sony and SCSI)
                     52:  */
                     53:
                     54: #include <sys/param.h>
                     55: #include <sys/systm.h>
                     56: #include <sys/errno.h>
                     57: #include <sys/ioctl.h>
                     58: #include <sys/syslog.h>
                     59: #include <sys/device.h>
                     60: #include <sys/proc.h>
                     61: #include <sys/buf.h>
                     62:
                     63: #include <machine/cpu.h>
                     64: #include <machine/intr.h>
                     65: #include <machine/bus.h>
                     66:
                     67: #include <sys/audioio.h>
                     68: #include <dev/audio_if.h>
                     69:
                     70: #include <dev/isa/isavar.h>
                     71: #include <dev/isa/isadmavar.h>
                     72:
                     73: #include <dev/isa/ad1848var.h>
                     74: #include <dev/isa/wssreg.h>
                     75: #include <dev/isa/pssreg.h>
                     76:
                     77: /* XXX Default WSS base */
                     78: #define WSS_BASE_ADDRESS 0x0530
                     79:
                     80: /*
                     81:  * Mixer devices
                     82:  */
                     83: #define PSS_MIC_IN_LVL         0
                     84: #define PSS_LINE_IN_LVL                1
                     85: #define PSS_DAC_LVL            2
                     86: #define PSS_REC_LVL            3
                     87: #define PSS_MON_LVL            4
                     88: #define PSS_MASTER_VOL         5
                     89: #define PSS_MASTER_TREBLE      6
                     90: #define PSS_MASTER_BASS                7
                     91: #define PSS_MIC_IN_MUTE                8
                     92: #define PSS_LINE_IN_MUTE       9
                     93: #define PSS_DAC_MUTE           10
                     94:
                     95: #define PSS_OUTPUT_MODE                11
                     96: #define        PSS_SPKR_MONO   0
                     97: #define        PSS_SPKR_STEREO 1
                     98: #define        PSS_SPKR_PSEUDO 2
                     99: #define        PSS_SPKR_SPATIAL 3
                    100:
                    101: #define PSS_RECORD_SOURCE      12
                    102:
                    103: /* Classes */
                    104: #define PSS_INPUT_CLASS                13
                    105: #define PSS_RECORD_CLASS       14
                    106: #define PSS_MONITOR_CLASS      15
                    107: #define PSS_OUTPUT_CLASS       16
                    108:
                    109:
                    110: struct pss_softc {
                    111:        struct  device sc_dev;          /* base device */
                    112:        void    *sc_ih;                 /* interrupt vectoring */
                    113:
                    114:        int     sc_iobase;              /* I/O port base address */
                    115:        int     sc_drq;                 /* dma channel */
                    116:
                    117:        struct  ad1848_softc *ad1848_sc;
                    118:
                    119:        int     out_port;
                    120:
                    121:        struct  ad1848_volume master_volume;
                    122:        int     master_mode;
                    123:
                    124:        int     monitor_treble;
                    125:        int     monitor_bass;
                    126:
                    127:        int     mic_mute, cd_mute, dac_mute;
                    128: };
                    129:
                    130: #ifdef notyet
                    131: struct mpu_softc {
                    132:        struct  device sc_dev;          /* base device */
                    133:        void    *sc_ih;                 /* interrupt vectoring */
                    134:
                    135:        int     sc_iobase;              /* MIDI I/O port base address */
                    136:        int     sc_irq;                 /* MIDI interrupt */
                    137: };
                    138:
                    139: struct pcd_softc {
                    140:        struct  device sc_dev;          /* base device */
                    141:        void    *sc_ih;                 /* interrupt vectoring */
                    142:
                    143:        int     sc_iobase;              /* CD I/O port base address */
                    144:        int     sc_irq;                 /* CD interrupt */
                    145: };
                    146: #endif
                    147:
                    148: #ifdef AUDIO_DEBUG
                    149: #define DPRINTF(x)     if (pssdebug) printf x
                    150: int    pssdebug = 0;
                    151: #else
                    152: #define DPRINTF(x)
                    153: #endif
                    154:
                    155: int    pssprobe(struct device *, void *, void *);
                    156: void   pssattach(struct device *, struct device *, void *);
                    157:
                    158: int    spprobe(struct device *, void *, void *);
                    159: void   spattach(struct device *, struct device *, void *);
                    160:
                    161: #ifdef notyet
                    162: int    mpuprobe(struct device *, void *, void *);
                    163: void   mpuattach(struct device *, struct device *, void *);
                    164:
                    165: int    pcdprobe(struct device *, void *, void *);
                    166: void   pcdattach(struct device *, struct device *, void *);
                    167: #endif
                    168:
                    169: int    pssintr(void *);
                    170: #ifdef notyet
                    171: int    mpuintr(void *);
                    172: #endif
                    173:
                    174: int    pss_speaker_ctl(void *, int);
                    175:
                    176: int    pss_getdev(void *, struct audio_device *);
                    177:
                    178: int    pss_mixer_set_port(void *, mixer_ctrl_t *);
                    179: int    pss_mixer_get_port(void *, mixer_ctrl_t *);
                    180: int    pss_query_devinfo(void *, mixer_devinfo_t *);
                    181:
                    182: #ifdef PSS_DSP
                    183: void   pss_dspwrite(struct pss_softc *, int);
                    184: #endif
                    185: void   pss_setaddr(int, int);
                    186: int    pss_setint(int, int);
                    187: int    pss_setdma(int, int);
                    188: int    pss_testirq(struct pss_softc *, int);
                    189: int    pss_testdma(struct pss_softc *, int);
                    190: #ifdef notyet
                    191: int    pss_reset_dsp(struct pss_softc *);
                    192: int    pss_download_dsp(struct pss_softc *, u_char *, int);
                    193: #endif
                    194: #ifdef AUDIO_DEBUG
                    195: void   pss_dump_regs(struct pss_softc *);
                    196: #endif
                    197: int    pss_set_master_gain(struct pss_softc *, struct ad1848_volume *);
                    198: int    pss_set_master_mode(struct pss_softc *, int);
                    199: int    pss_set_treble(struct pss_softc *, u_int);
                    200: int    pss_set_bass(struct pss_softc *, u_int);
                    201: int    pss_get_master_gain(struct pss_softc *, struct ad1848_volume *);
                    202: int    pss_get_master_mode(struct pss_softc *, u_int *);
                    203: int    pss_get_treble(struct pss_softc *, u_char *);
                    204: int    pss_get_bass(struct pss_softc *, u_char *);
                    205:
                    206: #ifdef AUDIO_DEBUG
                    207: void   wss_dump_regs(struct ad1848_softc *);
                    208: #endif
                    209:
                    210: /*
                    211:  * Define our interface to the higher level audio driver.
                    212:  */
                    213:
                    214: struct audio_hw_if pss_audio_if = {
                    215:        ad1848_open,
                    216:        ad1848_close,
                    217:        NULL,
                    218:        ad1848_query_encoding,
                    219:        ad1848_set_params,
                    220:        ad1848_round_blocksize,
                    221:        ad1848_commit_settings,
                    222:        ad1848_dma_init_output,
                    223:        ad1848_dma_init_input,
                    224:        ad1848_dma_output,
                    225:        ad1848_dma_input,
                    226:        ad1848_halt_out_dma,
                    227:        ad1848_halt_in_dma,
                    228:        pss_speaker_ctl,
                    229:        pss_getdev,
                    230:        NULL,
                    231:        pss_mixer_set_port,
                    232:        pss_mixer_get_port,
                    233:        pss_query_devinfo,
                    234:        ad1848_malloc,
                    235:        ad1848_free,
                    236:        ad1848_round,
                    237:        ad1848_mappage,
                    238:        ad1848_get_props,
                    239:        NULL,
                    240:        NULL
                    241: };
                    242:
                    243:
                    244: /* Interrupt translation for WSS config */
                    245: static u_char wss_interrupt_bits[16] = {
                    246:     0xff, 0xff, 0xff, 0xff,
                    247:     0xff, 0xff, 0xff, 0x08,
                    248:     0xff, 0x10, 0x18, 0x20,
                    249:     0xff, 0xff, 0xff, 0xff
                    250: };
                    251: /* ditto for WSS DMA channel */
                    252: static u_char wss_dma_bits[4] = {1, 2, 0, 3};
                    253:
                    254: struct cfattach pss_ca = {
                    255:        sizeof(struct pss_softc), pssprobe, pssattach
                    256: };
                    257:
                    258: struct cfdriver pss_cd = {
                    259:        NULL, "pss", DV_DULL, 1
                    260: };
                    261:
                    262: struct cfattach sp_ca = {
                    263:        sizeof(struct ad1848_softc), spprobe, spattach
                    264: };
                    265:
                    266: struct cfdriver sp_cd = {
                    267:        NULL, "sp", DV_DULL
                    268: };
                    269:
                    270: #ifdef notyet
                    271: struct cfattach mpu_ca = {
                    272:        sizeof(struct mpu_softc), mpuprobe, mpuattach
                    273: };
                    274:
                    275: struct cfdriver mpu_cd = {
                    276:        NULL, "mpu", DV_DULL
                    277: };
                    278:
                    279: struct cfattach pcd_ca = {
                    280:        sizeof(struct pcd_softc), pcdprobe, pcdattach
                    281: };
                    282:
                    283: struct cfdriver pcd_cd = {
                    284:        NULL, "pcd", DV_DULL
                    285: };
                    286: #endif
                    287:
                    288: struct audio_device pss_device = {
                    289:        "pss,ad1848",
                    290:        "",
                    291:        "PSS"
                    292: };
                    293:
                    294: #ifdef PSS_DSP
                    295: void
                    296: pss_dspwrite(sc, data)
                    297:        struct pss_softc *sc;
                    298:        int data;
                    299: {
                    300:     int i;
                    301:     int pss_base = sc->sc_iobase;
                    302:
                    303:     /*
                    304:      * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes
                    305:      * called while interrupts are disabled. This means that the timer is
                    306:      * disabled also. However the timeout situation is a abnormal condition.
                    307:      * Normally the DSP should be ready to accept commands after just couple of
                    308:      * loops.
                    309:      */
                    310:     for (i = 0; i < 5000000; i++) {
                    311:        if (inw(pss_base+PSS_STATUS) & PSS_WRITE_EMPTY) {
                    312:            outw(pss_base+PSS_DATA, data);
                    313:            return;
                    314:        }
                    315:     }
                    316:     printf ("pss: DSP Command (%04x) Timeout.\n", data);
                    317: }
                    318: #endif /* PSS_DSP */
                    319:
                    320: void
                    321: pss_setaddr(addr, configAddr)
                    322:        int addr;
                    323:        int configAddr;
                    324: {
                    325:     int val;
                    326:
                    327:     val = inw(configAddr);
                    328:     val &= ADDR_MASK;
                    329:     val |= (addr << 4);
                    330:     outw(configAddr,val);
                    331: }
                    332:
                    333: /* pss_setint
                    334:  * This function sets the correct bits in the
                    335:  * configuration register to
                    336:  * enable the chosen interrupt.
                    337:  */
                    338: int
                    339: pss_setint(intNum, configAddress)
                    340:        int intNum;
                    341:        int configAddress;
                    342: {
                    343:     int val;
                    344:
                    345:     switch(intNum) {
                    346:     case 3:
                    347:        val = inw(configAddress);
                    348:        val &= INT_MASK;
                    349:        val |= INT_3_BITS;
                    350:        break;
                    351:     case 5:
                    352:        val = inw(configAddress);
                    353:        val &= INT_MASK;
                    354:        val |= INT_5_BITS;
                    355:        break;
                    356:     case 7:
                    357:        val = inw(configAddress);
                    358:        val &= INT_MASK;
                    359:        val |= INT_7_BITS;
                    360:        break;
                    361:     case 9:
                    362:        val = inw(configAddress);
                    363:        val &= INT_MASK;
                    364:        val |= INT_9_BITS;
                    365:        break;
                    366:     case 10:
                    367:        val = inw(configAddress);
                    368:        val &= INT_MASK;
                    369:        val |= INT_10_BITS;
                    370:        break;
                    371:     case 11:
                    372:        val = inw(configAddress);
                    373:        val &= INT_MASK;
                    374:        val |= INT_11_BITS;
                    375:        break;
                    376:     case 12:
                    377:        val = inw(configAddress);
                    378:        val &= INT_MASK;
                    379:        val |= INT_12_BITS;
                    380:        break;
                    381:     default:
                    382:        DPRINTF(("pss_setint: invalid irq (%d)\n", intNum));
                    383:        return 1;
                    384:     }
                    385:     outw(configAddress,val);
                    386:     return 0;
                    387: }
                    388:
                    389: int
                    390: pss_setdma(dmaNum, configAddress)
                    391:        int dmaNum;
                    392:        int configAddress;
                    393: {
                    394:     int val;
                    395:
                    396:     switch(dmaNum) {
                    397:     case 0:
                    398:        val = inw(configAddress);
                    399:        val &= DMA_MASK;
                    400:        val |= DMA_0_BITS;
                    401:        break;
                    402:     case 1:
                    403:        val = inw(configAddress);
                    404:        val &= DMA_MASK;
                    405:        val |= DMA_1_BITS;
                    406:        break;
                    407:     case 3:
                    408:        val = inw(configAddress);
                    409:        val &= DMA_MASK;
                    410:        val |= DMA_3_BITS;
                    411:        break;
                    412:     case 5:
                    413:        val = inw(configAddress);
                    414:        val &= DMA_MASK;
                    415:        val |= DMA_5_BITS;
                    416:        break;
                    417:     case 6:
                    418:        val = inw(configAddress);
                    419:        val &= DMA_MASK;
                    420:        val |= DMA_6_BITS;
                    421:        break;
                    422:     case 7:
                    423:        val = inw(configAddress);
                    424:        val &= DMA_MASK;
                    425:        val |= DMA_7_BITS;
                    426:        break;
                    427:     default:
                    428:        DPRINTF(("pss_setdma: invalid drq (%d)\n", dmaNum));
                    429:        return 1;
                    430:     }
                    431:     outw(configAddress, val);
                    432:     return 0;
                    433: }
                    434:
                    435: /*
                    436:  * This function tests an interrupt number to see if
                    437:  * it is available. It takes the interrupt button
                    438:  * as its argument and returns TRUE if the interrupt
                    439:  * is ok.
                    440: */
                    441: int
                    442: pss_testirq(struct pss_softc *sc, int intNum)
                    443: {
                    444:     int config = sc->sc_iobase + PSS_CONFIG;
                    445:     int val;
                    446:     int ret;
                    447:     int i;
                    448:
                    449:     /* Set the interrupt bits */
                    450:     switch(intNum) {
                    451:     case 3:
                    452:        val = inw(config);
                    453:        val &= INT_MASK;        /* Special: 0 */
                    454:        break;
                    455:     case 5:
                    456:        val = inw(config);
                    457:        val &= INT_MASK;
                    458:        val |= INT_TEST_BIT | INT_5_BITS;
                    459:        break;
                    460:     case 7:
                    461:        val = inw(config);
                    462:        val &= INT_MASK;
                    463:        val |= INT_TEST_BIT | INT_7_BITS;
                    464:        break;
                    465:     case 9:
                    466:        val = inw(config);
                    467:        val &= INT_MASK;
                    468:        val |= INT_TEST_BIT | INT_9_BITS;
                    469:        break;
                    470:     case 10:
                    471:        val = inw(config);
                    472:        val &= INT_MASK;
                    473:        val |= INT_TEST_BIT | INT_10_BITS;
                    474:        break;
                    475:     case 11:
                    476:        val = inw(config);
                    477:        val &= INT_MASK;
                    478:        val |= INT_TEST_BIT | INT_11_BITS;
                    479:        break;
                    480:     case 12:
                    481:        val = inw(config);
                    482:        val &= INT_MASK;
                    483:        val |= INT_TEST_BIT | INT_12_BITS;
                    484:        break;
                    485:     default:
                    486:        DPRINTF(("pss_testirq: invalid irq (%d)\n", intNum));
                    487:        return 0;
                    488:     }
                    489:     outw(config, val);
                    490:
                    491:     /* Check if the interrupt is in use */
                    492:     /* Do it a few times in case there is a delay */
                    493:     ret = 0;
                    494:     for (i = 0; i < 5; i++) {
                    495:        val = inw(config);
                    496:        if (val & INT_TEST_PASS) {
                    497:            ret = 1;
                    498:            break;
                    499:        }
                    500:     }
                    501:
                    502:     /* Clear the Test bit and the interrupt bits */
                    503:     val = inw(config);
                    504:     val &= INT_TEST_BIT_MASK & INT_MASK;
                    505:     outw(config, val);
                    506:     return(ret);
                    507: }
                    508:
                    509: /*
                    510:  * This function tests a dma channel to see if
                    511:  * it is available. It takes the DMA channel button
                    512:  * as its argument and returns TRUE if the channel
                    513:  * is ok.
                    514:  */
                    515: int
                    516: pss_testdma(sc, dmaNum)
                    517:        struct pss_softc *sc;
                    518:        int dmaNum;
                    519: {
                    520:     int config = sc->sc_iobase + PSS_CONFIG;
                    521:     int val;
                    522:     int i, ret;
                    523:
                    524:     switch (dmaNum) {
                    525:     case 0:
                    526:        val = inw(config);
                    527:        val &= DMA_MASK;
                    528:        val |= DMA_TEST_BIT | DMA_0_BITS;
                    529:        break;
                    530:     case 1:
                    531:        val = inw(config);
                    532:        val &= DMA_MASK;
                    533:        val |= DMA_TEST_BIT | DMA_1_BITS;
                    534:        break;
                    535:     case 3:
                    536:        val = inw(config);
                    537:        val &= DMA_MASK;
                    538:        val |= DMA_TEST_BIT | DMA_3_BITS;
                    539:        break;
                    540:     case 5:
                    541:        val = inw(config);
                    542:        val &= DMA_MASK;
                    543:        val |= DMA_TEST_BIT | DMA_5_BITS;
                    544:        break;
                    545:     case 6:
                    546:        val = inw(config);
                    547:        val &= DMA_MASK;
                    548:        val |= DMA_TEST_BIT | DMA_6_BITS;
                    549:        break;
                    550:     case 7:
                    551:        val = inw(config);
                    552:        val &= DMA_MASK;
                    553:        val |= DMA_TEST_BIT | DMA_7_BITS;
                    554:        break;
                    555:     default:
                    556:        DPRINTF(("pss_testdma: invalid drq (%d)\n", dmaNum));
                    557:        return 0;
                    558:     }
                    559:     outw(config, val);
                    560:
                    561:     /* Check if the DMA channel is in use */
                    562:     /* Do it a few times in case there is a delay */
                    563:     ret = 0;
                    564:     for (i = 0; i < 3; i++) {
                    565:        val = inw(config);
                    566:        if (val & DMA_TEST_PASS) {
                    567:            ret = 1;
                    568:            break;
                    569:        }
                    570:     }
                    571:
                    572:     /* Clear the Test bit and the DMA bits */
                    573:     val = inw(config);
                    574:     val &= DMA_TEST_BIT_MASK & DMA_MASK;
                    575:     outw(config, val);
                    576:     return(ret);
                    577: }
                    578:
                    579: #ifdef notyet
                    580: int
                    581: pss_reset_dsp(sc)
                    582:        struct pss_softc *sc;
                    583: {
                    584:     u_long i;
                    585:     int pss_base = sc->sc_iobase;
                    586:
                    587:     outw(pss_base+PSS_CONTROL, PSS_RESET);
                    588:
                    589:     for (i = 0; i < 32768; i++)
                    590:        inw(pss_base+PSS_CONTROL);
                    591:
                    592:     outw(pss_base+PSS_CONTROL, 0);
                    593:
                    594:     return 1;
                    595: }
                    596:
                    597: /*
                    598:  * This function loads an image into the PSS
                    599:  * card.  The function loads the file by
                    600:  * resetting the dsp and feeding it the boot bytes.
                    601:  * First you feed the ASIC the first byte of
                    602:  * the boot sequence. The ASIC waits until it
                    603:  * detects a BMS and RD and asserts BR
                    604:  * and outputs the byte.  The host must poll for
                    605:  * the BG signal. It then feeds the ASIC another
                    606:  * byte which removes BR.
                    607:  */
                    608: int
                    609: pss_download_dsp(sc, block, size)
                    610:        struct pss_softc *sc;
                    611:        u_char *block;
                    612:        int size;
                    613: {
                    614:     int i, val, count;
                    615:     int pss_base = sc->sc_iobase;
                    616:
                    617:     DPRINTF(("pss: downloading boot code..."));
                    618:
                    619:     /* Warn DSP software that a boot is coming */
                    620:     outw(pss_base+PSS_DATA, 0x00fe);
                    621:
                    622:     for (i = 0; i < 32768; i++)
                    623:        if (inw(pss_base+PSS_DATA) == 0x5500)
                    624:            break;
                    625:     outw(pss_base+PSS_DATA, *block++);
                    626:
                    627:     pss_reset_dsp(sc);
                    628:
                    629:     DPRINTF(("start "));
                    630:
                    631:     count = 1;
                    632:     while(1) {
                    633:        int j;
                    634:        for (j=0; j<327670; j++) {
                    635:            /* Wait for BG to appear */
                    636:            if (inw(pss_base+PSS_STATUS) & PSS_FLAG3)
                    637:                break;
                    638:        }
                    639:
                    640:        if (j==327670) {
                    641:            /* It's ok we timed out when the file was empty */
                    642:            if (count >= size)
                    643:                break;
                    644:            else {
                    645:                printf("\npss: DownLoad timeout problems, byte %d=%d\n",
                    646:                       count, size);
                    647:                return 0;
                    648:            }
                    649:        }
                    650:        /* Send the next byte */
                    651:        outw(pss_base+PSS_DATA, *block++);
                    652:        count++;
                    653:     }
                    654:
                    655:     outw(pss_base+PSS_DATA, 0);
                    656:     for (i = 0; i < 32768; i++)
                    657:        (void) inw(pss_base+PSS_STATUS);
                    658:
                    659:     DPRINTF(("downloaded\n"));
                    660:
                    661:     for (i = 0; i < 32768; i++) {
                    662:        val = inw(pss_base+PSS_STATUS);
                    663:        if (val & PSS_READ_FULL)
                    664:            break;
                    665:     }
                    666:
                    667:     /* now read the version */
                    668:     for (i = 0; i < 32000; i++) {
                    669:        val = inw(pss_base+PSS_STATUS);
                    670:        if (val & PSS_READ_FULL)
                    671:            break;
                    672:     }
                    673:     if (i == 32000)
                    674:        return 0;
                    675:
                    676:     (void) inw(pss_base+PSS_DATA);
                    677:
                    678:     return 1;
                    679: }
                    680: #endif /* notyet */
                    681:
                    682: #ifdef AUDIO_DEBUG
                    683: void
                    684: wss_dump_regs(sc)
                    685:        struct ad1848_softc *sc;
                    686: {
                    687:
                    688:     printf("WSS reg: status=%02x\n",
                    689:           (u_char)inb(sc->sc_iobase-WSS_CODEC+WSS_STATUS));
                    690: }
                    691:
                    692: void
                    693: pss_dump_regs(sc)
                    694:        struct pss_softc *sc;
                    695: {
                    696:
                    697:     printf("PSS regs: status=%04x vers=%04x ",
                    698:           (u_short)inw(sc->sc_iobase+PSS_STATUS),
                    699:           (u_short)inw(sc->sc_iobase+PSS_ID_VERS));
                    700:
                    701:     printf("config=%04x wss_config=%04x\n",
                    702:           (u_short)inw(sc->sc_iobase+PSS_CONFIG),
                    703:           (u_short)inw(sc->sc_iobase+PSS_WSS_CONFIG));
                    704: }
                    705: #endif
                    706:
                    707: /*
                    708:  * Probe for the PSS hardware.
                    709:  */
                    710: int
                    711: pssprobe(parent, self, aux)
                    712:     struct device *parent;
                    713:     void *self;
                    714:     void *aux;
                    715: {
                    716:     struct pss_softc *sc = self;
                    717:     struct isa_attach_args *ia = aux;
                    718:     int iobase = ia->ia_iobase;
                    719:
                    720:     if (!PSS_BASE_VALID(iobase)) {
                    721:        DPRINTF(("pss: configured iobase %x invalid\n", iobase));
                    722:        return 0;
                    723:     }
                    724:
                    725:     /* Need to probe for iobase when IOBASEUNK {0x220 0x240} */
                    726:     if (iobase == IOBASEUNK) {
                    727:
                    728:        iobase = 0x220;
                    729:        if ((inw(iobase+PSS_ID_VERS) & 0xff00) == 0x4500)
                    730:            goto pss_found;
                    731:
                    732:        iobase = 0x240;
                    733:        if ((inw(iobase+PSS_ID_VERS) & 0xff00) == 0x4500)
                    734:            goto pss_found;
                    735:
                    736:        DPRINTF(("pss: no PSS found (at 0x220 or 0x240)\n"));
                    737:        return 0;
                    738:     }
                    739:     else if ((inw(iobase+PSS_ID_VERS) & 0xff00) != 0x4500) {
                    740:        DPRINTF(("pss: not a PSS - %x\n", inw(iobase+PSS_ID_VERS)));
                    741:        return 0;
                    742:     }
                    743:
                    744: pss_found:
                    745:     sc->sc_iobase = iobase;
                    746:
                    747:     /* Clear WSS config */
                    748:     pss_setaddr(WSS_BASE_ADDRESS, sc->sc_iobase+PSS_WSS_CONFIG); /* XXX! */
                    749:     outb(WSS_BASE_ADDRESS+WSS_CONFIG, 0);
                    750:
                    751:     /* Clear config registers (POR reset state) */
                    752:     outw(sc->sc_iobase+PSS_CONFIG, 0);
                    753:     outw(sc->sc_iobase+PSS_WSS_CONFIG, 0);
                    754:     outw(sc->sc_iobase+SB_CONFIG, 0);
                    755:     outw(sc->sc_iobase+MIDI_CONFIG, 0);
                    756:     outw(sc->sc_iobase+CD_CONFIG, 0);
                    757:
                    758:     if (ia->ia_irq == IRQUNK) {
                    759:        int i;
                    760:        for (i = 0; i < 16; i++) {
                    761:            if (pss_testirq(sc, i) != 0)
                    762:                break;
                    763:        }
                    764:        if (i == 16) {
                    765:            DPRINTF(("pss: unable to locate free IRQ channel\n"));
                    766:            return 0;
                    767:        }
                    768:        else {
                    769:            ia->ia_irq = i;
                    770:            DPRINTF(("pss: found IRQ %d free\n", i));
                    771:        }
                    772:     }
                    773:     else {
                    774:        if (pss_testirq(sc, ia->ia_irq) == 0) {
                    775:            DPRINTF(("pss: configured IRQ unavailable (%d)\n", ia->ia_irq));
                    776:            return 0;
                    777:        }
                    778:     }
                    779:
                    780:     /* XXX Need to deal with DRQUNK */
                    781:     if (pss_testdma(sc, ia->ia_drq) == 0) {
                    782:        DPRINTF(("pss: configured DMA channel unavailable (%d)\n", ia->ia_drq));
                    783:        return 0;
                    784:     }
                    785:
                    786:     ia->ia_iosize = PSS_NPORT;
                    787:
                    788:     /* Initialize PSS irq and dma */
                    789:     pss_setint(ia->ia_irq, sc->sc_iobase+PSS_CONFIG);
                    790:     pss_setdma(sc->sc_drq, sc->sc_iobase+PSS_CONFIG);
                    791:
                    792: #ifdef notyet
                    793:     /* Setup the Game port */
                    794: #ifdef PSS_GAMEPORT
                    795:     DPRINTF(("Turning Game Port On.\n"));
                    796:     outw(sc->sc_iobase+PSS_STATUS, inw(sc->sc_iobase+PSS_STATUS) | GAME_BIT);
                    797: #else
                    798:     outw(sc->sc_iobase+PSS_STATUS, inw(sc->sc_iobase+PSS_STATUS) & GAME_BIT_MASK);
                    799: #endif
                    800:
                    801:     /* Reset DSP */
                    802:     pss_reset_dsp(sc);
                    803: #endif /* notyet */
                    804:
                    805:     return 1;
                    806: }
                    807:
                    808: /*
                    809:  * Probe for the Soundport (ad1848)
                    810:  */
                    811: int
                    812: spprobe(parent, match, aux)
                    813:     struct device *parent;
                    814:     void *match, *aux;
                    815: {
                    816:     struct ad1848_softc *sc = match;
                    817:     struct pss_softc *pc = (void *) parent;
                    818:     struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
                    819:     struct isa_attach_args *ia = aux;
                    820:     u_char bits;
                    821:     int i;
                    822:
                    823:     sc->sc_iot = ia->ia_iot;
                    824:     sc->sc_iobase = cf->cf_iobase + WSS_CODEC;
                    825:
                    826:     /* Set WSS io address */
                    827:     pss_setaddr(cf->cf_iobase, pc->sc_iobase+PSS_WSS_CONFIG);
                    828:
                    829:     /* Is there an ad1848 chip at the WSS iobase ? */
                    830:     if (ad1848_probe(sc) == 0) {
                    831:        DPRINTF(("sp: no ad1848 ? iobase=%x\n", sc->sc_iobase));
                    832:        return 0;
                    833:     }
                    834:
                    835:     /* Setup WSS interrupt and DMA if auto */
                    836:     if (cf->cf_irq == IRQUNK) {
                    837:
                    838:        /* Find unused IRQ for WSS */
                    839:        for (i = 0; i < 12; i++) {
                    840:            if (wss_interrupt_bits[i] != 0xff) {
                    841:                if (pss_testirq(pc, i))
                    842:                    break;
                    843:            }
                    844:        }
                    845:        if (i == 12) {
                    846:            DPRINTF(("sp: unable to locate free IRQ for WSS\n"));
                    847:            return 0;
                    848:        }
                    849:        else {
                    850:            cf->cf_irq = i;
                    851:            sc->sc_irq = i;
                    852:            DPRINTF(("sp: found IRQ %d free\n", i));
                    853:        }
                    854:     }
                    855:     else {
                    856:        sc->sc_irq = cf->cf_irq;
                    857:        if (pss_testirq(pc, sc->sc_irq) == 0) {
                    858:            DPRINTF(("sp: configured IRQ unavailable (%d)\n", sc->sc_irq));
                    859:            return 0;
                    860:        }
                    861:     }
                    862:
                    863:     if (cf->cf_drq == DRQUNK) {
                    864:        /* Find unused DMA channel for WSS */
                    865:        for (i = 0; i < 4; i++) {
                    866:            if (wss_dma_bits[i]) {
                    867:                if (pss_testdma(pc, i))
                    868:                    break;
                    869:            }
                    870:        }
                    871:        if (i == 4) {
                    872:            DPRINTF(("sp: unable to locate free DMA channel for WSS\n"));
                    873:            return 0;
                    874:        }
                    875:        else {
                    876:            sc->sc_drq = cf->cf_drq = i;
                    877:            DPRINTF(("sp: found DMA %d free\n", i));
                    878:        }
                    879:     }
                    880:     else {
                    881:        if (pss_testdma(pc, sc->sc_drq) == 0) {
                    882:            DPRINTF(("sp: configured DMA channel unavailable (%d)\n", sc->sc_drq));
                    883:            return 0;
                    884:        }
                    885:        sc->sc_drq = cf->cf_drq;
                    886:     }
                    887:     sc->sc_recdrq = sc->sc_drq;
                    888:
                    889:     /* Set WSS config registers */
                    890:     if ((bits = wss_interrupt_bits[sc->sc_irq]) == 0xff) {
                    891:        DPRINTF(("sp: invalid interrupt configuration (irq=%d)\n", sc->sc_irq));
                    892:        return 0;
                    893:     }
                    894:
                    895:     outb(sc->sc_iobase+WSS_CONFIG, (bits | 0x40));
                    896:     if ((inb(sc->sc_iobase+WSS_STATUS) & 0x40) == 0)   /* XXX What do these bits mean ? */
                    897:        DPRINTF(("sp: IRQ %x\n", inb(sc->sc_iobase+WSS_STATUS)));
                    898:
                    899:     outb(sc->sc_iobase+WSS_CONFIG, (bits | wss_dma_bits[sc->sc_drq]));
                    900:
                    901:     pc->ad1848_sc = sc;
                    902:     sc->parent = pc;
                    903:
                    904:     return 1;
                    905: }
                    906:
                    907: #ifdef notyet
                    908: int
                    909: mpuprobe(parent, match, aux)
                    910:     struct device *parent;
                    911:     void *match, *aux;
                    912: {
                    913:     struct mpu_softc *sc = match;
                    914:     struct pss_softc *pc = (void *) parent;
                    915:     struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
                    916:
                    917:     /* Check if midi is enabled; if it is check the interrupt */
                    918:     sc->sc_iobase = cf->cf_iobase;
                    919:
                    920:     if (cf->cf_irq == IRQUNK) {
                    921:        int i;
                    922:        for (i = 0; i < 16; i++) {
                    923:            if (pss_testirq(pc, i) != 0)
                    924:                break;
                    925:        }
                    926:        if (i == 16) {
                    927:            printf("mpu: unable to locate free IRQ channel for MIDI\n");
                    928:            return 0;
                    929:        }
                    930:        else {
                    931:            cf->cf_irq = i;
                    932:            sc->sc_irq = i;
                    933:            DPRINTF(("mpu: found IRQ %d free\n", i));
                    934:        }
                    935:     }
                    936:     else {
                    937:        sc->sc_irq = cf->cf_irq;
                    938:
                    939:        if (pss_testirq(pc, sc->sc_irq) == 0) {
                    940:            printf("pss: configured MIDI IRQ unavailable (%d)\n", sc->sc_irq);
                    941:            return 0;
                    942:        }
                    943:     }
                    944:
                    945:     outw(pc->sc_iobase+MIDI_CONFIG,0);
                    946:     DPRINTF(("pss: mpu port 0x%x irq %d\n", sc->sc_iobase, sc->sc_irq));
                    947:     pss_setaddr(sc->sc_iobase, pc->sc_iobase+MIDI_CONFIG);
                    948:     pss_setint(sc->sc_irq, pc->sc_iobase+MIDI_CONFIG);
                    949:
                    950:     return 1;
                    951: }
                    952:
                    953: int
                    954: pcdprobe(parent, match, aux)
                    955:     struct device *parent;
                    956:     void *match, *aux;
                    957: {
                    958:     struct pcd_softc *sc = match;
                    959:     struct pss_softc *pc = (void *) parent;
                    960:     struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
                    961:     u_short val;
                    962:
                    963:     sc->sc_iobase = cf->cf_iobase;
                    964:
                    965:     pss_setaddr(sc->sc_iobase, pc->sc_iobase+CD_CONFIG);
                    966:
                    967:     /* Set the correct irq polarity. */
                    968:     val = inw(pc->sc_iobase+CD_CONFIG);
                    969:     outw(pc->sc_iobase+CD_CONFIG, 0);
                    970:     val &= CD_POL_MASK;
                    971:     val |= CD_POL_BIT; /* XXX if (pol) */
                    972:     outw(pc->sc_iobase+CD_CONFIG, val);
                    973:
                    974:     if (cf->cf_irq == IRQUNK) {
                    975:        int i;
                    976:        for (i = 0; i < 16; i++) {
                    977:            if (pss_testirq(pc, i) != 0)
                    978:                break;
                    979:        }
                    980:        if (i == 16) {
                    981:            printf("pcd: unable to locate free IRQ channel for CD\n");
                    982:            return 0;
                    983:        }
                    984:        else {
                    985:            cf->cf_irq = i;
                    986:            sc->sc_irq = i;
                    987:            DPRINTF(("pcd: found IRQ %d free\n", i));
                    988:        }
                    989:     }
                    990:     else {
                    991:        sc->sc_irq = cf->cf_irq;
                    992:
                    993:        if (pss_testirq(pc, sc->sc_irq) == 0) {
                    994:            printf("pcd: configured CD IRQ unavailable (%d)\n", sc->sc_irq);
                    995:            return 0;
                    996:        }
                    997:        return 1;
                    998:     }
                    999:     pss_setint(sc->sc_irq, pc->sc_iobase+CD_CONFIG);
                   1000:
                   1001:     return 1;
                   1002: }
                   1003: #endif /* notyet */
                   1004:
                   1005: /*
                   1006:  * Attach hardware to driver, attach hardware driver to audio
                   1007:  * pseudo-device driver .
                   1008:  */
                   1009: void
                   1010: pssattach(parent, self, aux)
                   1011:     struct device *parent, *self;
                   1012:     void *aux;
                   1013: {
                   1014:     struct pss_softc *sc = (struct pss_softc *)self;
                   1015:     struct isa_attach_args *ia = (struct isa_attach_args *)aux;
                   1016:     int iobase = ia->ia_iobase;
                   1017:     u_char vers;
                   1018:     struct ad1848_volume vol = {150, 150};
                   1019:
                   1020:     sc->sc_iobase = iobase;
                   1021:     sc->sc_drq = ia->ia_drq;
                   1022:
                   1023:     /* Setup interrupt handler for PSS */
                   1024:     sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_AUDIO,
                   1025:        pssintr, sc, sc->sc_dev.dv_xname);
                   1026:
                   1027:     vers = (inw(sc->sc_iobase+PSS_ID_VERS)&0xff) - 1;
                   1028:     printf(": ESC614%c\n", (vers > 0)?'A'+vers:' ');
                   1029:
                   1030:     (void)config_found(self, ia->ia_ic, NULL);         /* XXX */
                   1031:
                   1032:     sc->out_port = PSS_MASTER_VOL;
                   1033:
                   1034:     (void)pss_set_master_mode(sc, PSS_SPKR_STEREO);
                   1035:     (void)pss_set_master_gain(sc, &vol);
                   1036:     (void)pss_set_treble(sc, AUDIO_MAX_GAIN/2);
                   1037:     (void)pss_set_bass(sc, AUDIO_MAX_GAIN/2);
                   1038:
                   1039:     audio_attach_mi(&pss_audio_if, sc->ad1848_sc, &sc->ad1848_sc->sc_dev);
                   1040: }
                   1041:
                   1042: void
                   1043: spattach(parent, self, aux)
                   1044:     struct device *parent, *self;
                   1045:     void *aux;
                   1046: {
                   1047:     struct ad1848_softc *sc = (struct ad1848_softc *)self;
                   1048:     struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
                   1049:     isa_chipset_tag_t ic = aux;                                /* XXX */
                   1050:     int iobase = cf->cf_iobase;
                   1051:
                   1052:     sc->sc_iobase = iobase;
                   1053:     sc->sc_drq = cf->cf_drq;
                   1054:
                   1055:     sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
                   1056:        ad1848_intr, sc, sc->sc_dev.dv_xname);
                   1057:
                   1058:     sc->sc_isa = parent->dv_parent;
                   1059:
                   1060:     ad1848_attach(sc);
                   1061:
                   1062:     printf("\n");
                   1063: }
                   1064:
                   1065: #ifdef notyet
                   1066: void
                   1067: mpuattach(parent, self, aux)
                   1068:     struct device *parent, *self;
                   1069:     void *aux;
                   1070: {
                   1071:     struct mpu_softc *sc = (struct mpu_softc *)self;
                   1072:     struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
                   1073:     isa_chipset_tag_t ic = aux;                                /* XXX */
                   1074:     int iobase = cf->cf_iobase;
                   1075:
                   1076:     sc->sc_iobase = iobase;
                   1077:
                   1078:     sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
                   1079:        mpuintr, sc, sc->sc_dev.dv_xname);
                   1080:
                   1081:     /* XXX might use pssprint func ?? */
                   1082:     printf(" port 0x%x/%d irq %d\n",
                   1083:           sc->sc_iobase, MIDI_NPORT, cf->cf_irq);
                   1084: }
                   1085:
                   1086: void
                   1087: pcdattach(parent, self, aux)
                   1088:     struct device *parent, *self;
                   1089:     void *aux;
                   1090: {
                   1091:     struct pcd_softc *sc = (struct pcd_softc *)self;
                   1092:     struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
                   1093:     int iobase = cf->cf_iobase;
                   1094:
                   1095:     /*
                   1096:      * The pss driver simply enables the cd interface. The CD
                   1097:      * appropriate driver - scsi (aic6360) or Sony needs to be
                   1098:      * used after this to handle the device.
                   1099:      */
                   1100:     sc->sc_iobase = iobase;
                   1101:
                   1102:     /* XXX might use pssprint func ?? */
                   1103:     printf(" port 0x%x/%d irq %d\n",
                   1104:           sc->sc_iobase, 2, cf->cf_irq);
                   1105: }
                   1106: #endif /* notyet */
                   1107:
                   1108:
                   1109: int
                   1110: pss_set_master_gain(sc, gp)
                   1111:     struct pss_softc *sc;
                   1112:     struct ad1848_volume *gp;
                   1113: {
                   1114:     DPRINTF(("pss_set_master_gain: %d:%d\n", gp->left, gp->right));
                   1115:
                   1116: #ifdef PSS_DSP
                   1117:     if (gp->left > PHILLIPS_VOL_MAX)
                   1118:        gp->left = PHILLIPS_VOL_MAX;
                   1119:     if (gp->left < PHILLIPS_VOL_MIN)
                   1120:        gp->left = PHILLIPS_VOL_MIN;
                   1121:     if (gp->right > PHILLIPS_VOL_MAX)
                   1122:        gp->right = PHILLIPS_VOL_MAX;
                   1123:     if (gp->right < PHILLIPS_VOL_MIN)
                   1124:        gp->right = PHILLIPS_VOL_MIN;
                   1125:
                   1126:     pss_dspwrite(sc, SET_MASTER_COMMAND);
                   1127:     pss_dspwrite(sc, MASTER_VOLUME_LEFT|(PHILLIPS_VOL_CONSTANT + gp->left / PHILLIPS_VOL_STEP));
                   1128:     pss_dspwrite(sc, SET_MASTER_COMMAND);
                   1129:     pss_dspwrite(sc, MASTER_VOLUME_RIGHT|(PHILLIPS_VOL_CONSTANT + gp->right / PHILLIPS_VOL_STEP));
                   1130: #endif
                   1131:
                   1132:     sc->master_volume = *gp;
                   1133:     return(0);
                   1134: }
                   1135:
                   1136: int
                   1137: pss_set_master_mode(sc, mode)
                   1138:     struct pss_softc *sc;
                   1139:     int mode;
                   1140: {
                   1141:     short phillips_mode;
                   1142:
                   1143:     DPRINTF(("pss_set_master_mode: %d\n", mode));
                   1144:
                   1145:     if (mode == PSS_SPKR_STEREO)
                   1146:        phillips_mode = PSS_STEREO;
                   1147:     else if (mode == PSS_SPKR_PSEUDO)
                   1148:        phillips_mode = PSS_PSEUDO;
                   1149:     else if (mode == PSS_SPKR_SPATIAL)
                   1150:        phillips_mode = PSS_SPATIAL;
                   1151:     else if (mode == PSS_SPKR_MONO)
                   1152:        phillips_mode = PSS_MONO;
                   1153:     else
                   1154:        return (EINVAL);
                   1155:
                   1156: #ifdef PSS_DSP
                   1157:     pss_dspwrite(sc, SET_MASTER_COMMAND);
                   1158:     pss_dspwrite(sc, MASTER_SWITCH | mode);
                   1159: #endif
                   1160:
                   1161:     sc->master_mode = mode;
                   1162:
                   1163:     return(0);
                   1164: }
                   1165:
                   1166: int
                   1167: pss_set_treble(sc, treb)
                   1168:     struct pss_softc *sc;
                   1169:     u_int treb;
                   1170: {
                   1171:     DPRINTF(("pss_set_treble: %d\n", treb));
                   1172:
                   1173: #ifdef PSS_DSP
                   1174:     if (treb > PHILLIPS_TREBLE_MAX)
                   1175:        treb = PHILLIPS_TREBLE_MAX;
                   1176:     if (treb < PHILLIPS_TREBLE_MIN)
                   1177:        treb = PHILLIPS_TREBLE_MIN;
                   1178:     pss_dspwrite(sc, SET_MASTER_COMMAND);
                   1179:     pss_dspwrite(sc, MASTER_TREBLE|(PHILLIPS_TREBLE_CONSTANT + treb / PHILLIPS_TREBLE_STEP));
                   1180: #endif
                   1181:
                   1182:     sc->monitor_treble = treb;
                   1183:
                   1184:     return(0);
                   1185: }
                   1186:
                   1187: int
                   1188: pss_set_bass(sc, bass)
                   1189:     struct pss_softc *sc;
                   1190:     u_int bass;
                   1191: {
                   1192:     DPRINTF(("pss_set_bass: %d\n", bass));
                   1193:
                   1194: #ifdef PSS_DSP
                   1195:     if (bass > PHILLIPS_BASS_MAX)
                   1196:        bass = PHILLIPS_BASS_MAX;
                   1197:     if (bass < PHILLIPS_BASS_MIN)
                   1198:        bass = PHILLIPS_BASS_MIN;
                   1199:     pss_dspwrite(sc, SET_MASTER_COMMAND);
                   1200:     pss_dspwrite(sc, MASTER_BASS|(PHILLIPS_BASS_CONSTANT + bass / PHILLIPS_BASS_STEP));
                   1201: #endif
                   1202:
                   1203:     sc->monitor_bass = bass;
                   1204:
                   1205:     return(0);
                   1206: }
                   1207:
                   1208: int
                   1209: pss_get_master_gain(sc, gp)
                   1210:     struct pss_softc *sc;
                   1211:     struct ad1848_volume *gp;
                   1212: {
                   1213:     *gp = sc->master_volume;
                   1214:     return(0);
                   1215: }
                   1216:
                   1217: int
                   1218: pss_get_master_mode(sc, mode)
                   1219:     struct pss_softc *sc;
                   1220:     u_int *mode;
                   1221: {
                   1222:     *mode = sc->master_mode;
                   1223:     return(0);
                   1224: }
                   1225:
                   1226: int
                   1227: pss_get_treble(sc, tp)
                   1228:     struct pss_softc *sc;
                   1229:     u_char *tp;
                   1230: {
                   1231:     *tp = sc->monitor_treble;
                   1232:     return(0);
                   1233: }
                   1234:
                   1235: int
                   1236: pss_get_bass(sc, bp)
                   1237:     struct pss_softc *sc;
                   1238:     u_char *bp;
                   1239: {
                   1240:     *bp = sc->monitor_bass;
                   1241:     return(0);
                   1242: }
                   1243:
                   1244: int
                   1245: pss_speaker_ctl(addr, newstate)
                   1246:     void *addr;
                   1247:     int newstate;
                   1248: {
                   1249:     return(0);
                   1250: }
                   1251:
                   1252: int
                   1253: pssintr(arg)
                   1254:        void *arg;
                   1255: {
                   1256:     struct pss_softc *sc = arg;
                   1257:     u_short sr;
                   1258:
                   1259:     sr = inw(sc->sc_iobase+PSS_STATUS);
                   1260:
                   1261:     DPRINTF(("pssintr: sc=%p st=%x\n", sc, sr));
                   1262:
                   1263:     /* Acknowledge intr */
                   1264:     outw(sc->sc_iobase+PSS_IRQ_ACK, 0);
                   1265:
                   1266:     /* Is it one of ours ? */
                   1267:     if (sr & (PSS_WRITE_EMPTY|PSS_READ_FULL|PSS_IRQ|PSS_DMQ_TC)) {
                   1268:        /* XXX do something */
                   1269:        return 1;
                   1270:     }
                   1271:
                   1272:     return 0;
                   1273: }
                   1274:
                   1275: #ifdef notyet
                   1276: int
                   1277: mpuintr(arg)
                   1278:        void *arg;
                   1279: {
                   1280:     struct mpu_softc *sc = arg;
                   1281:     u_char sr;
                   1282:
                   1283:     sr = inb(sc->sc_iobase+MIDI_STATUS_REG);
                   1284:
                   1285:     printf("mpuintr: sc=%p sr=%x\n", sc, sr);
                   1286:
                   1287:     /* XXX Need to clear intr */
                   1288:     return 1;
                   1289: }
                   1290: #endif
                   1291:
                   1292: int
                   1293: pss_getdev(addr, retp)
                   1294:     void *addr;
                   1295:     struct audio_device *retp;
                   1296: {
                   1297:     DPRINTF(("pss_getdev: retp=%p\n", retp));
                   1298:
                   1299:     *retp = pss_device;
                   1300:     return 0;
                   1301: }
                   1302:
                   1303: static ad1848_devmap_t mappings[] = {
                   1304: { PSS_MIC_IN_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL },
                   1305: { PSS_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL },
                   1306: { PSS_DAC_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL },
                   1307: { PSS_MON_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL },
                   1308: { PSS_MIC_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL },
                   1309: { PSS_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL },
                   1310: { PSS_DAC_MUTE, AD1848_KIND_MUTE, AD1848_DAC_CHANNEL },
                   1311: { PSS_REC_LVL, AD1848_KIND_RECORDGAIN, -1 },
                   1312: { PSS_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
                   1313: };
                   1314:
                   1315: static int nummap = sizeof(mappings) / sizeof(mappings[0]);
                   1316:
                   1317: int
                   1318: pss_mixer_set_port(addr, cp)
                   1319:     void *addr;
                   1320:     mixer_ctrl_t *cp;
                   1321: {
                   1322:     struct ad1848_softc *ac = addr;
                   1323:     struct pss_softc *sc = ac->parent;
                   1324:     struct ad1848_volume vol;
                   1325:     int error = ad1848_mixer_set_port(ac, mappings, nummap, cp);
                   1326:
                   1327:     if (error != ENXIO)
                   1328:       return (error);
                   1329:
                   1330:     switch (cp->dev) {
                   1331:     case PSS_MASTER_VOL:       /* master volume */
                   1332:        if (cp->type == AUDIO_MIXER_VALUE) {
                   1333:            if (ad1848_to_vol(cp, &vol))
                   1334:                error = pss_set_master_gain(sc, &vol);
                   1335:        }
                   1336:        break;
                   1337:
                   1338:     case PSS_OUTPUT_MODE:
                   1339:        if (cp->type == AUDIO_MIXER_ENUM)
                   1340:            error = pss_set_master_mode(sc, cp->un.ord);
                   1341:        break;
                   1342:
                   1343:     case PSS_MASTER_TREBLE:    /* master treble */
                   1344:        if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1)
                   1345:            error = pss_set_treble(sc, (u_char)cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                   1346:        break;
                   1347:
                   1348:     case PSS_MASTER_BASS:      /* master bass */
                   1349:        if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1)
                   1350:            error = pss_set_bass(sc, (u_char)cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                   1351:        break;
                   1352:
                   1353:     default:
                   1354:            return ENXIO;
                   1355:            /*NOTREACHED*/
                   1356:     }
                   1357:
                   1358:     return 0;
                   1359: }
                   1360:
                   1361: int
                   1362: pss_mixer_get_port(addr, cp)
                   1363:     void *addr;
                   1364:     mixer_ctrl_t *cp;
                   1365: {
                   1366:     struct ad1848_softc *ac = addr;
                   1367:     struct pss_softc *sc = ac->parent;
                   1368:     struct ad1848_volume vol;
                   1369:     u_char eq;
                   1370:     int error = ad1848_mixer_get_port(ac, mappings, nummap, cp);
                   1371:
                   1372:     if (error != ENXIO)
                   1373:       return (error);
                   1374:
                   1375:     error = EINVAL;
                   1376:
                   1377:     switch (cp->dev) {
                   1378:     case PSS_MASTER_VOL:       /* master volume */
                   1379:        if (cp->type == AUDIO_MIXER_VALUE) {
                   1380:            error = pss_get_master_gain(sc, &vol);
                   1381:            if (!error)
                   1382:                ad1848_from_vol(cp, &vol);
                   1383:        }
                   1384:        break;
                   1385:
                   1386:     case PSS_MASTER_TREBLE:    /* master treble */
                   1387:        if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) {
                   1388:            error = pss_get_treble(sc, &eq);
                   1389:            if (!error)
                   1390:                cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = eq;
                   1391:        }
                   1392:        break;
                   1393:
                   1394:     case PSS_MASTER_BASS:      /* master bass */
                   1395:        if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) {
                   1396:            error = pss_get_bass(sc, &eq);
                   1397:            if (!error)
                   1398:                cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = eq;
                   1399:        }
                   1400:        break;
                   1401:
                   1402:     case PSS_OUTPUT_MODE:
                   1403:        if (cp->type == AUDIO_MIXER_ENUM)
                   1404:            error = pss_get_master_mode(sc, &cp->un.ord);
                   1405:        break;
                   1406:
                   1407:     default:
                   1408:        error = ENXIO;
                   1409:        break;
                   1410:     }
                   1411:
                   1412:     return(error);
                   1413: }
                   1414:
                   1415: int
                   1416: pss_query_devinfo(addr, dip)
                   1417:     void *addr;
                   1418:     mixer_devinfo_t *dip;
                   1419: {
                   1420:     DPRINTF(("pss_query_devinfo: index=%d\n", dip->index));
                   1421:
                   1422:     switch(dip->index) {
                   1423:     case PSS_MIC_IN_LVL:       /* Microphone */
                   1424:        dip->type = AUDIO_MIXER_VALUE;
                   1425:        dip->mixer_class = PSS_INPUT_CLASS;
                   1426:        dip->prev = AUDIO_MIXER_LAST;
                   1427:        dip->next = PSS_MIC_IN_MUTE;
                   1428:        strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
                   1429:        dip->un.v.num_channels = 2;
                   1430:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   1431:            sizeof dip->un.v.units.name);
                   1432:        break;
                   1433:
                   1434:     case PSS_LINE_IN_LVL:      /* line/CD */
                   1435:        dip->type = AUDIO_MIXER_VALUE;
                   1436:        dip->mixer_class = PSS_INPUT_CLASS;
                   1437:        dip->prev = AUDIO_MIXER_LAST;
                   1438:        dip->next = PSS_LINE_IN_MUTE;
                   1439:        strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
                   1440:        dip->un.v.num_channels = 2;
                   1441:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   1442:            sizeof dip->un.v.units.name);
                   1443:        break;
                   1444:
                   1445:     case PSS_DAC_LVL:          /*  dacout */
                   1446:        dip->type = AUDIO_MIXER_VALUE;
                   1447:        dip->mixer_class = PSS_INPUT_CLASS;
                   1448:        dip->prev = AUDIO_MIXER_LAST;
                   1449:        dip->next = PSS_DAC_MUTE;
                   1450:        strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
                   1451:        dip->un.v.num_channels = 2;
                   1452:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   1453:            sizeof dip->un.v.units.name);
                   1454:        break;
                   1455:
                   1456:     case PSS_REC_LVL:  /* record level */
                   1457:        dip->type = AUDIO_MIXER_VALUE;
                   1458:        dip->mixer_class = PSS_RECORD_CLASS;
                   1459:        dip->prev = AUDIO_MIXER_LAST;
                   1460:        dip->next = PSS_RECORD_SOURCE;
                   1461:        strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
                   1462:        dip->un.v.num_channels = 2;
                   1463:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   1464:            sizeof dip->un.v.units.name);
                   1465:        break;
                   1466:
                   1467:     case PSS_MON_LVL:  /* monitor level */
                   1468:        dip->type = AUDIO_MIXER_VALUE;
                   1469:        dip->mixer_class = PSS_MONITOR_CLASS;
                   1470:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1471:        strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
                   1472:        dip->un.v.num_channels = 1;
                   1473:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   1474:            sizeof dip->un.v.units.name);
                   1475:        break;
                   1476:
                   1477:     case PSS_MASTER_VOL:       /* master volume */
                   1478:        dip->type = AUDIO_MIXER_VALUE;
                   1479:        dip->mixer_class = PSS_OUTPUT_CLASS;
                   1480:        dip->prev = AUDIO_MIXER_LAST;
                   1481:        dip->next = PSS_OUTPUT_MODE;
                   1482:        strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
                   1483:        dip->un.v.num_channels = 2;
                   1484:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   1485:            sizeof dip->un.v.units.name);
                   1486:        break;
                   1487:
                   1488:     case PSS_MASTER_TREBLE:    /* master treble */
                   1489:        dip->type = AUDIO_MIXER_VALUE;
                   1490:        dip->mixer_class = PSS_OUTPUT_CLASS;
                   1491:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1492:        strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
                   1493:        dip->un.v.num_channels = 1;
                   1494:        strlcpy(dip->un.v.units.name, AudioNtreble,
                   1495:            sizeof dip->un.v.units.name);
                   1496:        break;
                   1497:
                   1498:     case PSS_MASTER_BASS:      /* master bass */
                   1499:        dip->type = AUDIO_MIXER_VALUE;
                   1500:        dip->mixer_class = PSS_OUTPUT_CLASS;
                   1501:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1502:        strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
                   1503:        dip->un.v.num_channels = 1;
                   1504:        strlcpy(dip->un.v.units.name, AudioNbass, sizeof dip->un.v.units.name);
                   1505:        break;
                   1506:
                   1507:     case PSS_OUTPUT_CLASS:                     /* output class descriptor */
                   1508:        dip->type = AUDIO_MIXER_CLASS;
                   1509:        dip->mixer_class = PSS_OUTPUT_CLASS;
                   1510:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1511:        strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
                   1512:        break;
                   1513:
                   1514:     case PSS_INPUT_CLASS:                      /* input class descriptor */
                   1515:        dip->type = AUDIO_MIXER_CLASS;
                   1516:        dip->mixer_class = PSS_INPUT_CLASS;
                   1517:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1518:        strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
                   1519:        break;
                   1520:
                   1521:     case PSS_MONITOR_CLASS:                    /* monitor class descriptor */
                   1522:        dip->type = AUDIO_MIXER_CLASS;
                   1523:        dip->mixer_class = PSS_MONITOR_CLASS;
                   1524:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1525:        strlcpy(dip->label.name, AudioCmonitor, sizeof dip->label.name);
                   1526:        break;
                   1527:
                   1528:     case PSS_RECORD_CLASS:                     /* record source class */
                   1529:        dip->type = AUDIO_MIXER_CLASS;
                   1530:        dip->mixer_class = PSS_RECORD_CLASS;
                   1531:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1532:        strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
                   1533:        break;
                   1534:
                   1535:     case PSS_MIC_IN_MUTE:
                   1536:        dip->mixer_class = PSS_INPUT_CLASS;
                   1537:        dip->type = AUDIO_MIXER_ENUM;
                   1538:        dip->prev = PSS_MIC_IN_LVL;
                   1539:        dip->next = AUDIO_MIXER_LAST;
                   1540:        goto mute;
                   1541:
                   1542:     case PSS_LINE_IN_MUTE:
                   1543:        dip->mixer_class = PSS_INPUT_CLASS;
                   1544:        dip->type = AUDIO_MIXER_ENUM;
                   1545:        dip->prev = PSS_LINE_IN_LVL;
                   1546:        dip->next = AUDIO_MIXER_LAST;
                   1547:        goto mute;
                   1548:
                   1549:     case PSS_DAC_MUTE:
                   1550:        dip->mixer_class = PSS_INPUT_CLASS;
                   1551:        dip->type = AUDIO_MIXER_ENUM;
                   1552:        dip->prev = PSS_DAC_LVL;
                   1553:        dip->next = AUDIO_MIXER_LAST;
                   1554:     mute:
                   1555:        strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
                   1556:        dip->un.e.num_mem = 2;
                   1557:        strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                   1558:            sizeof dip->un.e.member[0].label.name);
                   1559:        dip->un.e.member[0].ord = 0;
                   1560:        strlcpy(dip->un.e.member[1].label.name, AudioNon,
                   1561:            sizeof dip->un.e.member[1].label.name);
                   1562:        dip->un.e.member[1].ord = 1;
                   1563:        break;
                   1564:
                   1565:     case PSS_OUTPUT_MODE:
                   1566:        dip->mixer_class = PSS_OUTPUT_CLASS;
                   1567:        dip->type = AUDIO_MIXER_ENUM;
                   1568:        dip->prev = PSS_MASTER_VOL;
                   1569:        dip->next = AUDIO_MIXER_LAST;
                   1570:        strlcpy(dip->label.name, AudioNmode, sizeof dip->label.name);
                   1571:        dip->un.e.num_mem = 4;
                   1572:        strlcpy(dip->un.e.member[0].label.name, AudioNmono,
                   1573:            sizeof dip->un.e.member[0].label.name);
                   1574:        dip->un.e.member[0].ord = PSS_SPKR_MONO;
                   1575:        strlcpy(dip->un.e.member[1].label.name, AudioNstereo,
                   1576:            sizeof dip->un.e.member[1].label.name);
                   1577:        dip->un.e.member[1].ord = PSS_SPKR_STEREO;
                   1578:        strlcpy(dip->un.e.member[2].label.name, AudioNpseudo,
                   1579:            sizeof dip->un.e.member[2].label.name);
                   1580:        dip->un.e.member[2].ord = PSS_SPKR_PSEUDO;
                   1581:        strlcpy(dip->un.e.member[3].label.name, AudioNspatial,
                   1582:            sizeof dip->un.e.member[3].label.name);
                   1583:        dip->un.e.member[3].ord = PSS_SPKR_SPATIAL;
                   1584:        break;
                   1585:
                   1586:     case PSS_RECORD_SOURCE:
                   1587:        dip->mixer_class = PSS_RECORD_CLASS;
                   1588:        dip->type = AUDIO_MIXER_ENUM;
                   1589:        dip->prev = PSS_REC_LVL;
                   1590:        dip->next = AUDIO_MIXER_LAST;
                   1591:        strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
                   1592:        dip->un.e.num_mem = 3;
                   1593:        strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
                   1594:            sizeof dip->un.e.member[0].label.name);
                   1595:        dip->un.e.member[0].ord = PSS_MIC_IN_LVL;
                   1596:        strlcpy(dip->un.e.member[1].label.name, AudioNcd,
                   1597:            sizeof dip->un.e.member[1].label.name);
                   1598:        dip->un.e.member[1].ord = PSS_LINE_IN_LVL;
                   1599:        strlcpy(dip->un.e.member[2].label.name, AudioNdac,
                   1600:            sizeof dip->un.e.member[2].label.name);
                   1601:        dip->un.e.member[2].ord = PSS_DAC_LVL;
                   1602:        break;
                   1603:
                   1604:     default:
                   1605:        return ENXIO;
                   1606:        /*NOTREACHED*/
                   1607:     }
                   1608:     DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
                   1609:
                   1610:     return 0;
                   1611: }

CVSweb