1 /* Driver for SB16 ISA card 2 * Implementing audio/audio_fw.h 3 * 4 * February 2006 Integrated standalone driver with audio framework (Peter Boonstoppel) 5 * August 24 2005 Ported audio driver to user space (only audio playback) (Peter Boonstoppel) 6 * May 20 1995 SB16 Driver: Michel R. Prevenier 7 */ 8 9 10 #include "sb16.h" 11 #include "mixer.h" 12 13 14 static void dsp_dma_setup(phys_bytes address, int count, int sub_dev); 15 16 static int dsp_ioctl(unsigned long request, void *val, int *len); 17 static int dsp_set_size(unsigned int size); 18 static int dsp_set_speed(unsigned int speed); 19 static int dsp_set_stereo(unsigned int stereo); 20 static int dsp_set_bits(unsigned int bits); 21 static int dsp_set_sign(unsigned int sign); 22 static int dsp_get_max_frag_size(u32_t *val, int *len); 23 24 25 static unsigned int DspStereo = DEFAULT_STEREO; 26 static unsigned int DspSpeed = DEFAULT_SPEED; 27 static unsigned int DspBits = DEFAULT_BITS; 28 static unsigned int DspSign = DEFAULT_SIGN; 29 static unsigned int DspFragmentSize; 30 31 static phys_bytes DmaPhys; 32 static int running = FALSE; 33 34 35 sub_dev_t sub_dev[2]; 36 special_file_t special_file[3]; 37 drv_t drv; 38 39 40 41 int drv_init(void) { 42 drv.DriverName = "SB16"; 43 drv.NrOfSubDevices = 2; 44 drv.NrOfSpecialFiles = 3; 45 46 sub_dev[AUDIO].readable = 1; 47 sub_dev[AUDIO].writable = 1; 48 sub_dev[AUDIO].DmaSize = 64 * 1024; 49 sub_dev[AUDIO].NrOfDmaFragments = 2; 50 sub_dev[AUDIO].MinFragmentSize = 1024; 51 sub_dev[AUDIO].NrOfExtraBuffers = 4; 52 53 sub_dev[MIXER].writable = 0; 54 sub_dev[MIXER].readable = 0; 55 56 special_file[0].minor_dev_nr = 0; 57 special_file[0].write_chan = AUDIO; 58 special_file[0].read_chan = NO_CHANNEL; 59 special_file[0].io_ctl = AUDIO; 60 61 special_file[1].minor_dev_nr = 1; 62 special_file[1].write_chan = NO_CHANNEL; 63 special_file[1].read_chan = AUDIO; 64 special_file[1].io_ctl = AUDIO; 65 66 special_file[2].minor_dev_nr = 2; 67 special_file[2].write_chan = NO_CHANNEL; 68 special_file[2].read_chan = NO_CHANNEL; 69 special_file[2].io_ctl = MIXER; 70 71 return OK; 72 } 73 74 75 int drv_init_hw(void) { 76 int i; 77 int DspVersion[2]; 78 Dprint(("drv_init_hw():\n")); 79 80 if(drv_reset () != OK) { 81 Dprint(("sb16: No SoundBlaster card detected\n")); 82 return -1; 83 } 84 85 DspVersion[0] = DspVersion[1] = 0; 86 dsp_command(DSP_GET_VERSION); /* Get DSP version bytes */ 87 88 for(i = 1000; i; i--) { 89 if(sb16_inb(DSP_DATA_AVL) & 0x80) { 90 if(DspVersion[0] == 0) { 91 DspVersion[0] = sb16_inb(DSP_READ); 92 } else { 93 DspVersion[1] = sb16_inb(DSP_READ); 94 break; 95 } 96 } 97 } 98 99 if(DspVersion[0] < 4) { 100 Dprint(("sb16: No SoundBlaster 16 compatible card detected\n")); 101 return -1; 102 } 103 104 Dprint(("sb16: SoundBlaster DSP version %d.%d detected!\n", DspVersion[0], DspVersion[1])); 105 106 /* set SB to use our IRQ and DMA channels */ 107 mixer_set(MIXER_SET_IRQ, (1 << (SB_IRQ / 2 - 1))); 108 mixer_set(MIXER_SET_DMA, (1 << SB_DMA_8 | 1 << SB_DMA_16)); 109 110 DspFragmentSize = sub_dev[AUDIO].DmaSize / sub_dev[AUDIO].NrOfDmaFragments; 111 112 return OK; 113 } 114 115 116 117 int drv_reset(void) { 118 int i; 119 Dprint(("drv_reset():\n")); 120 121 sb16_outb(DSP_RESET, 1); 122 for(i = 0; i < 1000; i++); /* wait a while */ 123 sb16_outb(DSP_RESET, 0); 124 125 for(i = 0; i < 1000 && !(sb16_inb(DSP_DATA_AVL) & 0x80); i++); 126 127 if(sb16_inb(DSP_READ) != 0xAA) return EIO; /* No SoundBlaster */ 128 129 return OK; 130 } 131 132 133 134 int drv_start(int channel, int DmaMode) { 135 Dprint(("drv_start():\n")); 136 137 drv_reset(); 138 139 dsp_dma_setup(DmaPhys, DspFragmentSize * sub_dev[channel].NrOfDmaFragments, DmaMode); 140 141 dsp_set_speed(DspSpeed); 142 143 /* Put the speaker on */ 144 if(DmaMode == WRITE_DMA) { 145 dsp_command (DSP_CMD_SPKON); /* put speaker on */ 146 147 /* Program DSP with dma mode */ 148 dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_OUT : DSP_CMD_16BITAUTO_OUT)); 149 } else { 150 dsp_command (DSP_CMD_SPKOFF); /* put speaker off */ 151 152 /* Program DSP with dma mode */ 153 dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_IN : DSP_CMD_16BITAUTO_IN)); 154 } 155 156 /* Program DSP with transfer mode */ 157 if (!DspSign) { 158 dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_US : DSP_MODE_MONO_US)); 159 } else { 160 dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_S : DSP_MODE_MONO_S)); 161 } 162 163 /* Give length of fragment to DSP */ 164 if (DspBits == 8) { /* 8 bit transfer */ 165 /* #bytes - 1 */ 166 dsp_command((DspFragmentSize - 1) >> 0); 167 dsp_command((DspFragmentSize - 1) >> 8); 168 } else { /* 16 bit transfer */ 169 /* #words - 1 */ 170 dsp_command((DspFragmentSize - 1) >> 1); 171 dsp_command((DspFragmentSize - 1) >> 9); 172 } 173 174 running = TRUE; 175 176 return OK; 177 } 178 179 180 181 int drv_stop(int sub_dev) { 182 if(running) { 183 Dprint(("drv_stop():\n")); 184 dsp_command((DspBits == 8 ? DSP_CMD_DMA8HALT : DSP_CMD_DMA16HALT)); 185 running = FALSE; 186 drv_reenable_int(sub_dev); 187 } 188 return OK; 189 } 190 191 192 193 int drv_set_dma(u32_t dma, u32_t UNUSED(length), int UNUSED(chan)) { 194 Dprint(("drv_set_dma():\n")); 195 DmaPhys = dma; 196 return OK; 197 } 198 199 200 201 int drv_reenable_int(int UNUSED(chan)) { 202 Dprint(("drv_reenable_int()\n")); 203 sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL)); 204 return OK; 205 } 206 207 208 209 int drv_int_sum(void) { 210 return mixer_get(MIXER_IRQ_STATUS) & 0x0F; 211 } 212 213 214 215 int drv_int(int sub_dev) { 216 return sub_dev == AUDIO && mixer_get(MIXER_IRQ_STATUS) & 0x03; 217 } 218 219 220 221 int drv_pause(int chan) { 222 drv_stop(chan); 223 return OK; 224 } 225 226 227 228 int drv_resume(int UNUSED(chan)) { 229 dsp_command((DspBits == 8 ? DSP_CMD_DMA8CONT : DSP_CMD_DMA16CONT)); 230 return OK; 231 } 232 233 234 235 int drv_io_ctl(unsigned long request, void *val, int *len, int sub_dev) { 236 Dprint(("dsp_ioctl: got ioctl %lu, argument: %d sub_dev: %d\n", 237 request, val, sub_dev)); 238 239 if(sub_dev == AUDIO) { 240 return dsp_ioctl(request, val, len); 241 } else if(sub_dev == MIXER) { 242 return mixer_ioctl(request, val, len); 243 } 244 245 return EIO; 246 } 247 248 249 250 int drv_get_irq(char *irq) { 251 Dprint(("drv_get_irq():\n")); 252 *irq = SB_IRQ; 253 return OK; 254 } 255 256 257 258 int drv_get_frag_size(u32_t *frag_size, int UNUSED(sub_dev)) { 259 Dprint(("drv_get_frag_size():\n")); 260 *frag_size = DspFragmentSize; 261 return OK; 262 } 263 264 265 266 static int dsp_ioctl(unsigned long request, void *val, int *len) { 267 int status; 268 269 switch(request) { 270 case DSPIORATE: status = dsp_set_speed(*((u32_t*) val)); break; 271 case DSPIOSTEREO: status = dsp_set_stereo(*((u32_t*) val)); break; 272 case DSPIOBITS: status = dsp_set_bits(*((u32_t*) val)); break; 273 case DSPIOSIZE: status = dsp_set_size(*((u32_t*) val)); break; 274 case DSPIOSIGN: status = dsp_set_sign(*((u32_t*) val)); break; 275 case DSPIOMAX: status = dsp_get_max_frag_size(val, len); break; 276 case DSPIORESET: status = drv_reset(); break; 277 default: status = ENOTTY; break; 278 } 279 280 return status; 281 } 282 283 284 285 static void dsp_dma_setup(phys_bytes address, int count, int DmaMode) { 286 pvb_pair_t pvb[9]; 287 288 Dprint(("Setting up %d bit DMA\n", DspBits)); 289 290 if(DspBits == 8) { /* 8 bit sound */ 291 count--; 292 293 pv_set(pvb[0], DMA8_MASK, SB_DMA_8 | 0x04); /* Disable DMA channel */ 294 pv_set(pvb[1], DMA8_CLEAR, 0x00); /* Clear flip flop */ 295 296 /* set DMA mode */ 297 pv_set(pvb[2], DMA8_MODE, (DmaMode == WRITE_DMA ? DMA8_AUTO_PLAY : DMA8_AUTO_REC)); 298 299 pv_set(pvb[3], DMA8_ADDR, (u8_t)(address >> 0)); /* Low_byte of address */ 300 pv_set(pvb[4], DMA8_ADDR, (u8_t)(address >> 8)); /* High byte of address */ 301 pv_set(pvb[5], DMA8_PAGE, (u8_t)(address >> 16)); /* 64K page number */ 302 pv_set(pvb[6], DMA8_COUNT, (u8_t)(count >> 0)); /* Low byte of count */ 303 pv_set(pvb[7], DMA8_COUNT, (u8_t)(count >> 8)); /* High byte of count */ 304 pv_set(pvb[8], DMA8_MASK, SB_DMA_8); /* Enable DMA channel */ 305 306 sys_voutb(pvb, 9); 307 } else { /* 16 bit sound */ 308 count -= 2; 309 310 pv_set(pvb[0], DMA16_MASK, (SB_DMA_16 & 3) | 0x04); /* Disable DMA channel */ 311 312 pv_set(pvb[1], DMA16_CLEAR, 0x00); /* Clear flip flop */ 313 314 /* Set dma mode */ 315 pv_set(pvb[2], DMA16_MODE, (DmaMode == WRITE_DMA ? DMA16_AUTO_PLAY : DMA16_AUTO_REC)); 316 317 pv_set(pvb[3], DMA16_ADDR, (address >> 1) & 0xFF); /* Low_byte of address */ 318 pv_set(pvb[4], DMA16_ADDR, (address >> 9) & 0xFF); /* High byte of address */ 319 pv_set(pvb[5], DMA16_PAGE, (address >> 16) & 0xFE); /* 128K page number */ 320 pv_set(pvb[6], DMA16_COUNT, (u8_t)(count >> 1)); /* Low byte of count */ 321 pv_set(pvb[7], DMA16_COUNT, (u8_t)(count >> 9)); /* High byte of count */ 322 pv_set(pvb[8], DMA16_MASK, SB_DMA_16 & 3); /* Enable DMA channel */ 323 324 sys_voutb(pvb, 9); 325 } 326 } 327 328 329 330 static int dsp_set_size(unsigned int size) { 331 Dprint(("dsp_set_size(): set fragment size to %u\n", size)); 332 333 /* Sanity checks */ 334 if(size < sub_dev[AUDIO].MinFragmentSize || size > sub_dev[AUDIO].DmaSize / sub_dev[AUDIO].NrOfDmaFragments || size % 2 != 0) { 335 return EINVAL; 336 } 337 338 DspFragmentSize = size; 339 340 return OK; 341 } 342 343 344 345 static int dsp_set_speed(unsigned int speed) { 346 Dprint(("sb16: setting speed to %u, stereo = %d\n", speed, DspStereo)); 347 348 if(speed < DSP_MIN_SPEED || speed > DSP_MAX_SPEED) { 349 return EPERM; 350 } 351 352 /* Soundblaster 16 can be programmed with real sample rates 353 * instead of time constants 354 * 355 * Since you cannot sample and play at the same time 356 * we set in- and output rate to the same value 357 */ 358 359 dsp_command(DSP_INPUT_RATE); /* set input rate */ 360 dsp_command(speed >> 8); /* high byte of speed */ 361 dsp_command(speed); /* low byte of speed */ 362 dsp_command(DSP_OUTPUT_RATE); /* same for output rate */ 363 dsp_command(speed >> 8); 364 dsp_command(speed); 365 366 DspSpeed = speed; 367 368 return OK; 369 } 370 371 372 373 static int dsp_set_stereo(unsigned int stereo) { 374 if(stereo) { 375 DspStereo = 1; 376 } else { 377 DspStereo = 0; 378 } 379 380 return OK; 381 } 382 383 384 385 static int dsp_set_bits(unsigned int bits) { 386 /* Sanity checks */ 387 if(bits != 8 && bits != 16) { 388 return EINVAL; 389 } 390 391 DspBits = bits; 392 393 return OK; 394 } 395 396 397 398 static int dsp_set_sign(unsigned int sign) { 399 Dprint(("sb16: set sign to %u\n", sign)); 400 401 DspSign = (sign > 0 ? 1 : 0); 402 403 return OK; 404 } 405 406 407 408 static int dsp_get_max_frag_size(u32_t *val, int *len) { 409 *len = sizeof(*val); 410 *val = sub_dev[AUDIO].DmaSize / sub_dev[AUDIO].NrOfDmaFragments; 411 return OK; 412 } 413 414 415 416 int dsp_command(int value) { 417 int i; 418 419 for (i = 0; i < SB_TIMEOUT; i++) { 420 if((sb16_inb(DSP_STATUS) & 0x80) == 0) { 421 sb16_outb(DSP_COMMAND, value); 422 return OK; 423 } 424 } 425 426 Dprint(("sb16: SoundBlaster: DSP Command(%x) timeout\n", value)); 427 return -1; 428 } 429 430 431 432 int sb16_inb(int port) { 433 int s; 434 u32_t value; 435 436 if ((s=sys_inb(port, &value)) != OK) 437 panic("sys_inb() failed: %d", s); 438 439 return (int) value; 440 } 441 442 443 444 void sb16_outb(int port, int value) { 445 int s; 446 447 if ((s=sys_outb(port, value)) != OK) 448 panic("sys_outb() failed: %d", s); 449 } 450