📄 sb16_dsp.c
字号:
/*===========================================================================* * reply * *===========================================================================*/PRIVATE void reply(code, replyee, process, status)int code;int replyee;int process;int status;{ message m; m.m_type = code; /* TASK_REPLY or REVIVE */ m.REP_STATUS = status; /* result of device operation */ m.REP_PROC_NR = process; /* which user made the request */ send(replyee, &m);}/*===========================================================================* * init_buffer *===========================================================================*/PRIVATE void init_buffer(){/* Select a buffer that can safely be used for dma transfers. * Its absolute address is 'DmaPhys', the normal address is 'DmaPtr'. */#if (CHIP == INTEL) unsigned left; DmaPtr = DmaBuffer; sys_umap(SELF, D, (vir_bytes)DmaBuffer, (phys_bytes)sizeof(DmaBuffer), &DmaPhys); if((left = dma_bytes_left(DmaPhys)) < DMA_SIZE) { /* First half of buffer crosses a 64K boundary, can't DMA into that */ DmaPtr += left; DmaPhys += left; }#else /* CHIP != INTEL */ panic("SB16DSP","init_buffer() failed, CHIP != INTEL", 0);#endif /* CHIP == INTEL */}/*===========================================================================* * dsp_init *===========================================================================*/PRIVATE int dsp_init(){ int i, s; if(dsp_reset () != OK) { dprint("sb16: No SoundBlaster card detected\n"); return -1; } DspVersion[0] = DspVersion[1] = 0; dsp_command(DSP_GET_VERSION); /* Get DSP version bytes */ for(i = 1000; i; i--) { if(sb16_inb(DSP_DATA_AVL) & 0x80) { if(DspVersion[0] == 0) { DspVersion[0] = sb16_inb(DSP_READ); } else { DspVersion[1] = sb16_inb(DSP_READ); break; } } } if(DspVersion[0] < 4) { dprint("sb16: No SoundBlaster 16 compatible card detected\n"); return -1; } dprint("sb16: SoundBlaster DSP version %d.%d detected\n", DspVersion[0], DspVersion[1]); /* set SB to use our IRQ and DMA channels */ mixer_set(MIXER_SET_IRQ, (1 << (SB_IRQ / 2 - 1))); mixer_set(MIXER_SET_DMA, (1 << SB_DMA_8 | 1 << SB_DMA_16)); /* register interrupt vector and enable irq */ if ((s=sys_irqsetpolicy(SB_IRQ, IRQ_REENABLE, &irq_hook_id )) != OK) panic("SB16DSP", "Couldn't set IRQ policy", s); if ((s=sys_irqenable(&irq_hook_id)) != OK) panic("SB16DSP", "Couldn't enable IRQ", s); DspAvail = 1; return OK;}/*===========================================================================* * dsp_reset *===========================================================================*/PRIVATE int dsp_reset(){ int i; sb16_outb(DSP_RESET, 1); for(i = 0; i < 1000; i++); /* wait a while */ sb16_outb(DSP_RESET, 0); for(i = 0; i < 1000 && !(sb16_inb(DSP_DATA_AVL) & 0x80); i++); if(sb16_inb(DSP_READ) != 0xAA) return EIO; /* No SoundBlaster */ DmaBusy = -1; return OK;}/*===========================================================================* * dsp_command *===========================================================================*/PRIVATE int dsp_command(value)int value;{ int i, status; for (i = 0; i < SB_TIMEOUT; i++) { if((sb16_inb(DSP_STATUS) & 0x80) == 0) { sb16_outb(DSP_COMMAND, value); return OK; } } dprint("sb16: SoundBlaster: DSP Command(%x) timeout\n", value); return -1;}/*===========================================================================* * dsp_set_size *===========================================================================*/static int dsp_set_size(size)unsigned int size;{ dprint("dsp_set_size(): set fragment size to %u\n", size); /* Sanity checks */ if(size < DSP_MIN_FRAGMENT_SIZE || size > DSP_MAX_FRAGMENT_SIZE || size % 2 != 0) { return EINVAL; } DspFragmentSize = size; return OK;}/*===========================================================================* * dsp_set_speed *===========================================================================*/static int dsp_set_speed(speed)unsigned int speed;{ dprint("sb16: setting speed to %u, stereo = %d\n", speed, DspStereo); if(speed < DSP_MIN_SPEED || speed > DSP_MAX_SPEED) { return EPERM; } /* Soundblaster 16 can be programmed with real sample rates * instead of time constants * * Since you cannot sample and play at the same time * we set in- and output rate to the same value */ dsp_command(DSP_INPUT_RATE); /* set input rate */ dsp_command(speed >> 8); /* high byte of speed */ dsp_command(speed); /* low byte of speed */ dsp_command(DSP_OUTPUT_RATE); /* same for output rate */ dsp_command(speed >> 8); dsp_command(speed); DspSpeed = speed; return OK;}/*===========================================================================* * dsp_set_stereo *===========================================================================*/static int dsp_set_stereo(stereo)unsigned int stereo;{ if(stereo) { DspStereo = 1; } else { DspStereo = 0; } return OK;}/*===========================================================================* * dsp_set_bits *===========================================================================*/static int dsp_set_bits(bits)unsigned int bits;{ /* Sanity checks */ if(bits != 8 && bits != 16) { return EINVAL; } DspBits = bits; return OK;}/*===========================================================================* * dsp_set_sign *===========================================================================*/static int dsp_set_sign(sign)unsigned int sign;{ dprint("sb16: set sign to %u\n", sign); DspSign = (sign > 0 ? 1 : 0); return OK;}/*===========================================================================* * dsp_dma_setup *===========================================================================*/PRIVATE void dsp_dma_setup(address, count)phys_bytes address;int count;{ pvb_pair_t pvb[9]; dprint("Setting up %d bit DMA\n", DspBits); if(DspBits == 8) { /* 8 bit sound */ count--; pv_set(pvb[0], DMA8_MASK, SB_DMA_8 | 0x04); /* Disable DMA channel */ pv_set(pvb[1], DMA8_CLEAR, 0x00); /* Clear flip flop */ /* set DMA mode */ pv_set(pvb[2], DMA8_MODE, (DmaMode == DEV_WRITE ? DMA8_AUTO_PLAY : DMA8_AUTO_REC)); pv_set(pvb[3], DMA8_ADDR, address >> 0); /* Low_byte of address */ pv_set(pvb[4], DMA8_ADDR, address >> 8); /* High byte of address */ pv_set(pvb[5], DMA8_PAGE, address >> 16); /* 64K page number */ pv_set(pvb[6], DMA8_COUNT, count >> 0); /* Low byte of count */ pv_set(pvb[7], DMA8_COUNT, count >> 8); /* High byte of count */ pv_set(pvb[8], DMA8_MASK, SB_DMA_8); /* Enable DMA channel */ sys_voutb(pvb, 9); } else { /* 16 bit sound */ count-= 2; pv_set(pvb[0], DMA16_MASK, (SB_DMA_16 & 3) | 0x04); /* Disable DMA channel */ pv_set(pvb[1], DMA16_CLEAR, 0x00); /* Clear flip flop */ /* Set dma mode */ pv_set(pvb[2], DMA16_MODE, (DmaMode == DEV_WRITE ? DMA16_AUTO_PLAY : DMA16_AUTO_REC)); pv_set(pvb[3], DMA16_ADDR, (address >> 1) & 0xFF); /* Low_byte of address */ pv_set(pvb[4], DMA16_ADDR, (address >> 9) & 0xFF); /* High byte of address */ pv_set(pvb[5], DMA16_PAGE, (address >> 16) & 0xFE); /* 128K page number */ pv_set(pvb[6], DMA16_COUNT, count >> 1); /* Low byte of count */ pv_set(pvb[7], DMA16_COUNT, count >> 9); /* High byte of count */ pv_set(pvb[8], DMA16_MASK, SB_DMA_16 & 3); /* Enable DMA channel */ sys_voutb(pvb, 9); }}/*===========================================================================* * dsp_setup() *===========================================================================*/PRIVATE void dsp_setup(){ /* Set current sample speed */ dsp_set_speed(DspSpeed); /* Put the speaker on */ if(DmaMode == DEV_WRITE) { dsp_command (DSP_CMD_SPKON); /* put speaker on */ /* Program DSP with dma mode */ dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_OUT : DSP_CMD_16BITAUTO_OUT)); } else { dsp_command (DSP_CMD_SPKOFF); /* put speaker off */ /* Program DSP with dma mode */ dsp_command((DspBits == 8 ? DSP_CMD_8BITAUTO_IN : DSP_CMD_16BITAUTO_IN)); } /* Program DSP with transfer mode */ if (!DspSign) { dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_US : DSP_MODE_MONO_US)); } else { dsp_command((DspStereo == 1 ? DSP_MODE_STEREO_S : DSP_MODE_MONO_S)); } /* Give length of fragment to DSP */ if (DspBits == 8) { /* 8 bit transfer */ /* #bytes - 1 */ dsp_command((DspFragmentSize - 1) >> 0); dsp_command((DspFragmentSize - 1) >> 8); } else { /* 16 bit transfer */ /* #words - 1 */ dsp_command((DspFragmentSize - 1) >> 1); dsp_command((DspFragmentSize - 1) >> 9); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -