1 /* $NetBSD: pas.c,v 1.5 1995/04/17 12:07:23 cgd 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 * $Id: pas.c,v 1.5 1995/04/17 12:07:23 cgd Exp $ 36 */ 37 /* 38 * Todo: 39 * - look at other PAS drivers (for PAS native suport) 40 * - use common sb.c once emulation is setup 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/errno.h> 46 #include <sys/ioctl.h> 47 #include <sys/syslog.h> 48 #include <sys/device.h> 49 #include <sys/proc.h> 50 51 #include <machine/cpu.h> 52 #include <machine/pio.h> 53 54 #include <sys/audioio.h> 55 #include <dev/audio_if.h> 56 57 #include <dev/isa/isavar.h> 58 #include <dev/isa/isadmavar.h> 59 #include <i386/isa/icu.h> 60 61 #include <i386/isa/sbdspvar.h> 62 #include <i386/isa/sbreg.h> 63 64 #define DEFINE_TRANSLATIONS 65 #include <i386/isa/pasreg.h> 66 67 #define DEBUG /*XXX*/ 68 #ifdef DEBUG 69 #define DPRINTF(x) if (pasdebug) printf x 70 int pasdebug = 0; 71 #else 72 #define DPRINTF(x) 73 #endif 74 75 /* 76 * Software state, per SoundBlaster card. 77 * The soundblaster has multiple functionality, which we must demultiplex. 78 * One approach is to have one major device number for the soundblaster card, 79 * and use different minor numbers to indicate which hardware function 80 * we want. This would make for one large driver. Instead our approach 81 * is to partition the design into a set of drivers that share an underlying 82 * piece of hardware. Most things are hard to share, for example, the audio 83 * and midi ports. For audio, we might want to mix two processes' signals, 84 * and for midi we might want to merge streams (this is hard due to 85 * running status). Moreover, we should be able to re-use the high-level 86 * modules with other kinds of hardware. In this module, we only handle the 87 * most basic communications with the sb card. 88 */ 89 struct pas_softc { 90 struct device sc_dev; /* base device */ 91 struct isadev sc_id; /* ISA device */ 92 void *sc_ih; /* interrupt vectoring */ 93 94 u_short sc_iobase; /* PAS iobase */ 95 u_short sc_irq; /* PAS irq */ 96 u_short sc_drq; /* PAS drq */ 97 98 int model; 99 int rev; 100 101 struct sbdsp_softc sc_sbdsp; 102 }; 103 104 int pasopen __P((dev_t, int)); 105 106 int pasprobe(); 107 void pasattach(); 108 109 int pas_getdev __P((void *, struct audio_device *)); 110 111 112 /* 113 * Define our interface to the higher level audio driver. 114 */ 115 116 struct audio_hw_if pas_hw_if = { 117 pasopen, 118 sbdsp_close, 119 NULL, 120 sbdsp_set_in_sr, 121 sbdsp_get_in_sr, 122 sbdsp_set_out_sr, 123 sbdsp_get_out_sr, 124 sbdsp_query_encoding, 125 sbdsp_set_encoding, 126 sbdsp_get_encoding, 127 sbdsp_set_precision, 128 sbdsp_get_precision, 129 sbdsp_set_channels, 130 sbdsp_get_channels, 131 sbdsp_round_blocksize, 132 sbdsp_set_out_port, 133 sbdsp_get_out_port, 134 sbdsp_set_in_port, 135 sbdsp_get_in_port, 136 sbdsp_commit_settings, 137 sbdsp_get_silence, 138 sbdsp_expand, 139 sbdsp_compress, 140 sbdsp_dma_output, 141 sbdsp_dma_input, 142 sbdsp_haltdma, 143 sbdsp_haltdma, 144 sbdsp_contdma, 145 sbdsp_contdma, 146 sbdsp_speaker_ctl, 147 pas_getdev, 148 sbdsp_setfd, 149 sbdsp_mixer_set_port, 150 sbdsp_mixer_get_port, 151 sbdsp_mixer_query_devinfo, 152 0, /* not full-duplex */ 153 0 154 }; 155 156 /* The Address Translation code is used to convert I/O register addresses to 157 be relative to the given base -register */ 158 159 static char *pasnames[] = { 160 "", 161 "Plus", 162 "CDPC", 163 "16", 164 "16Basic" 165 }; 166 167 static struct audio_device pas_device = { 168 "PAS,??", 169 "", 170 "pas" 171 }; 172 173 /*XXX assume default I/O base address */ 174 #define pasread(p) inb(p) 175 #define paswrite(d, p) outb(p, d) 176 177 void 178 pasconf(int model, int sbbase, int sbirq, int sbdrq) 179 { 180 int i; 181 182 paswrite(0x00, INTERRUPT_MASK); 183 /* Local timer control register */ 184 paswrite(0x36, SAMPLE_COUNTER_CONTROL); 185 /* Sample rate timer (16 bit) */ 186 paswrite(0x36, SAMPLE_RATE_TIMER); 187 paswrite(0, SAMPLE_RATE_TIMER); 188 /* Local timer control register */ 189 paswrite(0x74, SAMPLE_COUNTER_CONTROL); 190 /* Sample count register (16 bit) */ 191 paswrite(0x74, SAMPLE_BUFFER_COUNTER); 192 paswrite(0, SAMPLE_BUFFER_COUNTER); 193 194 paswrite(P_C_PCM_MONO | P_C_PCM_DAC_MODE | 195 P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, 196 PCM_CONTROL); 197 paswrite(S_M_PCM_RESET | S_M_FM_RESET | 198 S_M_SB_RESET | S_M_MIXER_RESET, SERIAL_MIXER); 199 200 /*XXX*/ 201 paswrite(I_C_1_BOOT_RESET_ENABLE|1, IO_CONFIGURATION_1); 202 203 paswrite(I_C_2_PCM_DMA_DISABLED, IO_CONFIGURATION_2); 204 paswrite(I_C_3_PCM_IRQ_DISABLED, IO_CONFIGURATION_3); 205 206 #ifdef BROKEN_BUS_CLOCK 207 paswrite(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | 208 S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1); 209 #else 210 paswrite(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, 211 SYSTEM_CONFIGURATION_1); 212 #endif 213 214 /*XXX*/ 215 paswrite(0, SYSTEM_CONFIGURATION_2); 216 paswrite(0, SYSTEM_CONFIGURATION_3); 217 218 /* Sets mute off and selects filter rate of 17.897 kHz */ 219 paswrite(F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); 220 221 if (model == PAS_16 || model == PAS_16BASIC) 222 paswrite(8, PRESCALE_DIVIDER); 223 else 224 paswrite(0, PRESCALE_DIVIDER); 225 226 paswrite(P_M_MV508_ADDRESS | P_M_MV508_PCM, PARALLEL_MIXER); 227 paswrite(5, PARALLEL_MIXER); 228 229 /* 230 * Setup SoundBlaster emulation. 231 */ 232 paswrite((sbbase >> 4) & 0xf, EMULATION_ADDRESS); 233 paswrite(E_C_SB_IRQ_translate[sbirq] | E_C_SB_DMA_translate[sbdrq], 234 EMULATION_CONFIGURATION); 235 paswrite(C_E_SB_ENABLE, COMPATIBILITY_ENABLE); 236 237 /* 238 * Set mid-range levels. 239 */ 240 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER); 241 paswrite(P_M_MV508_LOUDNESS | P_M_MV508_ENHANCE_NONE, PARALLEL_MIXER); 242 243 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MASTER_A, PARALLEL_MIXER); 244 paswrite(50, PARALLEL_MIXER); 245 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MASTER_B, PARALLEL_MIXER); 246 paswrite(50, PARALLEL_MIXER); 247 248 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MIXER | P_M_MV508_SB, PARALLEL_MIXER); 249 paswrite(P_M_MV508_OUTPUTMIX | 30, PARALLEL_MIXER); 250 251 paswrite(P_M_MV508_ADDRESS | P_M_MV508_MIXER | P_M_MV508_MIC, PARALLEL_MIXER); 252 paswrite(P_M_MV508_INPUTMIX | 30, PARALLEL_MIXER); 253 } 254 255 struct cfdriver pascd = { 256 NULL, "pas", pasprobe, pasattach, DV_DULL, sizeof(struct pas_softc) 257 }; 258 259 /* 260 * Probe / attach routines. 261 */ 262 263 /* 264 * Probe for the soundblaster hardware. 265 */ 266 int 267 pasprobe(parent, self, aux) 268 struct device *parent, *self; 269 void *aux; 270 { 271 register struct pas_softc *sc = (void *)self; 272 register struct isa_attach_args *ia = aux; 273 register u_short iobase; 274 u_char id, t; 275 276 /* 277 * WARNING: Setting an option like W:1 or so that disables 278 * warm boot reset of the card will screw up this detect code 279 * something fierce. Adding code to handle this means possibly 280 * interfering with other cards on the bus if you have something 281 * on base port 0x388. SO be forewarned. 282 */ 283 /* Talk to first board */ 284 outb(MASTER_DECODE, 0xbc); 285 /* Set base address */ 286 287 #if 0 288 /* XXX Need to setup pseudo device */ 289 /* XXX What are good io addrs ? */ 290 if (iobase != PAS_DEFAULT_BASE) { 291 printf("pas: configured iobase %d invalid\n", iobase); 292 return 0; 293 } 294 #else 295 /* Start out talking to native PAS */ 296 iobase = PAS_DEFAULT_BASE; 297 #endif 298 299 outb(MASTER_DECODE, iobase >> 2); 300 /* One wait-state */ 301 paswrite(1, WAIT_STATE); 302 303 id = pasread(INTERRUPT_MASK); 304 if (id == 0xff || id == 0xfe) { 305 /* sanity */ 306 DPRINTF(("pas: bogus card id\n")); 307 return 0; 308 } 309 /* 310 * We probably have a PAS-series board, now check for a 311 * PAS2-series board by trying to change the board revision 312 * bits. PAS2-series hardware won't let you do this because 313 * the bits are read-only. 314 */ 315 t = id ^ 0xe0; 316 paswrite(t, INTERRUPT_MASK); 317 t = inb(INTERRUPT_MASK); 318 paswrite(id, INTERRUPT_MASK); 319 320 if (t != id) { 321 /* Not a PAS2 */ 322 printf("pas: detected card but PAS2 test failed\n"); 323 return 0; 324 } 325 /*XXX*/ 326 t = pasread(OPERATION_MODE_1) & 0xf; 327 sc->model = O_M_1_to_card[t]; 328 if (sc->model != 0) { 329 sc->rev = pasread(BOARD_REV_ID); 330 } 331 else { 332 DPRINTF(("pas: bogus model id\n")); 333 return 0; 334 } 335 336 if (sc->model >= 0) { 337 int irq = ia->ia_irq; 338 if (irq == IRQUNK) { 339 printf("pas: sb emulation requires known irq\n"); 340 return (0); 341 } 342 irq = ia->ia_irq; 343 pasconf(sc->model, ia->ia_iobase, irq, 1); 344 } else { 345 DPRINTF(("pas: could not probe pas\n")); 346 return (0); 347 } 348 349 /* Now a SoundBlaster */ 350 sc->sc_iobase = ia->ia_iobase; 351 /* and set the SB iobase into the DSP as well ... */ 352 sc->sc_sbdsp.sc_iobase = ia->ia_iobase; 353 if (sbdsp_reset(&sc->sc_sbdsp) < 0) { 354 DPRINTF(("pas: couldn't reset card\n")); 355 return 0; 356 } 357 358 /* 359 * Cannot auto-discover DMA channel. 360 */ 361 if (!SB_DRQ_VALID(ia->ia_drq)) { 362 printf("pas: configured dma chan %d invalid\n", ia->ia_drq); 363 return 0; 364 } 365 #ifdef NEWCONFIG 366 /* 367 * If the IRQ wasn't compiled in, auto-detect it. 368 */ 369 if (ia->ia_irq == IRQUNK) { 370 ia->ia_irq = isa_discoverintr(pasforceintr, aux); 371 sbdsp_reset(&sc->sc_sbdsp); 372 if (!SB_IRQ_VALID(ia->ia_irq)) { 373 printf("pas: couldn't auto-detect interrupt"); 374 return 0; 375 } 376 } else 377 #endif 378 if (!SB_IRQ_VALID(ia->ia_irq)) { 379 int irq = ia->ia_irq; 380 printf("pas: configured irq %d invalid\n", irq); 381 return 0; 382 } 383 384 sc->sc_sbdsp.sc_irq = ia->ia_irq; 385 sc->sc_sbdsp.sc_drq = ia->ia_drq; 386 387 if (sbdsp_probe(&sc->sc_sbdsp) == 0) { 388 DPRINTF(("pas: sbdsp probe failed\n")); 389 return 0; 390 } 391 392 ia->ia_iosize = SB_NPORT; 393 return 1; 394 } 395 396 #ifdef NEWCONFIG 397 void 398 pasforceintr(aux) 399 void *aux; 400 { 401 static char dmabuf; 402 struct isa_attach_args *ia = aux; 403 u_short iobase = ia->ia_iobase; 404 405 /* 406 * Set up a DMA read of one byte. 407 * XXX Note that at this point we haven't called 408 * at_setup_dmachan(). This is okay because it just 409 * allocates a buffer in case it needs to make a copy, 410 * and it won't need to make a copy for a 1 byte buffer. 411 * (I think that calling at_setup_dmachan() should be optional; 412 * if you don't call it, it will be called the first time 413 * it is needed (and you pay the latency). Also, you might 414 * never need the buffer anyway.) 415 */ 416 at_dma(1, &dmabuf, 1, ia->ia_drq); 417 if (pas_wdsp(iobase, SB_DSP_RDMA) == 0) { 418 (void)pas_wdsp(iobase, 0); 419 (void)pas_wdsp(iobase, 0); 420 } 421 } 422 #endif 423 424 /* 425 * Attach hardware to driver, attach hardware driver to audio 426 * pseudo-device driver . 427 */ 428 void 429 pasattach(parent, self, aux) 430 struct device *parent, *self; 431 void *aux; 432 { 433 register struct pas_softc *sc = (struct pas_softc *)self; 434 struct isa_attach_args *ia = (struct isa_attach_args *)aux; 435 register u_short iobase = ia->ia_iobase; 436 437 sc->sc_iobase = iobase; 438 439 #ifdef NEWCONFIG 440 isa_establish(&sc->sc_id, &sc->sc_dev); 441 #endif 442 sc->sc_ih = isa_intr_establish(ia->ia_irq, ISA_IST_EDGE, ISA_IPL_BIO, 443 sbdsp_intr, &sc->sc_sbdsp); 444 445 #ifdef NEWCONFIG 446 /* 447 * We limit DMA transfers to a page, and use the generic DMA handling 448 * code in isa.c. This code can end up copying a buffer, but since 449 * the audio driver uses relative small buffers this isn't likely. 450 * 451 * This allocation scheme means that the maximum transfer is limited 452 * by the page size (rather than 64k). This is reasonable. For 4K 453 * pages, the transfer time at 48KHz is 4096 / 48000 = 85ms. This 454 * is plenty long enough to amortize any fixed time overhead. 455 */ 456 at_setup_dmachan(sc->sc_dmachan, NBPG); 457 #endif 458 459 printf(" ProAudio Spectrum %s [rev %d] ", pasnames[sc->model], sc->rev); 460 461 sbdsp_attach(&sc->sc_sbdsp); 462 463 sprintf(pas_device.name, "pas,%s", pasnames[sc->model]); 464 sprintf(pas_device.version, "%d", sc->rev); 465 466 if (audio_hardware_attach(&pas_hw_if, &sc->sc_sbdsp) != 0) 467 printf("pas: could not attach to audio pseudo-device driver\n"); 468 } 469 470 int 471 pasopen(dev, flags) 472 dev_t dev; 473 int flags; 474 { 475 struct pas_softc *sc; 476 int unit = AUDIOUNIT(dev); 477 478 if (unit >= pascd.cd_ndevs) 479 return ENODEV; 480 481 sc = pascd.cd_devs[unit]; 482 if (!sc) 483 return ENXIO; 484 485 return sbdsp_open(&sc->sc_sbdsp, dev, flags); 486 } 487 488 int 489 pas_getdev(addr, retp) 490 void *addr; 491 struct audio_device *retp; 492 { 493 *retp = pas_device; 494 return 0; 495 } 496