#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include "iwdefs.h"
#include "iwprotos.h"
//
extern IWAVE iw;
//
//#########################################################################
// FILE: iwinit.c
//
// REMARKS: This file contains the definitions for the InterWave's DDK
//          functions dedicated to the configuration, initialization and
//          start up procedures of DDK structures and the hardware itself.
//
// UPDATE: 6/12/95
//#########################################################################
//
//  FUNCTION: IwaveInit
//
//  PROFILE: This function is defined in order to initialize the DDK by
//           determining the configuration of the InterWave Board via
//           an environment variable "IWCFG". This function is useful 
//           when you know the resource configuration of the InterWave 
//           IC and your system has no plug and play capability or when
//           your sound board is operating is system mode and you wish to
//           have control over the configuration via a utili
//
//#########################################################################
void IwaveInit(void)
{
 char *ptr;
 ptr=getenv("IWCFG");
 if(ptr!=NULL)
  {
	 sscanf(ptr,"%hx,%hx,%hx,%hx,%hx,%d,%d,%d,%d,%d,%d,%d,%d",
			 &iw.p2xr,
			 &iw.pcodar,
			 &iw.pcdrar,
			 &iw.pataar,
			 &iw.p401ar,
			 &iw.synth_irq,
			 &iw.midi_irq,
			 &iw.ext_irq,
			 &iw.mpu_irq,
			 &iw.emul_irq,
			 &iw.dma1_chan,
			 &iw.dma2_chan,
			 &iw.ext_dma);
	iw.cdatap=iw.pcodar+1;
	iw.csr1r =iw.pcodar+2;
	iw.cxdr  =iw.pcodar+3;      /* CPDR or CRDR */
	iw.p3xr  =iw.p2xr+0x100;
	iw.gmxr  =iw.p3xr;
	iw.gmxdr =iw.p3xr+1;        /* GMTDR or GMRDR */
	iw.svsr  =iw.p3xr+2;
	iw.igidxr=iw.p3xr+3;
	iw.i16dp =iw.p3xr+4;
	iw.i8dp  =iw.p3xr+5;
	iw.lmbdr =iw.p3xr+7;
  }
}
//#########################################################################
//
// FUNCTION: IwaveOpen
//
// PROFILE: This function sets up the IWAVE structure variable "iw" defined
//          by the DDK and necessary to creating applications for the
//          InterWave. The function also initializes the DMA and IRQ
//          structures for the interface to the sound board. The InterWave
//          IC is initialized as follows:
//
//          1. The selected mode of operation of the synth is programmed.
//          2. Interrupts and DMA requests are enabled onto ISA bus.
//          2. Line in and mic are disabled. Line out is enabled.
//
//          The "iw" variable contains pointers to the DMA and IRQ
//          structures and these must be initialized prior to calling
//          IwaveOpen. If no DMA or IRQ structures are needed by the
//          particular application, these pointers should be set to NULL.
//
//#########################################################################
BOOL IwaveOpen(BYTE voices, BYTE mode)
{
 char *ptr;

 if ((ptr=getenv("IWAVEID"))==NULL)
     return(FALSE);
 sscanf(ptr,"%lx",&iw.vendor);
 iw.csn=IwavePnpPing(iw.vendor);
 IwavePnpKey();
 IwavePnpWake(iw.csn);
 IwavePnpGetCfg();
 iw.cdatap=iw.pcodar+1;
 iw.csr1r =iw.pcodar+2;
 iw.cxdr  =iw.pcodar+3;             // CPDR or CRDR
 iw.gmxr  =iw.p3xr;
 iw.gmxdr =iw.p3xr+1;               // GMTDR or GMRDR
 iw.svsr  =iw.p3xr+2;
 iw.igidxr=iw.p3xr+3;
 iw.i16dp =iw.p3xr+4;
 iw.i8dp  =iw.p3xr+5;
 iw.lmbdr =iw.p3xr+7;
 iw.voices=voices;
 IwaveGusReset();                   // Place InterWave in GUS Mode
 IwaveCodecMode(CODEC_MODE3);       // Default codec mode
 if (mode==ENH_MODE)
 {
	  _poke(iw.igidxr,0x99);
	  iw.smode=_peek(iw.i8dp);
	  _poke(iw.igidxr,0x19);
	  _poke(iw.i8dp,(BYTE)(iw.smode|ENH_MODE));
 }
 iw.smode=mode;                    // Synth Mode
 iw.size_mem = IwaveMemSize();     // Bytes of RAM in this mode
//
 IwaveLineLevel(0,_CLOAI);
 IwaveLineLevel(0,_CROAI);
 IwaveLineMute(OFF,_CLOAI);
 IwaveLineMute(OFF,_CROAI);
 _poke(iw.pcodar,_CFIG3I|0x20);
 _poke(iw.cdatap,0xC2);           // Enable Mode 3 IRQs & Synth
 _poke(iw.p2xr,0x0B);             // Disable line in, mic and line out
 _poke(iw.igidxr,_URSTI);
 _poke(iw.i8dp,GF1_SET|GF1_OUT_ENABLE|GF1_IRQ_ENABLE);
//IwaveReset(voices);
 return(TRUE);
}
//#########################################################################
//
// FUNCTION: IwaveClose
//
// PROFILE: This function closes down a DDK application. It disables the
//          sound output, line in and mic input. It also restores the
//          PC's interrupt vector table.
//
//#########################################################################
BOOL IwaveClose(void)
{
  IwaveCodecMode(CODEC_MODE3);
  _poke(iw.pcodar,_CFIG3I | 0x20);
  _poke(iw.cdatap,0xC2);       // Enable Mode 3 IRQs & Synth
  IwaveLineLevel(0,_CLOAI);
  IwaveLineLevel(0,_CROAI);
  IwaveLineMute(ON,_CLOAI);
  IwaveLineMute(ON,_CROAI);
  _poke(iw.p2xr,0x03);         // Disable inputs and mute outputs
  IwaveGusReset();             // Reset InterWave board back to GUS Mode
  IwaveMaskIrqs();
  if (iw.flags&IW_HANDLERS_ON)
      IwaveResetIvt();
  return(TRUE);
}
//#########################################################################
//
// FUNCTION: IwaveSetInterface
//
// PROFILE: This function initializes DMA and IRQ structures defined by
//          the application for interrupt handling and DMA transfers. The
//          function takes pointers to such structures. If the application
//          will not use a particular interrupt or dma service the
//          respective pointer should be set to NULL.
//
//
//#########################################################################
void IwaveSetInterface(DMA *dma1,DMA *dma2,IRQ *irq1,IRQ *irq2)
{
 IRQ *irq_ptr;
 DMA *dma_ptr;
 BYTE udci, uici, i;
 int irq_no;
 int dma_chan;

 ENTER_CRITICAL;
 _poke(iw.igidxr,_IVERI);
 _poke(iw.i8dp,(BYTE)(_peek(iw.i8dp)|0x09));           /* enable access & reads */
 _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)|0x40));           /* set UMCR[6]=1 */
 _poke(iw.p2xr+0x0F,(BYTE)(_peek(iw.p2xr+0x0F)&0xF8)); /* URCR[2:0]=0 */
 uici=_peek(iw.p2xr+0x0B);                             /* read UICI */
 _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)&0xBF));           /* set UMCR[6]=0 */
 udci=_peek(iw.p2xr+0x0B);                             /* read UDCI */
 _poke(iw.i8dp,(BYTE)(_peek(iw.i8dp)&0xF6));           /* disable access & reads */
 LEAVE_CRITICAL;

 if(uici&0x40 && udci&0x80)                    /* all sources to IRQ2 */
	{
	  if (irq2!=(IRQ *)NULL)
			irq1=irq2;
	  else
			irq2=irq1;
	  iw.synth_irq=iw.midi_irq;
	}
 else
	if (uici&0x40)                               /* all sources to IRQ1 */
		{
			  if (irq1!=(IRQ *)NULL)
					irq2=irq1;
			  else
					irq1=irq2;
			  iw.midi_irq=iw.synth_irq;
		}

 if(udci&0x40)                    /* all sources to DMA chan 1 */
	{
	  if (dma1!=(DMA *)NULL)
			dma2=dma1;
	  else
			dma1=dma2;
	  iw.dma2_chan=iw.dma1_chan;
	}

 iw.synth=irq1;                  /* init pointers to structures */
 iw.midi=irq2;
 iw.dma1=dma1;
 iw.dma2=dma2;

