#ifdef __SC__
#include <int.h>
#endif
#include <stdio.h>
#include <dos.h>
#include "iwprotos.h"
#include "iwdefs.h"
//
extern IWAVE  iw;
//
#ifdef __PHARL__
extern void SaveSegRegs(void);  // These funcs are defined in iwpharl.asm
extern void GetSegRegs(void);
extern DWORD pSynthHandler;
extern DWORD pMidiHandler;
extern void xMidiHandler(void);
extern void xSynthHandler(void);
#endif
//#########################################################################
//
// FUNCTION: IwaveSetVect
//
// PROFILE: This function installs an interrupt handler pointed to
//          by "isr" to service interrupt number "int_no".
//
// UPDATE: 6/4/95  -- PharLap Update (BCC32)
//#########################################################################
void IwaveSetVect(int int_no, PVI isr)
{
#ifdef __HIGHC__
SaveSegRegs();              // Save segs values corresponding to program
_setrpvectp(int_no,isr);    // Set protected mode irq handler
#endif
//
#ifdef __SC__
int_intercept(int_no,isr,0);
#endif
//
#ifdef __WATCOMC__
//	union REGS	r;
//	r.x.eax = 0x0205;
//	r.h.bl = int_no;
//	r.x.edx = FP_OFF (isr);
//	r.w.cx = FP_SEG (isr);
//	int386 (0x31, &r, &r);	//set prot. vector thru DPMI
_dos_setvect(int_no,isr);
#endif

#ifdef MSOFTC
	asm   push ds;
	asm   lds dx,isr;
	asm   mov ax,int_no;
	asm   mov ah,0x25;
	asm   int 0x21;
	asm   pop ds;
#endif

#ifdef __BC16__       //BORLAND 16-bit Code
	asm   push ds;
	asm   lds dx,isr;
	asm   mov ah,0x25;
	_AL = int_no;
	asm   int 21h;
	asm   pop ds;
#endif
}
//##########################################################################
//
// FUNCTION: IwaveGetVect
//
// PROFILE: This function returns the address of the current  handler 
//          for interrupt number "int_no".
//
//###########################################################################
PVI IwaveGetVect(int int_no)
{
#ifdef __HIGHC__
return(_getpvect(int_no));
#endif
//
#ifdef __SC__
unsigned offset=0, seg=0;
int_getvector(int_no,&offset,&seg);
return((PVI)MK_FP(seg,offset));
#endif
//
#ifdef __WATCOMC__
//	union REGS	r;
//	r.x.eax = 0x0204;
//	r.h.bl = int_no;
//	int386 (0x31, &r, &r);
//	return ((PVI)MK_FP (r.w.cx, r.x.edx));
   return(_dos_getvect(int_no));
#endif

#ifdef MSOFTC
		asm   push ds;
		asm	mov ax,int_no;
		asm	mov ah,0x35;
		asm	int 0x21;
		asm	mov dx,es;
		asm	mov ax,bx;
		asm	pop ds;
#endif

#ifdef __BC16__
		asm     push ds;
		asm	mov ah,0x35;
		_AL = int_no;
		asm	int 21h;
		asm	mov dx,es;
		asm	mov ax,bx;
		asm	pop ds;
#endif
}
#ifdef __HIGHC__
//#########################################################################
//
// FUNCTION: GetrpVect
//
// PROFILE: This function returns the real and protected mode vectors
//          for a particular interrupt number. Implemnted to aid testing
//          of DDK under HIGH C.
//
//#########################################################################
void GetrpVect(int int_no, _real_int_handler_t *rvect, PVI *pvect)
{
  *rvect=_getrvect(int_no);
  *pvect=_getpvect(int_no);
}
//#########################################################################
//
// FUNCTION: SetrpVect
//
// PROFILE: This function restores the real and protected mode vectors
//          for a particular interrupt number. Implemnted to aid testing
//          of DDK under HIGH C. Useful after you've used _setrpvectp to
//          take over interrupts in both real and protected modes and you
//          want to restore them.
//
//#########################################################################
void SetrpVect(int int_no, _real_int_handler_t rvect, PVI pvect)
{
  _setrvect(int_no, rvect);
  _setpvect(int_no, pvect);
}
#endif
//#########################################################################
//
// FUNCTION: IwaveResetIvt
//
// PROFILE: This function restores the addresses corresponding to the
//          interrupts assigned to the synth and midi. Thus the PC's
//          interrupt vector table (IVT) is restored to its previous
//          state.
//
//#########################################################################
void IwaveResetIvt(void)
{
  int irq;

	irq = iw.synth_irq;
//#########################################################################
// Note that IRQ0-IRQ7 vector to INT 8 thru INT F
// and that IRQ8-IRQ15 vector to INT 70 thru INT 77.
//#########################################################################
	if (irq != 0)
	{
		 if (irq > 7)
			  irq += 0x68;
		 else
			  irq += 0x08;
#ifdef __SC__
       int_restore(irq);
#else
#ifdef __WATCOMC__
		 _dos_setvect(irq,iw.old_synth_vec);
#else
#ifdef __HIGHC__
		 _setrvect(irq,iw.old_synth_rvec);   // restore real-mode vector
		 _setpvect(irq,iw.old_synth_vec);    // restore prot-mode vector
#else
#ifdef __PHARL__
       _dx_rpmiv_set(irq,iw.old_synth_vec,iw.old_synth_rvec);
#else
		 IwaveSetVect(irq,iw.old_synth_vec);
#endif
#endif
#endif
#endif
	}
	irq = iw.midi_irq;
	if ((iw.synth_irq != irq) && (irq != 0))
	{
		if (irq > 7)
			irq += 0x68;
		else
			irq += 0x08;
#ifdef __SC__
      int_restore(irq);
#else
#ifdef __WATCOMC__
      _dos_setvect(irq,iw.old_midi_vec);
#else
#ifdef __HIGHC__
		 _setrvect(irq,iw.old_midi_rvec);   // restore real-mode vector
		 _setpvect(irq,iw.old_midi_vec);    // restore prot-mode vector
#else
#ifdef __PHARL__
		 _dx_rpmiv_set(irq,iw.old_midi_vec,iw.old_midi_rvec);
#else
		IwaveSetVect(irq,iw.old_midi_vec);
#endif
#endif
#endif
#endif
	}
}
//#########################################################################
//
// FUNCTION: IwaveSetIvt
//
// PROFILE: This function revectors the interrupt requests assigned to
//          the MIDI and Synthesizer to those specified in in the
//          "iw" variable and reflected in iw.synth_irq and iw.midi_irq
//          respectively. The interrupt vector table (IVT) is set up
//          with the new vectors to point to IwaveSynthHandler and
//          IwaveMidiHandler.
//
//#########################################################################
void IwaveSetIvt(void)
{
	int irq;
#ifdef __PHARL__
	CONFIG_INF cfg;
	PVI SynthHandler, MidiHandler;
#endif

	irq = iw.synth_irq;

//#########################################################################
// Note that IRQ0-IRQ7 vector to INT 8 thru INT F
// and that IRQ8-IRQ15 vector to INT 70 thru INT 77.
//#########################################################################

      if (irq != 0)
      {
        iw.flags|=IW_HANDLERS_ON;
        if (irq > 7)
            irq += 0x68;
        else
            irq += 0x08;

#ifdef __WATCOMC__
        iw.old_synth_vec=_dos_getvect(irq);
        _dos_setvect(irq,(PVI)IwaveSynthHandler);
#else
#ifdef __HIGHC__
        SaveSegRegs();
		  iw.old_synth_rvec= _getrvect(irq);           // real-mode vector
		  iw.old_synth_vec = _getpvect(irq);           // prot-mode vector
		  _setrpvectp(irq,(PVI)IwaveSynthHandler);     // Install Synth Vector
#else
#ifdef __PHARL__
      SaveSegRegs();
      pSynthHandler = (DWORD)IwaveSynthHandler;     // Init offset to callback
		_dx_config_inf(&cfg,(BYTE *)&cfg);
		_dx_rmiv_get(irq,&iw.old_synth_rvec);         // save old real vector
		_dx_pmiv_get(irq,&iw.old_synth_vec);          // save old prot vector
		FP_SET(SynthHandler,xSynthHandler,cfg.c_cs_sel);
		_dx_apmiv_set(irq,SynthHandler);              // install handler
#else
		  iw.old_synth_vec = IwaveGetVect(irq);       // save old vector
		  IwaveSetVect(irq,(PVI)IwaveSynthHandler);   // set up new handle
#endif
#endif
#endif
       }
      irq = iw.midi_irq;

      if ((iw.synth_irq != irq) && (irq != 0))
      {
        iw.flags|=IW_HANDLERS_ON;
        if (irq > 7)
            irq += 0x68;
        else
            irq += 0x08;
#ifdef __WATCOMC__
        iw.old_midi_vec = _dos_getvect(irq);
		  _dos_setvect(irq,(PVI)IwaveMidiHandler);
#else
#ifdef __HIGHC__
        SaveSegRegs();
		  iw.old_midi_rvec= _getrvect(irq);           // real-mode vector
		  iw.old_midi_vec = _getpvect(irq);           // prot-mode vector
		  _setrpvectp(irq,(PVI)IwaveMidiHandler);     // Install Midi Vector
#else
#ifdef __PHARL__
      SaveSegRegs();
      pMidiHandler=(DWORD)IwaveMidiHandler;        // Init offset to MIDI callback
		_dx_config_inf(&cfg,(BYTE *)&cfg);
		_dx_rmiv_get(irq,&iw.old_midi_rvec);         // save old real vector
		_dx_pmiv_get(irq,&iw.old_midi_vec);          // save old prot vector
		FP_SET(MidiHandler,xMidiHandler,cfg.c_cs_sel);
		_dx_apmiv_set(irq,MidiHandler);              // install handler
#else
		  iw.old_midi_vec = IwaveGetVect(irq);        // save old vector
		  IwaveSetVect(irq,(PVI)IwaveMidiHandler);    // set up a new handler
#endif
#endif
#endif
      }
}
//#########################################################################
//
// FUNCTION: IwaveUmaskIrqs
//
// PROFILE: This function enables IRQs at the PICs. This is done by
//          properly setting the mask register for the particular
//          levels to be enabled at the input to the controller. For
//          this issue the appropriate OCW1.
//
//#########################################################################
void IwaveUmaskIrqs(void)
{
BYTE imask;

#ifdef NEVER
	iw.gf1_sema4   = 0;
	iw.irq_pending = 0;
#endif

  if ((iw.synth_irq!=0)&&(iw.synth!=NULL))
   {
		//###################################################################
		// Enable or unmask IRQ line to 8259A for
		// the Synth interrupt.
		//###################################################################
		
	imask = _peek(iw.synth->imr);    /* Read IMR */
	imask &= iw.synth->mask;          /* Modify */
	_poke(iw.synth->imr,imask);     /* Write IMR */

 //###############################################################
 // Send a specific EOI in case of pending interrupt
 //###############################################################

	_poke(iw.synth->ocr,iw.synth->spec_eoi);  /* reset ISR bit */
	
   }

 //###############################################################
 // Enable or unmask IRQ line to 8259A for
 // the MIDI interrupt.
 //###############################################################

  if ((iw.midi!=NULL)&&(iw.midi_irq!=iw.synth_irq)&&(iw.midi_irq!=0))
  {
   imask = _peek(iw.midi->imr);
	imask &= iw.midi->mask;
	_poke(iw.midi->imr,imask);

 //################################################################
 //   Send a specific EOI in case of pending interrupt
 //################################################################

	_poke(iw.midi->ocr,iw.midi->spec_eoi);
	}

 //################################################################
 // Unmask IRQ 2 on master controller if using slave controller
 //################################################################

	if (iw.midi_irq > 7 || iw.synth_irq > 7)
	{
         imask = _peek(IMR1);
         imask &= IRQ2_UNMASK;
         _poke(IMR1,imask);

 //#################################################################
 // Send a specific EOI in case of pending interrupt
 //#################################################################

         _poke(OCR1,IRQ2_EOI);  /* reset the corresponding ISR bit */
	}
}
//#########################################################################
//
// FUNCTION: IwaveMaskIrqs
//
// PROFILE: This function disables IRQs at the PICs. This is done by
//          properly setting the mask register for the particular
//          levels to be disabled at the input to the controller.
//
//#########################################################################
void IwaveMaskIrqs(void)
{
BYTE imask;

 //#########################################################################
 // Disable or mask IRQ line to 8259A for the Synth interrupt.
 //#########################################################################

       if ((iw.synth!=NULL)&&(iw.synth_irq!=2)&&(iw.synth_irq!=0))
        {																      
           imask = _peek(iw.synth->imr);
           imask |= ~iw.synth->mask;
           _poke(iw.synth->imr,imask);
        }

 //#################################################################
 // Disable or mask IRQ line to 8259A for the MIDI interrupt.
 //#################################################################

       if ((iw.midi!=NULL)&&(iw.midi_irq!=2)&&(iw.midi_irq!=0))
        {
           imask = _peek(iw.midi->imr);
           imask |= ~iw.midi->mask;
           _poke(iw.midi->imr,imask);
        }
}
//#########################################################################
//
// FUNCTION: IwaveHandleDma
//
// PROFILE: This function handles DMA transfers between the PC system
//          and the InterWave. The DMA control register LDMACI is read
//          to determine the direction of the transfer.
//
//#########################################################################
void IwaveHandleDma(void)
{
BYTE ldmaci;

//#########################################################################
// Check to see if we need to service LM dma terminal count
// Note: This read also clears the pending irq.
//#########################################################################
 ENTER_CRITICAL;
 _poke(iw.igidxr,_LDMACI);                  /* select LDMACI */
 ldmaci= _peek(iw.i8dp);                    /* read LDMACI */
 LEAVE_CRITICAL;

 if (ldmaci&DMA_IRQ_PENDING)
 {
  if (iw.dma1->flags&DMA_SPLIT)
		IwaveDmaNext(iw.dma1);                /* handle cross over DMA page */
  else
  {                                         /* transfer just finished */
	iw.flags &= ~DMA_BUSY;                   /* show foreground it's done */
	iw.dma1->amnt_sent+=iw.dma1->cur_size;   /* total sent */
	iw.dma1->flags&=((~DMA_BUSY)&0x7FFF);

	if (ldmaci&DMA_UPLOAD)
#ifdef __SC__
		 iw.rec_dma_func(0);                  /* Record processing func */
	else
		 iw.play_dma_func(0);
#else
		 iw.rec_dma_func();                   /* Record processing func */
	else
		 iw.play_dma_func();
#endif
  }
 }
// LEAVE_CRITICAL;
}
//#########################################################################
//
// FUNCTION: IwaveHandleVoice
//
// PROFILE: This function handles interrupts caused by a particular
//          synth voice when such voice has either crossed an address
//          boundary or a volume boundary. Register SVII contains the
//          number of the voice that caused the interrupt as well as
//          the source (wavetable or volume ramp).
//
//          Note that SVII[7] and SVII[6] are 0 when the corresponding
//          interrupt has occured and SVII[5] is always 1. Indexing this
//          register with IGIDX=8F clears all internally stored interrupt
//          conditions. Indexing this register with IGIDXR=9F preserves
//          all internal interrupt indicators.
//
//#########################################################################
static void IwaveHandleVoice(void)
{
BYTE irq_source;
BYTE voice;
DWORD wave_ignore;
DWORD volume_ignore;
DWORD voice_bit;
BYTE saci;
BYTE svci;
//
//#########################################################################
// Clear the ignore flags. These flags are needed because we get lots of
// 'double' interrupts. This will only allow one interrupt per voice
//#########################################################################
//
wave_ignore = 0L;
volume_ignore = 0L;
//
//#########################################################################
// The InterWave will stack all pending wave table irq's. You
// should stay here & service ALL pending waveform IRQ's before
// returning.
//#########################################################################
//
while(TRUE)
{
 ENTER_CRITICAL;
 _poke(iw.igidxr,VOICE_IRQS);                    // select SVII
 irq_source = _peek(iw.i8dp);                    // read SVII
 LEAVE_CRITICAL;

 voice = irq_source & VOICE_NUMBER;              // pick off the voice #
 irq_source &=(VOICE_VOLUME_IRQ|VOICE_WAVE_IRQ); // isolate the irq bits

 if (irq_source==(VOICE_VOLUME_IRQ|VOICE_WAVE_IRQ))
	  break;			                               // No pending irqs left

 voice_bit = 1L<<voice;

 if ((irq_source & VOICE_WAVE_IRQ)==0x00)
  {
  if (!(wave_ignore & voice_bit))      // if no double irq, service it
   {
   wave_ignore |= voice_bit;

	_poke(iw.svsr,voice);               // select voice via SVSR
	_poke(iw.igidxr,_SACI_RD);          // select SACI for reading
	saci = _peek(iw.i8dp);              // read SACI

	_poke(iw.igidxr,_SVCI_RD);          // select SVCI for reading
   svci = _peek(iw.i8dp);              // read SVCI

//#########################################################################
//  If either LOOPING or ROLLOVER is on, don't  stop voice.
//#########################################################################

   if (!((saci & VC_LOOP_ENABLE)||(svci & VC_ROLLOVER)))
       IwaveStopVoice(voice);
  
   iw.wavetable_func(voice);           // waveform processing function
   }
}
   if ((irq_source&VOICE_VOLUME_IRQ)==0x00)
      {
       if (!(volume_ignore & voice_bit))
        {
	       volume_ignore |= voice_bit;

			 _poke(iw.svsr,voice);                   // select voice via SVSR
			 _poke(iw.igidxr,_SVCI_RD);              // select SVCI
			 svci = _peek(iw.i8dp);                  // read SVCI

//#########################################################################
// If volume looping is enabled, don't stop it
//#########################################################################

         if (!(svci & VC_LOOP_ENABLE))
             IwaveStopVolume(voice);

         iw.volume_func(voice);     // envelope processing function
        }
     }
  }
}
//#########################################################################
//
// FUNCTION: IwaveHandler
//
// PROFILE: This function is to act as a routing point to service
//          all interrupt requests from the InterWave. The function
//          identifies the source of the interrupt by reading register
//          UISR or CSR1R (Codec) and then calls all necessary handlers.
//          These registers are read until all interrupts are serviced.
//
//#########################################################################
static void IwaveHandler(void)
{
BYTE irq_source, adtimer;
WORD  midi_status, data;

while (TRUE)
{
 irq_source = _peek(iw.p2xr+0x06);            // read UISR
 if (irq_source==0x00)
     break;                                   // No more irqs

 if (irq_source&DMA_TC_IRQ)
     IwaveHandleDma();
    
 if (irq_source&(MIDI_TX_IRQ|MIDI_RX_IRQ))
  {
	 ENTER_CRITICAL;
	 midi_status = (WORD)_peek(iw.gmxr);     // read GMSR

	 if (irq_source&MIDI_TX_IRQ)
		  iw.midi_xmit_func(midi_status);     // midi xmit data processing

    if (irq_source&MIDI_RX_IRQ)
    {
	  data = (WORD)_peek(iw.gmxdr);          // read GMRDR - clears IRQ
	  iw.midi_rcv_func(midi_status,data);    // midi rcv data processing
	 }
    LEAVE_CRITICAL;
  }

 if (irq_source&(ALIB_TIMER1_IRQ|ALIB_TIMER2_IRQ))
  {
	 ENTER_CRITICAL;

	 _poke(iw.igidxr,_UASBCI);                 // select UASBCI
	 adtimer=_peek(iw.i8dp);

	 if(irq_source&ALIB_TIMER1_IRQ)
		_poke(iw.i8dp,(BYTE)(adtimer&~0x04));   // clear & disable IRQ

	 if(irq_source&ALIB_TIMER2_IRQ)
		_poke(iw.i8dp,(BYTE)(adtimer&~0x08));   // clear & disable IRQ

	 _poke(iw.i8dp,adtimer);                   // re-enable timer IRQ(s)
#ifdef __SC__
	 if(irq_source&ALIB_TIMER1_IRQ)
		 iw.timer1_func(0);

	 if(irq_source&ALIB_TIMER2_IRQ)
		 iw.timer2_func(0);
#else
	 if(irq_source&ALIB_TIMER1_IRQ)
		 iw.timer1_func();

	 if(irq_source&ALIB_TIMER2_IRQ)
		 iw.timer2_func();
#endif
	 LEAVE_CRITICAL;
  }

 if (irq_source & (WAVETABLE_IRQ | ENVELOPE_IRQ))
		IwaveHandleVoice();
}
 if (_peek(iw.pcodar+0x02)&CODEC_INT)   /* Codec Interrupts? */
   {
     BYTE source, reg;

     ENTER_CRITICAL;
	  reg=_peek(iw.pcodar)&0xE0;
     _poke(iw.pcodar,reg|_CSR3I);
     source = _peek(iw.cdatap);
     source&=(CODEC_PLAY_IRQ|CODEC_REC_IRQ|CODEC_TIMER_IRQ);

	  if (source&CODEC_PLAY_IRQ)
        {
			iw.codec_play_func(source);
			if ((iw.dma2!=NULL)&&(iw.dma2->flags&CODEC_DMA)&&(iw.dma2->type==DMA_READ))
				{
				 iw.dma2->flags&=~(DMA_BUSY|CODEC_DMA);
				 iw.flags&=~DMA_BUSY;
             iw.dma2->amnt_sent+=iw.dma2->cur_size;
             }
			_poke(iw.pcodar,reg|_CSR3I);
			_poke(iw.cdatap,CODEC_REC_IRQ|CODEC_TIMER_IRQ);
        }
	  if (source&CODEC_REC_IRQ)
        {
			iw.codec_rec_func(source);
			if ((iw.dma1!=NULL)&&(iw.dma1->flags&CODEC_DMA)&&(iw.dma1->type==DMA_WRITE))
				{
				 iw.dma1->flags&=~(DMA_BUSY|CODEC_DMA);
				 iw.flags&=~DMA_BUSY;
				 iw.dma1->amnt_sent+=iw.dma1->cur_size;
				}
			_poke(iw.pcodar,reg|_CSR3I);
			_poke(iw.cdatap,CODEC_PLAY_IRQ|CODEC_TIMER_IRQ);
		  }

	  if (source&CODEC_TIMER_IRQ)
		  {
#ifdef __SC__
			iw.codec_timer_func(0);
#else
         iw.codec_timer_func();
#endif
			_poke(iw.pcodar,reg|_CSR3I);
			_poke(iw.cdatap,(CODEC_PLAY_IRQ|CODEC_REC_IRQ));
		  }
	LEAVE_CRITICAL;
  }
}
//#########################################################################
//
// FUNCTION: IwaveHandleCodec
//
// PROFILE: This function determines the source of an interrupt within
//          Codec and activates the appropriate registered callback for
//          processing.
//
//#########################################################################
static void IwaveHandleCodec(void)
{
  BYTE source, cfg1, cmode;

 ENTER_CRITICAL;

 _poke(iw.pcodar,_CSR3I);
 source = _peek(iw.cdatap);
 source&=(CODEC_PLAY_IRQ|CODEC_REC_IRQ|CODEC_TIMER_IRQ);

 if (source&CODEC_PLAY_IRQ)
	  {
		 _poke(iw.pcodar,_CFIG1I);
		 cfg1=_peek(iw.cdatap);
		 _poke(iw.pcodar,_CMODEI);
		 cmode=_peek(iw.cdatap);
		 iw.codec_play_func(source,cfg1,cmode);
		 _poke(iw.pcodar,_CSR3I);
		 _poke(iw.cdatap,CODEC_REC_IRQ|CODEC_TIMER_IRQ);
	  }
 if (source&CODEC_REC_IRQ)
	  {
		 _poke(iw.pcodar,_CFIG1I);
		 cfg1=_peek(iw.cdatap);
		 _poke(iw.pcodar,_CMODEI);
		 cmode=_peek(iw.cdatap);
		 iw.codec_rec_func(source,cfg1,cmode);
		 _poke(iw.pcodar,_CSR3I);
		 _poke(iw.cdatap,CODEC_PLAY_IRQ|CODEC_TIMER_IRQ);
	  }
 if (source&CODEC_TIMER_IRQ)
  {
#ifdef __SC__
	 iw.codec_timer_func(0);
#else
	 iw.codec_timer_func();
#endif
	 _poke(iw.pcodar,_CSR3I);
	 _poke(iw.cdatap,(CODEC_PLAY_IRQ|CODEC_REC_IRQ));
  }
 LEAVE_CRITICAL;
}
//#########################################################################
//
// FUNCTION: IwaveSynthHandler
//
// PROFILE: This function is the interrupt handler for the synthesizer
//          interrupt requests. This is the code that takes over
//          immediately after the interrupt occurs. All it does is to
//          send EOI to the controller(s) to allow further interrupts
//          and then calls a function that will eventually route the
//          request to the appropriate function.
//
//#########################################################################
#ifdef __SC__
int IwaveSynthHandler(struct INT_DATA *ps)
#else
INTERRUPT IwaveSynthHandler(void)
#endif
{
#ifdef __PHARL__
GetSegRegs();
#endif
//#########################################################################
//  Reset the ISR bit(s) to allow further interrupts. Do this at both
//  controllers if needed.
//#########################################################################
 _poke(iw.synth->ocr,iw.synth->spec_eoi);

 if (iw.synth_irq > 7)
     _poke(OCR1,EOI);

 IwaveHandler();		// Go to main handler
#ifdef __SC__
 return(0);
#endif
}
//#########################################################################
//
// FUNCTION: IwaveMidiHandler
//
// PROFILE: This function is the interrupt handler for the MIDI
//          interrupt requests. This is the code that takes over
//          immediately after the interrupt occurs. All it does is to
//          send EOI to the controller(s) to allow further interrupts
//          and then calls a function that will eventually route the
//          request to the appropriate function.
//
//#########################################################################
#ifdef __SC__
int IwaveMidiHandler(struct INT_DATA *pm)
#else
INTERRUPT IwaveMidiHandler(void)
#endif
{
#ifdef __PHARL__
GetSegRegs();
#endif
//#########################################################################
//  Reset the ISR bit(s) to allow further interrupts. Do this at both
//  controllers if needed.
//#########################################################################
 _poke(iw.midi->ocr,iw.midi->spec_eoi);

 if (iw.midi_irq > 7)
	  _poke(OCR1,EOI);

 IwaveHandler();		// Go to main handler 
#ifdef __SC__
 return(0);
#endif
}
//#########################################################################
//
// FUNCTION: IwaveDefFunc
//
// PROFILE: This is the function that gets executed if no other handler
//          is defined.
//
//#########################################################################
void IwaveDefFunc(void)
{
}
//#########################################################################
//
// FUNCTION: IwaveSetCallback
//
// PROFILE: This function installs the application-defined handlers for
//          the different interrupt events from the InterWave. The
//          install consists of setting pointers inside of "iw".
//
//#########################################################################
PFV IwaveSetCallback(PFV handler, BYTE handle)
{
 PFV old_handler;

 switch(handle)
 {
   case PLAY_DMA_HANDLER:
        old_handler=iw.play_dma_func;
        iw.play_dma_func=handler;
        break;
   case REC_DMA_HANDLER:
        old_handler=iw.rec_dma_func;
        iw.rec_dma_func=handler;
        break;
   case MIDI_TX_HANDLER:
        old_handler=iw.midi_xmit_func;
        iw.midi_xmit_func=handler;
        break;
   case MIDI_RX_HANDLER:
        old_handler=iw.midi_rcv_func;
        iw.midi_rcv_func=handler;
        break;
   case TIMER1_HANDLER:
        old_handler=iw.timer1_func;
        iw.timer1_func=handler;
        break;
   case TIMER2_HANDLER:
        old_handler=iw.timer2_func;
        iw.timer2_func=handler;
        break;
   case WAVE_HANDLER:
        old_handler=iw.wavetable_func;
        iw.wavetable_func=handler;
        break;
	case VOLUME_HANDLER:
		  old_handler=iw.volume_func;
		  iw.volume_func=handler;
		  break;
	case CODEC_TIMER_HANDLER:
		  old_handler=iw.codec_timer_func;
		  iw.codec_timer_func=handler;
		  break;
	case CODEC_PLAY_HANDLER:
		  old_handler=iw.codec_play_func;
		  iw.codec_play_func=handler;
		  break;
	case CODEC_REC_HANDLER:
		  old_handler=iw.codec_rec_func;
		  iw.codec_rec_func=handler;
		  break;
   default:
        old_handler=(PFV)NULL;
        break;
 }
 return(old_handler);
}
#ifdef NEVER
void
leave_critical()
{
	_gf1_data.gf1_sema4--;
	if (_gf1_data.gf1_sema4 == 0)
		{
		if (_gf1_data.irq_pending)
			{
			_gf1_data.irq_pending = 0;
			gf1_handler();
			}
		}
}
#endif
