7 Mikmod driver for output on Creative Labs Soundblasters & compatibles
12 MSDOS: BC(y) Watcom(y) DJGPP(y)
18 (n) - no (not possible or not useful)
19 (?) - may be possible, but not tested
36 /***************************************************************************
37 >>>>>>>>>>>>>>>>>>>>>>>>> Lowlevel SB stuff <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
38 ***************************************************************************/
40 static UWORD sb_port; /* sb base port */
43 Define some important SB i/o ports:
46 #define MIXER_ADDRESS (sb_port+0x4)
47 #define MIXER_DATA (sb_port+0x5)
48 #define DSP_RESET (sb_port+0x6)
49 #define DSP_READ_DATA (sb_port+0xa)
50 #define DSP_WRITE_DATA (sb_port+0xc)
51 #define DSP_WRITE_STATUS (sb_port+0xc)
52 #define DSP_DATA_AVAIL (sb_port+0xe)
55 static void SB_MixerStereo(void)
57 Enables stereo output for DSP versions 3.00 >= ver < 4.00
60 outportb(MIXER_ADDRESS,0xe);
61 outportb(MIXER_DATA,inportb(MIXER_DATA)|2);
66 static void SB_MixerMono(void)
68 Disables stereo output for DSP versions 3.00 >= ver < 4.00
71 outportb(MIXER_ADDRESS,0xe);
72 outportb(MIXER_DATA,inportb(MIXER_DATA)&0xfd);
77 static BOOL SB_WaitDSPWrite(void)
79 Waits until the DSP is ready to be written to.
81 returns FALSE on timeout
87 if(!(inportb(DSP_WRITE_STATUS)&0x80)) return 1;
94 static BOOL SB_WaitDSPRead(void)
96 Waits until the DSP is ready to read from.
98 returns FALSE on timeout
104 if(inportb(DSP_DATA_AVAIL)&0x80) return 1;
111 static BOOL SB_WriteDSP(UBYTE data)
113 Writes byte 'data' to the DSP.
115 returns FALSE on timeout.
118 if(!SB_WaitDSPWrite()) return 0;
119 outportb(DSP_WRITE_DATA,data);
125 static UWORD SB_ReadDSP(void)
127 Reads a byte from the DSP.
129 returns 0xffff on timeout.
132 if(!SB_WaitDSPRead()) return 0xffff;
133 return(inportb(DSP_READ_DATA));
138 static void SB_SpeakerOn(void)
140 Enables DAC speaker output.
148 static void SB_SpeakerOff(void)
150 Disables DAC speaker output
158 static void SB_ResetDSP(void)
164 /* reset the DSP by sending 1, (delay), then 0 */
165 outportb(DSP_RESET,1);
166 for(t=0;t<8;t++) inportb(DSP_RESET);
167 outportb(DSP_RESET,0);
172 static BOOL SB_Ping(void)
174 Checks if a SB is present at the current baseport by
175 resetting the DSP and checking if it returned the value 0xaa.
177 returns: TRUE => SB is present
178 FALSE => No SB detected
182 return(SB_ReadDSP()==0xaa);
187 static UWORD SB_GetDSPVersion(void)
189 Gets SB-dsp version. returns 0xffff if dsp didn't respond.
194 if(!SB_WriteDSP(0xe1)) return 0xffff;
204 /***************************************************************************
205 >>>>>>>>>>>>>>>>>>>>>>>>> The actual SB driver <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
206 ***************************************************************************/
208 static DMAMEM *SB_DMAMEM;
209 static char *SB_DMABUF;
211 static UBYTE SB_TIMECONSTANT;
213 static UWORD sb_int; /* interrupt vector that belongs to sb_irq */
214 static UWORD sb_ver; /* DSP version number */
215 static UBYTE sb_irq; /* sb irq */
216 static UBYTE sb_lodma; /* 8 bit dma channel (1.0/2.0/pro) */
217 static UBYTE sb_hidma; /* 16 bit dma channel (16/16asp) */
218 static UBYTE sb_dma; /* current dma channel */
221 static BOOL SB_IsThere(void)
231 if((envptr=getenv("BLASTER"))==NULL) return 0;
235 /* skip whitespace */
237 do c=*(envptr++); while(c==' ' || c=='\t');
239 /* reached end of string? -> exit */
247 sb_port=strtol(envptr,&endptr,16);
252 sb_irq=strtol(envptr,&endptr,10);
253 //added on 11/5/98 by Victor Rachels to hardwire 2->9
256 //end this section addition - VR
261 sb_lodma=strtol(envptr,&endptr,10);
266 sb_hidma=strtol(envptr,&endptr,10);
270 strtol(envptr,&endptr,16);
276 if(sb_port==0xffff || sb_irq==0xff || sb_lodma==0xff) return 0;
278 /* determine interrupt vector */
280 sb_int = (sb_irq>7) ? sb_irq+104 : sb_irq+8;
282 if(!SB_Ping()) return 0;
284 /* get dsp version. */
286 if((sb_ver=SB_GetDSPVersion())==0xffff) return 0;
292 static void interrupt newhandler(MIRQARGS)
300 if(md_mode & DMODE_16BITS)
301 inportb(sb_port+0xf);
303 inportb(DSP_DATA_AVAIL);
309 static PVI oldhandler;
312 static BOOL SB_Init(void)
317 myerr="No such hardware detected, check your 'BLASTER' env. variable";
321 /* printf("SB version %x\n",sb_ver); */
322 /* if(sb_ver>0x200) sb_ver=0x200; */
324 if(sb_ver>=0x400 && sb_hidma==0xff){
325 myerr="High-dma setting in 'BLASTER' variable is required for SB-16";
329 if(sb_ver<0x400 && md_mode&DMODE_16BITS){
330 /* DSP versions below 4.00 can't do 16 bit sound. */
331 md_mode&=~DMODE_16BITS;
334 if(sb_ver<0x300 && md_mode&DMODE_STEREO){
335 /* DSP versions below 3.00 can't do stereo sound. */
336 md_mode&=~DMODE_STEREO;
339 /* Use low dma channel for 8 bit, high dma for 16 bit */
341 sb_dma=(md_mode & DMODE_16BITS) ? sb_hidma : sb_lodma;
346 if(md_mode & DMODE_STEREO) t<<=1;
348 SB_TIMECONSTANT=256-(1000000L/t);
351 if(SB_TIMECONSTANT>210) SB_TIMECONSTANT=210;
354 if(SB_TIMECONSTANT>233) SB_TIMECONSTANT=233;
357 md_mixfreq=1000000L/(256-SB_TIMECONSTANT);
358 if(md_mode & DMODE_STEREO) md_mixfreq>>=1;
361 if(!VC_Init()) return 0;
363 SB_DMAMEM=MDma_AllocMem(md_dmabufsize);
367 myerr="Couldn't allocate page-contiguous dma-buffer";
371 SB_DMABUF=(char *)MDma_GetPtr(SB_DMAMEM);
373 oldhandler=MIrq_SetHandler(sb_irq,newhandler);
379 static void SB_Exit(void)
381 MIrq_SetHandler(sb_irq,oldhandler);
382 MDma_FreeMem(SB_DMAMEM);
391 static void SB_Update(void)
395 curr=(md_dmabufsize-MDma_Todo(sb_dma))&0xfffc;
397 if(curr==last) return;
400 todo=curr-last; index=last;
401 last+=VC_WriteBytes(&SB_DMABUF[index],todo);
402 MDma_Commit(SB_DMAMEM,index,todo);
403 if(last>=md_dmabufsize) last=0;
406 todo=md_dmabufsize-last;
407 VC_WriteBytes(&SB_DMABUF[last],todo);
408 MDma_Commit(SB_DMAMEM,last,todo);
409 last=VC_WriteBytes(SB_DMABUF,curr);
410 MDma_Commit(SB_DMAMEM,0,curr);
417 static void SB_PlayStart(void)
421 MIrq_OnOff(sb_irq,1);
423 if(sb_ver>=0x300 && sb_ver<0x400){
424 if(md_mode & DMODE_STEREO){
432 /* clear the dma buffer to zero (16 bits
433 signed ) or 0x80 (8 bits unsigned) */
435 if(md_mode & DMODE_16BITS)
436 memset(SB_DMABUF,0,md_dmabufsize);
438 memset(SB_DMABUF,0x80,md_dmabufsize);
440 MDma_Commit(SB_DMAMEM,0,md_dmabufsize);
442 if(!MDma_Start(sb_dma,SB_DMAMEM,md_dmabufsize,INDEF_WRITE)){
450 SB_WriteDSP(SB_TIMECONSTANT);
457 else if(sb_ver==0x200){
473 SB_WriteDSP(md_mixfreq>>8);
474 SB_WriteDSP(md_mixfreq&0xff);
476 if(md_mode & DMODE_16BITS){
478 SB_WriteDSP((md_mode & DMODE_STEREO) ? 0x30 : 0x10);
482 SB_WriteDSP((md_mode & DMODE_STEREO) ? 0x20 : 0x00);
491 static void SB_PlayStop(void)
498 MIrq_OnOff(sb_irq,0);
504 "Soundblaster & compatibles",
505 "MikMod Soundblaster Driver v2.1 for 1.0 / 2.0 / Pro / 16",
515 VC_VoiceSetFrequency,