//#########################################################
//  Now initialize IRQ structures if applicable.
//#########################################################

 for (i=1; i<=2; i++)
 {
	if(i==1)
	 {
	  irq_no = iw.synth_irq;
	  irq_ptr = iw.synth;
	 }
	else
	 {
	  irq_no = iw.midi_irq;
	  irq_ptr = iw.midi;
	 }

	if (irq_ptr!=(IRQ *)NULL)
	 {
	  if (irq_no > 7)
		  {
			irq_ptr->imr=IMR2;
			irq_ptr->ocr=OCR2;
		  }
	  else
		  {
			irq_ptr->imr=IMR1;
			irq_ptr->ocr=OCR1;
		  }

	  irq_ptr->spec_eoi=0x60+(irq_no&0x07);
	  irq_ptr->mask=~(1<<(irq_no&0x07));

	}
 }
//###########################################################
//  Now initialize DMA structures if applicable.
//###########################################################
 for (i=1; i<=2; i++)
 {
  if(i==1)
	 {
	  dma_chan = iw.dma1_chan;
	  dma_ptr = iw.dma1;
	 }
  else
	 {
	  dma_chan = iw.dma2_chan;
	  dma_ptr = iw.dma2;
	 }

  if (dma_ptr!=(DMA *)NULL)
	{
	 BYTE channel;
	 channel = dma_chan&0x03;
	 dma_ptr->flags=0x00;
	 dma_ptr->channel=dma_chan;
	 dma_ptr->enable = channel;
	 dma_ptr->disable= channel|DMA_SET_MASK;
	 dma_ptr->cur_mode=channel;
	 dma_ptr->write= channel|0x44;           /* upload mode */
	 dma_ptr->read=channel|0x48;             /* download mode */
	 dma_ptr->cur_control=0x00;

	 if (dma_chan < 3)
	  {
		 dma_ptr->single= DMA1_SNGL;
		 dma_ptr->mode = DMA1_MODE;
		 dma_ptr->clear_ff=DMA1_CLRFF;
	  }
	 else
	  {
		 dma_ptr->single= DMA2_SNGL;
		 dma_ptr->mode = DMA2_MODE;
		 dma_ptr->clear_ff=DMA2_CLRFF;
	  }

	 switch(dma_chan)
	 {
		case 0:
		dma_ptr->addr=DMA0_ADDR;
		dma_ptr->page=DMA0_PAGE;
		dma_ptr->count=DMA0_CNT;
		break;
		case 1:
		dma_ptr->addr=DMA1_ADDR;
		dma_ptr->page=DMA1_PAGE;
		dma_ptr->count=DMA1_CNT;
		break;
		case 2:
		dma_ptr->addr=DMA2_ADDR;
		dma_ptr->page=DMA2_PAGE;
		dma_ptr->count=DMA2_CNT;
		break;
		case 3:
		dma_ptr->addr=DMA3_ADDR;
		dma_ptr->page=DMA3_PAGE;
		dma_ptr->count=DMA3_CNT;
		break;
		case 4:
		dma_ptr->addr=DMA4_ADDR;
		dma_ptr->page=DMA4_PAGE;
		dma_ptr->count=DMA4_CNT;
		break;
		case 5:
		dma_ptr->addr=DMA5_ADDR;
		dma_ptr->page=DMA5_PAGE;
		dma_ptr->count=DMA5_CNT;
		break;
		case 6:
		dma_ptr->addr=DMA6_ADDR;
		dma_ptr->page=DMA6_PAGE;
		dma_ptr->count=DMA6_CNT;
		break;
		case 7:
		dma_ptr->addr=DMA7_ADDR;
		dma_ptr->page=DMA7_PAGE;
		dma_ptr->count=DMA7_CNT;
		break;
	 }
  }
 }
 IwaveSetIvt();
 IwaveUmaskIrqs();
}
//#########################################################################
//
// FUNCTION: IwaveRegisterIRQ
//
// PROFILE: This function initializes IRQ structures defined by the
//          application for interrupt handling. Note that if the IRQ sources
//          have been combined or routed at the InterWave hardware to go
//          to one channel this function will select one of the structures
//          to serve as an interface.
//
//#########################################################################
void IwaveRegisterIRQ(IRQ *irq1,IRQ *irq2)
{
 IRQ *irq_ptr;
 BYTE udci, uici, i;
 int irq_no;

 ENTER_CRITICAL;
 _poke(iw.igidxr,_IVERI);
 _poke(iw.i8dp,(BYTE)(_peek(iw.i8dp)|0x09));           // enable access & reads
 _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)|0x40));           // set UMCR[6]=1
 _poke(iw.p2xr+0x0F,(BYTE)(_peek(iw.p2xr+0x0F)&0xF8)); // URCR[2:0]=0 
 uici=_peek(iw.p2xr+0x0B);                             // read UICI 
 _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)&0xBF));           // set UMCR[6]=0 
 udci=_peek(iw.p2xr+0x0B);                             // read UDCI
 _poke(iw.i8dp,(BYTE)(_peek(iw.i8dp)&0xF6));           // disable access & reads
 LEAVE_CRITICAL;

 if(uici&0x40 && udci&0x80)                    // all sources to IRQ2 
	{
	  if (irq2!=(IRQ *)NULL)
			irq1=irq2;
	  else
			irq2=irq1;
	  iw.synth_irq=iw.midi_irq;
	}
 else
	if (uici&0x40)                               // all sources to IRQ1
		{
			  if (irq1!=(IRQ *)NULL)
					irq2=irq1;
			  else
					irq1=irq2;
			  iw.midi_irq=iw.synth_irq;
		}
 iw.synth=irq1;
 iw.midi=irq2;
