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

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

1.1       nbrk        1: /*     $OpenBSD: gus.c,v 1.29 2006/03/04 12:42:23 miod Exp $   */
                      2: /*     $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1996 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Ken Hornstein and John Kohl.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *        This product includes software developed by the NetBSD
                     22:  *       Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  *
                     42:  * TODO:
                     43:  *     . figure out why mixer activity while sound is playing causes problems
                     44:  *       (phantom interrupts?)
                     45:  *     . figure out a better deinterleave strategy that avoids sucking up
                     46:  *       CPU, memory and cache bandwidth.  (Maybe a special encoding?
                     47:  *       Maybe use the double-speed sampling/hardware deinterleave trick
                     48:  *       from the GUS SDK?)  A 486/33 isn't quite fast enough to keep
                     49:  *       up with 44.1kHz 16-bit stereo output without some drop-outs.
                     50:  *     . use CS4231 for 16-bit sampling, for a-law and mu-law playback.
                     51:  *     . actually test full-duplex sampling(recording) and playback.
                     52:  */
                     53:
                     54: /*
                     55:  * Gravis UltraSound driver
                     56:  *
                     57:  * For more detailed information, see the GUS developers' kit
                     58:  * available on the net at:
                     59:  *
                     60:  * http://www.gravis.com/Public/sdk/GUSDK222.ZIP
                     61:  *
                     62:  *             See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
                     63:  *
                     64:  */
                     65:
                     66: /*
                     67:  * The GUS Max has a slightly strange set of connections between the CS4231
                     68:  * and the GF1 and the DMA interconnects.  It's set up so that the CS4231 can
                     69:  * be playing while the GF1 is loading patches from the system.
                     70:  *
                     71:  * Here's a recreation of the DMA interconnect diagram:
                     72:  *
                     73:  *       GF1
                     74:  *   +---------+                                digital
                     75:  *   |         |  record                        ASIC
                     76:  *   |         |--------------+
                     77:  *   |         |              |                       +--------+
                     78:  *   |         | play (dram)  |      +----+    |       |
                     79:  *   |         |--------------(------|-\  |    |   +-+  |
                     80:  *   +---------+              |      |  >-|----|---|C|--|------  dma chan 1
                     81:  *                            |  +---|-/  |    |   +-+ |
                     82:  *                            |  |   +----+    |    |   |
                     83:  *                            |         |   +----+    |    |   |
                     84:  *   +---------+        +-+   +--(---|-\  |    |    |   |
                     85:  *   |         | play   |8|      |   |  >-|----|----+---|------  dma chan 2
                     86:  *   | ---C----|--------|/|------(---|-/  |    |        |
                     87:  *   |    ^    |record  |1|      |   +----+    |       |
                     88:  *   |    |    |   /----|6|------+            +--------+
                     89:  *   | ---+----|--/     +-+
                     90:  *   +---------+
                     91:  *     CS4231  8-to-16 bit bus conversion, if needed
                     92:  *
                     93:  *
                     94:  * "C" is an optional combiner.
                     95:  *
                     96:  */
                     97:
                     98: #include <sys/param.h>
                     99: #include <sys/systm.h>
                    100: #include <sys/errno.h>
                    101: #include <sys/ioctl.h>
                    102: #include <sys/syslog.h>
                    103: #include <sys/device.h>
                    104: #include <sys/proc.h>
                    105: #include <sys/buf.h>
                    106: #include <sys/fcntl.h>
                    107: #include <sys/malloc.h>
                    108: #include <sys/kernel.h>
                    109: #include <sys/timeout.h>
                    110:
                    111: #include <machine/cpu.h>
                    112: #include <machine/intr.h>
                    113: #include <machine/bus.h>
                    114: #include <machine/cpufunc.h>
                    115: #include <sys/audioio.h>
                    116: #include <dev/audio_if.h>
                    117: #include <dev/mulaw.h>
                    118: #include <dev/auconv.h>
                    119:
                    120: #include <dev/isa/isavar.h>
                    121: #include <dev/isa/isadmavar.h>
                    122:
                    123: #include <dev/ic/ics2101reg.h>
                    124: #include <dev/ic/cs4231reg.h>
                    125: #include <dev/ic/ad1848reg.h>
                    126: #include <dev/isa/ics2101var.h>
                    127: #include <dev/isa/ad1848var.h>
                    128: #include <dev/isa/cs4231var.h>
                    129: #include "gusreg.h"
                    130: #include "gusvar.h"
                    131:
                    132: #ifdef AUDIO_DEBUG
                    133: #define GUSPLAYDEBUG   /*XXX*/
                    134: #define DPRINTF(x)     if (gusdebug) printf x
                    135: #define DMAPRINTF(x)   if (gusdmadebug) printf x
                    136: int    gusdebug = 0;
                    137: int    gusdmadebug = 0;
                    138: #else
                    139: #define DPRINTF(x)
                    140: #define DMAPRINTF(x)
                    141: #endif
                    142: int    gus_dostereo = 1;
                    143:
                    144: #define NDMARECS 2048
                    145: #ifdef GUSPLAYDEBUG
                    146: int    gusstats = 0;
                    147:
                    148: struct dma_record dmarecords[NDMARECS];
                    149:
                    150: int dmarecord_index = 0;
                    151: #endif
                    152:
                    153: struct cfdriver gus_cd = {
                    154:        NULL, "gus", DV_DULL
                    155: };
                    156:
                    157: /*
                    158:  * A mapping from IRQ/DRQ values to the values used in the GUS's internal
                    159:  * registers.  A zero means that the referenced IRQ/DRQ is invalid
                    160:  */
                    161: const int gus_irq_map[] = {
                    162:        IRQUNK, IRQUNK, 1, 3, IRQUNK, 2, IRQUNK, 4, IRQUNK, 1, IRQUNK, 5, 6,
                    163:        IRQUNK, IRQUNK, 7
                    164: };
                    165: const int gus_drq_map[] = {
                    166:        DRQUNK, 1, DRQUNK, 2, DRQUNK, 3, 4, 5
                    167: };
                    168:
                    169: /*
                    170:  * A list of valid base addresses for the GUS
                    171:  */
                    172:
                    173: const int gus_base_addrs[] = {
                    174:        0x210, 0x220, 0x230, 0x240, 0x250, 0x260
                    175: };
                    176: const int gus_addrs = sizeof(gus_base_addrs) / sizeof(gus_base_addrs[0]);
                    177:
                    178: /*
                    179:  * Maximum frequency values of the GUS based on the number of currently active
                    180:  * voices.  Since the GUS samples a voice every 1.6 us, the maximum frequency
                    181:  * is dependent on the number of active voices.  Yes, it is pretty weird.
                    182:  */
                    183:
                    184: static const int gus_max_frequency[] = {
                    185:                44100,          /* 14 voices */
                    186:                41160,          /* 15 voices */
                    187:                38587,          /* 16 voices */
                    188:                36317,          /* 17 voices */
                    189:                34300,          /* 18 voices */
                    190:                32494,          /* 19 voices */
                    191:                30870,          /* 20 voices */
                    192:                29400,          /* 21 voices */
                    193:                28063,          /* 22 voices */
                    194:                26843,          /* 23 voices */
                    195:                25725,          /* 24 voices */
                    196:                24696,          /* 25 voices */
                    197:                23746,          /* 26 voices */
                    198:                22866,          /* 27 voices */
                    199:                22050,          /* 28 voices */
                    200:                21289,          /* 29 voices */
                    201:                20580,          /* 30 voices */
                    202:                19916,          /* 31 voices */
                    203:                19293           /* 32 voices */
                    204: };
                    205: /*
                    206:  * A mapping of linear volume levels to the logarithmic volume values used
                    207:  * by the GF1 chip on the GUS.  From GUS SDK vol1.c.
                    208:  */
                    209:
                    210: static const unsigned short gus_log_volumes[512] = {
                    211:  0x0000,
                    212:  0x0700, 0x07ff, 0x0880, 0x08ff, 0x0940, 0x0980, 0x09c0, 0x09ff, 0x0a20,
                    213:  0x0a40, 0x0a60, 0x0a80, 0x0aa0, 0x0ac0, 0x0ae0, 0x0aff, 0x0b10, 0x0b20,
                    214:  0x0b30, 0x0b40, 0x0b50, 0x0b60, 0x0b70, 0x0b80, 0x0b90, 0x0ba0, 0x0bb0,
                    215:  0x0bc0, 0x0bd0, 0x0be0, 0x0bf0, 0x0bff, 0x0c08, 0x0c10, 0x0c18, 0x0c20,
                    216:  0x0c28, 0x0c30, 0x0c38, 0x0c40, 0x0c48, 0x0c50, 0x0c58, 0x0c60, 0x0c68,
                    217:  0x0c70, 0x0c78, 0x0c80, 0x0c88, 0x0c90, 0x0c98, 0x0ca0, 0x0ca8, 0x0cb0,
                    218:  0x0cb8, 0x0cc0, 0x0cc8, 0x0cd0, 0x0cd8, 0x0ce0, 0x0ce8, 0x0cf0, 0x0cf8,
                    219:  0x0cff, 0x0d04, 0x0d08, 0x0d0c, 0x0d10, 0x0d14, 0x0d18, 0x0d1c, 0x0d20,
                    220:  0x0d24, 0x0d28, 0x0d2c, 0x0d30, 0x0d34, 0x0d38, 0x0d3c, 0x0d40, 0x0d44,
                    221:  0x0d48, 0x0d4c, 0x0d50, 0x0d54, 0x0d58, 0x0d5c, 0x0d60, 0x0d64, 0x0d68,
                    222:  0x0d6c, 0x0d70, 0x0d74, 0x0d78, 0x0d7c, 0x0d80, 0x0d84, 0x0d88, 0x0d8c,
                    223:  0x0d90, 0x0d94, 0x0d98, 0x0d9c, 0x0da0, 0x0da4, 0x0da8, 0x0dac, 0x0db0,
                    224:  0x0db4, 0x0db8, 0x0dbc, 0x0dc0, 0x0dc4, 0x0dc8, 0x0dcc, 0x0dd0, 0x0dd4,
                    225:  0x0dd8, 0x0ddc, 0x0de0, 0x0de4, 0x0de8, 0x0dec, 0x0df0, 0x0df4, 0x0df8,
                    226:  0x0dfc, 0x0dff, 0x0e02, 0x0e04, 0x0e06, 0x0e08, 0x0e0a, 0x0e0c, 0x0e0e,
                    227:  0x0e10, 0x0e12, 0x0e14, 0x0e16, 0x0e18, 0x0e1a, 0x0e1c, 0x0e1e, 0x0e20,
                    228:  0x0e22, 0x0e24, 0x0e26, 0x0e28, 0x0e2a, 0x0e2c, 0x0e2e, 0x0e30, 0x0e32,
                    229:  0x0e34, 0x0e36, 0x0e38, 0x0e3a, 0x0e3c, 0x0e3e, 0x0e40, 0x0e42, 0x0e44,
                    230:  0x0e46, 0x0e48, 0x0e4a, 0x0e4c, 0x0e4e, 0x0e50, 0x0e52, 0x0e54, 0x0e56,
                    231:  0x0e58, 0x0e5a, 0x0e5c, 0x0e5e, 0x0e60, 0x0e62, 0x0e64, 0x0e66, 0x0e68,
                    232:  0x0e6a, 0x0e6c, 0x0e6e, 0x0e70, 0x0e72, 0x0e74, 0x0e76, 0x0e78, 0x0e7a,
                    233:  0x0e7c, 0x0e7e, 0x0e80, 0x0e82, 0x0e84, 0x0e86, 0x0e88, 0x0e8a, 0x0e8c,
                    234:  0x0e8e, 0x0e90, 0x0e92, 0x0e94, 0x0e96, 0x0e98, 0x0e9a, 0x0e9c, 0x0e9e,
                    235:  0x0ea0, 0x0ea2, 0x0ea4, 0x0ea6, 0x0ea8, 0x0eaa, 0x0eac, 0x0eae, 0x0eb0,
                    236:  0x0eb2, 0x0eb4, 0x0eb6, 0x0eb8, 0x0eba, 0x0ebc, 0x0ebe, 0x0ec0, 0x0ec2,
                    237:  0x0ec4, 0x0ec6, 0x0ec8, 0x0eca, 0x0ecc, 0x0ece, 0x0ed0, 0x0ed2, 0x0ed4,
                    238:  0x0ed6, 0x0ed8, 0x0eda, 0x0edc, 0x0ede, 0x0ee0, 0x0ee2, 0x0ee4, 0x0ee6,
                    239:  0x0ee8, 0x0eea, 0x0eec, 0x0eee, 0x0ef0, 0x0ef2, 0x0ef4, 0x0ef6, 0x0ef8,
                    240:  0x0efa, 0x0efc, 0x0efe, 0x0eff, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05,
                    241:  0x0f06, 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e,
                    242:  0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, 0x0f17,
                    243:  0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, 0x0f1f, 0x0f20,
                    244:  0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27, 0x0f28, 0x0f29,
                    245:  0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, 0x0f2f, 0x0f30, 0x0f31, 0x0f32,
                    246:  0x0f33, 0x0f34, 0x0f35, 0x0f36, 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b,
                    247:  0x0f3c, 0x0f3d, 0x0f3e, 0x0f3f, 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44,
                    248:  0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d,
                    249:  0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56,
                    250:  0x0f57, 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f,
                    251:  0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, 0x0f68,
                    252:  0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71,
                    253:  0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, 0x0f78, 0x0f79, 0x0f7a,
                    254:  0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, 0x0f80, 0x0f81, 0x0f82, 0x0f83,
                    255:  0x0f84, 0x0f85, 0x0f86, 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c,
                    256:  0x0f8d, 0x0f8e, 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95,
                    257:  0x0f96, 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e,
                    258:  0x0f9f, 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7,
                    259:  0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, 0x0fb0,
                    260:  0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, 0x0fb8, 0x0fb9,
                    261:  0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, 0x0fc0, 0x0fc1, 0x0fc2,
                    262:  0x0fc3, 0x0fc4, 0x0fc5, 0x0fc6, 0x0fc7, 0x0fc8, 0x0fc9, 0x0fca, 0x0fcb,
                    263:  0x0fcc, 0x0fcd, 0x0fce, 0x0fcf, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4,
                    264:  0x0fd5, 0x0fd6, 0x0fd7, 0x0fd8, 0x0fd9, 0x0fda, 0x0fdb, 0x0fdc, 0x0fdd,
                    265:  0x0fde, 0x0fdf, 0x0fe0, 0x0fe1, 0x0fe2, 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe6,
                    266:  0x0fe7, 0x0fe8, 0x0fe9, 0x0fea, 0x0feb, 0x0fec, 0x0fed, 0x0fee, 0x0fef,
                    267:  0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8,
                    268:  0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff};
                    269:
                    270: /*
                    271:  * Interface to higher level audio driver
                    272:  */
                    273: struct audio_hw_if gus_hw_if = {
                    274:        gusopen,
                    275:        gusclose,
                    276:        NULL,                           /* drain */
                    277:
                    278:        gus_query_encoding,
                    279:
                    280:        gus_set_params,
                    281:
                    282:        gus_round_blocksize,
                    283:
                    284:        gus_commit_settings,
                    285:
                    286:        NULL,
                    287:        NULL,
                    288:
                    289:        gus_dma_output,
                    290:        gus_dma_input,
                    291:        gus_halt_out_dma,
                    292:        gus_halt_in_dma,
                    293:        gus_speaker_ctl,
                    294:
                    295:        gus_getdev,
                    296:        NULL,
                    297:        gus_mixer_set_port,
                    298:        gus_mixer_get_port,
                    299:        gus_mixer_query_devinfo,
                    300:        ad1848_malloc,
                    301:        ad1848_free,
                    302:        ad1848_round,
                    303:        ad1848_mappage,
                    304:        gus_get_props,
                    305:
                    306:        NULL,
                    307:        NULL
                    308: };
                    309:
                    310: static struct audio_hw_if gusmax_hw_if = {
                    311:        gusmaxopen,
                    312:        gusmax_close,
                    313:        NULL,                           /* drain */
                    314:
                    315:        gus_query_encoding, /* query encoding */
                    316:
                    317:        gusmax_set_params,
                    318:
                    319:        gusmax_round_blocksize,
                    320:
                    321:        gusmax_commit_settings,
                    322:
                    323:        NULL,
                    324:        NULL,
                    325:
                    326:        gusmax_dma_output,
                    327:        gusmax_dma_input,
                    328:        gusmax_halt_out_dma,
                    329:        gusmax_halt_in_dma,
                    330:
                    331:        gusmax_speaker_ctl,
                    332:
                    333:        gus_getdev,
                    334:        NULL,
                    335:        gusmax_mixer_set_port,
                    336:        gusmax_mixer_get_port,
                    337:        gusmax_mixer_query_devinfo,
                    338:        ad1848_malloc,
                    339:        ad1848_free,
                    340:        ad1848_round,
                    341:        ad1848_mappage,
                    342:        gusmax_get_props,
                    343: };
                    344:
                    345: /*
                    346:  * Some info about the current audio device
                    347:  */
                    348: struct audio_device gus_device = {
                    349:        "UltraSound",
                    350:        "",
                    351:        "gus",
                    352: };
                    353:
                    354:
                    355: int
                    356: gusopen(addr, flags)
                    357:        void *addr;
                    358:        int flags;
                    359: {
                    360:        struct gus_softc *sc = addr;
                    361:
                    362:        DPRINTF(("gusopen() called\n"));
                    363:
                    364:        if (sc->sc_flags & GUS_OPEN)
                    365:                return EBUSY;
                    366:
                    367:        /*
                    368:         * Some initialization
                    369:         */
                    370:
                    371:        sc->sc_flags |= GUS_OPEN;
                    372:        sc->sc_dmabuf = 0;
                    373:        sc->sc_playbuf = -1;
                    374:        sc->sc_bufcnt = 0;
                    375:        sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
                    376:        sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET;
                    377:
                    378:        if (HAS_CODEC(sc)) {
                    379:                ad1848_open(&sc->sc_codec, flags);
                    380:                sc->sc_codec.mute[AD1848_AUX1_CHANNEL] = 0;
                    381:                ad1848_mute_channel(&sc->sc_codec, AD1848_AUX1_CHANNEL, 0); /* turn on DAC output */
                    382:                if (flags & FREAD) {
                    383:                        sc->sc_codec.mute[AD1848_MONO_CHANNEL] = 0;
                    384:                        ad1848_mute_channel(&sc->sc_codec, AD1848_MONO_CHANNEL, 0);
                    385:                }
                    386:        } else if (flags & FREAD) {
                    387:                /* enable/unmute the microphone */
                    388:                if (HAS_MIXER(sc)) {
                    389:                        gusics_mic_mute(&sc->sc_mixer, 0);
                    390:                } else
                    391:                        gus_mic_ctl(sc, SPKR_ON);
                    392:        }
                    393:        if (sc->sc_nbufs == 0)
                    394:            gus_round_blocksize(sc, GUS_BUFFER_MULTIPLE); /* default blksiz */
                    395:        return 0;
                    396: }
                    397:
                    398: int
                    399: gusmaxopen(addr, flags)
                    400:        void *addr;
                    401:        int flags;
                    402: {
                    403:        struct ad1848_softc *ac = addr;
                    404:        return gusopen(ac->parent, flags);
                    405: }
                    406:
                    407: void
                    408: gus_deinterleave(sc, buf, size)
                    409:        struct gus_softc *sc;
                    410:        void *buf;
                    411:        int size;
                    412: {
                    413:        /* deinterleave the stereo data.  We can use sc->sc_deintr_buf
                    414:           for scratch space. */
                    415:        int i;
                    416:
                    417:        if (size > sc->sc_blocksize) {
                    418:                printf("gus: deinterleave %d > %d\n", size, sc->sc_blocksize);
                    419:                return;
                    420:        } else if (size < sc->sc_blocksize) {
                    421:                DPRINTF(("gus: deinterleave %d < %d\n", size, sc->sc_blocksize));
                    422:        }
                    423:
                    424:        /*
                    425:         * size is in bytes.
                    426:         */
                    427:        if (sc->sc_precision == 16) {
                    428:                u_short *dei = sc->sc_deintr_buf;
                    429:                u_short *sbuf = buf;
                    430:                size >>= 1;             /* bytecnt to shortcnt */
                    431:                /* copy 2nd of each pair of samples to the staging area, while
                    432:                   compacting the 1st of each pair into the original area. */
                    433:                for (i = 0; i < size/2-1; i++)  {
                    434:                        dei[i] = sbuf[i*2+1];
                    435:                        sbuf[i+1] = sbuf[i*2+2];
                    436:                }
                    437:                /*
                    438:                 * this has copied one less sample than half of the
                    439:                 * buffer.  The first sample of the 1st stream was
                    440:                 * already in place and didn't need copying.
                    441:                 * Therefore, we've moved all of the 1st stream's
                    442:                 * samples into place.  We have one sample from 2nd
                    443:                 * stream in the last slot of original area, not
                    444:                 * copied to the staging area (But we don't need to!).
                    445:                 * Copy the remainder of the original stream into place.
                    446:                 */
                    447:                bcopy(dei, &sbuf[size/2], i * sizeof(short));
                    448:        } else {
                    449:                u_char *dei = sc->sc_deintr_buf;
                    450:                u_char *sbuf = buf;
                    451:                for (i = 0; i < size/2-1; i++)  {
                    452:                        dei[i] = sbuf[i*2+1];
                    453:                        sbuf[i+1] = sbuf[i*2+2];
                    454:                }
                    455:                bcopy(dei, &sbuf[size/2], i);
                    456:        }
                    457: }
                    458:
                    459: /*
                    460:  * Actually output a buffer to the DSP chip
                    461:  */
                    462:
                    463: int
                    464: gusmax_dma_output(addr, buf, size, intr, arg)
                    465:        void * addr;
                    466:        void *buf;
                    467:        int size;
                    468:        void (*intr)(void *);
                    469:        void *arg;
                    470: {
                    471:        struct ad1848_softc *ac = addr;
                    472:        return gus_dma_output(ac->parent, buf, size, intr, arg);
                    473: }
                    474:
                    475: /*
                    476:  * called at splgus() from interrupt handler.
                    477:  */
                    478: void
                    479: stereo_dmaintr(arg)
                    480:        void *arg;
                    481: {
                    482:     struct gus_softc *sc = arg;
                    483:     struct stereo_dma_intr *sa = &sc->sc_stereo;
                    484:
                    485:     DMAPRINTF(("stereo_dmaintr"));
                    486:
                    487:     /*
                    488:      * Put other half in its place, then call the real interrupt routine :)
                    489:      */
                    490:
                    491:     sc->sc_dmaoutintr = sa->intr;
                    492:     sc->sc_outarg = sa->arg;
                    493:
                    494: #ifdef GUSPLAYDEBUG
                    495:     if (gusstats) {
                    496:       microtime(&dmarecords[dmarecord_index].tv);
                    497:       dmarecords[dmarecord_index].gusaddr = sa->dmabuf;
                    498:       dmarecords[dmarecord_index].bsdaddr = sa->buffer;
                    499:       dmarecords[dmarecord_index].count = sa->size;
                    500:       dmarecords[dmarecord_index].channel = 1;
                    501:       dmarecords[dmarecord_index++].direction = 1;
                    502:       dmarecord_index = dmarecord_index % NDMARECS;
                    503:     }
                    504: #endif
                    505:
                    506:     gusdmaout(sc, sa->flags, sa->dmabuf, (caddr_t) sa->buffer, sa->size);
                    507:
                    508:     sa->flags = 0;
                    509:     sa->dmabuf = 0;
                    510:     sa->buffer = 0;
                    511:     sa->size = 0;
                    512:     sa->intr = 0;
                    513:     sa->arg = 0;
                    514: }
                    515:
                    516: /*
                    517:  * Start up DMA output to the card.
                    518:  * Called at splgus/splaudio already, either from intr handler or from
                    519:  * generic audio code.
                    520:  */
                    521: int
                    522: gus_dma_output(addr, buf, size, intr, arg)
                    523:        void * addr;
                    524:        void *buf;
                    525:        int size;
                    526:        void (*intr)(void *);
                    527:        void *arg;
                    528: {
                    529:        struct gus_softc *sc = addr;
                    530:        u_char *buffer = buf;
                    531:        u_long boarddma;
                    532:        int flags;
                    533:
                    534:        DMAPRINTF(("gus_dma_output %d @ %p\n", size, buf));
                    535:
                    536:        if (size != sc->sc_blocksize) {
                    537:            DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n",
                    538:                     size, sc->sc_blocksize));
                    539:            return EINVAL;
                    540:        }
                    541:
                    542:        flags = GUSMASK_DMA_WRITE;
                    543:        if (sc->sc_precision == 16)
                    544:            flags |= GUSMASK_DMA_DATA_SIZE;
                    545:        if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
                    546:            sc->sc_encoding == AUDIO_ENCODING_ALAW ||
                    547:            sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE ||
                    548:            sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE)
                    549:            flags |= GUSMASK_DMA_INVBIT;
                    550:
                    551:        if (sc->sc_channels == 2) {
                    552:                if (sc->sc_precision == 16) {
                    553:                        if (size & 3) {
                    554:                                DPRINTF(("gus_dma_output: unpaired 16bit samples"));
                    555:                                size &= 3;
                    556:                        }
                    557:                } else if (size & 1) {
                    558:                        DPRINTF(("gus_dma_output: unpaired samples"));
                    559:                        size &= 1;
                    560:                }
                    561:                if (size == 0)
                    562:                        return 0;
                    563:
                    564:                gus_deinterleave(sc, (void *)buffer, size);
                    565:
                    566:                size >>= 1;
                    567:
                    568:                boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
                    569:
                    570:                sc->sc_stereo.intr = intr;
                    571:                sc->sc_stereo.arg = arg;
                    572:                sc->sc_stereo.size = size;
                    573:                sc->sc_stereo.dmabuf = boarddma + GUS_LEFT_RIGHT_OFFSET;
                    574:                sc->sc_stereo.buffer = buffer + size;
                    575:                sc->sc_stereo.flags = flags;
                    576:                if (gus_dostereo) {
                    577:                  intr = stereo_dmaintr;
                    578:                  arg = sc;
                    579:                }
                    580:        } else
                    581:                boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
                    582:
                    583:
                    584:        sc->sc_flags |= GUS_LOCKED;
                    585:        sc->sc_dmaoutintr = intr;
                    586:        sc->sc_outarg = arg;
                    587:
                    588: #ifdef GUSPLAYDEBUG
                    589:        if (gusstats) {
                    590:          microtime(&dmarecords[dmarecord_index].tv);
                    591:          dmarecords[dmarecord_index].gusaddr = boarddma;
                    592:          dmarecords[dmarecord_index].bsdaddr = buffer;
                    593:          dmarecords[dmarecord_index].count = size;
                    594:          dmarecords[dmarecord_index].channel = 0;
                    595:          dmarecords[dmarecord_index++].direction = 1;
                    596:          dmarecord_index = dmarecord_index % NDMARECS;
                    597:        }
                    598: #endif
                    599:
                    600:        gusdmaout(sc, flags, boarddma, (caddr_t) buffer, size);
                    601:
                    602:        return 0;
                    603: }
                    604:
                    605: void
                    606: gusmax_close(addr)
                    607:        void *addr;
                    608: {
                    609:        struct ad1848_softc *ac = addr;
                    610:        struct gus_softc *sc = ac->parent;
                    611: #if 0
                    612:        ac->mute[AD1848_AUX1_CHANNEL] = MUTE_ALL;
                    613:        ad1848_mute_channel(ac, MUTE_ALL); /* turn off DAC output */
                    614: #endif
                    615:        ad1848_close(ac);
                    616:        gusclose(sc);
                    617: }
                    618:
                    619: /*
                    620:  * Close out device stuff.  Called at splgus() from generic audio layer.
                    621:  */
                    622: void
                    623: gusclose(addr)
                    624:        void *addr;
                    625: {
                    626:        struct gus_softc *sc = addr;
                    627:
                    628:         DPRINTF(("gus_close: sc=%p\n", sc));
                    629:
                    630:
                    631: /*     if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ {
                    632:                gus_halt_out_dma(sc);
                    633:        }
                    634: /*     if (sc->sc_flags & GUS_DMAIN_ACTIVE) */ {
                    635:                gus_halt_in_dma(sc);
                    636:        }
                    637:        sc->sc_flags &= ~(GUS_OPEN|GUS_LOCKED|GUS_DMAOUT_ACTIVE|GUS_DMAIN_ACTIVE);
                    638:
                    639:        if (sc->sc_deintr_buf) {
                    640:                free(sc->sc_deintr_buf, M_DEVBUF);
                    641:                sc->sc_deintr_buf = NULL;
                    642:        }
                    643:        /* turn off speaker, etc. */
                    644:
                    645:        /* make sure the voices shut up: */
                    646:        gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
                    647:        gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
                    648: }
                    649:
                    650: /*
                    651:  * Service interrupts.  Farm them off to helper routines if we are using the
                    652:  * GUS for simple playback/record
                    653:  */
                    654:
                    655: #ifdef AUDIO_DEBUG
                    656: int gusintrcnt;
                    657: int gusdmaintrcnt;
                    658: int gusvocintrcnt;
                    659: #endif
                    660:
                    661: int
                    662: gusintr(arg)
                    663:        void *arg;
                    664: {
                    665:        struct gus_softc *sc = arg;
                    666:        bus_space_tag_t iot = sc->sc_iot;
                    667:        bus_space_handle_t ioh1 = sc->sc_ioh1;
                    668:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                    669:        unsigned char intr;
                    670:
                    671:        int retval = 0;
                    672:
                    673:        DPRINTF(("gusintr\n"));
                    674: #ifdef AUDIO_DEBUG
                    675:        gusintrcnt++;
                    676: #endif
                    677:        if (HAS_CODEC(sc))
                    678:                retval = ad1848_intr(&sc->sc_codec);
                    679:        if ((intr = bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
                    680:                DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags));
                    681: #ifdef AUDIO_DEBUG
                    682:                gusdmaintrcnt++;
                    683: #endif
                    684:                retval += gus_dmaout_intr(sc);
                    685:                if (sc->sc_flags & GUS_DMAIN_ACTIVE) {
                    686:                    SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
                    687:                    intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
                    688:                    if (intr & GUSMASK_SAMPLE_DMATC) {
                    689:                        retval += gus_dmain_intr(sc);
                    690:                    }
                    691:                }
                    692:        }
                    693:        if (intr & (GUSMASK_IRQ_VOICE | GUSMASK_IRQ_VOLUME)) {
                    694:                DMAPRINTF(("gusintr voice flags=%x\n", sc->sc_flags));
                    695: #ifdef AUDIO_DEBUG
                    696:                gusvocintrcnt++;
                    697: #endif
                    698:                retval += gus_voice_intr(sc);
                    699:        }
                    700:        if (retval)
                    701:                return 1;
                    702:        return retval;
                    703: }
                    704:
                    705: int gus_bufcnt[GUS_MEM_FOR_BUFFERS / GUS_BUFFER_MULTIPLE];
                    706: int gus_restart;                               /* how many restarts? */
                    707: int gus_stops;                         /* how many times did voice stop? */
                    708: int gus_falsestops;                    /* stopped but not done? */
                    709: int gus_continues;
                    710:
                    711: struct playcont {
                    712:        struct timeval tv;
                    713:        u_int playbuf;
                    714:        u_int dmabuf;
                    715:        u_char bufcnt;
                    716:        u_char vaction;
                    717:        u_char voccntl;
                    718:        u_char volcntl;
                    719:        u_long curaddr;
                    720:        u_long endaddr;
                    721: } playstats[NDMARECS];
                    722:
                    723: int playcntr;
                    724:
                    725: void
                    726: gus_dmaout_timeout(arg)
                    727:        void *arg;
                    728: {
                    729:        struct gus_softc *sc = arg;
                    730:        bus_space_tag_t iot = sc->sc_iot;
                    731:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                    732:        int s;
                    733:
                    734:        printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
                    735:        /*
                    736:         * Stop any DMA.
                    737:         */
                    738:
                    739:        s = splgus();
                    740:        SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
                    741:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
                    742:
                    743: #if 0
                    744:        /* XXX we will dmadone below? */
                    745:        isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
                    746: #endif
                    747:
                    748:        gus_dmaout_dointr(sc);
                    749:        splx(s);
                    750: }
                    751:
                    752:
                    753: /*
                    754:  * Service DMA interrupts.  This routine will only get called if we're doing
                    755:  * a DMA transfer for playback/record requests from the audio layer.
                    756:  */
                    757:
                    758: int
                    759: gus_dmaout_intr(sc)
                    760:        struct gus_softc *sc;
                    761: {
                    762:        bus_space_tag_t iot = sc->sc_iot;
                    763:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                    764:
                    765:        /*
                    766:         * If we got a DMA transfer complete from the GUS DRAM, then deal
                    767:         * with it.
                    768:         */
                    769:
                    770:        SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
                    771:        if (bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
                    772:            timeout_del(&sc->sc_dma_tmo);
                    773:            gus_dmaout_dointr(sc);
                    774:            return 1;
                    775:        }
                    776:        return 0;
                    777: }
                    778:
                    779: void
                    780: gus_dmaout_dointr(sc)
                    781:        struct gus_softc *sc;
                    782: {
                    783:        bus_space_tag_t iot = sc->sc_iot;
                    784:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                    785:
                    786:        /* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */
                    787:        isa_dmadone(sc->sc_dev.dv_parent, sc->sc_drq);
                    788:        sc->sc_flags &= ~GUS_DMAOUT_ACTIVE;  /* pending DMA is done */
                    789:        DMAPRINTF(("gus_dmaout_dointr %d @ %p\n", sc->sc_dmaoutcnt,
                    790:                   sc->sc_dmaoutaddr));
                    791:
                    792:        /*
                    793:         * to prevent clicking, we need to copy last sample
                    794:         * from last buffer to scratch area just before beginning of
                    795:         * buffer.  However, if we're doing formats that are converted by
                    796:         * the card during the DMA process, we need to pick up the converted
                    797:         * byte rather than the one we have in memory.
                    798:         */
                    799:        if (sc->sc_dmabuf == sc->sc_nbufs - 1) {
                    800:          int i;
                    801:          switch (sc->sc_encoding) {
                    802:          case AUDIO_ENCODING_SLINEAR_LE:
                    803:          case AUDIO_ENCODING_SLINEAR_BE:
                    804:            if (sc->sc_precision == 8)
                    805:              goto byte;
                    806:            /* we have the native format */
                    807:            for (i = 1; i <= 2; i++)
                    808:              guspoke(iot, ioh2, sc->sc_gusaddr -
                    809:                      (sc->sc_nbufs - 1) * sc->sc_chanblocksize - i,
                    810:                      sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]);
                    811:            break;
                    812:          case AUDIO_ENCODING_ULINEAR_LE:
                    813:          case AUDIO_ENCODING_ULINEAR_BE:
                    814:            guspoke(iot, ioh2, sc->sc_gusaddr -
                    815:                    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 2,
                    816:                    guspeek(iot, ioh2,
                    817:                            sc->sc_gusaddr + sc->sc_chanblocksize - 2));
                    818:          case AUDIO_ENCODING_ALAW:
                    819:          case AUDIO_ENCODING_ULAW:
                    820:          byte:
                    821:            /* we need to fetch the translated byte, then stuff it. */
                    822:            guspoke(iot, ioh2, sc->sc_gusaddr -
                    823:                    (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1,
                    824:                    guspeek(iot, ioh2,
                    825:                            sc->sc_gusaddr + sc->sc_chanblocksize - 1));
                    826:            break;
                    827:          }
                    828:        }
                    829:        /*
                    830:         * If this is the first half of stereo, "ignore" this one
                    831:         * and copy out the second half.
                    832:         */
                    833:        if (sc->sc_dmaoutintr == stereo_dmaintr) {
                    834:            (*sc->sc_dmaoutintr)(sc->sc_outarg);
                    835:            return;
                    836:        }
                    837:        /*
                    838:         * If the voice is stopped, then start it.  Reset the loop
                    839:         * and roll bits.  Call the audio layer routine, since if
                    840:         * we're starting a stopped voice, that means that the next
                    841:         * buffer can be filled
                    842:         */
                    843:
                    844:        sc->sc_flags &= ~GUS_LOCKED;
                    845:        if (sc->sc_voc[GUS_VOICE_LEFT].voccntl &
                    846:            GUSMASK_VOICE_STOPPED) {
                    847:            if (sc->sc_flags & GUS_PLAYING) {
                    848:                printf("%s: playing yet stopped?\n", sc->sc_dev.dv_xname);
                    849:            }
                    850:            sc->sc_bufcnt++; /* another yet to be played */
                    851:            gus_start_playing(sc, sc->sc_dmabuf);
                    852:            gus_restart++;
                    853:        } else {
                    854:            /*
                    855:             * set the sound action based on which buffer we
                    856:             * just transferred.  If we just transferred buffer 0
                    857:             * we want the sound to loop when it gets to the nth
                    858:             * buffer; if we just transferred
                    859:             * any other buffer, we want the sound to roll over
                    860:             * at least one more time.  The voice interrupt
                    861:             * handlers will take care of accounting &
                    862:             * setting control bits if it's not caught up to us
                    863:             * yet.
                    864:             */
                    865:            if (++sc->sc_bufcnt == 2) {
                    866:                /*
                    867:                 * XXX
                    868:                 * If we're too slow in reaction here,
                    869:                 * the voice could be just approaching the
                    870:                 * end of its run.  It should be set to stop,
                    871:                 * so these adjustments might not DTRT.
                    872:                 */
                    873:                if (sc->sc_dmabuf == 0 &&
                    874:                    sc->sc_playbuf == sc->sc_nbufs - 1) {
                    875:                    /* player is just at the last buf, we're at the
                    876:                       first.  Turn on looping, turn off rolling. */
                    877:                    sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
                    878:                    sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~GUSMASK_VOICE_ROLL;
                    879:                    playstats[playcntr].vaction = 3;
                    880:                } else {
                    881:                    /* player is at previous buf:
                    882:                       turn on rolling, turn off looping */
                    883:                    sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
                    884:                    sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
                    885:                    playstats[playcntr].vaction = 4;
                    886:                }
                    887: #ifdef GUSPLAYDEBUG
                    888:                if (gusstats) {
                    889:                  microtime(&playstats[playcntr].tv);
                    890:                  playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
                    891:                  playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
                    892:                  playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
                    893:                  playstats[playcntr].playbuf = sc->sc_playbuf;
                    894:                  playstats[playcntr].dmabuf = sc->sc_dmabuf;
                    895:                  playstats[playcntr].bufcnt = sc->sc_bufcnt;
                    896:                  playstats[playcntr++].curaddr = gus_get_curaddr(sc, GUS_VOICE_LEFT);
                    897:                  playcntr = playcntr % NDMARECS;
                    898:                }
                    899: #endif
                    900:                bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
                    901:                SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                    902:                bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
                    903:                SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
                    904:                bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
                    905:            }
                    906:        }
                    907:        gus_bufcnt[sc->sc_bufcnt-1]++;
                    908:        /*
                    909:         * flip to the next DMA buffer
                    910:         */
                    911:
                    912:        sc->sc_dmabuf = ++sc->sc_dmabuf % sc->sc_nbufs;
                    913:        /*
                    914:         * See comments below about DMA admission control strategy.
                    915:         * We can call the upper level here if we have an
                    916:         * idle buffer (not currently playing) to DMA into.
                    917:         */
                    918:        if (sc->sc_dmaoutintr && sc->sc_bufcnt < sc->sc_nbufs) {
                    919:            /* clean out to prevent double calls */
                    920:            void (*pfunc)(void *) = sc->sc_dmaoutintr;
                    921:            void *arg = sc->sc_outarg;
                    922:
                    923:            sc->sc_outarg = 0;
                    924:            sc->sc_dmaoutintr = 0;
                    925:            (*pfunc)(arg);
                    926:        }
                    927: }
                    928:
                    929: /*
                    930:  * Service voice interrupts
                    931:  */
                    932:
                    933: int
                    934: gus_voice_intr(sc)
                    935:        struct gus_softc *sc;
                    936: {
                    937:        bus_space_tag_t iot = sc->sc_iot;
                    938:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                    939:        int ignore = 0, voice, rval = 0;
                    940:        unsigned char intr, status;
                    941:
                    942:        /*
                    943:         * The point of this may not be obvious at first.  A voice can
                    944:         * interrupt more than once; according to the GUS SDK we are supposed
                    945:         * to ignore multiple interrupts for the same voice.
                    946:         */
                    947:
                    948:        while(1) {
                    949:                SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
                    950:                intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
                    951:
                    952:                if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
                    953:                        == (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
                    954:                        /*
                    955:                         * No more interrupts, time to return
                    956:                         */
                    957:                        return rval;
                    958:
                    959:                if ((intr & GUSMASK_WIRQ_VOICE) == 0) {
                    960:
                    961:                    /*
                    962:                     * We've got a voice interrupt.  Ignore previous
                    963:                     * interrupts by the same voice.
                    964:                     */
                    965:
                    966:                    rval = 1;
                    967:                    voice = intr & GUSMASK_WIRQ_VOICEMASK;
                    968:
                    969:                    if ((1 << voice) & ignore)
                    970:                        break;
                    971:
                    972:                    ignore |= 1 << voice;
                    973:
                    974:                    /*
                    975:                     * If the voice is stopped, then force it to stop
                    976:                     * (this stops it from continuously generating IRQs)
                    977:                     */
                    978:
                    979:                    SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL+0x80);
                    980:                    status = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
                    981:                    if (status & GUSMASK_VOICE_STOPPED) {
                    982:                        if (voice != GUS_VOICE_LEFT) {
                    983:                            DMAPRINTF(("%s: spurious voice %d stop?\n",
                    984:                                       sc->sc_dev.dv_xname, voice));
                    985:                            gus_stop_voice(sc, voice, 0);
                    986:                            continue;
                    987:                        }
                    988:                        gus_stop_voice(sc, voice, 1);
                    989:                        /* also kill right voice */
                    990:                        gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
                    991:                        sc->sc_bufcnt--; /* it finished a buffer */
                    992:                        if (sc->sc_bufcnt > 0) {
                    993:                            /*
                    994:                             * probably a race to get here: the voice
                    995:                             * stopped while the DMA code was just trying to
                    996:                             * get the next buffer in place.
                    997:                             * Start the voice again.
                    998:                             */
                    999:                            printf("%s: stopped voice not drained? (%x)\n",
                   1000:                                   sc->sc_dev.dv_xname, sc->sc_bufcnt);
                   1001:                            gus_falsestops++;
                   1002:
                   1003:                            sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
                   1004:                            gus_start_playing(sc, sc->sc_playbuf);
                   1005:                        } else if (sc->sc_bufcnt < 0) {
                   1006: #ifdef DDB
                   1007:                            printf("%s: negative bufcnt in stopped voice\n",
                   1008:                                   sc->sc_dev.dv_xname);
                   1009:                            Debugger();
                   1010: #else
                   1011:                            panic("%s: negative bufcnt in stopped voice",
                   1012:                                  sc->sc_dev.dv_xname);
                   1013: #endif
                   1014:                        } else {
                   1015:                            sc->sc_playbuf = -1; /* none are active */
                   1016:                            gus_stops++;
                   1017:                        }
                   1018:                        /* fall through to callback and admit another
                   1019:                           buffer.... */
                   1020:                    } else if (sc->sc_bufcnt != 0) {
                   1021:                        /*
                   1022:                         * This should always be taken if the voice
                   1023:                         * is not stopped.
                   1024:                         */
                   1025:                        gus_continues++;
                   1026:                        if (gus_continue_playing(sc, voice)) {
                   1027:                                /*
                   1028:                                 * we shouldn't have continued--active DMA
                   1029:                                 * is in the way in the ring, for
                   1030:                                 * some as-yet undebugged reason.
                   1031:                                 */
                   1032:                                gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
                   1033:                                /* also kill right voice */
                   1034:                                gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
                   1035:                                sc->sc_playbuf = -1;
                   1036:                                gus_stops++;
                   1037:                        }
                   1038:                    }
                   1039:                    /*
                   1040:                     * call the upper level to send on down another
                   1041:                     * block. We do admission rate control as follows:
                   1042:                     *
                   1043:                     * When starting up output (in the first N
                   1044:                     * blocks), call the upper layer after the DMA is
                   1045:                     * complete (see above in gus_dmaout_intr()).
                   1046:                     *
                   1047:                     * When output is already in progress and we have
                   1048:                     * no more GUS buffers to use for DMA, the DMA
                   1049:                     * output routines do not call the upper layer.
                   1050:                     * Instead, we call the DMA completion routine
                   1051:                     * here, after the voice interrupts indicating
                   1052:                     * that it's finished with a buffer.
                   1053:                     *
                   1054:                     * However, don't call anything here if the DMA
                   1055:                     * output flag is set, (which shouldn't happen)
                   1056:                     * because we'll squish somebody else's DMA if
                   1057:                     * that's the case.  When DMA is done, it will
                   1058:                     * call back if there is a spare buffer.
                   1059:                     */
                   1060:                    if (sc->sc_dmaoutintr && !(sc->sc_flags & GUS_LOCKED)) {
                   1061:                        if (sc->sc_dmaoutintr == stereo_dmaintr)
                   1062:                            printf("gusdmaout botch?\n");
                   1063:                        else {
                   1064:                            /* clean out to avoid double calls */
                   1065:                            void (*pfunc)(void *) = sc->sc_dmaoutintr;
                   1066:                            void *arg = sc->sc_outarg;
                   1067:
                   1068:                            sc->sc_outarg = 0;
                   1069:                            sc->sc_dmaoutintr = 0;
                   1070:                            (*pfunc)(arg);
                   1071:                        }
                   1072:                    }
                   1073:                }
                   1074:
                   1075:                /*
                   1076:                 * Ignore other interrupts for now
                   1077:                 */
                   1078:        }
                   1079:        return 0;
                   1080: }
                   1081:
                   1082: void
                   1083: gus_start_playing(sc, bufno)
                   1084:        struct gus_softc *sc;
                   1085:        int bufno;
                   1086: {
                   1087:        bus_space_tag_t iot = sc->sc_iot;
                   1088:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1089:        /*
                   1090:         * Start the voices playing, with buffer BUFNO.
                   1091:         */
                   1092:
                   1093:        /*
                   1094:         * Loop or roll if we have buffers ready.
                   1095:         */
                   1096:
                   1097:        if (sc->sc_bufcnt == 1) {
                   1098:                sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE);
                   1099:                sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
                   1100:        } else {
                   1101:                if (bufno == sc->sc_nbufs - 1) {
                   1102:                        sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
                   1103:                        sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
                   1104:                } else {
                   1105:                        sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
                   1106:                        sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
                   1107:                }
                   1108:        }
                   1109:
                   1110:        bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
                   1111:
                   1112:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                   1113:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
                   1114:
                   1115:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
                   1116:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
                   1117:
                   1118:        sc->sc_voc[GUS_VOICE_LEFT].current_addr =
                   1119:                GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno;
                   1120:        sc->sc_voc[GUS_VOICE_LEFT].end_addr =
                   1121:                sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1;
                   1122:        sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
                   1123:                sc->sc_voc[GUS_VOICE_LEFT].current_addr +
                   1124:                (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0);
                   1125:        /*
                   1126:         * set up right channel to just loop forever, no interrupts,
                   1127:         * starting at the buffer we just filled.  We'll feed it data
                   1128:         * at the same time as left channel.
                   1129:         */
                   1130:        sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE;
                   1131:        sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL);
                   1132:
                   1133: #ifdef GUSPLAYDEBUG
                   1134:        if (gusstats) {
                   1135:                microtime(&playstats[playcntr].tv);
                   1136:                playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr;
                   1137:
                   1138:                playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
                   1139:                playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
                   1140:                playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
                   1141:                playstats[playcntr].playbuf = bufno;
                   1142:                playstats[playcntr].dmabuf = sc->sc_dmabuf;
                   1143:                playstats[playcntr].bufcnt = sc->sc_bufcnt;
                   1144:                playstats[playcntr++].vaction = 5;
                   1145:                playcntr = playcntr % NDMARECS;
                   1146:        }
                   1147: #endif
                   1148:
                   1149:        bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_RIGHT);
                   1150:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                   1151:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl);
                   1152:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
                   1153:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl);
                   1154:
                   1155:        gus_start_voice(sc, GUS_VOICE_RIGHT, 0);
                   1156:        gus_start_voice(sc, GUS_VOICE_LEFT, 1);
                   1157:        if (sc->sc_playbuf == -1)
                   1158:                /* mark start of playing */
                   1159:                sc->sc_playbuf = bufno;
                   1160: }
                   1161:
                   1162: int
                   1163: gus_continue_playing(sc, voice)
                   1164:        struct gus_softc *sc;
                   1165:        int voice;
                   1166: {
                   1167:        bus_space_tag_t iot = sc->sc_iot;
                   1168:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1169:
                   1170:        /*
                   1171:         * stop this voice from interrupting while we work.
                   1172:         */
                   1173:
                   1174:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                   1175:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ));
                   1176:
                   1177:        /*
                   1178:         * update playbuf to point to the buffer the hardware just started
                   1179:         * playing
                   1180:         */
                   1181:        sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
                   1182:
                   1183:        /*
                   1184:         * account for buffer just finished
                   1185:         */
                   1186:        if (--sc->sc_bufcnt == 0) {
                   1187:                DPRINTF(("gus: bufcnt 0 on continuing voice?\n"));
                   1188:        }
                   1189:        if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) {
                   1190:                printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
                   1191:                return 1;
                   1192:        }
                   1193:
                   1194:        /*
                   1195:         * Select the end of the buffer based on the currently active
                   1196:         * buffer, [plus extra contiguous buffers (if ready)].
                   1197:         */
                   1198:
                   1199:        /*
                   1200:         * set endpoint at end of buffer we just started playing.
                   1201:         *
                   1202:         * The total gets -1 because end addrs are one less than you might
                   1203:         * think (the end_addr is the address of the last sample to play)
                   1204:         */
                   1205:        gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
                   1206:                        sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
                   1207:
                   1208:        if (sc->sc_bufcnt < 2) {
                   1209:                /*
                   1210:                 * Clear out the loop and roll flags, and rotate the currently
                   1211:                 * playing buffer.  That way, if we don't manage to get more
                   1212:                 * data before this buffer finishes, we'll just stop.
                   1213:                 */
                   1214:                sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
                   1215:                sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
                   1216:                playstats[playcntr].vaction = 0;
                   1217:        } else {
                   1218:                /*
                   1219:                 * We have some buffers to play.  set LOOP if we're on the
                   1220:                 * last buffer in the ring, otherwise set ROLL.
                   1221:                 */
                   1222:                if (sc->sc_playbuf == sc->sc_nbufs - 1) {
                   1223:                        sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
                   1224:                        sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
                   1225:                        playstats[playcntr].vaction = 1;
                   1226:                } else {
                   1227:                        sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
                   1228:                        sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
                   1229:                        playstats[playcntr].vaction = 2;
                   1230:                }
                   1231:        }
                   1232: #ifdef GUSPLAYDEBUG
                   1233:        if (gusstats) {
                   1234:                microtime(&playstats[playcntr].tv);
                   1235:                playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
                   1236:
                   1237:                playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
                   1238:                playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
                   1239:                playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
                   1240:                playstats[playcntr].playbuf = sc->sc_playbuf;
                   1241:                playstats[playcntr].dmabuf = sc->sc_dmabuf;
                   1242:                playstats[playcntr++].bufcnt = sc->sc_bufcnt;
                   1243:                playcntr = playcntr % NDMARECS;
                   1244:        }
                   1245: #endif
                   1246:
                   1247:        /*
                   1248:         * (re-)set voice parameters.  This will reenable interrupts from this
                   1249:         * voice.
                   1250:         */
                   1251:
                   1252:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                   1253:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
                   1254:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
                   1255:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
                   1256:        return 0;
                   1257: }
                   1258:
                   1259: /*
                   1260:  * Send/receive data into GUS's DRAM using DMA.  Called at splgus()
                   1261:  */
                   1262:
                   1263: void
                   1264: gusdmaout(sc, flags, gusaddr, buffaddr, length)
                   1265:        struct gus_softc *sc;
                   1266:        int flags, length;
                   1267:        u_long gusaddr;
                   1268:        caddr_t buffaddr;
                   1269: {
                   1270:        unsigned char c = (unsigned char) flags;
                   1271:        bus_space_tag_t iot = sc->sc_iot;
                   1272:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1273:
                   1274:        DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags));
                   1275:
                   1276:        sc->sc_gusaddr = gusaddr;
                   1277:
                   1278:        /*
                   1279:         * If we're using a 16 bit DMA channel, we have to jump through some
                   1280:         * extra hoops; this includes translating the DRAM address a bit
                   1281:         */
                   1282:
                   1283:        if (sc->sc_drq >= 4) {
                   1284:                c |= GUSMASK_DMA_WIDTH;
                   1285:                gusaddr = convert_to_16bit(gusaddr);
                   1286:        }
                   1287:
                   1288:        /*
                   1289:         * Add flag bits that we always set - fast DMA, enable IRQ
                   1290:         */
                   1291:
                   1292:        c |= GUSMASK_DMA_ENABLE | GUSMASK_DMA_R0 | GUSMASK_DMA_IRQ;
                   1293:
                   1294:        /*
                   1295:         * Make sure the GUS _isn't_ setup for DMA
                   1296:         */
                   1297:
                   1298:        SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
                   1299:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
                   1300:
                   1301:        /*
                   1302:         * Tell the PC DMA controller to start doing DMA
                   1303:         */
                   1304:
                   1305:        sc->sc_dmaoutaddr = (u_char *) buffaddr;
                   1306:        sc->sc_dmaoutcnt = length;
                   1307:        isa_dmastart(sc->sc_dev.dv_parent, sc->sc_drq, buffaddr, length,
                   1308:            NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
                   1309:
                   1310:        /*
                   1311:         * Set up DMA address - use the upper 16 bits ONLY
                   1312:         */
                   1313:
                   1314:        sc->sc_flags |= GUS_DMAOUT_ACTIVE;
                   1315:
                   1316:        SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_START);
                   1317:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (int) (gusaddr >> 4));
                   1318:
                   1319:        /*
                   1320:         * Tell the GUS to start doing DMA
                   1321:         */
                   1322:
                   1323:        SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
                   1324:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, c);
                   1325:
                   1326:        /*
                   1327:         * XXX If we don't finish in one second, give up...
                   1328:         */
                   1329:        timeout_add(&sc->sc_dma_tmo, hz);
                   1330: }
                   1331:
                   1332: /*
                   1333:  * Start a voice playing on the GUS.  Called from interrupt handler at
                   1334:  * splgus().
                   1335:  */
                   1336:
                   1337: void
                   1338: gus_start_voice(sc, voice, intrs)
                   1339:        struct gus_softc *sc;
                   1340:        int voice;
                   1341:        int intrs;
                   1342: {
                   1343:        bus_space_tag_t iot = sc->sc_iot;
                   1344:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1345:        u_long start;
                   1346:        u_long current;
                   1347:        u_long end;
                   1348:
                   1349:        /*
                   1350:         * Pick all the values for the voice out of the gus_voice struct
                   1351:         * and use those to program the voice
                   1352:         */
                   1353:
                   1354:        start = sc->sc_voc[voice].start_addr;
                   1355:        current = sc->sc_voc[voice].current_addr;
                   1356:        end = sc->sc_voc[voice].end_addr;
                   1357:
                   1358:        /*
                   1359:         * If we're using 16 bit data, mangle the addresses a bit
                   1360:         */
                   1361:
                   1362:        if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) {
                   1363:                /* -1 on start so that we get onto sample boundary--other
                   1364:                   code always sets it for 1-byte rollover protection */
                   1365:                start = convert_to_16bit(start-1);
                   1366:                current = convert_to_16bit(current);
                   1367:                end = convert_to_16bit(end);
                   1368:        }
                   1369:
                   1370:        /*
                   1371:         * Select the voice we want to use, and program the data addresses
                   1372:         */
                   1373:
                   1374:        bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
                   1375:
                   1376:        SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
                   1377:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(start));
                   1378:        SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
                   1379:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(start));
                   1380:
                   1381:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
                   1382:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(current));
                   1383:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
                   1384:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(current));
                   1385:
                   1386:        SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
                   1387:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(end));
                   1388:        SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
                   1389:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(end));
                   1390:
                   1391:        /*
                   1392:         * (maybe) enable interrupts, disable voice stopping
                   1393:         */
                   1394:
                   1395:        if (intrs) {
                   1396:                sc->sc_flags |= GUS_PLAYING; /* playing is about to start */
                   1397:                sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_IRQ;
                   1398:                DMAPRINTF(("gus voice playing=%x\n", sc->sc_flags));
                   1399:        } else
                   1400:                sc->sc_voc[voice].voccntl &= ~GUSMASK_VOICE_IRQ;
                   1401:        sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_STOPPED |
                   1402:                GUSMASK_STOP_VOICE);
                   1403:
                   1404:        /*
                   1405:         * Tell the GUS about it.  Note that we're doing volume ramping here
                   1406:         * from 0 up to the set volume to help reduce clicks.
                   1407:         */
                   1408:
                   1409:        SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
                   1410:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
                   1411:        SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
                   1412:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
                   1413:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
                   1414:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x00);
                   1415:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
                   1416:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 63);
                   1417:
                   1418:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                   1419:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
                   1420:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
                   1421:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
                   1422:        delay(50);
                   1423:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                   1424:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
                   1425:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
                   1426:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
                   1427:
                   1428: }
                   1429:
                   1430: /*
                   1431:  * Stop a given voice.  called at splgus()
                   1432:  */
                   1433:
                   1434: void
                   1435: gus_stop_voice(sc, voice, intrs_too)
                   1436:        struct gus_softc *sc;
                   1437:        int voice;
                   1438:        int intrs_too;
                   1439: {
                   1440:        bus_space_tag_t iot = sc->sc_iot;
                   1441:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1442:
                   1443:        sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED |
                   1444:                GUSMASK_STOP_VOICE;
                   1445:        if (intrs_too) {
                   1446:          sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_IRQ);
                   1447:          /* no more DMA to do */
                   1448:          sc->sc_flags &= ~GUS_PLAYING;
                   1449:        }
                   1450:        DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags));
                   1451:
                   1452:        guspoke(iot, ioh2, 0L, 0);
                   1453:
                   1454:        bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
                   1455:
                   1456:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
                   1457:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   1458:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                   1459:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
                   1460:        delay(100);
                   1461:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
                   1462:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   1463:        SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                   1464:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
                   1465:
                   1466:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
                   1467:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   1468:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
                   1469:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   1470:
                   1471: }
                   1472:
                   1473:
                   1474: /*
                   1475:  * Set the volume of a given voice.  Called at splgus().
                   1476:  */
                   1477: void
                   1478: gus_set_volume(sc, voice, volume)
                   1479:        struct gus_softc *sc;
                   1480:        int voice, volume;
                   1481: {
                   1482:        bus_space_tag_t iot = sc->sc_iot;
                   1483:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1484:        unsigned int gusvol;
                   1485:
                   1486:        gusvol = gus_log_volumes[volume < 512 ? volume : 511];
                   1487:
                   1488:        sc->sc_voc[voice].current_volume = gusvol;
                   1489:
                   1490:        bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
                   1491:
                   1492:        SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
                   1493:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
                   1494:
                   1495:        SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
                   1496:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
                   1497:
                   1498:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
                   1499:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
                   1500:        delay(500);
                   1501:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
                   1502:
                   1503: }
                   1504:
                   1505: /*
                   1506:  * Interface to the audio layer.
                   1507:  */
                   1508:
                   1509: int
                   1510: gusmax_set_params(addr, setmode, usemode, p, r)
                   1511:        void *addr;
                   1512:        int setmode, usemode;
                   1513:        struct audio_params *p, *r;
                   1514: {
                   1515:        struct ad1848_softc *ac = addr;
                   1516:        struct gus_softc *sc = ac->parent;
                   1517:        int error;
                   1518:
                   1519:        error = ad1848_set_params(ac, setmode, usemode, p, r);
                   1520:        if (error)
                   1521:                return error;
                   1522:        error = gus_set_params(sc, setmode, usemode, p, r);
                   1523:        return error;
                   1524: }
                   1525:
                   1526: int
                   1527: gus_set_params(addr, setmode, usemode, p, r)
                   1528:        void *addr;
                   1529:        int setmode, usemode;
                   1530:        struct audio_params *p, *r;
                   1531: {
                   1532:        struct gus_softc *sc = addr;
                   1533:        int s;
                   1534:
                   1535:        switch (p->encoding) {
                   1536:        case AUDIO_ENCODING_ULAW:
                   1537:        case AUDIO_ENCODING_ALAW:
                   1538:        case AUDIO_ENCODING_SLINEAR_LE:
                   1539:        case AUDIO_ENCODING_ULINEAR_LE:
                   1540:        case AUDIO_ENCODING_SLINEAR_BE:
                   1541:        case AUDIO_ENCODING_ULINEAR_BE:
                   1542:                break;
                   1543:        default:
                   1544:                return (EINVAL);
                   1545:        }
                   1546:
                   1547:        s = splaudio();
                   1548:
                   1549:        if (p->precision == 8) {
                   1550:                sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16;
                   1551:                sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16;
                   1552:        } else {
                   1553:                sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
                   1554:                sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
                   1555:        }
                   1556:
                   1557:        sc->sc_encoding = p->encoding;
                   1558:        sc->sc_precision = p->precision;
                   1559:        sc->sc_channels = p->channels;
                   1560:
                   1561:        splx(s);
                   1562:
                   1563:        if (p->sample_rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
                   1564:                p->sample_rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
                   1565:        if (setmode & AUMODE_RECORD)
                   1566:                sc->sc_irate = p->sample_rate;
                   1567:        if (setmode & AUMODE_PLAY)
                   1568:                sc->sc_orate = p->sample_rate;
                   1569:
                   1570:        switch (p->encoding) {
                   1571:        case AUDIO_ENCODING_ULAW:
                   1572:                p->sw_code = mulaw_to_ulinear8;
                   1573:                r->sw_code = ulinear8_to_mulaw;
                   1574:                break;
                   1575:        case AUDIO_ENCODING_ALAW:
                   1576:                p->sw_code = alaw_to_ulinear8;
                   1577:                r->sw_code = ulinear8_to_alaw;
                   1578:                break;
                   1579:        case AUDIO_ENCODING_ULINEAR_BE:
                   1580:        case AUDIO_ENCODING_SLINEAR_BE:
                   1581:                r->sw_code = p->sw_code = swap_bytes;
                   1582:                break;
                   1583:        }
                   1584:
                   1585:        return 0;
                   1586: }
                   1587:
                   1588: /*
                   1589:  * Interface to the audio layer - set the blocksize to the correct number
                   1590:  * of units
                   1591:  */
                   1592:
                   1593: int
                   1594: gusmax_round_blocksize(addr, blocksize)
                   1595:        void * addr;
                   1596:        int blocksize;
                   1597: {
                   1598:        struct ad1848_softc *ac = addr;
                   1599:        struct gus_softc *sc = ac->parent;
                   1600:
                   1601: /*     blocksize = ad1848_round_blocksize(ac, blocksize);*/
                   1602:        return gus_round_blocksize(sc, blocksize);
                   1603: }
                   1604:
                   1605: int
                   1606: gus_round_blocksize(addr, blocksize)
                   1607:        void * addr;
                   1608:        int blocksize;
                   1609: {
                   1610:        struct gus_softc *sc = addr;
                   1611:
                   1612:        DPRINTF(("gus_round_blocksize called\n"));
                   1613:
                   1614:        if ((sc->sc_encoding == AUDIO_ENCODING_ULAW ||
                   1615:             sc->sc_encoding == AUDIO_ENCODING_ALAW) && blocksize > 32768)
                   1616:                blocksize = 32768;
                   1617:        else if (blocksize > 65536)
                   1618:                blocksize = 65536;
                   1619:
                   1620:        if ((blocksize % GUS_BUFFER_MULTIPLE) != 0)
                   1621:                blocksize = (blocksize / GUS_BUFFER_MULTIPLE + 1) *
                   1622:                        GUS_BUFFER_MULTIPLE;
                   1623:
                   1624:        /* set up temporary buffer to hold the deinterleave, if necessary
                   1625:           for stereo output */
                   1626:        if (sc->sc_deintr_buf) {
                   1627:                free(sc->sc_deintr_buf, M_DEVBUF);
                   1628:                sc->sc_deintr_buf = NULL;
                   1629:        }
                   1630:        sc->sc_deintr_buf = malloc(blocksize/2, M_DEVBUF, M_WAITOK);
                   1631:
                   1632:        sc->sc_blocksize = blocksize;
                   1633:        /* multi-buffering not quite working yet. */
                   1634:        sc->sc_nbufs = /*GUS_MEM_FOR_BUFFERS / blocksize*/ 2;
                   1635:
                   1636:        gus_set_chan_addrs(sc);
                   1637:
                   1638:        return blocksize;
                   1639: }
                   1640:
                   1641: int
                   1642: gus_get_out_gain(addr)
                   1643:        caddr_t addr;
                   1644: {
                   1645:        struct gus_softc *sc = (struct gus_softc *) addr;
                   1646:
                   1647:        DPRINTF(("gus_get_out_gain called\n"));
                   1648:        return sc->sc_ogain / 2;
                   1649: }
                   1650:
                   1651: inline void gus_set_voices(sc, voices)
                   1652: struct gus_softc *sc;
                   1653: int voices;
                   1654: {
                   1655:        bus_space_tag_t iot = sc->sc_iot;
                   1656:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1657:        /*
                   1658:         * Select the active number of voices
                   1659:         */
                   1660:
                   1661:        SELECT_GUS_REG(iot, ioh2, GUSREG_ACTIVE_VOICES);
                   1662:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (voices-1) | 0xc0);
                   1663:
                   1664:        sc->sc_voices = voices;
                   1665: }
                   1666:
                   1667: /*
                   1668:  * Actually set the settings of various values on the card
                   1669:  */
                   1670:
                   1671: int
                   1672: gusmax_commit_settings(addr)
                   1673:        void * addr;
                   1674: {
                   1675:        struct ad1848_softc *ac = addr;
                   1676:        struct gus_softc *sc = ac->parent;
                   1677:        int error;
                   1678:
                   1679:        error = ad1848_commit_settings(ac);
                   1680:        if (error)
                   1681:                return error;
                   1682:        return gus_commit_settings(sc);
                   1683: }
                   1684:
                   1685: /*
                   1686:  * Commit the settings.  Called at normal IPL.
                   1687:  */
                   1688: int
                   1689: gus_commit_settings(addr)
                   1690:        void * addr;
                   1691: {
                   1692:        struct gus_softc *sc = addr;
                   1693:        int s;
                   1694:
                   1695:        DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain));
                   1696:
                   1697:
                   1698:        s = splgus();
                   1699:
                   1700:        gus_set_recrate(sc, sc->sc_irate);
                   1701:        gus_set_volume(sc, GUS_VOICE_LEFT, sc->sc_ogain);
                   1702:        gus_set_volume(sc, GUS_VOICE_RIGHT, sc->sc_ogain);
                   1703:        gus_set_samprate(sc, GUS_VOICE_LEFT, sc->sc_orate);
                   1704:        gus_set_samprate(sc, GUS_VOICE_RIGHT, sc->sc_orate);
                   1705:        splx(s);
                   1706:        gus_set_chan_addrs(sc);
                   1707:
                   1708:        return 0;
                   1709: }
                   1710:
                   1711: void
                   1712: gus_set_chan_addrs(sc)
                   1713: struct gus_softc *sc;
                   1714: {
                   1715:        /*
                   1716:         * We use sc_nbufs * blocksize bytes of storage in the on-board GUS
                   1717:         * ram.
                   1718:         * For mono, each of the sc_nbufs buffers is DMA'd to in one chunk,
                   1719:         * and both left & right channels play the same buffer.
                   1720:         *
                   1721:         * For stereo, each channel gets a contiguous half of the memory,
                   1722:         * and each has sc_nbufs buffers of size blocksize/2.
                   1723:         * Stereo data are deinterleaved in main memory before the DMA out
                   1724:         * routines are called to queue the output.
                   1725:         *
                   1726:         * The blocksize per channel is kept in sc_chanblocksize.
                   1727:         */
                   1728:        if (sc->sc_channels == 2)
                   1729:            sc->sc_chanblocksize = sc->sc_blocksize/2;
                   1730:        else
                   1731:            sc->sc_chanblocksize = sc->sc_blocksize;
                   1732:
                   1733:        sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1;
                   1734:        sc->sc_voc[GUS_VOICE_RIGHT].start_addr =
                   1735:            (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0)
                   1736:              + GUS_MEM_OFFSET - 1;
                   1737:        sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
                   1738:            sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 1;
                   1739:        sc->sc_voc[GUS_VOICE_RIGHT].end_addr =
                   1740:            sc->sc_voc[GUS_VOICE_RIGHT].start_addr +
                   1741:            sc->sc_nbufs * sc->sc_chanblocksize;
                   1742:
                   1743: }
                   1744:
                   1745: /*
                   1746:  * Set the sample rate of the given voice.  Called at splgus().
                   1747:  */
                   1748:
                   1749: void
                   1750: gus_set_samprate(sc, voice, freq)
                   1751:        struct gus_softc *sc;
                   1752:        int voice, freq;
                   1753: {
                   1754:        bus_space_tag_t iot = sc->sc_iot;
                   1755:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1756:        unsigned int fc;
                   1757:        u_long temp, f = (u_long) freq;
                   1758:
                   1759:        /*
                   1760:         * calculate fc based on the number of active voices;
                   1761:         * we need to use longs to preserve enough bits
                   1762:         */
                   1763:
                   1764:        temp = (u_long) gus_max_frequency[sc->sc_voices-GUS_MIN_VOICES];
                   1765:
                   1766:        fc = (unsigned int)(((f << 9L) + (temp >> 1L)) / temp);
                   1767:
                   1768:        fc <<= 1;
                   1769:
                   1770:
                   1771:        /*
                   1772:         * Program the voice frequency, and set it in the voice data record
                   1773:         */
                   1774:
                   1775:        bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
                   1776:        SELECT_GUS_REG(iot, ioh2, GUSREG_FREQ_CONTROL);
                   1777:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, fc);
                   1778:
                   1779:        sc->sc_voc[voice].rate = freq;
                   1780:
                   1781: }
                   1782:
                   1783: /*
                   1784:  * Set the sample rate of the recording frequency.  Formula is from the GUS
                   1785:  * SDK.  Called at splgus().
                   1786:  */
                   1787:
                   1788: void
                   1789: gus_set_recrate(sc, rate)
                   1790:        struct gus_softc *sc;
                   1791:        u_long rate;
                   1792: {
                   1793:        bus_space_tag_t iot = sc->sc_iot;
                   1794:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1795:        u_char realrate;
                   1796:        DPRINTF(("gus_set_recrate %lu\n", rate));
                   1797:
                   1798: #if 0
                   1799:        realrate = 9878400/(16*(rate+2)); /* formula from GUS docs */
                   1800: #endif
                   1801:        realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */
                   1802:
                   1803:        SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_FREQ);
                   1804:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, realrate);
                   1805: }
                   1806:
                   1807: /*
                   1808:  * Interface to the audio layer - turn the output on or off.  Note that some
                   1809:  * of these bits are flipped in the register
                   1810:  */
                   1811:
                   1812: int
                   1813: gusmax_speaker_ctl(addr, newstate)
                   1814:        void * addr;
                   1815:        int newstate;
                   1816: {
                   1817:        struct ad1848_softc *sc = addr;
                   1818:        return gus_speaker_ctl(sc->parent, newstate);
                   1819: }
                   1820:
                   1821: int
                   1822: gus_speaker_ctl(addr, newstate)
                   1823:        void * addr;
                   1824:        int newstate;
                   1825: {
                   1826:        struct gus_softc *sc = (struct gus_softc *) addr;
                   1827:        bus_space_tag_t iot = sc->sc_iot;
                   1828:        bus_space_handle_t ioh1 = sc->sc_ioh1;
                   1829:
                   1830:        /* Line out bit is flipped: 0 enables, 1 disables */
                   1831:        if ((newstate == SPKR_ON) &&
                   1832:            (sc->sc_mixcontrol & GUSMASK_LINE_OUT)) {
                   1833:                sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT;
                   1834:                bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
                   1835:        }
                   1836:        if ((newstate == SPKR_OFF) &&
                   1837:            (sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) {
                   1838:                sc->sc_mixcontrol |= GUSMASK_LINE_OUT;
                   1839:                bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
                   1840:        }
                   1841:
                   1842:        return 0;
                   1843: }
                   1844:
                   1845: int
                   1846: gus_linein_ctl(addr, newstate)
                   1847:        void * addr;
                   1848:        int newstate;
                   1849: {
                   1850:        struct gus_softc *sc = (struct gus_softc *) addr;
                   1851:        bus_space_tag_t iot = sc->sc_iot;
                   1852:        bus_space_handle_t ioh1 = sc->sc_ioh1;
                   1853:
                   1854:        /* Line in bit is flipped: 0 enables, 1 disables */
                   1855:        if ((newstate == SPKR_ON) &&
                   1856:            (sc->sc_mixcontrol & GUSMASK_LINE_IN)) {
                   1857:                sc->sc_mixcontrol &= ~GUSMASK_LINE_IN;
                   1858:                bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
                   1859:        }
                   1860:        if ((newstate == SPKR_OFF) &&
                   1861:            (sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) {
                   1862:                sc->sc_mixcontrol |= GUSMASK_LINE_IN;
                   1863:                bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
                   1864:        }
                   1865:
                   1866:        return 0;
                   1867: }
                   1868:
                   1869: int
                   1870: gus_mic_ctl(addr, newstate)
                   1871:        void * addr;
                   1872:        int newstate;
                   1873: {
                   1874:        struct gus_softc *sc = (struct gus_softc *) addr;
                   1875:        bus_space_tag_t iot = sc->sc_iot;
                   1876:        bus_space_handle_t ioh1 = sc->sc_ioh1;
                   1877:
                   1878:        /* Mic bit is normal: 1 enables, 0 disables */
                   1879:        if ((newstate == SPKR_ON) &&
                   1880:            (sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) {
                   1881:                sc->sc_mixcontrol |= GUSMASK_MIC_IN;
                   1882:                bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
                   1883:        }
                   1884:        if ((newstate == SPKR_OFF) &&
                   1885:            (sc->sc_mixcontrol & GUSMASK_MIC_IN)) {
                   1886:                sc->sc_mixcontrol &= ~GUSMASK_MIC_IN;
                   1887:                bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
                   1888:        }
                   1889:
                   1890:        return 0;
                   1891: }
                   1892:
                   1893: /*
                   1894:  * Set the end address of a give voice.  Called at splgus()
                   1895:  */
                   1896:
                   1897: void
                   1898: gus_set_endaddr(sc, voice, addr)
                   1899:        struct gus_softc *sc;
                   1900:        int voice;
                   1901:        u_long addr;
                   1902: {
                   1903:        bus_space_tag_t iot = sc->sc_iot;
                   1904:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1905:
                   1906:        sc->sc_voc[voice].end_addr = addr;
                   1907:
                   1908:        if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
                   1909:                addr = convert_to_16bit(addr);
                   1910:
                   1911:        SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
                   1912:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
                   1913:        SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
                   1914:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
                   1915:
                   1916: }
                   1917:
                   1918: #ifdef GUSPLAYDEBUG
                   1919: /*
                   1920:  * Set current address.  called at splgus()
                   1921:  */
                   1922: void
                   1923: gus_set_curaddr(sc, voice, addr)
                   1924:        struct gus_softc *sc;
                   1925:        int voice;
                   1926:        u_long addr;
                   1927: {
                   1928:        bus_space_tag_t iot = sc->sc_iot;
                   1929:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1930:
                   1931:        sc->sc_voc[voice].current_addr = addr;
                   1932:
                   1933:        if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
                   1934:                addr = convert_to_16bit(addr);
                   1935:
                   1936:        bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
                   1937:
                   1938:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
                   1939:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
                   1940:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
                   1941:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
                   1942:
                   1943: }
                   1944:
                   1945: /*
                   1946:  * Get current GUS playback address.  Called at splgus().
                   1947:  */
                   1948: u_long
                   1949: gus_get_curaddr(sc, voice)
                   1950:        struct gus_softc *sc;
                   1951:        int voice;
                   1952: {
                   1953:        bus_space_tag_t iot = sc->sc_iot;
                   1954:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   1955:        u_long addr;
                   1956:
                   1957:        bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
                   1958:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
                   1959:        addr = (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) & 0x1fff) << 7;
                   1960:        SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
                   1961:        addr |= (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) >> 9L) & 0x7f;
                   1962:
                   1963:        if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
                   1964:            addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */
                   1965:        DPRINTF(("gus voice %d curaddr %ld end_addr %ld\n",
                   1966:                 voice, addr, sc->sc_voc[voice].end_addr));
                   1967:        /* XXX sanity check the address? */
                   1968:
                   1969:        return(addr);
                   1970: }
                   1971: #endif
                   1972:
                   1973: /*
                   1974:  * Convert an address value to a "16 bit" value - why this is necessary I
                   1975:  * have NO idea
                   1976:  */
                   1977:
                   1978: u_long
                   1979: convert_to_16bit(address)
                   1980:        u_long address;
                   1981: {
                   1982:        u_long old_address;
                   1983:
                   1984:        old_address = address;
                   1985:        address >>= 1;
                   1986:        address &= 0x0001ffffL;
                   1987:        address |= (old_address & 0x000c0000L);
                   1988:
                   1989:        return (address);
                   1990: }
                   1991:
                   1992: /*
                   1993:  * Write a value into the GUS's DRAM
                   1994:  */
                   1995:
                   1996: void
                   1997: guspoke(iot, ioh2, address, value)
                   1998:        bus_space_tag_t iot;
                   1999:        bus_space_handle_t ioh2;
                   2000:        long address;
                   2001:        unsigned char value;
                   2002: {
                   2003:
                   2004:        /*
                   2005:         * Select the DRAM address
                   2006:         */
                   2007:
                   2008:        SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
                   2009:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
                   2010:        SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
                   2011:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
                   2012:
                   2013:        /*
                   2014:         * Actually write the data
                   2015:         */
                   2016:
                   2017:        bus_space_write_1(iot, ioh2, GUS_DRAM_DATA, value);
                   2018: }
                   2019:
                   2020: /*
                   2021:  * Read a value from the GUS's DRAM
                   2022:  */
                   2023:
                   2024: unsigned char
                   2025: guspeek(iot, ioh2, address)
                   2026:        bus_space_tag_t iot;
                   2027:        bus_space_handle_t ioh2;
                   2028:        u_long address;
                   2029: {
                   2030:
                   2031:        /*
                   2032:         * Select the DRAM address
                   2033:         */
                   2034:
                   2035:        SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
                   2036:        bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
                   2037:        SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
                   2038:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
                   2039:
                   2040:        /*
                   2041:         * Read in the data from the board
                   2042:         */
                   2043:
                   2044:        return (unsigned char) bus_space_read_1(iot, ioh2, GUS_DRAM_DATA);
                   2045: }
                   2046:
                   2047: /*
                   2048:  * Reset the Gravis UltraSound card, completely
                   2049:  */
                   2050:
                   2051: void
                   2052: gusreset(sc, voices)
                   2053:        struct gus_softc *sc;
                   2054:        int voices;
                   2055: {
                   2056:        bus_space_tag_t iot = sc->sc_iot;
                   2057:        bus_space_handle_t ioh1 = sc->sc_ioh1;
                   2058:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   2059:        bus_space_handle_t ioh4 = sc->sc_ioh4;
                   2060:        int i,s;
                   2061:
                   2062:        s = splgus();
                   2063:
                   2064:        /*
                   2065:         * Reset the GF1 chip
                   2066:         */
                   2067:
                   2068:        SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
                   2069:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
                   2070:
                   2071:        delay(500);
                   2072:
                   2073:        /*
                   2074:         * Release reset
                   2075:         */
                   2076:
                   2077:        SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
                   2078:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
                   2079:
                   2080:        delay(500);
                   2081:
                   2082:        /*
                   2083:         * Reset MIDI port as well
                   2084:         */
                   2085:
                   2086:        bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, MIDI_RESET);
                   2087:
                   2088:        delay(500);
                   2089:
                   2090:        bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, 0x00);
                   2091:
                   2092:        /*
                   2093:         * Clear interrupts
                   2094:         */
                   2095:
                   2096:        SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
                   2097:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
                   2098:        SELECT_GUS_REG(iot, ioh2, GUSREG_TIMER_CONTROL);
                   2099:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
                   2100:        SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
                   2101:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
                   2102:
                   2103:        gus_set_voices(sc, voices);
                   2104:
                   2105:        bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
                   2106:        SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
                   2107:        bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
                   2108:        SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
                   2109:        bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
                   2110:        SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
                   2111:        bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
                   2112:
                   2113:        /*
                   2114:         * Reset voice specific information
                   2115:         */
                   2116:
                   2117:        for(i = 0; i < voices; i++) {
                   2118:                bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) i);
                   2119:
                   2120:                SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
                   2121:
                   2122:                sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED |
                   2123:                        GUSMASK_STOP_VOICE;
                   2124:
                   2125:                bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
                   2126:
                   2127:                sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED |
                   2128:                                GUSMASK_STOP_VOLUME;
                   2129:
                   2130:                SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
                   2131:                bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
                   2132:
                   2133:                delay(100);
                   2134:
                   2135:                gus_set_samprate(sc, i, 8000);
                   2136:                SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
                   2137:                bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   2138:                SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
                   2139:                bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   2140:                SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
                   2141:                bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   2142:                SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
                   2143:                bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   2144:                SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
                   2145:                bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x01);
                   2146:                SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
                   2147:                bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x10);
                   2148:                SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
                   2149:                bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0xe0);
                   2150:                SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
                   2151:                bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   2152:
                   2153:                SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
                   2154:                bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   2155:                SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
                   2156:                bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
                   2157:                SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
                   2158:                bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x07);
                   2159:        }
                   2160:
                   2161:        /*
                   2162:         * Clear out any pending IRQs
                   2163:         */
                   2164:
                   2165:        bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
                   2166:        SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
                   2167:        bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
                   2168:        SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
                   2169:        bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
                   2170:        SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
                   2171:        bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
                   2172:
                   2173:        SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
                   2174:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
                   2175:                GUSMASK_IRQ_ENABLE);
                   2176:
                   2177:        splx(s);
                   2178: }
                   2179:
                   2180:
                   2181: int
                   2182: gus_init_cs4231(sc)
                   2183:        struct gus_softc *sc;
                   2184: {
                   2185:        bus_space_tag_t iot = sc->sc_iot;
                   2186:        bus_space_handle_t ioh1 = sc->sc_ioh1;
                   2187:        int port = sc->sc_iobase;
                   2188:        u_char ctrl;
                   2189:
                   2190:        ctrl = (port & 0xf0) >> 4;      /* set port address middle nibble */
                   2191:        /*
                   2192:         * The codec is a bit weird--swapped dma channels.
                   2193:         */
                   2194:        ctrl |= GUS_MAX_CODEC_ENABLE;
                   2195:        if (sc->sc_drq >= 4)
                   2196:                ctrl |= GUS_MAX_RECCHAN16;
                   2197:        if (sc->sc_recdrq >= 4)
                   2198:                ctrl |= GUS_MAX_PLAYCHAN16;
                   2199:
                   2200:        bus_space_write_1(iot, ioh1, GUS_MAX_CTRL, ctrl);
                   2201:
                   2202:        sc->sc_codec.sc_iot = sc->sc_iot;
                   2203:        sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE;
                   2204:
                   2205:        if (ad1848_mapprobe(&sc->sc_codec, sc->sc_codec.sc_iobase) == 0) {
                   2206:                sc->sc_flags &= ~GUS_CODEC_INSTALLED;
                   2207:                return (0);
                   2208:        } else {
                   2209:                struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN};
                   2210:                sc->sc_flags |= GUS_CODEC_INSTALLED;
                   2211:                sc->sc_codec.parent = sc;
                   2212:                sc->sc_codec.sc_drq = sc->sc_recdrq;
                   2213:                sc->sc_codec.sc_recdrq = sc->sc_drq;
                   2214:                gus_hw_if = gusmax_hw_if;
                   2215:                /* enable line in and mic in the GUS mixer; the codec chip
                   2216:                   will do the real mixing for them. */
                   2217:                sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */
                   2218:                sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */
                   2219:                bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
                   2220:
                   2221:                ad1848_attach(&sc->sc_codec);
                   2222:                /* turn on pre-MUX microphone gain. */
                   2223:                ad1848_set_mic_gain(&sc->sc_codec, &vol);
                   2224:
                   2225:                return (1);
                   2226:        }
                   2227: }
                   2228:
                   2229:
                   2230: /*
                   2231:  * Return info about the audio device, for the AUDIO_GETINFO ioctl
                   2232:  */
                   2233:
                   2234: int
                   2235: gus_getdev(addr, dev)
                   2236:        void * addr;
                   2237:        struct audio_device *dev;
                   2238: {
                   2239:        *dev = gus_device;
                   2240:        return 0;
                   2241: }
                   2242:
                   2243: /*
                   2244:  * stubs (XXX)
                   2245:  */
                   2246:
                   2247: int
                   2248: gus_set_in_gain(addr, gain, balance)
                   2249:        caddr_t addr;
                   2250:        u_int gain;
                   2251:        u_char balance;
                   2252: {
                   2253:        DPRINTF(("gus_set_in_gain called\n"));
                   2254:        return 0;
                   2255: }
                   2256:
                   2257: int
                   2258: gus_get_in_gain(addr)
                   2259:        caddr_t addr;
                   2260: {
                   2261:        DPRINTF(("gus_get_in_gain called\n"));
                   2262:        return 0;
                   2263: }
                   2264:
                   2265: int
                   2266: gusmax_dma_input(addr, buf, size, callback, arg)
                   2267:        void * addr;
                   2268:        void *buf;
                   2269:        int size;
                   2270:        void (*callback)(void *);
                   2271:        void *arg;
                   2272: {
                   2273:        struct ad1848_softc *sc = addr;
                   2274:        return gus_dma_input(sc->parent, buf, size, callback, arg);
                   2275: }
                   2276:
                   2277: /*
                   2278:  * Start sampling the input source into the requested DMA buffer.
                   2279:  * Called at splgus(), either from top-half or from interrupt handler.
                   2280:  */
                   2281: int
                   2282: gus_dma_input(addr, buf, size, callback, arg)
                   2283:        void * addr;
                   2284:        void *buf;
                   2285:        int size;
                   2286:        void (*callback)(void *);
                   2287:        void *arg;
                   2288: {
                   2289:        struct gus_softc *sc = addr;
                   2290:        bus_space_tag_t iot = sc->sc_iot;
                   2291:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   2292:        u_char dmac;
                   2293:        DMAPRINTF(("gus_dma_input called\n"));
                   2294:
                   2295:        /*
                   2296:         * Sample SIZE bytes of data from the card, into buffer at BUF.
                   2297:         */
                   2298:
                   2299:        if (sc->sc_precision == 16)
                   2300:            return EINVAL;              /* XXX */
                   2301:
                   2302:        /* set DMA modes */
                   2303:        dmac = GUSMASK_SAMPLE_IRQ|GUSMASK_SAMPLE_START;
                   2304:        if (sc->sc_recdrq >= 4)
                   2305:                dmac |= GUSMASK_SAMPLE_DATA16;
                   2306:        if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
                   2307:            sc->sc_encoding == AUDIO_ENCODING_ALAW ||
                   2308:            sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE ||
                   2309:            sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE)
                   2310:            dmac |= GUSMASK_SAMPLE_INVBIT;
                   2311:        if (sc->sc_channels == 2)
                   2312:            dmac |= GUSMASK_SAMPLE_STEREO;
                   2313:        isa_dmastart(sc->sc_dev.dv_parent, sc->sc_recdrq, buf, size,
                   2314:            NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
                   2315:
                   2316:        DMAPRINTF(("gus_dma_input isadma_started\n"));
                   2317:        sc->sc_flags |= GUS_DMAIN_ACTIVE;
                   2318:        sc->sc_dmainintr = callback;
                   2319:        sc->sc_inarg = arg;
                   2320:        sc->sc_dmaincnt = size;
                   2321:        sc->sc_dmainaddr = buf;
                   2322:
                   2323:        SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
                   2324:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, dmac);      /* Go! */
                   2325:
                   2326:
                   2327:        DMAPRINTF(("gus_dma_input returning\n"));
                   2328:
                   2329:        return 0;
                   2330: }
                   2331:
                   2332: int
                   2333: gus_dmain_intr(sc)
                   2334:        struct gus_softc *sc;
                   2335: {
                   2336:         void (*callback)(void *);
                   2337:        void *arg;
                   2338:
                   2339:        DMAPRINTF(("gus_dmain_intr called\n"));
                   2340:        if (sc->sc_dmainintr) {
                   2341:            isa_dmadone(sc->sc_dev.dv_parent, sc->sc_recdrq);
                   2342:            callback = sc->sc_dmainintr;
                   2343:            arg = sc->sc_inarg;
                   2344:
                   2345:            sc->sc_dmainaddr = 0;
                   2346:            sc->sc_dmaincnt = 0;
                   2347:            sc->sc_dmainintr = 0;
                   2348:            sc->sc_inarg = 0;
                   2349:
                   2350:            sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
                   2351:            DMAPRINTF(("calling dmain_intr callback %p(%p)\n", callback, arg));
                   2352:            (*callback)(arg);
                   2353:            return 1;
                   2354:        } else {
                   2355:            DMAPRINTF(("gus_dmain_intr false?\n"));
                   2356:            return 0;                   /* XXX ??? */
                   2357:        }
                   2358: }
                   2359:
                   2360: int
                   2361: gusmax_halt_out_dma(addr)
                   2362:        void * addr;
                   2363: {
                   2364:        struct ad1848_softc *sc = addr;
                   2365:        return gus_halt_out_dma(sc->parent);
                   2366: }
                   2367:
                   2368:
                   2369: int
                   2370: gusmax_halt_in_dma(addr)
                   2371:        void * addr;
                   2372: {
                   2373:        struct ad1848_softc *sc = addr;
                   2374:        return gus_halt_in_dma(sc->parent);
                   2375: }
                   2376:
                   2377: /*
                   2378:  * Stop any DMA output.  Called at splgus().
                   2379:  */
                   2380: int
                   2381: gus_halt_out_dma(addr)
                   2382:        void * addr;
                   2383: {
                   2384:        struct gus_softc *sc = addr;
                   2385:        bus_space_tag_t iot = sc->sc_iot;
                   2386:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   2387:
                   2388:        DMAPRINTF(("gus_halt_out_dma called\n"));
                   2389:        /*
                   2390:         * Make sure the GUS _isn't_ setup for DMA
                   2391:         */
                   2392:
                   2393:        SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
                   2394:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
                   2395:
                   2396:        timeout_del(&sc->sc_dma_tmo);
                   2397:        isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
                   2398:        sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED);
                   2399:        sc->sc_dmaoutintr = 0;
                   2400:        sc->sc_outarg = 0;
                   2401:        sc->sc_dmaoutaddr = 0;
                   2402:        sc->sc_dmaoutcnt = 0;
                   2403:        sc->sc_dmabuf = 0;
                   2404:        sc->sc_bufcnt = 0;
                   2405:        sc->sc_playbuf = -1;
                   2406:        /* also stop playing */
                   2407:        gus_stop_voice(sc, GUS_VOICE_LEFT, 1);
                   2408:        gus_stop_voice(sc, GUS_VOICE_RIGHT, 0);
                   2409:
                   2410:        return 0;
                   2411: }
                   2412:
                   2413: /*
                   2414:  * Stop any DMA output.  Called at splgus().
                   2415:  */
                   2416: int
                   2417: gus_halt_in_dma(addr)
                   2418:        void * addr;
                   2419: {
                   2420:        struct gus_softc *sc = addr;
                   2421:        bus_space_tag_t iot = sc->sc_iot;
                   2422:        bus_space_handle_t ioh2 = sc->sc_ioh2;
                   2423:        DMAPRINTF(("gus_halt_in_dma called\n"));
                   2424:
                   2425:        /*
                   2426:         * Make sure the GUS _isn't_ setup for DMA
                   2427:         */
                   2428:
                   2429:        SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
                   2430:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH,
                   2431:             bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
                   2432:
                   2433:        isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_recdrq);
                   2434:        sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
                   2435:        sc->sc_dmainintr = 0;
                   2436:        sc->sc_inarg = 0;
                   2437:        sc->sc_dmainaddr = 0;
                   2438:        sc->sc_dmaincnt = 0;
                   2439:
                   2440:        return 0;
                   2441: }
                   2442:
                   2443:
                   2444: ad1848_devmap_t gusmapping[] = {
                   2445:   {GUSMAX_DAC_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL},
                   2446:   {GUSMAX_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL},
                   2447:   {GUSMAX_MONO_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL},
                   2448:   {GUSMAX_CD_LVL, AD1848_KIND_LVL, AD1848_AUX2_CHANNEL},
                   2449:   {GUSMAX_MONITOR_LVL, AD1848_KIND_LVL, AD1848_MONITOR_CHANNEL},
                   2450:   {GUSMAX_OUT_LVL, AD1848_KIND_LVL, AD1848_DAC_CHANNEL},
                   2451:   {GUSMAX_DAC_MUTE, AD1848_KIND_MUTE, AD1848_AUX1_CHANNEL},
                   2452:   {GUSMAX_LINE_IN_MUTE, AD1848_KIND_MUTE, AD1848_LINE_CHANNEL},
                   2453:   {GUSMAX_MONO_MUTE, AD1848_KIND_MUTE, AD1848_MONO_CHANNEL},
                   2454:   {GUSMAX_CD_MUTE, AD1848_KIND_MUTE, AD1848_AUX2_CHANNEL},
                   2455:   {GUSMAX_MONITOR_MUTE, AD1848_KIND_MUTE, AD1848_MONITOR_CHANNEL},
                   2456:   {GUSMAX_REC_LVL, AD1848_KIND_RECORDGAIN, -1},
                   2457:   {GUSMAX_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
                   2458: };
                   2459:
                   2460: int nummap = sizeof(gusmapping) / sizeof(gusmapping[0]);
                   2461:
                   2462: int
                   2463: gusmax_mixer_get_port(addr, cp)
                   2464:        void *addr;
                   2465:        mixer_ctrl_t *cp;
                   2466: {
                   2467:        struct ad1848_softc *ac = addr;
                   2468:        struct gus_softc *sc = ac->parent;
                   2469:        struct ad1848_volume vol;
                   2470:        int error = ad1848_mixer_get_port(ac, gusmapping, nummap, cp);
                   2471:
                   2472:        if (error != ENXIO)
                   2473:          return (error);
                   2474:
                   2475:        error = EINVAL;
                   2476:
                   2477:        switch (cp->dev) {
                   2478:        case GUSMAX_SPEAKER_LVL:        /* fake speaker for mute naming */
                   2479:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2480:                        if (sc->sc_mixcontrol & GUSMASK_LINE_OUT)
                   2481:                                vol.left = vol.right = AUDIO_MAX_GAIN;
                   2482:                        else
                   2483:                                vol.left = vol.right = AUDIO_MIN_GAIN;
                   2484:                        error = 0;
                   2485:                        ad1848_from_vol(cp, &vol);
                   2486:                }
                   2487:                break;
                   2488:
                   2489:        case GUSMAX_SPEAKER_MUTE:
                   2490:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2491:                        cp->un.ord = sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
                   2492:                        error = 0;
                   2493:                }
                   2494:                break;
                   2495:        default:
                   2496:                error = ENXIO;
                   2497:                break;
                   2498:        }
                   2499:
                   2500:        return(error);
                   2501: }
                   2502:
                   2503: int
                   2504: gus_mixer_get_port(addr, cp)
                   2505:        void *addr;
                   2506:        mixer_ctrl_t *cp;
                   2507: {
                   2508:        struct gus_softc *sc = addr;
                   2509:        struct ics2101_softc *ic = &sc->sc_mixer;
                   2510:        struct ad1848_volume vol;
                   2511:        int error = EINVAL;
                   2512:
                   2513:        DPRINTF(("gus_mixer_get_port: dev=%d type=%d\n", cp->dev, cp->type));
                   2514:
                   2515:        if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
                   2516:                return ENXIO;
                   2517:
                   2518:        switch (cp->dev) {
                   2519:
                   2520:        case GUSICS_MIC_IN_MUTE:        /* Microphone */
                   2521:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2522:                        if (HAS_MIXER(sc))
                   2523:                                cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
                   2524:                        else
                   2525:                                cp->un.ord =
                   2526:                                    sc->sc_mixcontrol & GUSMASK_MIC_IN ? 0 : 1;
                   2527:                        error = 0;
                   2528:                }
                   2529:                break;
                   2530:
                   2531:        case GUSICS_LINE_IN_MUTE:
                   2532:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2533:                        if (HAS_MIXER(sc))
                   2534:                                cp->un.ord = ic->sc_mute[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
                   2535:                        else
                   2536:                                cp->un.ord =
                   2537:                                    sc->sc_mixcontrol & GUSMASK_LINE_IN ? 1 : 0;
                   2538:                        error = 0;
                   2539:                }
                   2540:                break;
                   2541:
                   2542:        case GUSICS_MASTER_MUTE:
                   2543:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2544:                        if (HAS_MIXER(sc))
                   2545:                                cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
                   2546:                        else
                   2547:                                cp->un.ord =
                   2548:                                    sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0;
                   2549:                        error = 0;
                   2550:                }
                   2551:                break;
                   2552:
                   2553:        case GUSICS_DAC_MUTE:
                   2554:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2555:                        cp->un.ord = ic->sc_mute[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
                   2556:                        error = 0;
                   2557:                }
                   2558:                break;
                   2559:
                   2560:        case GUSICS_CD_MUTE:
                   2561:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2562:                        cp->un.ord = ic->sc_mute[GUSMIX_CHAN_CD][ICSMIX_LEFT];
                   2563:                        error = 0;
                   2564:                }
                   2565:                break;
                   2566:
                   2567:        case GUSICS_MASTER_LVL:
                   2568:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2569:                        vol.left = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_LEFT];
                   2570:                        vol.right = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_RIGHT];
                   2571:                        if (ad1848_from_vol(cp, &vol))
                   2572:                                error = 0;
                   2573:                }
                   2574:                break;
                   2575:
                   2576:        case GUSICS_MIC_IN_LVL: /* Microphone */
                   2577:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2578:                        vol.left = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_LEFT];
                   2579:                        vol.right = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_RIGHT];
                   2580:                        if (ad1848_from_vol(cp, &vol))
                   2581:                                error = 0;
                   2582:                }
                   2583:                break;
                   2584:
                   2585:        case GUSICS_LINE_IN_LVL:        /* line in */
                   2586:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2587:                        vol.left = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_LEFT];
                   2588:                        vol.right = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_RIGHT];
                   2589:                        if (ad1848_from_vol(cp, &vol))
                   2590:                                error = 0;
                   2591:                }
                   2592:                break;
                   2593:
                   2594:
                   2595:        case GUSICS_CD_LVL:
                   2596:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2597:                        vol.left = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_LEFT];
                   2598:                        vol.right = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_RIGHT];
                   2599:                        if (ad1848_from_vol(cp, &vol))
                   2600:                                error = 0;
                   2601:                }
                   2602:                break;
                   2603:
                   2604:        case GUSICS_DAC_LVL:            /* dac out */
                   2605:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2606:                        vol.left = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_LEFT];
                   2607:                        vol.right = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_RIGHT];
                   2608:                        if (ad1848_from_vol(cp, &vol))
                   2609:                                error = 0;
                   2610:                }
                   2611:                break;
                   2612:
                   2613:
                   2614:        case GUSICS_RECORD_SOURCE:
                   2615:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2616:                        /* Can't set anything else useful, sigh. */
                   2617:                         cp->un.ord = 0;
                   2618:                }
                   2619:                break;
                   2620:
                   2621:        default:
                   2622:                return ENXIO;
                   2623:            /*NOTREACHED*/
                   2624:        }
                   2625:        return error;
                   2626: }
                   2627:
                   2628: void
                   2629: gusics_master_mute(ic, mute)
                   2630:        struct ics2101_softc *ic;
                   2631:        int mute;
                   2632: {
                   2633:        ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_LEFT, mute);
                   2634:        ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_RIGHT, mute);
                   2635: }
                   2636:
                   2637: void
                   2638: gusics_mic_mute(ic, mute)
                   2639:        struct ics2101_softc *ic;
                   2640:        int mute;
                   2641: {
                   2642:        ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_LEFT, mute);
                   2643:        ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_RIGHT, mute);
                   2644: }
                   2645:
                   2646: void
                   2647: gusics_linein_mute(ic, mute)
                   2648:        struct ics2101_softc *ic;
                   2649:        int mute;
                   2650: {
                   2651:        ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_LEFT, mute);
                   2652:        ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_RIGHT, mute);
                   2653: }
                   2654:
                   2655: void
                   2656: gusics_cd_mute(ic, mute)
                   2657:        struct ics2101_softc *ic;
                   2658:        int mute;
                   2659: {
                   2660:        ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_LEFT, mute);
                   2661:        ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_RIGHT, mute);
                   2662: }
                   2663:
                   2664: void
                   2665: gusics_dac_mute(ic, mute)
                   2666:        struct ics2101_softc *ic;
                   2667:        int mute;
                   2668: {
                   2669:        ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_LEFT, mute);
                   2670:        ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_RIGHT, mute);
                   2671: }
                   2672:
                   2673: int
                   2674: gusmax_mixer_set_port(addr, cp)
                   2675:        void *addr;
                   2676:        mixer_ctrl_t *cp;
                   2677: {
                   2678:        struct ad1848_softc *ac = addr;
                   2679:        struct gus_softc *sc = ac->parent;
                   2680:        struct ad1848_volume vol;
                   2681:        int error = ad1848_mixer_set_port(ac, gusmapping, nummap, cp);
                   2682:
                   2683:        if (error != ENXIO)
                   2684:          return (error);
                   2685:
                   2686:        DPRINTF(("gusmax_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
                   2687:
                   2688:        switch (cp->dev) {
                   2689:        case GUSMAX_SPEAKER_LVL:
                   2690:                if (cp->type == AUDIO_MIXER_VALUE &&
                   2691:                    cp->un.value.num_channels == 1) {
                   2692:                        if (ad1848_to_vol(cp, &vol)) {
                   2693:                                gus_speaker_ctl(sc, vol.left > AUDIO_MIN_GAIN ?
                   2694:                                                SPKR_ON : SPKR_OFF);
                   2695:                                error = 0;
                   2696:                        }
                   2697:                }
                   2698:                break;
                   2699:
                   2700:        case GUSMAX_SPEAKER_MUTE:
                   2701:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2702:                        gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
                   2703:                        error = 0;
                   2704:                }
                   2705:                break;
                   2706:
                   2707:        default:
                   2708:                return ENXIO;
                   2709:            /*NOTREACHED*/
                   2710:     }
                   2711:     return error;
                   2712: }
                   2713:
                   2714: int
                   2715: gus_mixer_set_port(addr, cp)
                   2716:        void *addr;
                   2717:        mixer_ctrl_t *cp;
                   2718: {
                   2719:        struct gus_softc *sc = addr;
                   2720:        struct ics2101_softc *ic = &sc->sc_mixer;
                   2721:        struct ad1848_volume vol;
                   2722:        int error = EINVAL;
                   2723:
                   2724:        DPRINTF(("gus_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type));
                   2725:
                   2726:        if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE)
                   2727:                return ENXIO;
                   2728:
                   2729:        switch (cp->dev) {
                   2730:
                   2731:        case GUSICS_MIC_IN_MUTE:        /* Microphone */
                   2732:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2733:                        DPRINTF(("mic mute %d\n", cp->un.ord));
                   2734:                        if (HAS_MIXER(sc)) {
                   2735:                                gusics_mic_mute(ic, cp->un.ord);
                   2736:                        }
                   2737:                        gus_mic_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
                   2738:                        error = 0;
                   2739:                }
                   2740:                break;
                   2741:
                   2742:        case GUSICS_LINE_IN_MUTE:
                   2743:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2744:                        DPRINTF(("linein mute %d\n", cp->un.ord));
                   2745:                        if (HAS_MIXER(sc)) {
                   2746:                                gusics_linein_mute(ic, cp->un.ord);
                   2747:                        }
                   2748:                        gus_linein_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
                   2749:                        error = 0;
                   2750:                }
                   2751:                break;
                   2752:
                   2753:        case GUSICS_MASTER_MUTE:
                   2754:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2755:                        DPRINTF(("master mute %d\n", cp->un.ord));
                   2756:                        if (HAS_MIXER(sc)) {
                   2757:                                gusics_master_mute(ic, cp->un.ord);
                   2758:                        }
                   2759:                        gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON);
                   2760:                        error = 0;
                   2761:                }
                   2762:                break;
                   2763:
                   2764:        case GUSICS_DAC_MUTE:
                   2765:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2766:                        gusics_dac_mute(ic, cp->un.ord);
                   2767:                        error = 0;
                   2768:                }
                   2769:                break;
                   2770:
                   2771:        case GUSICS_CD_MUTE:
                   2772:                if (cp->type == AUDIO_MIXER_ENUM) {
                   2773:                        gusics_cd_mute(ic, cp->un.ord);
                   2774:                        error = 0;
                   2775:                }
                   2776:                break;
                   2777:
                   2778:        case GUSICS_MASTER_LVL:
                   2779:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2780:                        if (ad1848_to_vol(cp, &vol)) {
                   2781:                                ics2101_mix_attenuate(ic,
                   2782:                                                      GUSMIX_CHAN_MASTER,
                   2783:                                                      ICSMIX_LEFT,
                   2784:                                                      vol.left);
                   2785:                                ics2101_mix_attenuate(ic,
                   2786:                                                      GUSMIX_CHAN_MASTER,
                   2787:                                                      ICSMIX_RIGHT,
                   2788:                                                      vol.right);
                   2789:                                error = 0;
                   2790:                        }
                   2791:                }
                   2792:                break;
                   2793:
                   2794:        case GUSICS_MIC_IN_LVL: /* Microphone */
                   2795:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2796:                        if (ad1848_to_vol(cp, &vol)) {
                   2797:                                ics2101_mix_attenuate(ic,
                   2798:                                                      GUSMIX_CHAN_MIC,
                   2799:                                                      ICSMIX_LEFT,
                   2800:                                                      vol.left);
                   2801:                                ics2101_mix_attenuate(ic,
                   2802:                                                      GUSMIX_CHAN_MIC,
                   2803:                                                      ICSMIX_RIGHT,
                   2804:                                                      vol.right);
                   2805:                                error = 0;
                   2806:                        }
                   2807:                }
                   2808:                break;
                   2809:
                   2810:        case GUSICS_LINE_IN_LVL:        /* line in */
                   2811:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2812:                        if (ad1848_to_vol(cp, &vol)) {
                   2813:                                ics2101_mix_attenuate(ic,
                   2814:                                                      GUSMIX_CHAN_LINE,
                   2815:                                                      ICSMIX_LEFT,
                   2816:                                                      vol.left);
                   2817:                                ics2101_mix_attenuate(ic,
                   2818:                                                      GUSMIX_CHAN_LINE,
                   2819:                                                      ICSMIX_RIGHT,
                   2820:                                                      vol.right);
                   2821:                                error = 0;
                   2822:                        }
                   2823:                }
                   2824:                break;
                   2825:
                   2826:
                   2827:        case GUSICS_CD_LVL:
                   2828:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2829:                        if (ad1848_to_vol(cp, &vol)) {
                   2830:                                ics2101_mix_attenuate(ic,
                   2831:                                                      GUSMIX_CHAN_CD,
                   2832:                                                      ICSMIX_LEFT,
                   2833:                                                      vol.left);
                   2834:                                ics2101_mix_attenuate(ic,
                   2835:                                                      GUSMIX_CHAN_CD,
                   2836:                                                      ICSMIX_RIGHT,
                   2837:                                                      vol.right);
                   2838:                                error = 0;
                   2839:                        }
                   2840:                }
                   2841:                break;
                   2842:
                   2843:        case GUSICS_DAC_LVL:            /* dac out */
                   2844:                if (cp->type == AUDIO_MIXER_VALUE) {
                   2845:                        if (ad1848_to_vol(cp, &vol)) {
                   2846:                                ics2101_mix_attenuate(ic,
                   2847:                                                      GUSMIX_CHAN_DAC,
                   2848:                                                      ICSMIX_LEFT,
                   2849:                                                      vol.left);
                   2850:                                ics2101_mix_attenuate(ic,
                   2851:                                                      GUSMIX_CHAN_DAC,
                   2852:                                                      ICSMIX_RIGHT,
                   2853:                                                      vol.right);
                   2854:                                error = 0;
                   2855:                        }
                   2856:                }
                   2857:                break;
                   2858:
                   2859:
                   2860:        case GUSICS_RECORD_SOURCE:
                   2861:                if (cp->type == AUDIO_MIXER_ENUM && cp->un.ord == 0) {
                   2862:                        /* Can't set anything else useful, sigh. */
                   2863:                        error = 0;
                   2864:                }
                   2865:                break;
                   2866:
                   2867:        default:
                   2868:                return ENXIO;
                   2869:            /*NOTREACHED*/
                   2870:        }
                   2871:        return error;
                   2872: }
                   2873:
                   2874: int
                   2875: gus_get_props(addr)
                   2876:        void *addr;
                   2877: {
                   2878:        struct gus_softc *sc = addr;
                   2879:        return AUDIO_PROP_MMAP |
                   2880:                (sc->sc_recdrq == sc->sc_drq ? 0 : AUDIO_PROP_FULLDUPLEX);
                   2881: }
                   2882:
                   2883: int
                   2884: gusmax_get_props(addr)
                   2885:        void *addr;
                   2886: {
                   2887:        struct ad1848_softc *ac = addr;
                   2888:        return gus_get_props(ac->parent);
                   2889: }
                   2890:
                   2891: int
                   2892: gusmax_mixer_query_devinfo(addr, dip)
                   2893:        void *addr;
                   2894:        mixer_devinfo_t *dip;
                   2895: {
                   2896:        DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
                   2897:
                   2898:        switch(dip->index) {
                   2899: #if 0
                   2900:     case GUSMAX_MIC_IN_LVL:    /* Microphone */
                   2901:        dip->type = AUDIO_MIXER_VALUE;
                   2902:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   2903:        dip->prev = AUDIO_MIXER_LAST;
                   2904:        dip->next = GUSMAX_MIC_IN_MUTE;
                   2905:        strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
                   2906:        dip->un.v.num_channels = 2;
                   2907:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   2908:            sizeof dip->un.v.units.name);
                   2909:        break;
                   2910: #endif
                   2911:
                   2912:     case GUSMAX_MONO_LVL:      /* mono/microphone mixer */
                   2913:        dip->type = AUDIO_MIXER_VALUE;
                   2914:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   2915:        dip->prev = AUDIO_MIXER_LAST;
                   2916:        dip->next = GUSMAX_MONO_MUTE;
                   2917:        strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
                   2918:        dip->un.v.num_channels = 1;
                   2919:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   2920:            sizeof dip->un.v.units.name);
                   2921:        break;
                   2922:
                   2923:     case GUSMAX_DAC_LVL:               /*  dacout */
                   2924:        dip->type = AUDIO_MIXER_VALUE;
                   2925:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   2926:        dip->prev = AUDIO_MIXER_LAST;
                   2927:        dip->next = GUSMAX_DAC_MUTE;
                   2928:        strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
                   2929:        dip->un.v.num_channels = 2;
                   2930:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   2931:            sizeof dip->un.v.units.name);
                   2932:        break;
                   2933:
                   2934:     case GUSMAX_LINE_IN_LVL:   /* line */
                   2935:        dip->type = AUDIO_MIXER_VALUE;
                   2936:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   2937:        dip->prev = AUDIO_MIXER_LAST;
                   2938:        dip->next = GUSMAX_LINE_IN_MUTE;
                   2939:        strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
                   2940:        dip->un.v.num_channels = 2;
                   2941:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   2942:            sizeof dip->un.v.units.name);
                   2943:        break;
                   2944:
                   2945:     case GUSMAX_CD_LVL:                /* cd */
                   2946:        dip->type = AUDIO_MIXER_VALUE;
                   2947:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   2948:        dip->prev = AUDIO_MIXER_LAST;
                   2949:        dip->next = GUSMAX_CD_MUTE;
                   2950:        strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
                   2951:        dip->un.v.num_channels = 2;
                   2952:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   2953:            sizeof dip->un.v.units.name);
                   2954:        break;
                   2955:
                   2956:
                   2957:     case GUSMAX_MONITOR_LVL:   /* monitor level */
                   2958:        dip->type = AUDIO_MIXER_VALUE;
                   2959:        dip->mixer_class = GUSMAX_MONITOR_CLASS;
                   2960:        dip->next = GUSMAX_MONITOR_MUTE;
                   2961:        dip->prev = AUDIO_MIXER_LAST;
                   2962:        strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
                   2963:        dip->un.v.num_channels = 1;
                   2964:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   2965:            sizeof dip->un.v.units.name);
                   2966:        break;
                   2967:
                   2968:     case GUSMAX_OUT_LVL:               /* cs4231 output volume: not useful? */
                   2969:        dip->type = AUDIO_MIXER_VALUE;
                   2970:        dip->mixer_class = GUSMAX_MONITOR_CLASS;
                   2971:        dip->prev = dip->next = AUDIO_MIXER_LAST;
                   2972:        strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
                   2973:        dip->un.v.num_channels = 2;
                   2974:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   2975:            sizeof dip->un.v.units.name);
                   2976:        break;
                   2977:
                   2978:     case GUSMAX_SPEAKER_LVL:           /* fake speaker volume */
                   2979:        dip->type = AUDIO_MIXER_VALUE;
                   2980:        dip->mixer_class = GUSMAX_MONITOR_CLASS;
                   2981:        dip->prev = AUDIO_MIXER_LAST;
                   2982:        dip->next = GUSMAX_SPEAKER_MUTE;
                   2983:        strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
                   2984:        dip->un.v.num_channels = 2;
                   2985:        strlcpy(dip->un.v.units.name, AudioNvolume,
                   2986:            sizeof dip->un.v.units.name);
                   2987:        break;
                   2988:
                   2989:     case GUSMAX_LINE_IN_MUTE:
                   2990:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   2991:        dip->type = AUDIO_MIXER_ENUM;
                   2992:        dip->prev = GUSMAX_LINE_IN_LVL;
                   2993:        dip->next = AUDIO_MIXER_LAST;
                   2994:        goto mute;
                   2995:
                   2996:     case GUSMAX_DAC_MUTE:
                   2997:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   2998:        dip->type = AUDIO_MIXER_ENUM;
                   2999:        dip->prev = GUSMAX_DAC_LVL;
                   3000:        dip->next = AUDIO_MIXER_LAST;
                   3001:        goto mute;
                   3002:
                   3003:     case GUSMAX_CD_MUTE:
                   3004:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   3005:        dip->type = AUDIO_MIXER_ENUM;
                   3006:        dip->prev = GUSMAX_CD_LVL;
                   3007:        dip->next = AUDIO_MIXER_LAST;
                   3008:        goto mute;
                   3009:
                   3010:     case GUSMAX_MONO_MUTE:
                   3011:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   3012:        dip->type = AUDIO_MIXER_ENUM;
                   3013:        dip->prev = GUSMAX_MONO_LVL;
                   3014:        dip->next = AUDIO_MIXER_LAST;
                   3015:        goto mute;
                   3016:
                   3017:     case GUSMAX_MONITOR_MUTE:
                   3018:        dip->mixer_class = GUSMAX_OUTPUT_CLASS;
                   3019:        dip->type = AUDIO_MIXER_ENUM;
                   3020:        dip->prev = GUSMAX_MONITOR_LVL;
                   3021:        dip->next = AUDIO_MIXER_LAST;
                   3022:        goto mute;
                   3023:
                   3024:     case GUSMAX_SPEAKER_MUTE:
                   3025:        dip->mixer_class = GUSMAX_OUTPUT_CLASS;
                   3026:        dip->type = AUDIO_MIXER_ENUM;
                   3027:        dip->prev = GUSMAX_SPEAKER_LVL;
                   3028:        dip->next = AUDIO_MIXER_LAST;
                   3029:     mute:
                   3030:        strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
                   3031:        dip->un.e.num_mem = 2;
                   3032:        strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                   3033:            sizeof dip->un.e.member[0].label.name);
                   3034:        dip->un.e.member[0].ord = 0;
                   3035:        strlcpy(dip->un.e.member[1].label.name, AudioNon,
                   3036:            sizeof dip->un.e.member[1].label.name);
                   3037:        dip->un.e.member[1].ord = 1;
                   3038:        break;
                   3039:
                   3040:     case GUSMAX_REC_LVL:       /* record level */
                   3041:        dip->type = AUDIO_MIXER_VALUE;
                   3042:        dip->mixer_class = GUSMAX_RECORD_CLASS;
                   3043:        dip->prev = AUDIO_MIXER_LAST;
                   3044:        dip->next = GUSMAX_RECORD_SOURCE;
                   3045:        strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
                   3046:        dip->un.v.num_channels = 2;
                   3047:        strlcpy(dip->un.v.units.name, AudioNvolume, sizeof dip->un.v.units.name);
                   3048:        break;
                   3049:
                   3050:     case GUSMAX_RECORD_SOURCE:
                   3051:        dip->mixer_class = GUSMAX_RECORD_CLASS;
                   3052:        dip->type = AUDIO_MIXER_ENUM;
                   3053:        dip->prev = GUSMAX_REC_LVL;
                   3054:        dip->next = AUDIO_MIXER_LAST;
                   3055:        strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
                   3056:        dip->un.e.num_mem = 4;
                   3057:        strlcpy(dip->un.e.member[0].label.name, AudioNoutput,
                   3058:            sizeof dip->un.e.member[0].label.name);
                   3059:        dip->un.e.member[0].ord = DAC_IN_PORT;
                   3060:        strlcpy(dip->un.e.member[1].label.name, AudioNmicrophone,
                   3061:            sizeof dip->un.e.member[1].label.name);
                   3062:        dip->un.e.member[1].ord = MIC_IN_PORT;
                   3063:        strlcpy(dip->un.e.member[2].label.name, AudioNdac,
                   3064:            sizeof dip->un.e.member[2].label.name);
                   3065:        dip->un.e.member[2].ord = AUX1_IN_PORT;
                   3066:        strlcpy(dip->un.e.member[3].label.name, AudioNline,
                   3067:            sizeof dip->un.e.member[3].label.name);
                   3068:        dip->un.e.member[3].ord = LINE_IN_PORT;
                   3069:        break;
                   3070:
                   3071:     case GUSMAX_INPUT_CLASS:                   /* input class descriptor */
                   3072:        dip->type = AUDIO_MIXER_CLASS;
                   3073:        dip->mixer_class = GUSMAX_INPUT_CLASS;
                   3074:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   3075:        strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
                   3076:        break;
                   3077:
                   3078:     case GUSMAX_OUTPUT_CLASS:                  /* output class descriptor */
                   3079:        dip->type = AUDIO_MIXER_CLASS;
                   3080:        dip->mixer_class = GUSMAX_OUTPUT_CLASS;
                   3081:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   3082:        strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
                   3083:        break;
                   3084:
                   3085:     case GUSMAX_MONITOR_CLASS:                 /* monitor class descriptor */
                   3086:        dip->type = AUDIO_MIXER_CLASS;
                   3087:        dip->mixer_class = GUSMAX_MONITOR_CLASS;
                   3088:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   3089:        strlcpy(dip->label.name, AudioCmonitor, sizeof dip->label.name);
                   3090:        break;
                   3091:
                   3092:     case GUSMAX_RECORD_CLASS:                  /* record source class */
                   3093:        dip->type = AUDIO_MIXER_CLASS;
                   3094:        dip->mixer_class = GUSMAX_RECORD_CLASS;
                   3095:        dip->next = dip->prev = AUDIO_MIXER_LAST;
                   3096:        strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
                   3097:        break;
                   3098:
                   3099:     default:
                   3100:        return ENXIO;
                   3101:        /*NOTREACHED*/
                   3102:     }
                   3103:     DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
                   3104:        return 0;
                   3105: }
                   3106:
                   3107: int
                   3108: gus_mixer_query_devinfo(addr, dip)
                   3109:        void *addr;
                   3110:        mixer_devinfo_t *dip;
                   3111: {
                   3112:        struct gus_softc *sc = addr;
                   3113:
                   3114:        DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
                   3115:
                   3116:        if (!HAS_MIXER(sc) && dip->index > GUSICS_MASTER_MUTE)
                   3117:                return ENXIO;
                   3118:
                   3119:        switch(dip->index) {
                   3120:
                   3121:        case GUSICS_MIC_IN_LVL: /* Microphone */
                   3122:                dip->type = AUDIO_MIXER_VALUE;
                   3123:                dip->mixer_class = GUSICS_INPUT_CLASS;
                   3124:                dip->prev = AUDIO_MIXER_LAST;
                   3125:                dip->next = GUSICS_MIC_IN_MUTE;
                   3126:                strlcpy(dip->label.name, AudioNmicrophone,
                   3127:                    sizeof dip->label.name);
                   3128:                dip->un.v.num_channels = 2;
                   3129:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   3130:                    sizeof dip->un.v.units.name);
                   3131:                break;
                   3132:
                   3133:        case GUSICS_LINE_IN_LVL:        /* line */
                   3134:                dip->type = AUDIO_MIXER_VALUE;
                   3135:                dip->mixer_class = GUSICS_INPUT_CLASS;
                   3136:                dip->prev = AUDIO_MIXER_LAST;
                   3137:                dip->next = GUSICS_LINE_IN_MUTE;
                   3138:                strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
                   3139:                dip->un.v.num_channels = 2;
                   3140:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   3141:                    sizeof dip->un.v.units.name);
                   3142:                break;
                   3143:
                   3144:        case GUSICS_CD_LVL:             /* cd */
                   3145:                dip->type = AUDIO_MIXER_VALUE;
                   3146:                dip->mixer_class = GUSICS_INPUT_CLASS;
                   3147:                dip->prev = AUDIO_MIXER_LAST;
                   3148:                dip->next = GUSICS_CD_MUTE;
                   3149:                strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
                   3150:                dip->un.v.num_channels = 2;
                   3151:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   3152:                    sizeof dip->un.v.units.name);
                   3153:                break;
                   3154:
                   3155:        case GUSICS_DAC_LVL:            /*  dacout */
                   3156:                dip->type = AUDIO_MIXER_VALUE;
                   3157:                dip->mixer_class = GUSICS_INPUT_CLASS;
                   3158:                dip->prev = AUDIO_MIXER_LAST;
                   3159:                dip->next = GUSICS_DAC_MUTE;
                   3160:                strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
                   3161:                dip->un.v.num_channels = 2;
                   3162:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   3163:                    sizeof dip->un.v.units.name);
                   3164:                break;
                   3165:
                   3166:        case GUSICS_MASTER_LVL:         /*  master output */
                   3167:                dip->type = AUDIO_MIXER_VALUE;
                   3168:                dip->mixer_class = GUSICS_OUTPUT_CLASS;
                   3169:                dip->prev = AUDIO_MIXER_LAST;
                   3170:                dip->next = GUSICS_MASTER_MUTE;
                   3171:                strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
                   3172:                dip->un.v.num_channels = 2;
                   3173:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   3174:                    sizeof dip->un.v.units.name);
                   3175:                break;
                   3176:
                   3177:
                   3178:        case GUSICS_LINE_IN_MUTE:
                   3179:                dip->mixer_class = GUSICS_INPUT_CLASS;
                   3180:                dip->type = AUDIO_MIXER_ENUM;
                   3181:                dip->prev = GUSICS_LINE_IN_LVL;
                   3182:                dip->next = AUDIO_MIXER_LAST;
                   3183:                goto mute;
                   3184:
                   3185:        case GUSICS_DAC_MUTE:
                   3186:                dip->mixer_class = GUSICS_INPUT_CLASS;
                   3187:                dip->type = AUDIO_MIXER_ENUM;
                   3188:                dip->prev = GUSICS_DAC_LVL;
                   3189:                dip->next = AUDIO_MIXER_LAST;
                   3190:                goto mute;
                   3191:
                   3192:        case GUSICS_CD_MUTE:
                   3193:                dip->mixer_class = GUSICS_INPUT_CLASS;
                   3194:                dip->type = AUDIO_MIXER_ENUM;
                   3195:                dip->prev = GUSICS_CD_LVL;
                   3196:                dip->next = AUDIO_MIXER_LAST;
                   3197:                goto mute;
                   3198:
                   3199:        case GUSICS_MIC_IN_MUTE:
                   3200:                dip->mixer_class = GUSICS_INPUT_CLASS;
                   3201:                dip->type = AUDIO_MIXER_ENUM;
                   3202:                dip->prev = GUSICS_MIC_IN_LVL;
                   3203:                dip->next = AUDIO_MIXER_LAST;
                   3204:                goto mute;
                   3205:
                   3206:        case GUSICS_MASTER_MUTE:
                   3207:                dip->mixer_class = GUSICS_OUTPUT_CLASS;
                   3208:                dip->type = AUDIO_MIXER_ENUM;
                   3209:                dip->prev = GUSICS_MASTER_LVL;
                   3210:                dip->next = AUDIO_MIXER_LAST;
                   3211: mute:
                   3212:                strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
                   3213:                dip->un.e.num_mem = 2;
                   3214:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                   3215:                    sizeof dip->un.e.member[0].label.name);
                   3216:                dip->un.e.member[0].ord = 0;
                   3217:                strlcpy(dip->un.e.member[1].label.name, AudioNon,
                   3218:                    sizeof dip->un.e.member[1].label.name);
                   3219:                dip->un.e.member[1].ord = 1;
                   3220:                break;
                   3221:
                   3222:        case GUSICS_RECORD_SOURCE:
                   3223:                dip->mixer_class = GUSICS_RECORD_CLASS;
                   3224:                dip->type = AUDIO_MIXER_ENUM;
                   3225:                dip->prev = dip->next = AUDIO_MIXER_LAST;
                   3226:                strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
                   3227:                dip->un.e.num_mem = 1;
                   3228:                strlcpy(dip->un.e.member[0].label.name, AudioNoutput,
                   3229:                    sizeof dip->un.e.member[0].label.name);
                   3230:                dip->un.e.member[0].ord = GUSICS_MASTER_LVL;
                   3231:                break;
                   3232:
                   3233:        case GUSICS_INPUT_CLASS:
                   3234:                dip->type = AUDIO_MIXER_CLASS;
                   3235:                dip->mixer_class = GUSICS_INPUT_CLASS;
                   3236:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   3237:                strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
                   3238:                break;
                   3239:
                   3240:        case GUSICS_OUTPUT_CLASS:
                   3241:                dip->type = AUDIO_MIXER_CLASS;
                   3242:                dip->mixer_class = GUSICS_OUTPUT_CLASS;
                   3243:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   3244:                strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
                   3245:                break;
                   3246:
                   3247:        case GUSICS_RECORD_CLASS:
                   3248:                dip->type = AUDIO_MIXER_CLASS;
                   3249:                dip->mixer_class = GUSICS_RECORD_CLASS;
                   3250:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   3251:                strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
                   3252:                break;
                   3253:
                   3254:        default:
                   3255:                return ENXIO;
                   3256:        /*NOTREACHED*/
                   3257:        }
                   3258:        DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
                   3259:        return 0;
                   3260: }
                   3261:
                   3262: int
                   3263: gus_query_encoding(addr, fp)
                   3264:        void *addr;
                   3265:        struct audio_encoding *fp;
                   3266: {
                   3267:        switch (fp->index) {
                   3268:        case 0:
                   3269:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
                   3270:                fp->encoding = AUDIO_ENCODING_ULAW;
                   3271:                fp->precision = 8;
                   3272:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                   3273:                break;
                   3274:        case 1:
                   3275:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
                   3276:                fp->encoding = AUDIO_ENCODING_SLINEAR;
                   3277:                fp->precision = 8;
                   3278:                fp->flags = 0;
                   3279:                break;
                   3280:        case 2:
                   3281:                strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
                   3282:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
                   3283:                fp->precision = 16;
                   3284:                fp->flags = 0;
                   3285:                break;
                   3286:        case 3:
                   3287:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
                   3288:                fp->encoding = AUDIO_ENCODING_ULINEAR;
                   3289:                fp->precision = 8;
                   3290:                fp->flags = 0;
                   3291:                break;
                   3292:        case 4:
                   3293:                strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
                   3294:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
                   3295:                fp->precision = 16;
                   3296:                fp->flags = 0;
                   3297:                break;
                   3298:        case 5:
                   3299:                strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
                   3300:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
                   3301:                fp->precision = 16;
                   3302:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                   3303:                break;
                   3304:        case 6:
                   3305:                strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
                   3306:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
                   3307:                fp->precision = 16;
                   3308:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                   3309:                break;
                   3310:        case 7:
                   3311:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
                   3312:                fp->encoding = AUDIO_ENCODING_ALAW;
                   3313:                fp->precision = 8;
                   3314:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                   3315:                break;
                   3316:
                   3317:        default:
                   3318:                return(EINVAL);
                   3319:                /*NOTREACHED*/
                   3320:        }
                   3321:        return (0);
                   3322: }
                   3323:
                   3324: /*
                   3325:  * Setup the ICS mixer in "transparent" mode: reset everything to a sensible
                   3326:  * level.  Levels as suggested by GUS SDK code.
                   3327:  */
                   3328:
                   3329: void
                   3330: gus_init_ics2101(sc)
                   3331:        struct gus_softc *sc;
                   3332: {
                   3333:        struct ics2101_softc *ic = &sc->sc_mixer;
                   3334:        sc->sc_mixer.sc_iot = sc->sc_iot;
                   3335:        sc->sc_mixer.sc_selio = GUS_MIXER_SELECT;
                   3336:        sc->sc_mixer.sc_selio_ioh = sc->sc_ioh3;
                   3337:        sc->sc_mixer.sc_dataio = GUS_MIXER_DATA;
                   3338:        sc->sc_mixer.sc_dataio_ioh = sc->sc_ioh2;
                   3339:        sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0;
                   3340:
                   3341:        ics2101_mix_attenuate(ic,
                   3342:                              GUSMIX_CHAN_MIC,
                   3343:                              ICSMIX_LEFT,
                   3344:                              ICSMIX_MIN_ATTN);
                   3345:        ics2101_mix_attenuate(ic,
                   3346:                              GUSMIX_CHAN_MIC,
                   3347:                              ICSMIX_RIGHT,
                   3348:                              ICSMIX_MIN_ATTN);
                   3349:        /*
                   3350:         * Start with microphone muted by the mixer...
                   3351:         */
                   3352:        gusics_mic_mute(ic, 1);
                   3353:
                   3354:        /* ... and enabled by the GUS master mix control */
                   3355:        gus_mic_ctl(sc, SPKR_ON);
                   3356:
                   3357:        ics2101_mix_attenuate(ic,
                   3358:                              GUSMIX_CHAN_LINE,
                   3359:                              ICSMIX_LEFT,
                   3360:                              ICSMIX_MIN_ATTN);
                   3361:        ics2101_mix_attenuate(ic,
                   3362:                              GUSMIX_CHAN_LINE,
                   3363:                              ICSMIX_RIGHT,
                   3364:                              ICSMIX_MIN_ATTN);
                   3365:
                   3366:        ics2101_mix_attenuate(ic,
                   3367:                              GUSMIX_CHAN_CD,
                   3368:                              ICSMIX_LEFT,
                   3369:                              ICSMIX_MIN_ATTN);
                   3370:        ics2101_mix_attenuate(ic,
                   3371:                              GUSMIX_CHAN_CD,
                   3372:                              ICSMIX_RIGHT,
                   3373:                              ICSMIX_MIN_ATTN);
                   3374:
                   3375:        ics2101_mix_attenuate(ic,
                   3376:                              GUSMIX_CHAN_DAC,
                   3377:                              ICSMIX_LEFT,
                   3378:                              ICSMIX_MIN_ATTN);
                   3379:        ics2101_mix_attenuate(ic,
                   3380:                              GUSMIX_CHAN_DAC,
                   3381:                              ICSMIX_RIGHT,
                   3382:                              ICSMIX_MIN_ATTN);
                   3383:
                   3384:        ics2101_mix_attenuate(ic,
                   3385:                              ICSMIX_CHAN_4,
                   3386:                              ICSMIX_LEFT,
                   3387:                              ICSMIX_MAX_ATTN);
                   3388:        ics2101_mix_attenuate(ic,
                   3389:                              ICSMIX_CHAN_4,
                   3390:                              ICSMIX_RIGHT,
                   3391:                              ICSMIX_MAX_ATTN);
                   3392:
                   3393:        ics2101_mix_attenuate(ic,
                   3394:                              GUSMIX_CHAN_MASTER,
                   3395:                              ICSMIX_LEFT,
                   3396:                              ICSMIX_MIN_ATTN);
                   3397:        ics2101_mix_attenuate(ic,
                   3398:                              GUSMIX_CHAN_MASTER,
                   3399:                              ICSMIX_RIGHT,
                   3400:                              ICSMIX_MIN_ATTN);
                   3401:        /* unmute other stuff: */
                   3402:        gusics_cd_mute(ic, 0);
                   3403:        gusics_dac_mute(ic, 0);
                   3404:        gusics_linein_mute(ic, 0);
                   3405:        return;
                   3406: }
                   3407:
                   3408:
                   3409:
                   3410: void
                   3411: gus_subattach(sc, ia)
                   3412:        struct gus_softc *sc;
                   3413:        struct isa_attach_args *ia;
                   3414: {
                   3415:        int             i;
                   3416:        bus_space_tag_t iot;
                   3417:        unsigned char   c,d,m;
                   3418:
                   3419:        iot = sc->sc_iot;
                   3420:
                   3421:        /*
                   3422:         * Figure out our board rev, and see if we need to initialize the
                   3423:         * mixer
                   3424:         */
                   3425:
                   3426:        c = bus_space_read_1(iot, sc->sc_ioh3, GUS_BOARD_REV);
                   3427:        if (c != 0xff)
                   3428:                sc->sc_revision = c;
                   3429:        else
                   3430:                sc->sc_revision = 0;
                   3431:
                   3432:        SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_RESET);
                   3433:        bus_space_write_1(iot, sc->sc_ioh2, GUS_DATA_HIGH, 0x00);
                   3434:
                   3435:        gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */
                   3436:        gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */
                   3437:
                   3438:        /*
                   3439:         * Setup the IRQ and DRQ lines in software, using values from
                   3440:         * config file
                   3441:         */
                   3442:
                   3443:        m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT;           /* disable all */
                   3444:
                   3445:        c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ;
                   3446:
                   3447:        if (sc->sc_recdrq == sc->sc_drq)
                   3448:                d = (unsigned char) (gus_drq_map[sc->sc_drq] |
                   3449:                                GUSMASK_BOTH_RQ);
                   3450:        else
                   3451:                d = (unsigned char) (gus_drq_map[sc->sc_drq] |
                   3452:                                gus_drq_map[sc->sc_recdrq] << 3);
                   3453:
                   3454:        /*
                   3455:         * Program the IRQ and DMA channels on the GUS.  Note that we hardwire
                   3456:         * the GUS to only use one IRQ channel, but we give the user the
                   3457:         * option of using two DMA channels (the other one given by the drq2
                   3458:         * option in the config file).  Two DMA channels are needed for full-
                   3459:         * duplex operation.
                   3460:         *
                   3461:         * The order of these operations is very magical.
                   3462:         */
                   3463:
                   3464:        disable_intr();         /* XXX needed? */
                   3465:
                   3466:        bus_space_write_1(iot, sc->sc_ioh1, GUS_REG_CONTROL, GUS_REG_IRQCTL);
                   3467:        bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL, m);
                   3468:        bus_space_write_1(iot, sc->sc_ioh1, GUS_IRQCTL_CONTROL, 0x00);
                   3469:        bus_space_write_1(iot, sc->sc_ioh1, 0x0f, 0x00);
                   3470:
                   3471:        bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL, m);
                   3472:
                   3473:        /* magic reset? */
                   3474:        bus_space_write_1(iot, sc->sc_ioh1, GUS_DMA_CONTROL, d | 0x80);
                   3475:
                   3476:        bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL,
                   3477:            m | GUSMASK_CONTROL_SEL);
                   3478:        bus_space_write_1(iot, sc->sc_ioh1, GUS_IRQ_CONTROL, c);
                   3479:
                   3480:        bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL, m);
                   3481:        bus_space_write_1(iot, sc->sc_ioh1, GUS_DMA_CONTROL, d);
                   3482:
                   3483:        bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL,
                   3484:            m | GUSMASK_CONTROL_SEL);
                   3485:        bus_space_write_1(iot, sc->sc_ioh1, GUS_IRQ_CONTROL, c);
                   3486:
                   3487:        bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT, 0x00);
                   3488:
                   3489:        /* enable line in, line out.  leave mic disabled. */
                   3490:        bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL,
                   3491:             (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
                   3492:        bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT, 0x00);
                   3493:
                   3494:        enable_intr();
                   3495:
                   3496:        sc->sc_mixcontrol =
                   3497:                (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN);
                   3498:
                   3499:        sc->sc_codec.sc_isa = sc->sc_isa;
                   3500:
                   3501:        if (sc->sc_revision >= 5 && sc->sc_revision <= 9) {
                   3502:                sc->sc_flags |= GUS_MIXER_INSTALLED;
                   3503:                gus_init_ics2101(sc);
                   3504:        }
                   3505:        if (sc->sc_revision < 10 || !gus_init_cs4231(sc)) {
                   3506:                /* Not using the CS4231, so create our DMA maps. */
                   3507:                if (sc->sc_drq != -1) {
                   3508:                        if (isa_dmamap_create(sc->sc_isa, sc->sc_drq,
                   3509:                            MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
                   3510:                                printf("%s: can't create map for drq %d\n",
                   3511:                                       sc->sc_dev.dv_xname, sc->sc_drq);
                   3512:                                return;
                   3513:                        }
                   3514:                }
                   3515:                if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) {
                   3516:                        if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq,
                   3517:                            MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
                   3518:                                printf("%s: can't create map for drq %d\n",
                   3519:                                       sc->sc_dev.dv_xname, sc->sc_recdrq);
                   3520:                                return;
                   3521:                        }
                   3522:                }
                   3523:        }
                   3524:
                   3525:        timeout_set(&sc->sc_dma_tmo, gus_dmaout_timeout, sc);
                   3526:
                   3527:        SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_RESET);
                   3528:        /*
                   3529:         * Check to see how much memory we have on this card; see if any
                   3530:         * "mirroring" occurs.  We're assuming at least 256K already exists
                   3531:         * on the card; otherwise the initial probe would have failed
                   3532:         */
                   3533:
                   3534:        guspoke(iot, sc->sc_ioh2, 0L, 0x00);
                   3535:        for(i = 1; i < 1024; i++) {
                   3536:                u_long loc;
                   3537:
                   3538:                /*
                   3539:                 * See if we've run into mirroring yet
                   3540:                 */
                   3541:
                   3542:                if (guspeek(iot, sc->sc_ioh2, 0L) != 0)
                   3543:                        break;
                   3544:
                   3545:                loc = i << 10;
                   3546:
                   3547:                guspoke(iot, sc->sc_ioh2, loc, 0xaa);
                   3548:                if (guspeek(iot, sc->sc_ioh2, loc) != 0xaa)
                   3549:                        break;
                   3550:        }
                   3551:
                   3552:        sc->sc_dsize = i;
                   3553:        /*
                   3554:         * The "official" (3.x) version number cannot easily be obtained.
                   3555:         * The revision register does not correspond to the minor number
                   3556:         * of the board version. Simply use the revision register as
                   3557:         * identification.
                   3558:         */
                   3559:        snprintf(gus_device.version, sizeof gus_device.version, "%d",
                   3560:            sc->sc_revision);
                   3561:
                   3562:        printf(": ver %d", sc->sc_revision);
                   3563:        if (sc->sc_revision >= 10)
                   3564:                printf(", MAX");
                   3565:        else {
                   3566:                if (HAS_MIXER(sc))
                   3567:                        printf(", ICS2101 mixer");
                   3568:                if (HAS_CODEC(sc))
                   3569:                        printf(", %s codec/mixer", sc->sc_codec.chip_name);
                   3570:        }
                   3571:        printf(", %dKB DRAM, ", sc->sc_dsize);
                   3572:        if (sc->sc_recdrq == sc->sc_drq) {
                   3573:                printf("half-duplex");
                   3574:        } else {
                   3575:                printf("full-duplex, record drq %d", sc->sc_recdrq);
                   3576:        }
                   3577:
                   3578:        printf("\n");
                   3579:
                   3580:        /*
                   3581:         * Setup a default interrupt handler
                   3582:         */
                   3583:
                   3584:        /* XXX we shouldn't have to use splgus == splclock, nor should
                   3585:         * we use IPL_CLOCK.
                   3586:         */
                   3587:        sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
                   3588:            IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */, sc->sc_dev.dv_xname);
                   3589:
                   3590:        /*
                   3591:         * Set some default values
                   3592:         * XXX others start with 8kHz mono mulaw
                   3593:         */
                   3594:
                   3595:        sc->sc_irate = sc->sc_orate = 44100;
                   3596:        sc->sc_encoding = AUDIO_ENCODING_SLINEAR_LE;
                   3597:        sc->sc_precision = 16;
                   3598:        sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
                   3599:        sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
                   3600:        sc->sc_channels = 1;
                   3601:        sc->sc_ogain = 340;
                   3602:        gus_commit_settings(sc);
                   3603:
                   3604:        /*
                   3605:         * We always put the left channel full left & right channel
                   3606:         * full right.
                   3607:         * For mono playback, we set up both voices playing the same buffer.
                   3608:         */
                   3609:        bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT,
                   3610:            (u_char)GUS_VOICE_LEFT);
                   3611:        SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_PAN_POS);
                   3612:        bus_space_write_1(iot, sc->sc_ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
                   3613:
                   3614:        bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT,
                   3615:            (u_char)GUS_VOICE_RIGHT);
                   3616:        SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_PAN_POS);
                   3617:        bus_space_write_1(iot, sc->sc_ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
                   3618:
                   3619:        /*
                   3620:         * Attach to the generic audio layer
                   3621:         */
                   3622:
                   3623:        audio_attach_mi(&gus_hw_if, HAS_CODEC(sc) ? (void *)&sc->sc_codec :
                   3624:            (void *)sc, &sc->sc_dev);
                   3625: }
                   3626:
                   3627: /*
                   3628:  * Test to see if a particular I/O base is valid for the GUS.  Return true
                   3629:  * if it is.
                   3630:  */
                   3631:
                   3632: int
                   3633: gus_test_iobase (iot, iobase)
                   3634:        bus_space_tag_t iot;
                   3635:        int iobase;
                   3636: {
                   3637:        bus_space_handle_t ioh1, ioh2, ioh3, ioh4;
                   3638:        u_char s1, s2;
                   3639:        int s, rv = 0;
                   3640:
                   3641:        /* Map i/o space */
                   3642:        if (bus_space_map(iot, iobase, GUS_NPORT1, 0, &ioh1))
                   3643:                return 0;
                   3644:        if (bus_space_map(iot, iobase+GUS_IOH2_OFFSET, GUS_NPORT2, 0, &ioh2))
                   3645:                goto bad1;
                   3646:
                   3647:        /* XXX Maybe we shouldn't fail on mapping this, but just assume
                   3648:         * the card is of revision 0? */
                   3649:        if (bus_space_map(iot, iobase+GUS_IOH3_OFFSET, GUS_NPORT3, 0, &ioh3))
                   3650:                goto bad2;
                   3651:
                   3652:        if (bus_space_map(iot, iobase+GUS_IOH4_OFFSET, GUS_NPORT4, 0, &ioh4))
                   3653:                goto bad3;
                   3654:
                   3655:        /*
                   3656:         * Reset GUS to an initial state before we do anything.
                   3657:         */
                   3658:
                   3659:        s = splgus();
                   3660:        delay(500);
                   3661:
                   3662:        SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
                   3663:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
                   3664:
                   3665:        delay(500);
                   3666:
                   3667:        SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
                   3668:        bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
                   3669:
                   3670:        delay(500);
                   3671:
                   3672:        splx(s);
                   3673:
                   3674:        /*
                   3675:         * See if we can write to the board's memory
                   3676:         */
                   3677:
                   3678:        s1 = guspeek(iot, ioh2, 0L);
                   3679:        s2 = guspeek(iot, ioh2, 1L);
                   3680:
                   3681:        guspoke(iot, ioh2, 0L, 0xaa);
                   3682:        guspoke(iot, ioh2, 1L, 0x55);
                   3683:
                   3684:        if (guspeek(iot, ioh2, 0L) != 0xaa)
                   3685:                goto bad;
                   3686:
                   3687:        guspoke(iot, ioh2, 0L, s1);
                   3688:        guspoke(iot, ioh2, 1L, s2);
                   3689:
                   3690:        rv = 1;
                   3691:
                   3692: bad:
                   3693:        bus_space_unmap(iot, ioh4, GUS_NPORT4);
                   3694: bad3:
                   3695:        bus_space_unmap(iot, ioh3, GUS_NPORT3);
                   3696: bad2:
                   3697:        bus_space_unmap(iot, ioh2, GUS_NPORT2);
                   3698: bad1:
                   3699:        bus_space_unmap(iot, ioh1, GUS_NPORT1);
                   3700:        return rv;
                   3701: }

CVSweb