home *** CD-ROM | disk | FTP | other *** search
- #include <dos.h>
- #include "audio.h"
- #include "mpg123.h"
- #include "mdma.h"
- #include "mirq.h"
-
- void UltraSetInterface(int,int,int,int);
- void GF1OutB(UBYTE,UBYTE);
- void GF1OutW(UBYTE,UWORD);
- UBYTE UltraPeek(ULONG);
- void interrupt far gf1handler(void);
- void gf1_delay(void);
- void UltraPoke(ULONG,UBYTE);
- BOOL UltraProbe(void);
- void UltraDisableOutput(void);
- void UltraDisableLineIn(void);
- void UltraDisableMicIn(void);
- BOOL UltraDetect(void);
- int next(int);
- UWORD UltraSizeDram();
- void ultrastop();
- void ultrastart();
- UBYTE GF1InB(UBYTE);
- void UltraReset(int);
- BOOL UltraPP(ULONG);
- void UltraClose();
- void UltraSetFrequency(ULONG);
- ULONG convert_to_16bit(ULONG);
- ULONG UltraReadVoice(UBYTE);
- ULONG make_physical_address(UWORD,UWORD,UBYTE);
- UWORD GF1InW(UBYTE);
-
- UWORD GUS_PORT;
- UBYTE GUS_VOICES;
- UBYTE GUS_MIX_IMAGE;
-
- UWORD GUS_DRAM_DMA;
- UWORD GUS_ADC_DMA;
- UWORD GUS_GF1_IRQ;
- UWORD GUS_MIDI_IRQ;
-
- UBYTE GUS_SELECT; /* currently selected GF1 register */
-
- PVI oldhandler;
-
- DMAMEM * dma_control;
-
- static int store,play,playing;
- int bufs,memsize;
-
- int audio_open(struct audio_info_struct *ai)
- {
- UBYTE vmode,mode;
-
- if (ultradetect() == 0)
- {
- perror("Ultrasound not detected (sorry. SB support not finished)");
- return -1;
- }
-
- GUS_MIX_IMAGE=0x0b;
-
- UltraDisableLineIn();
- UltraDisableMicIn();
- UltraDisableOutput();
-
- UltraReset(14);
-
- if ((memsize=UltraSizeDram())==0)
- {
- perror("Go buy some memory for your GUS.");
- return -1;
- }
-
- oldhandler=MIrq_SetHandler(GUS_GF1_IRQ,gf1handler);
-
- MIrq_OnOff(GUS_GF1_IRQ,1);
-
- bufs=memsize/(AUDIOBUFSIZE*2/1024);
- store=0;
- play=0;
- playing=2;
-
- outportb(GF1_VOICE_SELECT,0);
-
- GF1OutW(SET_START_HIGH,0);
- GF1OutW(SET_START_LOW,0);
-
- vmode = VC_ROLLOVER|VOLUME_STOPPED|STOP_VOLUME;
- GF1OutB(SET_VOLUME_CONTROL,vmode);
- gf1_delay();
- GF1OutB(SET_VOLUME_CONTROL,vmode);
-
- GF1OutB(SET_BALANCE,0);
-
- GF1OutW(SET_VOLUME,0xfff<<4);
-
- mode=(VC_DATA_TYPE|VOICE_STOPPED|STOP_VOICE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
-
- outportb(GF1_VOICE_SELECT,1);
-
- GF1OutW(SET_START_HIGH,ADDR_HIGH(convert_to_16bit(bufs*AUDIOBUFSIZE)));
- GF1OutW(SET_START_LOW,ADDR_LOW(convert_to_16bit(bufs*AUDIOBUFSIZE)));
-
- vmode = VC_ROLLOVER|VOLUME_STOPPED|STOP_VOLUME;
- GF1OutB(SET_VOLUME_CONTROL,vmode);
- gf1_delay();
- GF1OutB(SET_VOLUME_CONTROL,vmode);
-
- GF1OutB(SET_BALANCE,0xf);
-
- GF1OutW(SET_VOLUME,0xfff<<4);
-
- mode=(VOICE_STOPPED|STOP_VOICE|VC_DATA_TYPE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
-
- dma_control = MDma_AllocMem(AUDIOBUFSIZE);
-
- return 0;
- }
-
- int audio_set_rate(struct audio_info_struct *ai)
- {
- outportb(GF1_VOICE_SELECT,0);
- UltraSetFrequency(ai->rate);
- outportb(GF1_VOICE_SELECT,1);
- UltraSetFrequency(ai->rate);
- return 0;
- }
-
- int audio_set_channels(struct audio_info_struct *ai)
- {
- return 0;
- }
-
- #define DMA_MODE ((GUS_DRAM_DMA>=4)?DMA_WIDTH_16:0)|DMA_DATA_16|DMA_READ
-
- int audio_play_samples(struct audio_info_struct *ai,short *src,int size)
- {
- char * ptr;
- int c,s,addr;
- char * dma_block;
- dma_block = MDma_GetPtr(dma_control);
-
- fprintf(stderr,"playing %d, play %d, store %d, ltrue %d, rtrue %d ",playing,play,store,UltraReadVoice(0)/AUDIOBUFSIZE,UltraReadVoice(1)/AUDIOBUFSIZE-bufs);
-
- if (playing != 2)
- while (store == play)
- if (playing == 0)
- ultrastart();
-
- ptr=(char *) src;
- addr=store*AUDIOBUFSIZE;
-
- for(c=0;c<size;c+=2,ptr+=4)
- {
- *(dma_block+c)=*(ptr);
- *(dma_block+c+1)=*(ptr+1);
- }
-
- GF1OutW(SET_DMA_ADDRESS,(addr>>4));
- GF1OutB(DMA_CONTROL,DMA_MODE);
-
- MDma_Start(GUS_DRAM_DMA,dma_control,size,WRITE_DMA);
-
- GF1OutB(DMA_CONTROL,DMA_MODE|DMA_ENABLE);
-
- while (MDma_ToDo(GUS_DRAM_DMA)<AUDIOBUFSIZE);
-
- MDma_Stop(GUS_DRAM_DMA);
-
- ptr=(char *) src;
- addr=store*AUDIOBUFSIZE+bufs*AUDIOBUFSIZE;
-
- for(c=0;c<size;c+=2,ptr+=4)
- {
- *(dma_block+c)=*(ptr+2);
- *(dma_block+c+1)=*(ptr+3);
- }
-
- GF1OutW(SET_DMA_ADDRESS,(addr)>>4);
-
- GF1OutB(DMA_CONTROL,DMA_MODE);
-
- MDma_Start(GUS_DRAM_DMA,dma_control,size,WRITE_DMA);
-
- GF1OutB(DMA_CONTROL,DMA_MODE|DMA_ENABLE);
-
- while (MDma_ToDo(GUS_DRAM_DMA)<AUDIOBUFSIZE);
-
- MDma_Stop(GUS_DRAM_DMA);
-
- store=next(store);
- if (playing == 2)
- playing=0;
-
- return 0;
- }
-
- int audio_close(struct audio_info_struct *ai)
- {
- UltraClose();
- MDma_FreeMem(dma_control);
- return 0;
- }
-
- static void interrupt far gf1handler(MIRQARGS)
- {
- ULONG phys_end;
- UBYTE oldselect=GUS_SELECT;
- UBYTE mode;
-
- inportb(GF1_IRQ_STAT);
- GF1InB(GET_IRQV);
-
- play=next(play);
-
- outportb(GF1_VOICE_SELECT,0);
- phys_end = convert_to_16bit(play*AUDIOBUFSIZE+AUDIOBUFSIZE-1);
- GF1OutW(SET_END_HIGH,ADDR_HIGH(phys_end));
- GF1OutW(SET_END_LOW,ADDR_LOW(phys_end));
-
- outportb(GF1_VOICE_SELECT,1);
- phys_end = convert_to_16bit(bufs*AUDIOBUFSIZE+play*AUDIOBUFSIZE+AUDIOBUFSIZE-1);
- GF1OutW(SET_END_HIGH,ADDR_HIGH(phys_end));
- GF1OutW(SET_END_LOW,ADDR_LOW(phys_end));
-
- if (play == bufs-1)
- {
- outportb(GF1_VOICE_SELECT,0);
- mode=(VC_WAVE_IRQ|VC_DATA_TYPE|VC_LOOP_ENABLE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
-
- outportb(GF1_VOICE_SELECT,1);
- mode=(VC_DATA_TYPE|VC_LOOP_ENABLE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
- }
- else
- {
- outportb(GF1_VOICE_SELECT,0);
- mode=(VC_WAVE_IRQ|VC_DATA_TYPE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
-
- outportb(GF1_VOICE_SELECT,1);
- mode=(VC_DATA_TYPE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
- }
-
- if (play == store)
- {
- ultrastop();
- }
-
- UltraSelect(oldselect);
- MIrq_EOI(GUS_GF1_IRQ);
- }
-
- void UltraReset(int voices)
- {
- int v;
-
- if(voices<14) voices=14;
- if(voices>32) voices=32;
-
- GUS_VOICES=voices;
-
- GF1OutB(MASTER_RESET,0x00);
-
- for(v=0;v<10;v++) gf1_delay();
-
- GF1OutB(MASTER_RESET,GF1_MASTER_RESET);
-
- for (v=0;v<10;v++) gf1_delay();
-
- outportb(GF1_MIDI_CTRL,MIDI_RESET);
-
- for (v=0;v<10;v++) gf1_delay();
-
- outportb(GF1_MIDI_CTRL,0x00);
-
- for (v=0;v<10;v++) gf1_delay();
-
- UltraSetInterface(GUS_DRAM_DMA,GUS_ADC_DMA,GUS_GF1_IRQ,GUS_MIDI_IRQ);
-
- /* Clear all interrupts. */
- GF1OutB(DMA_CONTROL,0x00);
- GF1OutB(TIMER_CONTROL,0x00);
- GF1OutB(SAMPLE_CONTROL,0x00);
-
- /* Set the number of active voices */
- GF1OutB(SET_VOICES,((voices-1) | 0xC0));
-
- /* Clear interrupts on voices. */
- /* Reading the status ports will clear the irqs. */
-
- inportb(GF1_IRQ_STAT);
- GF1InB(DMA_CONTROL);
- GF1InB(SAMPLE_CONTROL);
- GF1InB(GET_IRQV);
-
- for(v=0;v<voices;v++){
-
- outportb(GF1_PAGE,v);
-
- GF1OutB(SET_CONTROL,VOICE_STOPPED|STOP_VOICE);
- GF1OutB(SET_VOLUME_CONTROL,VOLUME_STOPPED|STOP_VOLUME);
-
- gf1_delay(); /* Wait 4.8 micos. or more. */
-
- GF1OutW(SET_FREQUENCY,0x0400);
- GF1OutW(SET_START_HIGH,0);
- GF1OutW(SET_START_LOW,0);
- GF1OutW(SET_END_HIGH,0);
- GF1OutW(SET_END_LOW,0);
- GF1OutB(SET_VOLUME_RATE,0x01);
- GF1OutB(SET_VOLUME_START,0x10);
- GF1OutB(SET_VOLUME_END,0xe0);
- GF1OutW(SET_VOLUME,0x0000);
-
- GF1OutW(SET_ACC_HIGH,0);
- GF1OutW(SET_ACC_LOW,0);
- GF1OutB(SET_BALANCE,0x07);
- }
-
- inportb(GF1_IRQ_STAT);
-
- GF1InB(DMA_CONTROL);
- GF1InB(SAMPLE_CONTROL);
- GF1InB(GET_IRQV);
-
- GF1OutB(MASTER_RESET,GF1_MASTER_RESET|GF1_OUTPUT_ENABLE|GF1_MASTER_IRQ);
- }
-
- UWORD UltraSizeDram(void)
- {
- if(!UltraPP(0)) return 0;
- if(!UltraPP(262144)) return 256;
- if(!UltraPP(524288)) return 512;
- if(!UltraPP(786432)) return 768;
- return 1024;
- }
-
- UBYTE GF1InB(UBYTE x)
- {
- UltraSelect(x);
- return inportb(GF1_DATA_HI);
- }
-
- BOOL UltraPP(ULONG address)
- {
- UBYTE s,t;
- s=UltraPeek(address);
- UltraPoke(address,0xaa);
- t=UltraPeek(address);
- UltraPoke(address,s);
- return(t==0xaa);
- }
-
- void UltraClose(void)
- {
- MIrq_OnOff(GUS_GF1_IRQ,0);
- MIrq_SetHandler(GUS_GF1_IRQ,oldhandler);
- UltraDisableOutput();
- UltraDisableLineIn();
- UltraDisableMicIn();
- UltraReset(14);
- }
-
- void UltraSetFrequency(ULONG speed_khz)
- {
- // GF1OutW(SET_FREQUENCY,(((speed_khz<<9L)+(44100>>1L))/44100)<<1);
- GF1OutW(SET_FREQUENCY,(int)(((float)speed_khz)/43.0243902439));
- }
-
- void ultrastop()
- {
- UBYTE mode;
-
- outportb(GF1_VOICE_SELECT,0);
- mode=VC_DATA_TYPE|VOICE_STOPPED|STOP_VOICE;
-
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
-
- outportb(GF1_VOICE_SELECT,1);
- mode=VC_DATA_TYPE|VOICE_STOPPED|STOP_VOICE;
-
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
-
- playing=0;
- }
-
- void ultrastart()
- {
- ULONG phys_end;
- ULONG phys_begin;
- UBYTE mode;
-
- outportb(GF1_VOICE_SELECT,0);
- phys_begin = convert_to_16bit(play*AUDIOBUFSIZE);
- phys_end = convert_to_16bit(play*AUDIOBUFSIZE+AUDIOBUFSIZE-1);
-
- GF1OutW(SET_ACC_LOW,ADDR_LOW(phys_begin));
- GF1OutW(SET_ACC_HIGH,ADDR_HIGH(phys_begin));
-
- GF1OutW(SET_END_HIGH,ADDR_HIGH(phys_end));
- GF1OutW(SET_END_LOW,ADDR_LOW(phys_end));
-
- outportb(GF1_VOICE_SELECT,1);
- phys_begin = convert_to_16bit(play*AUDIOBUFSIZE+bufs*AUDIOBUFSIZE);
- phys_end = convert_to_16bit(play*AUDIOBUFSIZE+bufs*AUDIOBUFSIZE+AUDIOBUFSIZE-1);
-
- GF1OutW(SET_ACC_LOW,ADDR_LOW(phys_begin));
- GF1OutW(SET_ACC_HIGH,ADDR_HIGH(phys_begin));
-
- GF1OutW(SET_END_HIGH,ADDR_HIGH(phys_end));
- GF1OutW(SET_END_LOW,ADDR_LOW(phys_end));
-
- outportb(GF1_VOICE_SELECT,0);
-
- mode=(VC_WAVE_IRQ|VC_DATA_TYPE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
-
- outportb(GF1_VOICE_SELECT,1);
-
- mode=(VC_DATA_TYPE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
-
- if (play == bufs-1)
- {
- outportb(GF1_VOICE_SELECT,0);
- mode=(VC_WAVE_IRQ|VC_DATA_TYPE|VC_LOOP_ENABLE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
-
- outportb(GF1_VOICE_SELECT,1);
- mode=(VC_DATA_TYPE|VC_LOOP_ENABLE);
- GF1OutB(SET_CONTROL,mode);
- gf1_delay();
- GF1OutB(SET_CONTROL,mode);
- }
-
- playing=1;
- }
-
- ULONG convert_to_16bit(ULONG address)
- /* unsigned long address; /* 20 bit ultrasound dram address */
- {
- ULONG hold_address;
-
- hold_address = address;
-
- /* Convert to 16 translated address. */
- address = address >> 1;
-
- /* Zero out bit 17. */
- address &= 0x0001ffffL;
-
- /* Reset bits 18 and 19. */
- address |= (hold_address & 0x000c0000L);
-
- return(address);
- }
-
- void GF1OutB(UBYTE x,UBYTE y)
- {
- UltraSelect(x);
- outportb(GF1_DATA_HI,y);
- }
-
- void GF1OutW(UBYTE x,UWORD y)
- {
- UltraSelect(x);
- outport(GF1_DATA_LOW,y);
- }
-
- UBYTE UltraPeek(ULONG address)
- {
- GF1OutW(SET_DRAM_LOW,address);
- GF1OutB(SET_DRAM_HIGH,(address>>16)&0xff); /* 8 bits */
- return(inportb(GF1_DRAM));
- }
-
- void gf1_delay(void)
- {
- inportb(GF1_DRAM);
- inportb(GF1_DRAM);
- inportb(GF1_DRAM);
- inportb(GF1_DRAM);
- inportb(GF1_DRAM);
- inportb(GF1_DRAM);
- inportb(GF1_DRAM);
- }
-
- void UltraPoke(ULONG address,UBYTE data)
- {
- GF1OutW(SET_DRAM_LOW,(short)address&0xffff);
- GF1OutB(SET_DRAM_HIGH,(address>>16)&0xff);
- outportb(GF1_DRAM,data);
- }
-
- BOOL UltraProbe(void)
- {
- UBYTE s1,s2,t1,t2;
-
- /* Pull a reset on the GF1 */
-
- GF1OutB(MASTER_RESET,0x00);
-
- /* Wait a little while ... */
- gf1_delay();
- gf1_delay();
-
- /* Release Reset */
- GF1OutB(MASTER_RESET,GF1_MASTER_RESET);
-
- gf1_delay();
- gf1_delay();
-
- s1=UltraPeek(0); s2=UltraPeek(1);
- UltraPoke(0,0xaa); t1=UltraPeek(0);
- UltraPoke(1,0x55); t2=UltraPeek(1);
- UltraPoke(0,s1); UltraPoke(1,s2);
-
- return(t1==0xaa && t2==0x55);
- }
-
- void UltraDisableOutput(void)
- {
- GUS_MIX_IMAGE |= ENABLE_OUTPUT;
- outportb(GF1_MIX_CTRL,GUS_MIX_IMAGE);
- }
-
- void UltraDisableLineIn(void)
- {
- GUS_MIX_IMAGE |= ENABLE_LINE_IN;
- outportb(GF1_MIX_CTRL,GUS_MIX_IMAGE);
- }
-
- void UltraDisableMicIn(void)
- {
- GUS_MIX_IMAGE &= ~ENABLE_MIC_IN;
- outportb(GF1_MIX_CTRL,GUS_MIX_IMAGE);
- }
-
- BOOL UltraDetect(void)
- {
- char * pointa;
-
- pointa=(char *)getenv("ULTRASND");
- if(pointa==0) return 0;
-
- if(sscanf(pointa,"%hx,%hd,%hd,%hd,%hd",
- &GUS_PORT,
- &GUS_DRAM_DMA,
- &GUS_ADC_DMA,
- &GUS_GF1_IRQ,
- &GUS_MIDI_IRQ)!=5) return 0;
-
- return(UltraProbe());
- }
-
-
- int next(int supa)
- {
- if (supa+1 == bufs)
- return 0;
- return (supa+1);
- }
-
- UBYTE dmalatch[8] ={ 0,1,0,2,0,3,4,5 };
- UBYTE irqlatch[16] ={ 0,0,1,3,0,2,0,4,0,0,0,5,6,0,0,7 };
-
- void UltraSetInterface(int dram,int adc,int gf1,int midi)
- /* int dram; /* dram dma chan */
- /* int adc; /* adc dma chan */
- /* int gf1; /* gf1 irq # */
- /* int midi; /* midi irq # */
- {
- UBYTE gf1_irq, midi_irq,dram_dma,adc_dma;
- UBYTE irq_control,dma_control;
- UBYTE mix_image;
-
- /* Don't need to check for 0 irq #. Its latch entry = 0 */
- gf1_irq =irqlatch[gf1];
- midi_irq=irqlatch[midi];
- midi_irq<<=3;
-
- dram_dma=dmalatch[dram];
- adc_dma =dmalatch[adc];
- adc_dma<<=3;
-
- irq_control=dma_control=0x0;
-
- mix_image=GUS_MIX_IMAGE;
-
- irq_control|=gf1_irq;
-
- if((gf1==midi) && (gf1!=0))
- irq_control|=0x40;
- else
- irq_control|=midi_irq;
-
- dma_control|=dram_dma;
-
- if((dram==adc) && (dram!=0))
- dma_control|=0x40;
- else
- dma_control|=adc_dma;
-
- /* Set up for Digital ASIC */
- outportb(GUS_PORT+0x0f,0x5);
- outportb(GF1_MIX_CTRL,mix_image);
- outportb(GF1_IRQ_CTRL,0x0);
- outportb(GUS_PORT+0x0f,0x0);
-
- /* First do DMA control register */
- outportb(GF1_MIX_CTRL,mix_image);
- outportb(GF1_IRQ_CTRL,dma_control|0x80);
-
- /* IRQ CONTROL REG */
- outportb(GF1_MIX_CTRL,mix_image|0x40);
- outportb(GF1_IRQ_CTRL,irq_control);
-
- /* First do DMA control register */
- outportb(GF1_MIX_CTRL,mix_image);
- outportb(GF1_IRQ_CTRL,dma_control);
-
- /* IRQ CONTROL REG */
- outportb(GF1_MIX_CTRL,mix_image|0x40);
- outportb(GF1_IRQ_CTRL,irq_control);
-
- /* IRQ CONTROL, ENABLE IRQ */
- /* just to Lock out writes to irq\dma register ... */
- outportb(GF1_VOICE_SELECT,0);
-
- /* enable output & irq, disable line & mic input */
- mix_image|=0x09;
- outportb(GF1_MIX_CTRL,mix_image);
-
- /* just to Lock out writes to irq\dma register ... */
- outportb(GF1_VOICE_SELECT,0x0);
-
- /* put image back .... */
- GUS_MIX_IMAGE=mix_image;
- }
-
- ULONG UltraReadVoice(UBYTE voice)
- {
- outportb(GF1_VOICE_SELECT,voice);
- return(make_physical_address(GF1InW(GET_ACC_LOW),GF1InW(GET_ACC_HIGH),GF1InB(GET_CONTROL))&0xfffffL);
- }
-
- ULONG make_physical_address(UWORD low,UWORD high,UBYTE mode)
- {
- UWORD lower_16, upper_16;
- ULONG ret_address, bit_19_20;
-
- upper_16 = high >> 9;
- lower_16 = ((high & 0x01ff) << 7) | ((low >> 9) & 0x007f);
-
- ret_address = MAKE_MS_SWORD(upper_16) + lower_16;
-
- if (mode & VC_DATA_TYPE)
- {
- bit_19_20 = ret_address & 0xC0000;
- ret_address <<= 1;
- ret_address &= 0x3ffff;
- ret_address |= bit_19_20;
- }
-
- return( ret_address );
- }
-
- UWORD GF1InW(UBYTE x)
- {
- UltraSelect(x);
- return inport(GF1_DATA_LOW);
- }
-