//
//####################################################
//  Now initialize IRQ structures if applicable.
//####################################################
//
 for (i=1; i<=2; i++)
 {
	if(i==1)
	 {
	  irq_no = iw.synth_irq;
	  irq_ptr = iw.synth;
	 }
	else
	 {
	  irq_no = iw.midi_irq;
	  irq_ptr = iw.midi;
	 }

	if (irq_ptr!=(IRQ *)NULL)
	 {
	  if (irq_no > 7)
		  {
			irq_ptr->imr=IMR2;
			irq_ptr->ocr=OCR2;
		  }
	  else
		  {
			irq_ptr->imr=IMR1;
			irq_ptr->ocr=OCR1;
		  }
	  irq_ptr->spec_eoi=0x60+(irq_no&0x07);
	  irq_ptr->mask=~(1<<(irq_no&0x07));
	}
 }
 IwaveSetIvt();
 IwaveUmaskIrqs();
}
//#########################################################################
//
// FUNCTION: IwaveRegisterDMA
//
// PROFILE: This function initializes DMA structures defined by the
//          application for interrupt handling. Note that if the DMA request
//          sources have been combined and routed to either channel 1 or
//          channel 2, this function will select one of the structures to
//          serve as the interface.
//
//#########################################################################
void
IwaveRegisterDMA(DMA *dma1,DMA *dma2)
{
 DMA *dma_ptr;
 int dma_chan;
 BYTE i, udci;

 ENTER_CRITICAL;
 _poke(iw.igidxr,_IVERI);
 _poke(iw.i8dp,(BYTE)(_peek(iw.i8dp)|0x09));           /* enable access & reads */
 _poke(iw.p2xr+0x0F,(BYTE)(_peek(iw.p2xr+0x0F)&0xF8)); /* URCR[2:0]=0 */
 _poke(iw.p2xr,(BYTE)(_peek(iw.p2xr)&0xBF));           /* set UMCR[6]=0 */
 udci=_peek(iw.p2xr+0x0B);                             /* read UDCI */
 _poke(iw.i8dp,(BYTE)(_peek(iw.i8dp)&0xF6));           /* disable access & reads */
 LEAVE_CRITICAL;

 if(udci&0x40)                                 /* all sources to DMA chan 1 */
	{
	  if (dma1!=(DMA *)NULL)
			dma2=dma1;
	  else
			dma1=dma2;
	  iw.dma2_chan=iw.dma1_chan;
	}

 iw.dma1=dma1;
 iw.dma2=dma2;
 
//####################################################
//  Now initialize DMA structures if applicable.
//####################################################

 for (i=1; i<=2; i++)
 {
  if(i==1)
	 {
	  dma_chan = iw.dma1_chan;
	  dma_ptr = iw.dma1;
	 }
  else
	 {
	  dma_chan = iw.dma2_chan;
	  dma_ptr = iw.dma2;
	 }

  if (dma_ptr!=(DMA *)NULL)
	{
	 BYTE channel;
	 channel = dma_chan&0x03;
	 dma_ptr->flags=0x00;
	 dma_ptr->channel=dma_chan;
	 dma_ptr->enable = channel;
	 dma_ptr->disable= channel|DMA_SET_MASK;
	 dma_ptr->cur_mode=channel;
	 dma_ptr->write= channel|0x44;           /* upload mode */
	 dma_ptr->read=channel|0x48;             /* download mode */
	 dma_ptr->cur_control=0x00;

	 if (dma_chan < 3)
	  {
		 dma_ptr->single= DMA1_SNGL;
		 dma_ptr->mode = DMA1_MODE;
		 dma_ptr->clear_ff=DMA1_CLRFF;
	  }
	 else
	  {
		 dma_ptr->single= DMA2_SNGL;
		 dma_ptr->mode = DMA2_MODE;
		 dma_ptr->clear_ff=DMA2_CLRFF;
	  }

	 switch(dma_chan)
	 {
		case 0:
		dma_ptr->addr=DMA0_ADDR;
		dma_ptr->page=DMA0_PAGE;
		dma_ptr->count=DMA0_CNT;
		break;
		case 1:
		dma_ptr->addr=DMA1_ADDR;
		dma_ptr->page=DMA1_PAGE;
		dma_ptr->count=DMA1_CNT;
		break;
		case 2:
		dma_ptr->addr=DMA2_ADDR;
		dma_ptr->page=DMA2_PAGE;
		dma_ptr->count=DMA2_CNT;
		break;
		case 3:
		dma_ptr->addr=DMA3_ADDR;
		dma_ptr->page=DMA3_PAGE;
		dma_ptr->count=DMA3_CNT;
		break;
		case 4:
		dma_ptr->addr=DMA4_ADDR;
		dma_ptr->page=DMA4_PAGE;
		dma_ptr->count=DMA4_CNT;
		break;
		case 5:
		dma_ptr->addr=DMA5_ADDR;
		dma_ptr->page=DMA5_PAGE;
		dma_ptr->count=DMA5_CNT;
		break;
		case 6:
		dma_ptr->addr=DMA6_ADDR;
		dma_ptr->page=DMA6_PAGE;
		dma_ptr->count=DMA6_CNT;
		break;
		case 7:
		dma_ptr->addr=DMA7_ADDR;
		dma_ptr->page=DMA7_PAGE;
		dma_ptr->count=DMA7_CNT;
		break;
	 }
  }
 }
}
//#########################################################################
//
// FUNCTION: IwaveReset
//
// PROFILE: This function performs a full initialization of the InterWave.
//          All interrupts are cleared and voices are initialized to a
//          default value. The input to this function is the number of
//          voices to be initialized.
//
//#########################################################################
BOOL
IwaveReset(BYTE voices)
{
 BYTE v;

 if (voices<14||voices>32)
     return(FALSE);

 iw.voices=voices;
 IwaveMemPoke(0L,0x00);
 IwaveMemPoke(1L,0x00);

// IwaveGusReset();

// _poke(iw.p3xr,MIDI_RESET);                   /* Reset the MIDI port */
 
//####################################
//  Clear all interrupts
//####################################
 _poke(iw.igidxr,_LDMACI);                      /* select LDMACI */
 _poke(iw.i8dp,0x00);

 _poke(iw.igidxr,_UASBCI);                      /* select UASBCI */
 _poke(iw.i8dp,0x00);

// _poke(iw.igidxr,SAMPLE_CONTROL);             /* Not needed for IW */
// _poke(iw.i8dp,0x00);

//############################################
//  Set the number of active voices
//############################################
 _poke(iw.igidxr,SET_VOICES);                  /* select SAVI */
 _poke(iw.i8dp,(BYTE)((voices-1)|0xC0));

//############################################
// Clear interrupts on all voices
//#############################################

 (void)_peek(iw.p2xr+0x06);                      /* read from UISR */ 
 _poke(iw.igidxr,_LDMACI);                       /* select LDMACI */
 (void)_peek(iw.i8dp);
// _poke(iw.igidxr,SAMPLE_CONTROL);
// (void)_peek(iw.i8dp);
 _poke(iw.igidxr,_SVII);                        /* select SVII */ 
 (void)_peek(iw.i8dp);

 for (v=0; v<voices; v++)
   {
     _poke(iw.svsr,v);                          /* select voice */

     _poke(iw.igidxr,_SACI_WR);                 /* select SACI */
     _poke(iw.i8dp,VOICE_STOP|VOICE_STOPPED);

     _poke(iw.igidxr,_SVCI_WR);                 /* select SVCI */
     _poke(iw.i8dp,VOLUME_STOPPED|VOLUME_STOP);

//###############################################################
// Each voice specific register will be initialized
// here for the sake of completeness. Each application
// should set these registers as needed.
//###############################################################

     _poke(iw.igidxr,_SFCI_WR);           /* select SFCI */
     _pokew(iw.i16dp,0x0400);             /* default in IW */

     _poke(iw.igidxr,_SASHI_WR);          /* select SASHI */
     _pokew(iw.i16dp,0x0000);
     _poke(iw.igidxr,_SASLI_WR);             /* select SASLI */
     _pokew(iw.i16dp,0x0000);

     _poke(iw.igidxr,_SAEHI_WR);          /* select SAEHI */
     _pokew(iw.i16dp,0x0000);
     _poke(iw.igidxr,_SAELI_WR);          /* select SAELI */
     _pokew(iw.i16dp,0x0000);

     _poke(iw.igidxr,_SVRI_WR);           /* select SVRI */
     _poke(iw.i8dp,0x01);

     _poke(iw.igidxr,_SVSI_WR);           /* select SVSI */
     _poke(iw.i8dp,0x10);
     _poke(iw.igidxr,_SVEI_WR);           /* select SVEI */
     _poke(iw.i8dp,0xE0);

     _poke(iw.igidxr,_SVLI_WR);         /* select SVLI */
     _pokew(iw.i8dp,0x0000);

     _poke(iw.igidxr,_SAHI_WR);           /* select SAHI */
     _pokew(iw.i16dp,0x0000);
     _poke(iw.igidxr,_SALI_WR);           /* select SALI */
     _pokew(iw.i16dp,0x0000);

     _poke(iw.igidxr,_SROI_WR);           /* select SROI */
     _poke(iw.i8dp,0x07);
    }
    
 (void)_peek(iw.p2xr+0x06);               /* read from UISR */
 _poke(iw.igidxr,_LDMACI);                /* select LDMACI */
 (void)_peek(iw.i8dp);
 _poke(iw.igidxr,_SVII);               /* select SVII */ 
 (void)_peek(iw.i8dp);

 return(TRUE);
      
}
//#########################################################################
//
// FUNCTION: IwaveGusReset
//
// PROFILE: This function resets the InterWave to place it in GUS
//          mode. The following registers are affected as indicated:
//
//          1. SGMI[0]=0. GUS Compatible mode.
//          2. LDICI, LDMACI, UASRR, UASBCI, LMFSI are all reset.
//          3. URSTI[2:1], LMCI[1:0], UADR[7:5,1:0] are reset.
//
//          Also, interrupts associated with a write to UI2XCR,
//          with a write to UADR (UISR[4]) and all synthesizer
//          interrupts. 
//#########################################################################
void IwaveGusReset(void)
{
  _poke(iw.igidxr,_URSTI);       /* Pull reset */
  _poke(iw.i8dp,0x00);
  IwaveDelay(1);
  _poke(iw.i8dp,0x01);           /* Release reset */
  IwaveDelay(1); 
}
//#########################################################################
//
// FUNCTION: IwavePnpGetCfg
//
// PROFILE: This function reads the PnP registers of the InterWave card
//          with the specified CSN and fills the configuration members of
//          an variable "iw". This function is called at the start of
//          a InterWave sound application to query the InterWave IC for
//          configuration of I/O space, DMA and IRQ channels.
//
//          This function assumes that the card has been properly
//          configured and that it is in the configuration mode so that
//          its configuration registers can be read.
//
//#########################################################################
void IwavePnpGetCfg(void)
{
  WORD val;

//#########################################################################
// Read in the I/O space, DMA and IRQ configurations for the audio device.
//#########################################################################
  ENTER_CRITICAL;
  IwavePnpDevice(AUDIO);
  _poke(_PIDXR,0x60);                         /* select P2X0HI */
  val = ((WORD)_peek(iw.pnprdp))<<8;          /* get P2XR[9:8] */
  _poke(_PIDXR,0x61);                         /* select P2XRLI */
  iw.p2xr=val+(WORD)_peek(iw.pnprdp);         /* get P2XR[7:4] */

  _poke(_PIDXR,0x62);                         /* select P3X0HI */
  val = ((WORD)_peek(iw.pnprdp))<<8;          /* get P3XR[9:8] */
  _poke(_PIDXR,0x63);                         /* select P3X0LI */
  iw.p3xr=val+(WORD)_peek(iw.pnprdp);         /* get P3XR[7:3] */

  _poke(_PIDXR,0x64);                         /* select PHCAI */
  val = ((WORD)_peek(iw.pnprdp))<<8;          /* get PCODAR[9:8] */
  _poke(_PIDXR,0x65);                         /* select PLCAI */
  iw.pcodar=val+(WORD)_peek(iw.pnprdp);       /* get PCODAR[7:2] */

  _poke(_PIDXR,0x70);                         /* select PUI1SI */
  iw.synth_irq=(WORD)(_peek(iw.pnprdp)&0x0F); /* Synth IRQ number */

  _poke(_PIDXR,0x72);                         /* select PUI2SI */
  iw.midi_irq=(WORD)(_peek(iw.pnprdp)&0x0F);  /* MIDI IRQ number */

  _poke(_PIDXR,0x74);                         /* select PUD1SI */
  iw.dma1_chan=_peek(iw.pnprdp)&0x07;         /* DMA1 chan (LMC/Codec Rec) */

  _poke(_PIDXR,0x75);                         /* select PUD2SI */
  iw.dma2_chan=_peek(iw.pnprdp)&0x07;         /* DMA2 chan (codec play) */

//######################################################
// To get External Device resource configuration
// select the External Device.
//#######################################################

  IwavePnpDevice(EXT);                       /* select external device */
  _poke(_PIDXR,0x60);                        /* select PRAHI */
  val = ((WORD)_peek(iw.pnprdp))<<8;         /* get PCDRAR[9:8] */
  _poke(_PIDXR,0x61);                        /* select PRALI */
  iw.pcdrar=val+(WORD)_peek(iw.pnprdp);      /* get PCDRAR[7:4] */
  _poke(_PIDXR,0x62);                        /* select PATAHI */
  val = ((WORD)_peek(iw.pnprdp))<<8;         /* get PATAAR[9:8] */
  _poke(_PIDXR,0x63);                        /* select PATALI */
  iw.pataar=val+(WORD)_peek(iw.pnprdp);      /* get PATAAR[7:1] */

  _poke(_PIDXR,0x70);                        /* select PRISI */
  iw.ext_irq=(WORD)(_peek(iw.pnprdp)&0x0F);  /* Ext Dev IRQ number */

  _poke(_PIDXR,0x74);                        /* select PRDSI */
  iw.ext_chan=_peek(iw.pnprdp)&0x07;         /* Ext Dev DMA channel */

  IwavePnpDevice(MPU401);                    /* Select MPU401 Device */
  _poke(_PIDXR,0x60);                        /* select P401HI */
  val = ((WORD)_peek(iw.pnprdp))<<8;         /* get P401AR[9:8] */
  _poke(_PIDXR,0x61);                        /* select P401LI */
  iw.p401ar=val+(WORD)_peek(iw.pnprdp);      /* get P401AR[7:1] */

  _poke(_PIDXR,0x70);                        /* select PMISI */
  iw.mpu_irq=(WORD)(_peek(iw.pnprdp)&0x0F);  /* MPU401 Dev IRQ number */

  IwavePnpDevice(GAME);                      /* Select GAME logical Device */
	_poke(_PIDXR,0x60);                       /* select P201HI */
  val = ((WORD)_peek(iw.pnprdp))<<8;         /* get P201AR[9:8] */
  _poke(_PIDXR,0x61);                        /* select P201LI */
  iw.p201ar=val+(WORD)_peek(iw.pnprdp);      /* get P201AR[7:6] */

  IwavePnpDevice(EMULATION);                 /* Select SB and ADLIB Device */
  _poke(_PIDXR,0x60);                        /* select P388HI */
  val=((WORD)_peek(iw.pnprdp))<<8;           /* get P388AR[9:8] */
  _poke(_PIDXR,0x61);                        /* select P388LI */
  iw.p388ar=val+_peek(iw.pnprdp);            /* get P388AR[7:6] */
  _poke(_PIDXR,0x70);                        /* select PSBISI */
  iw.emul_irq=(WORD)(_peek(iw.pnprdp)&0x0F); /* emulation Dev IRQ number */
  LEAVE_CRITICAL;
}
//#########################################################################
//
// FUNCTION: IwavePnpSetCfg
//
// PROFILE: This function reads the configuration members of variable "iw"
//          and configures the I/O space, DMA and IRQ channels on the
//          InterWave accordingly. This function is called when an InterWave
//          sound application wishes to re-configure the InterWave hardware.
//
//          This function assumes that the PnP interface is in the
//          configuration state so that its configuration registers can be
//          programmed.
//
//#########################################################################
void IwavePnpSetCfg(void)
{
  ENTER_CRITICAL;
  IwavePnpDevice(AUDIO);                  /* select audio device */
  _poke(_PIDXR,0x60);                     /* select P2X0HI */
  _poke(_PNPWRP,(BYTE)(iw.p2xr>>8));      /* set P2XR[9:8] */
  _poke(_PIDXR,0x61);                     /* select P2X0LI */
  _poke(_PNPWRP,(BYTE)iw.p2xr);           /* set P2XR[7:4] */
														/* P2XR[3:0]=0   */
  _poke(_PIDXR,0x62);                     /* select P3X0HI */
  _poke(_PNPWRP,(BYTE)(iw.p3xr>>8));      /* set P3XR[9:8] */
  _poke(_PIDXR,0x63);                     /* select P3X0LI */
  _poke(_PNPWRP,(BYTE)(iw.p3xr));         /* set P3XR[7:3] */
														/* P3XR[2:0]=0   */
  _poke(_PIDXR,0x64);                     /* select PHCAI */
  _poke(_PNPWRP,(BYTE)(iw.pcodar>>8));    /* set PCODAR[9:8] */
  _poke(_PIDXR,0x65);                     /* select PLCAI */
  _poke(_PNPWRP,(BYTE)iw.pcodar);         /* set PCODAR[7:2] */

  _poke(_PIDXR,0x70);                      /* select PUI1SI */
  _poke(_PNPWRP,(BYTE)(iw.synth_irq&0x0F));/* Synth IRQ number */
  _poke(_PIDXR,0x72);                      /* select PUI2SI */
  _poke(_PNPWRP,(BYTE)(iw.midi_irq&0x0F)); /* MIDI IRQ number */

  _poke(_PIDXR,0x74);                      /* select PUD1SI */
  _poke(_PNPWRP,(BYTE)(iw.dma1_chan&0x07));/* DMA channel 1 */
  _poke(_PIDXR,0x75);                      /* select PUD2SI */
  _poke(_PNPWRP,(BYTE)(iw.dma2_chan&0x07));/* DMA channel 2 */

  IwavePnpDevice(EXT);
  _poke(_PIDXR,0x60);                     /* select PRAHI */
  _poke(_PNPWRP,(BYTE)(iw.pcdrar>>8));    /* set PCDRAR[9:8] */
  _poke(_PIDXR,0x61);                     /* select PRALI */
  _poke(_PNPWRP,(BYTE)iw.pcdrar);         /* set PCDRAR[7:3] */
														/* PCDRAR[2:0]=0 */
  _poke(_PIDXR,0x62);                     /* select PATAHI */
  _poke(_PNPWRP,(BYTE)(iw.pataar>>8));    /* set PATAAR[9:8] */
  _poke(_PIDXR,0x63);                     /* select PATALI */
  _poke(_PNPWRP,(BYTE)iw.pataar);         /* set PATAAR[7:1] */
														/* PATAAR[0]=0 */
  _poke(_PIDXR,0x70);                     /* select PRISI */
  _poke(_PNPWRP,(BYTE)(iw.ext_irq&0x0F)); /* Ext Dev IRQ number */
  _poke(_PIDXR,0x74);                     /* select PRDSI */
  _poke(_PNPWRP,(BYTE)(iw.ext_chan&0x07));/* Ext Dev DMA channel */

  IwavePnpDevice(GAME);
  _poke(_PIDXR,0x60);                     /* select P201HI */
  _poke(_PNPWRP,(BYTE)(iw.p201ar>>8));    /* set P201RAR[9:8] */
  _poke(_PIDXR,0x61);                     /* select P201LI */
  _poke(_PNPWRP,(BYTE)iw.p201ar);         /* set P201AR[7:6] */

  IwavePnpDevice(EMULATION);
  _poke(_PIDXR,0x60);                     /* select P388HI */
  _poke(_PNPWRP,(BYTE)(iw.p388ar>>8));    /* set P388AR[9:8] */
  _poke(_PIDXR,0x61);                     /* select P388LI */
  _poke(_PNPWRP,(BYTE)iw.p388ar);         /* set P388AR[7:6] */

  _poke(_PIDXR,0x70);                     /* select PSBISI */
  _poke(_PNPWRP,(BYTE)(iw.emul_irq&0x0F));/* emulation IRQ number */

  IwavePnpDevice(MPU401);
  _poke(_PIDXR,0x60);                     /* select P401HI */
  _poke(_PNPWRP,(BYTE)(iw.p401ar>>8));    /* set P401AR[9:8] */
  _poke(_PIDXR,0x61);                     /* select P401LI */
  _poke(_PNPWRP,(BYTE)iw.p401ar);         /* set P401AR[7:1] */

  _poke(_PIDXR,0x70);                     /* select PMISI */
  _poke(_PNPWRP,(BYTE)(iw.mpu_irq&0x0F)); /* MPU emulation IRQ number */
  LEAVE_CRITICAL;
}
//#########################################################################
//
// FUNCTION: IwaveCfgIOSpace
//
// PROFILE: This function reads the configuration members of variable "iw"
//          and configures the I/O space only.
//
//          This function assumes that the PnP interface is in the
//          configuration state so that its configuration registers can be
//          programmed.
//
//#########################################################################
void IwaveCfgIOSpace(void)
{
  ENTER_CRITICAL;
  IwavePnpDevice(AUDIO);                  /* select audio device */
  _poke(_PIDXR,0x60);                     /* select P2X0HI */
  _poke(_PNPWRP,(BYTE)(iw.p2xr>>8));      /* set P2XR[9:8] */
  _poke(_PIDXR,0x61);                     /* select P2X0LI */
  _poke(_PNPWRP,(BYTE)iw.p2xr);           /* set P2XR[7:4] */
														/* P2XR[3:0]=0   */
  _poke(_PIDXR,0x62);                     /* select P3X0HI */
  _poke(_PNPWRP,(BYTE)(iw.p3xr>>8));      /* set P3XR[9:8] */
  _poke(_PIDXR,0x63);                     /* select P3X0LI */
  _poke(_PNPWRP,(BYTE)(iw.p3xr));         /* set P3XR[7:3] */
														/* P3XR[2:0]=0   */
  _poke(_PIDXR,0x64);                     /* select PHCAI */
  _poke(_PNPWRP,(BYTE)(iw.pcodar>>8));    /* set PCODAR[9:8] */
  _poke(_PIDXR,0x65);                     /* select PLCAI */
  _poke(_PNPWRP,(BYTE)iw.pcodar);         /* set PCODAR[7:2] */
//
  IwavePnpDevice(EXT);
  _poke(_PIDXR,0x60);                     /* select PRAHI */
  _poke(_PNPWRP,(BYTE)(iw.pcdrar>>8));    /* set PCDRAR[9:8] */
  _poke(_PIDXR,0x61);                     /* select PRALI */
  _poke(_PNPWRP,(BYTE)iw.pcdrar);         /* set PCDRAR[7:3] */
														/* PCDRAR[2:0]=0 */
  _poke(_PIDXR,0x62);                     /* select PATAHI */
  _poke(_PNPWRP,(BYTE)(iw.pataar>>8));    /* set PATAAR[9:8] */
  _poke(_PIDXR,0x63);                     /* select PATALI */
  _poke(_PNPWRP,(BYTE)iw.pataar);         /* set PATAAR[7:1] */
														/* PATAAR[0]=0 */
  IwavePnpDevice(GAME);
  _poke(_PIDXR,0x60);                     /* select P201HI */
  _poke(_PNPWRP,(BYTE)(iw.p201ar>>8));    /* set P201RAR[9:8] */
  _poke(_PIDXR,0x61);                     /* select P201LI */
  _poke(_PNPWRP,(BYTE)iw.p201ar);         /* set P201AR[7:6] */

  IwavePnpDevice(EMULATION);
  _poke(_PIDXR,0x60);                     /* select P388HI */
  _poke(_PNPWRP,(BYTE)(iw.p388ar>>8));    /* set P388AR[9:8] */
  _poke(_PIDXR,0x61);                     /* select P388LI */
  _poke(_PNPWRP,(BYTE)iw.p388ar);         /* set P388AR[7:6] */

  IwavePnpDevice(MPU401);
  _poke(_PIDXR,0x60);                     /* select P401HI */
  _poke(_PNPWRP,(BYTE)(iw.p401ar>>8));    /* set P401AR[9:8] */
  _poke(_PIDXR,0x61);                     /* select P401LI */
  _poke(_PNPWRP,(BYTE)iw.p401ar);         /* set P401AR[7:1] */
  LEAVE_CRITICAL;
}
