1 /* $NetBSD: pas.c,v 1.24 1997/04/06 00:54:25 augustss Exp $ */ 2 3 /* 4 * Copyright (c) 1991-1993 Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the Computer Systems 18 * Engineering Group at Lawrence Berkeley Laboratory. 19 * 4. Neither the name of the University nor of the Laboratory may be used 20 * to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 */ 36 /* 37 * Todo: 38 * - look at other PAS drivers (for PAS native suport) 39 * - use common sb.c once emulation is setup 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/errno.h> 45 #include <sys/ioctl.h> 46 #include <sys/syslog.h> 47 #include <sys/device.h> 48 #include <sys/proc.h> 49 50 #include <machine/cpu.h> 51 #include <machine/intr.h> 52 #include <machine/pio.h> 53 54 #include <sys/audioio.h> 55 #include <dev/audio_if.h> 56 #include <dev/mulaw.h> 57 58 #include <dev/isa/isavar.h> 59 #include <dev/isa/isadmavar.h> 60 61 #include <dev/isa/sbdspvar.h> 62 #include <dev/isa/sbreg.h> 63 64 #define DEFINE_TRANSLATIONS 65 #include <dev/isa/pasreg.h> 66 67 #ifdef AUDIO_DEBUG 68 #define DPRINTF(x) if (pasdebug) printf x 69 int pasdebug = 0; 70 #else 71 #define DPRINTF(x) 72 #endif 73 74 /* 75 * Software state, per SoundBlaster card. 76 * The soundblaster has multiple functionality, which we must demultiplex. 77 * One approach is to have one major device number for the soundblaster card, 78 * and use different minor numbers to indicate which hardware function 79 * we want. This would make for one large driver. Instead our approach 80 * is to partition the design into a set of drivers that share an underlying 81 * piece of hardware. Most things are hard to share, for example, the audio 82 * and midi ports. For audio, we might want to mix two processes' signals, 83 * and for midi we might want to merge streams (this is hard due to 84 * running status). Moreover, we should be able to re-use the high-level 85 * modules with other kinds of hardware. In this module, we only handle the 86 * most basic communications with the sb card. 87 */ 88 struct pas_softc { 89 struct sbdsp_softc sc_sbdsp; /* base device, &c. */ 90 91 int model; 92 int rev; 93 }; 94 95 int pasopen __P((dev_t, int)); 96 int pas_getdev __P((void *, struct audio_device *)); 97 void pasconf __P((int, int, int, int)); 98 99 100 /* 101 * Define our interface to the higher level audio driver. 102 */ 103 104 struct audio_hw_if pas_hw_if = { 105 pasopen, 106 sbdsp_close, 107 NULL, 108 sbdsp_set_in_sr, 109 sbdsp_get_in_sr, 110 sbdsp_set_out_sr, 111 sbdsp_get_out_sr, 112 sbdsp_query_encoding, 113 sbdsp_set_format, 114 sbdsp_get_encoding, 115 sbdsp_get_precision, 116 sbdsp_set_channels, 117 sbdsp_get_channels, 118 sbdsp_round_blocksize, 119 sbdsp_set_out_port, 120 sbdsp_get_out_port, 121 sbdsp_set_in_port, 122 sbdsp_get_in_port, 123 sbdsp_commit_settings, 124 mulaw_expand, 125 mulaw_compress, 126 sbdsp_dma_output, 127 sbdsp_dma_input, 128 sbdsp_haltdma, 129 sbdsp_haltdma, 130 sbdsp_contdma, 131 sbdsp_contdma, 132 sbdsp_speaker_ctl, 133 pas_getdev, 134 sbdsp_setfd, 135 sbdsp_mixer_set_port, 136 sbdsp_mixer_get_port, 137 sbdsp_mixer_query_devinfo, 138 0, /* not full-duplex */ 139 0 140 }; 141 142 /* The Address Translation code is used to convert I/O register addresses to 143 be relative to the given base -register */ 144 145 static char *pasnames[] = { 146 "", 147 "Plus", 148 "CDPC", 149 "16", 150 "16Basic" 151 }; 152 153 static struct audio_device pas_device = { 154 "PAS,??", 155 "", 156 "pas" 157 }; 158 159 /*XXX assume default I/O base address */ 160 #define pasread(p) inb(p) 161 #define paswrite(d, p) outb(p, d) 162 163 void 164 pasconf(model, sbbase, sbirq, sbdrq) 165 int model; 166 int sbbase; 167 int sbirq; 168 int sbdrq; 169 { 170 paswrite(0x00, INTERRUPT_MASK); 171 /* Local timer control register */ 172 paswrite(0x36, SAMPLE_COUNTER_CONTROL); 173 /* Sample rate timer (16 bit) */ 174 paswrite(0x36, SAMPLE_RATE_TIMER); 175 paswrite(0, SAMPLE_RATE_TIMER); 176 /* Local timer control register */ 177 paswrite(0x74, SAMPLE_COUNTER_CONTROL); 178 /* Sample count register (16 bit) */ 179 paswrite(0x74, SAMPLE_BUFFER_COUNTER); 180 paswrite(0, SAMPLE_BUFFER_COUNTER); 181 182 paswrite(P_C_PCM_MONO | P_C_PCM_DAC_MODE | 183 P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, 184 PCM_CONTROL); 185 paswrite(S_M_PCM_RESET | S_M_FM_RESET | 186 S_M_SB_RESET | S_M_MIXER_RESET, SERIAL_MIXER); 187 188 /*XXX*/ 189 paswrite(I_C_1_BOOT_RESET_ENABLE|1, IO_CONFIGURATION_1); 190 191 paswrite(I_C_2_PCM_DMA_DISABLED, IO_CONFIGURATION_2); 192 paswrite(I_C_3_PCM_IRQ_DISABLED, IO_CONFIGURATION_3); 193 194 #ifdef BROKEN_BUS_CLOCK 195 paswrite(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | 196 S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1); 197 #else 198 paswrite(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, 199 SYSTEM_CONFIGURATION_1); 200 #endif 201 202 /*XXX*/ 203 paswrite(0, SYSTEM_CONFIGURATION_2); 204 paswrite(0, SYSTEM_CONFIGURATION_3); 205 206 /* Sets mute off and selects filter rate of 17.897 kHz */ 207 paswrite(F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); 208 209 if (model == PAS_16 || model == PAS_16BASIC) 210 paswrite(8, PRESCALE_DIVIDER); 211 else 212 paswrite(0, PRESCALE_DIVIDER); 213 214 paswrite(P_M_MV508_ADDRESS | P_M_MV508_PCM, PARALLEL_MIXER); 215 paswrite(5, PARALLEL_MIXER); 216 217 /* 218 * Setup SoundBlaster emulation. 219 */ 220 paswrite((sbbase >> 4) & 0xf, EMULATION_ADDRESS); 221 paswrite(E_C_SB_IRQ_translate[sbirq] | E_C_SB_DMA_translate[sbdrq], 222 EMULATION_CONFIGURATION); 223 paswrite(C_E_SB_ENABLE, COMPATIBILITY_ENABLE); 224 225 /* 226 * Set mid-range levels. 227 */ 228 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER); 229 paswrite(P_M_MV508_LOUDNESS | P_M_MV508_ENHANCE_NONE, PARALLEL_MIXER); 230 231 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MASTER_A, PARALLEL_MIXER); 232 paswrite(50, PARALLEL_MIXER); 233 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MASTER_B, PARALLEL_MIXER); 234 paswrite(50, PARALLEL_MIXER); 235 236 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MIXER | P_M_MV508_SB, PARALLEL_MIXER); 237 paswrite(P_M_MV508_OUTPUTMIX | 30, PARALLEL_MIXER); 238 239 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MIXER | P_M_MV508_MIC, PARALLEL_MIXER); 240 paswrite(P_M_MV508_INPUTMIX | 30, PARALLEL_MIXER); 241 } 242 243 int pasprobe __P((struct device *, void *, void *)); 244 void pasattach __P((struct device *, struct device *, void *)); 245 246 struct cfattach pas_ca = { 247 sizeof(struct pas_softc), pasprobe, pasattach 248 }; 249 250 struct cfdriver pas_cd = { 251 NULL, "pas", DV_DULL 252 }; 253 254 /* 255 * Probe / attach routines. 256 */ 257 258 /* 259 * Probe for the soundblaster hardware. 260 */ 261 int 262 pasprobe(parent, match, aux) 263 struct device *parent; 264 void *match, *aux; 265 { 266 register struct pas_softc *sc = match; 267 register struct isa_attach_args *ia = aux; 268 register int iobase; 269 u_char id, t; 270 271 /* 272 * WARNING: Setting an option like W:1 or so that disables 273 * warm boot reset of the card will screw up this detect code 274 * something fierce. Adding code to handle this means possibly 275 * interfering with other cards on the bus if you have something 276 * on base port 0x388. SO be forewarned. 277 */ 278 /* Talk to first board */ 279 outb(MASTER_DECODE, 0xbc); 280 /* Set base address */ 281 282 #if 0 283 /* XXX Need to setup pseudo device */ 284 /* XXX What are good io addrs ? */ 285 if (iobase != PAS_DEFAULT_BASE) { 286 printf("pas: configured iobase %d invalid\n", iobase); 287 return 0; 288 } 289 #else 290 /* Start out talking to native PAS */ 291 iobase = PAS_DEFAULT_BASE; 292 #endif 293 294 outb(MASTER_DECODE, iobase >> 2); 295 /* One wait-state */ 296 paswrite(1, WAIT_STATE); 297 298 id = pasread(INTERRUPT_MASK); 299 if (id == 0xff || id == 0xfe) { 300 /* sanity */ 301 DPRINTF(("pas: bogus card id\n")); 302 return 0; 303 } 304 /* 305 * We probably have a PAS-series board, now check for a 306 * PAS2-series board by trying to change the board revision 307 * bits. PAS2-series hardware won't let you do this because 308 * the bits are read-only. 309 */ 310 t = id ^ 0xe0; 311 paswrite(t, INTERRUPT_MASK); 312 t = inb(INTERRUPT_MASK); 313 paswrite(id, INTERRUPT_MASK); 314 315 if (t != id) { 316 /* Not a PAS2 */ 317 printf("pas: detected card but PAS2 test failed\n"); 318 return 0; 319 } 320 /*XXX*/ 321 t = pasread(OPERATION_MODE_1) & 0xf; 322 sc->model = O_M_1_to_card[t]; 323 if (sc->model != 0) { 324 sc->rev = pasread(BOARD_REV_ID); 325 } 326 else { 327 DPRINTF(("pas: bogus model id\n")); 328 return 0; 329 } 330 331 if (sc->model >= 0) { 332 if (ia->ia_irq == IRQUNK) { 333 printf("pas: sb emulation requires known irq\n"); 334 return (0); 335 } 336 pasconf(sc->model, ia->ia_iobase, ia->ia_irq, 1); 337 } else { 338 DPRINTF(("pas: could not probe pas\n")); 339 return (0); 340 } 341 342 /* Now a SoundBlaster */ 343 sc->sc_sbdsp.sc_iobase = ia->ia_iobase; 344 sc->sc_sbdsp.sc_iot = ia->ia_iot; 345 if (sbdsp_reset(&sc->sc_sbdsp) < 0) { 346 DPRINTF(("pas: couldn't reset card\n")); 347 return 0; 348 } 349 350 /* 351 * Cannot auto-discover DMA channel. 352 */ 353 if (!SB_DRQ_VALID(ia->ia_drq)) { 354 printf("pas: configured dma chan %d invalid\n", ia->ia_drq); 355 return 0; 356 } 357 #ifdef NEWCONFIG 358 /* 359 * If the IRQ wasn't compiled in, auto-detect it. 360 */ 361 if (ia->ia_irq == IRQUNK) { 362 ia->ia_irq = isa_discoverintr(pasforceintr, aux); 363 sbdsp_reset(&sc->sc_sbdsp); 364 if (!SB_IRQ_VALID(ia->ia_irq)) { 365 printf("pas: couldn't auto-detect interrupt"); 366 return 0; 367 } 368 } else 369 #endif 370 if (!SB_IRQ_VALID(ia->ia_irq)) { 371 printf("pas: configured irq chan %d invalid\n", ia->ia_irq); 372 return 0; 373 } 374 375 sc->sc_sbdsp.sc_irq = ia->ia_irq; 376 sc->sc_sbdsp.sc_drq8 = ia->ia_drq; 377 sc->sc_sbdsp.sc_drq16 = -1; /* XXX */ 378 379 if (sbdsp_probe(&sc->sc_sbdsp) == 0) { 380 DPRINTF(("pas: sbdsp probe failed\n")); 381 return 0; 382 } 383 384 ia->ia_iosize = SB_NPORT; 385 return 1; 386 } 387 388 #ifdef NEWCONFIG 389 void 390 pasforceintr(aux) 391 void *aux; 392 { 393 static char dmabuf; 394 struct isa_attach_args *ia = aux; 395 int iobase = ia->ia_iobase; 396 397 /* 398 * Set up a DMA read of one byte. 399 * XXX Note that at this point we haven't called 400 * at_setup_dmachan(). This is okay because it just 401 * allocates a buffer in case it needs to make a copy, 402 * and it won't need to make a copy for a 1 byte buffer. 403 * (I think that calling at_setup_dmachan() should be optional; 404 * if you don't call it, it will be called the first time 405 * it is needed (and you pay the latency). Also, you might 406 * never need the buffer anyway.) 407 */ 408 at_dma(DMAMODE_READ, &dmabuf, 1, ia->ia_drq); 409 if (pas_wdsp(iobase, SB_DSP_RDMA) == 0) { 410 (void)pas_wdsp(iobase, 0); 411 (void)pas_wdsp(iobase, 0); 412 } 413 } 414 #endif 415 416 /* 417 * Attach hardware to driver, attach hardware driver to audio 418 * pseudo-device driver . 419 */ 420 void 421 pasattach(parent, self, aux) 422 struct device *parent, *self; 423 void *aux; 424 { 425 register struct pas_softc *sc = (struct pas_softc *)self; 426 struct isa_attach_args *ia = (struct isa_attach_args *)aux; 427 register int iobase = ia->ia_iobase; 428 int err; 429 430 sc->sc_sbdsp.sc_iobase = iobase; 431 sc->sc_sbdsp.sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, 432 IST_EDGE, IPL_AUDIO, sbdsp_intr, &sc->sc_sbdsp); 433 434 printf(" ProAudio Spectrum %s [rev %d] ", pasnames[sc->model], 435 sc->rev); 436 437 sbdsp_attach(&sc->sc_sbdsp); 438 439 sprintf(pas_device.name, "pas,%s", pasnames[sc->model]); 440 sprintf(pas_device.version, "%d", sc->rev); 441 442 if ((err = audio_hardware_attach(&pas_hw_if, &sc->sc_sbdsp)) != 0) 443 printf("pas: could not attach to audio pseudo-device driver (%d)\n", err); 444 } 445 446 int 447 pasopen(dev, flags) 448 dev_t dev; 449 int flags; 450 { 451 struct pas_softc *sc; 452 int unit = AUDIOUNIT(dev); 453 454 if (unit >= pas_cd.cd_ndevs) 455 return ENODEV; 456 457 sc = pas_cd.cd_devs[unit]; 458 if (!sc) 459 return ENXIO; 460 461 return sbdsp_open(&sc->sc_sbdsp, dev, flags); 462 } 463 464 int 465 pas_getdev(addr, retp) 466 void *addr; 467 struct audio_device *retp; 468 { 469 *retp = pas_device; 470 return 0; 471 } 472