delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/01/29/22:28:47

From: Me <gmitch AT ime DOT net>
Newsgroups: comp.os.msdos.djgpp
Subject: Porting 16bit software for 32bit DJGPP
Date: Wed, 29 Jan 1997 17:04:17 -0800
Organization: Maine Medical Center
Lines: 902
Message-ID: <32EFF391.CB6@ime.net>
NNTP-Posting-Host: mitchg-home.mmc.org
Mime-Version: 1.0
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

This is a multi-part message in MIME format.

--------------7E1E274D67D
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Can someone please help me with porting this 16 bit program to compoile
and run with djgpp v2? Thanks in advance.

--------------7E1E274D67D
Content-Type: text/plain; charset=us-ascii; name="SNDSCAPE.C"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="SNDSCAPE.C"


/****************************************************************************
 ENSONIQ Soundscape Digital Audio Driver
 DOS Real-Mode Version
 Created 09/08/95, ENSONIQ Corp.
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <dos.h>
#include "sndscape.h"


/****************************************************************************
 EXTERNAL GLOBAL VARS - hardware config info ...
****************************************************************************/

WORD                  BasePort;     /* Gate Array/MPU-401 base port */
short                 MidiIrq;      /* the MPU-401 IRQ */
WORD                  WavePort;     /* the CODEC base port */
short                 WaveIrq;      /* the PCM IRQ */
short                 DmaChan;      /* the PCM DMA channel */


/****************************************************************************
 INTERNAL GLOBAL VARS - all kinds of stuff ...
****************************************************************************/

/* This var MUST be pre-initialized !!! */
BYTE                  Flags = 0x00; /* driver state flags */
#define FLAG_DETECTED 0x01
#define FLAG_OPENED   0x02
#define FLAG_CODECON  0x04

short                 Windx;        /* Wave IRQ index - for reg writes */
short                 Mindx;        /* MIDI IRQ index - for reg writes */

char       * volatile NextBuffer;   /* dynamic DMA A/B buffer pointer */
char                * DmaBuffP;     /* pointer to aligned dma buff */
DWORD                 DmaPaddr;     /* physical DMA address */
char                  DmaBuffer[BUFFERSIZE*2]; /* the dma buffer space */

#ifdef USE_CODEC_IRQ
void (interrupt * VecSav)();    /* int vector save area */
WORD                  PicBase;      /* the PIC base port */
short                 IrqMask;      /* IRQ mask value */
short                 IrqMaskSav;   /* save area for IRQ mask */
short                 Vector;       /* the Wave interrupt vector num */
#endif

short                 CdCfgSav;     /* gate array register save area */
short                 DmaCfgSav;    /* gate array register save area */
short                 IntCfgSav;    /* gate array register save area */

short                 DacSavL;      /* DAC left volume save */
short                 DacSavR;      /* DAC right volume save */
short                 CdxSavL;      /* CD/Aux left volume save */
short                 CdxSavR;      /* CD/Aux right volume save */

short const           SsIrqs[4] = { 9, 5, 7, 10 };  /* Soundscape IRQs */
short const           RsIrqs[4] = { 9, 7, 5, 15 };  /* an older IRQ set */
short const         * Irqs;         /* pointer to one of the IRQ sets */

DMAC_REGS       const DmacRegs[4] =
{                                   /* the DMAC regs for chans 0-3 ... */
    { 0x00, 0x01, 0x08, 0x0a, 0x0b, 0x0c, 0x87 },
    { 0x02, 0x03, 0x08, 0x0a, 0x0b, 0x0c, 0x83 },
    { 0x04, 0x05, 0x08, 0x0a, 0x0b, 0x0c, 0x81 },
    { 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0x82 }
};

DMAC_REGS const *     DmacRegP;     /* a pointer to a DMAC reg struct */


/****************************************************************************
 EXTERNAL DRIVER FUNCTIONS
****************************************************************************/

/*
  short DetectSoundscape(void);

  This function is used to detect the presence of a Soundscape card in a
  system. It will read the hardware config info from the SNDSCAPE.INI file,
  the path to which is indicated by the SNDSCAPE environment variable. This
  config info will be stored in global variable space for the other driver
  functions to reference. Once the config settings have been determined, a
  hardware test will be performed to see if the Soundscape card is actually
  present. If this function is not explicitly called by the application, it
  it will be called by the OpenSoundscape function.

  INPUTS:
    None

  RETURNS:
    0   - if Soundscape detection was successful
    -1  - if
        The SNDSCAPE environment variable was not found
        The SNDSCAPE.INI file cannot be opened
        The SNDSCAPE.INI file is missing information or is corrupted
        The Soundscape hardware is not detected
*/

short DetectSoundscape(void)
{
    char static   str[78];
    short         tmp, status;
    char          *ep;
    FILE          *fp;

    /* default status to failure */
    status = -1;

    /* initialize some local vars ... */
    fp = 0;

    /* get the environment var and build the filename; then open it */
    if( (ep = getenv("SNDSCAPE")) == NULL )
        goto exit;

    strcpy(str, ep);
    if( str[strlen(str) - 1] == '\\' )
        str[strlen(str) - 1] = '\0';
    strcat(str, "\\SNDSCAPE.INI");
    if( (fp = fopen(str, "r")) == NULL )
        goto exit;

    /* read all of the necessary config info ... */
    if( GetConfigEntry(str, "Product", fp) )
        goto exit;

    /* if an old product name is read, set the IRQs accordingly */
    strupr(str);
    if( !strstr(str, "SOUNDFX") && !strstr(str, "MEDIA_FX") )
        Irqs = SsIrqs;
    else
        Irqs = RsIrqs;

    if( GetConfigEntry(str, "Port", fp) )
        goto exit;
    BasePort = (WORD) strtol(str, NULL, 16);

    if( GetConfigEntry(str, "WavePort", fp) )
        goto exit;
    WavePort = (WORD) strtol(str, NULL, 16);

    if( GetConfigEntry(str, "IRQ", fp) )
        goto exit;
    MidiIrq = (short) strtol(str, NULL, 10);
    if( MidiIrq == 2)
        MidiIrq = 9;

    if( GetConfigEntry(str, "SBIRQ", fp) )
        goto exit;
    WaveIrq = (short) strtol(str, NULL, 10);
    if( WaveIrq == 2 )
        WaveIrq = 9;

    if( GetConfigEntry(str, "DMA", fp) )
        goto exit;
    DmaChan = (short) strtol(str, NULL, 10);

    /* see if Soundscape is there by reading HW ... */
    if( (inp(BasePort + GA_HOSTCTL_OFF) & 0x78) != 0x00 )
        goto exit;
    if( (inp(BasePort + GA_ADDR_OFF) & 0xf0) == 0xf0 )
        goto exit;

    outp(BasePort + GA_ADDR_OFF, 0xf5);
    tmp = inp(BasePort + GA_ADDR_OFF);
    if( (tmp & 0xf0) == 0xf0)
        goto exit;
    if( (tmp & 0x0f) != 0x05)
        goto exit;

    /* now do a quick check to make sure the CoDec is there too */
    if( (inp(WavePort) & 0x80) != 0x00 )
        goto exit;

    /* flag success !!! */
    status = 0;
    Flags |= FLAG_DETECTED;
exit:
    if( fp != NULL )
        fclose(fp);

    return status;
}


/*
  short OpenSoundscape(void);

  This function opens the Soundscape driver. It will setup the Soundscape
  hardware for Native PCM mode (the default mode is Sound Blaster emulation).
  It will first call the DetectSoundscape function it it determines that it
  has not already been called.

  INPUTS:
    None.

  RETURNS:
    0   - if successful
    -1  - if the DetectSoundscape function needed to be called and
          returned unnsuccessful
*/

short OpenSoundscape(void)
{
    /* already opened? if so, success */
    if( Flags & FLAG_OPENED )
        return 0;

    /* see if we need to detect first */
    if( !(Flags & FLAG_DETECTED) )
        if( DetectSoundscape() != 0 )
            return -1;

    /* Clear possible CODEC and SoundBlaster emulation interrupts */
    outp(WavePort + CD_STATUS_OFF, 0x00);
    inp(0x22e);

#ifdef USE_CODEC_IRQ
    /* install the interrupt vector */
    Vector = (WaveIrq < 8 ? 0x08 : 0x70) + (WaveIrq & 0x07);
    VecSav = _dos_getvect(Vector);
    _dos_setvect(Vector, WaveIsr);

    /* enable the CODEC interrupt pin */
    CdWrite(CD_PINCTL_REG, CdRead(CD_PINCTL_REG) | 0x02);

    /* Setup PIC/IRQ vars, unmask our IRQ */
    PicBase = WaveIrq < 8 ? 0x20 : 0xa0;
    IrqMask = 1 << (WaveIrq & 0x07);
    IrqMaskSav = inp(PicBase + 1) & IrqMask;
    outp(PicBase + 1, inp(PicBase + 1) & ~IrqMask);
#else
    /* disable the CODEC interrupt pin */
    CdWrite(CD_PINCTL_REG, CdRead(CD_PINCTL_REG) & 0xfd);
#endif

    /* Align the DMA buffer within the allocated space */
    DmaBuffP = DmaBuffer;
    DmaPaddr = (DWORD) (char *) DmaBuffer;
    DmaPaddr = ((DmaPaddr >> 12) & 0x000ffff0) + (WORD) DmaPaddr;
    if( DmaPaddr >> 16 != (DmaPaddr + BUFFERSIZE-1) >> 16 )
    {
        DmaPaddr += BUFFERSIZE;
        DmaBuffP += BUFFERSIZE;
    }

    /* Set DMA controller register set pointer based on channel */
    DmacRegP = &DmacRegs[DmaChan];

    /* Save some regs, do some resource re-routing */
    /* derive the MIDI and Wave IRQ indices (0-3) for reg writes */
    for( Mindx = 0; Mindx < 4; ++Mindx )
        if( MidiIrq == *(Irqs + Mindx) )
            break;
    for( Windx = 0; Windx < 4; ++Windx )
        if( WaveIrq == *(Irqs + Windx) )
            break;

    /* setup the CoDec DMA polarity */
    GaWrite(GA_DMACFG_REG, 0x50);

    /* give the CoDec control of the DMA and Wave IRQ resources */
    CdCfgSav = GaRead(GA_CDCFG_REG);
    GaWrite(GA_CDCFG_REG, 0x89 | (DmaChan << 4) | (Windx << 1));
    
    /* pull the Sound Blaster emulation off of those resources */
    DmaCfgSav = GaRead(GA_DMAB_REG);
    GaWrite(GA_DMAB_REG, 0x20);
    IntCfgSav = GaRead(GA_INTCFG_REG);
    GaWrite(GA_INTCFG_REG, 0xf0 | (Mindx << 2) | Mindx);

    /* Save all volumes that we might use, init some levels */
    DacSavL = CdRead(CD_DACL_REG);
    DacSavR = CdRead(CD_DACR_REG);
    CdxSavL = CdRead(CD_CDAUXL_REG);
    CdxSavR = CdRead(CD_CDAUXL_REG);

    /* Init the DAC volume to ... full */
    SetDacVol(127, 127);

    /* Put the CoDec into mode change state */
    outp(WavePort + CD_ADDR_OFF, 0x40);

    /* Setup CoDec mode - single DMA chan, AutoCal on */
    CdWrite(CD_CONFIG_REG, 0x0c);

    /* exit mode change state */
    outp(WavePort + CD_ADDR_OFF, 0x00);

    /* flag open status and return */
    Flags |= FLAG_OPENED;

    return 0;
}


/*
  short StartCoDec(WORD srate, BOOL stereo, BOOL size16bit);

  This function will start the CoDec auto-restart DMA process.

  INPUTS:
    srate      - the audio sample rate in Hertz
    stereo     - FALSE for mono data, TRUE for L/R interleaved stereo data
    size16bit  - FALSE for 8-bit unsigned data, TRUE for 16-bit signed data

  RETURNS:
    0          - if the CoDec was started successfully
    -1         - if the driver has not been opened or if the sample rate
                 is unacceptable
*/

short StartCoDec(WORD srate, BOOL stereo, BOOL size16bit)
{
    DWORD        i;
    WORD         tmp;

    /* if the driver is not open, fail */
    if( !(Flags & FLAG_OPENED) )
        return -1;

    /* make sure the CODEC is not already running */
    if( Flags & FLAG_CODECON )
        StopCoDec();

    /* set format .... */
    /* init the format register value */
    tmp = 0;

    /* find the sample rate */
    switch(srate)
    {
        case 8000U:
            tmp = 0x00;
            break;
        case 11025U:
            tmp = 0x03;
            break;
        case 16000U:
            tmp = 0x02;
            break;
        case 22050U:
            tmp = 0x07;
            break;
        case 32000U:
            tmp = 0x06;
            break;
        case 44100U:
            tmp = 0x0b;
            break;
        case 48000U:
            tmp = 0x0c;
            break;
        default:
            return -1;
    }

    /* set other format bits ... */
    if( stereo == TRUE )
        tmp |= 0x10;
    if( size16bit == TRUE )
        tmp |= 0x40;

    /* put the the CoDec in mode change state */
    outp(WavePort + CD_ADDR_OFF, 0x40);

    /* and write the format register */
    CdWrite(CD_FORMAT_REG, tmp);

    /* delay for internal re-synch */
    for( i = 0; i < 200000UL; ++i )
        inp(BasePort + GA_ADDR_OFF);

    /* exit mode change state */
    outp(WavePort + CD_ADDR_OFF, 0x00);

    /* pre-fill the audio buffer with silence */
    tmp = size16bit == TRUE ? 0x00 : 0x80;
    for( i = 0; i < BUFFERSIZE; ++i )
        *(DmaBuffP + i) = (char) tmp;

    /* init the "next-buffer" ptr */
    NextBuffer = NULL;

#ifdef USE_CODEC_IRQ
    /* Write CODEC interrupt count - sample frames per half-buffer (n-1). */
    tmp = BUFFERSIZE/2;
    if( stereo == TRUE )
        tmp >>= 1;
    if( size16bit == TRUE )
        tmp >>= 1;
    CdWrite(CD_LCOUNT_REG, (tmp - 1));
    CdWrite(CD_UCOUNT_REG, ((tmp - 1) >> 8));
#endif

    /* Setup the PC DMA Controller */
    outp(DmacRegP->mask, 0x04 | DmaChan);
    outp(DmacRegP->mode, DMAC_AUTO_OUT | DmaChan);
    outp(DmacRegP->page, (int) (DmaPaddr >> 16));

    /* Disable around 2-byte programming sequences */
    _disable();
    outp(DmacRegP->clrff, 0x00);
    outp(DmacRegP->addr, (int) DmaPaddr);
    outp(DmacRegP->addr, (int) DmaPaddr >> 8);
    outp(DmacRegP->count, BUFFERSIZE - 1);
    outp(DmacRegP->count, (BUFFERSIZE - 1) >> 8);
    _enable();

    /* clear status, unmask the PC DMA Controller */
    inp(DmacRegP->status);
    outp(DmacRegP->mask, DmaChan);

    /* disable mode change state and start the CoDec */
    outp(WavePort + CD_ADDR_OFF, 0x00);
    CdWrite(CD_CONFIG_REG, 0x01);

    /* flag CODEC-on status and return */
    Flags |= FLAG_CODECON;

    return 0;
}


/*
  char *GetNextBuffer(void);

  This function is used by the application, normally in a polling fashion,
  to get a pointer to the next buffer half to be filled/stored.

  INPUTS:
    None

  RETURNS:
    0      - if the CoDec is not ready for audio data / has no audio data
    non-0  - a pointer to a BUFFERSIZE/2 byte buffer will be returned if
         the CoDec is ready for data / just filled a buffer
*/

char *GetNextBuffer(void)
{
    BYTE    *p;

#ifdef USE_CODEC_IRQ

    if( (p = NextBuffer) != NULL )
        NextBuffer = NULL;

    return p;
#else
    if( GetDmaCount() < BUFFERSIZE/2 )
        p = DmaBuffer;
    else
        p = DmaBuffer + BUFFERSIZE/2;

    if( p == (BYTE)NextBuffer )
        return NULL;

    NextBuffer = p;
    return p;
#endif
}


/*
  void PauseCoDec(void);

  This function will pause the CoDec auto-restart DMA process.
  Don't use this to stop the CoDec - use the StopCoDec function to do
  that; it will cleanup DRQs.

  INPUTS:
    None

  RETURNS:
    Nothing
*/

void PauseCoDec()
{
    CdWrite(CD_CONFIG_REG, CdRead(CD_CONFIG_REG) & 0xfc);
    return;
}


/*
  void ResumeCoDec(void);

  This function will pause the CoDec auto-restart DMA process.

  INPUTS:
    None

  RETURNS:
    Nothing
*/

void ResumeCoDec(void)
{
    CdWrite(CD_CONFIG_REG, 0x01);
    return;
}


/*
  void StopCoDec(void);

  This function will stop the CoDec auto-restart DMA process.

  INPUTS:
    None

  RETURNS:
    Nothing
*/

void StopCoDec(void)
{
    WORD   i;

    CdWrite(CD_CONFIG_REG, CdRead(CD_CONFIG_REG) & 0xfc);

    /* Let the CoDec receive its last DACK(s). The DMAC must not be */
    /* masked while the CoDec has DRQs pending. */
    for( i = 0; i < 64; ++i )
        if( !(inp(DmacRegP->status) & (0x10 << DmaChan)) )
            break;

#ifdef USE_CODEC_IRQ
    ;
#else
    /* clear internal CODEC interrupt status */
    outp(WavePort + CD_STATUS_OFF, 0x00);
#endif

    /* unflag CODEC-on status and return */
    Flags &= ~FLAG_CODECON;

    return;
}


/*
  void CloseSoundscape(void);

  This function will make sure the CoDec is stopped, return the Soundscape
  hardware to it's default Sound Blaster emulation mode, de-install the PCM
  interrupt, resore the PIC mask, and do other cleanup.

  INPUTS:
    None

  RETURNS:
    None
*/

void CloseSoundscape(void)
{
    /* if we're not open, just return */
    if( !(Flags & FLAG_OPENED) )
        return;

    /* if the CoDec is running, stop it */
    if( Flags & FLAG_CODECON )
        StopCoDec();

    /* mask the PC DMA Controller */
    outp(DmacRegP->mask, 0x04 | DmaChan);

    /* restore all volumes ... */
    CdWrite(CD_DACL_REG, DacSavL);
    CdWrite(CD_DACR_REG, DacSavR);
    CdWrite(CD_CDAUXL_REG, CdxSavL);
    CdWrite(CD_CDAUXL_REG, CdxSavR);

    /* if necessary, restore gate array resource registers */
    GaWrite(GA_INTCFG_REG, IntCfgSav);
    GaWrite(GA_DMAB_REG, DmaCfgSav);
    GaWrite(GA_CDCFG_REG, CdCfgSav);

#ifdef USE_CODEC_IRQ
    /* disable the CoDec interrupt pin */
    CdWrite(CD_PINCTL_REG, CdRead(CD_PINCTL_REG) & 0xfd);

    /* restore pic mask state */
    outp(PicBase + 1, inp(PicBase + 1) | IrqMaskSav);

    /* restore the interrupt vector */
    _dos_setvect(Vector, VecSav);
#endif

    /* unflag open status and return */
    Flags &= ~FLAG_OPENED;

    return;
}


/*
  void SetDacVol(short lvol, short rvol);

  This function sets the left and right DAC output level in the CoDec.

  INPUTS:
    lvol  - left volume, 0-127
    rvol  - right volume, 0-127

  RETURNS:
    Nothing

*/

void SetDacVol(short lvol, short rvol)
{
    CdWrite(CD_DACL_REG, (~lvol & 0x7f) >> 1);
    CdWrite(CD_DACR_REG, (~rvol & 0x7f) >> 1);
    return;
}


/*
  void SetCdRomVol(short lvol, short rvol);

  This function sets the left and right CD-ROM output level in the CoDec.

  INPUTS:
    lvol  - left volume, 0-127
    rvol  - right volume, 0-127

  RETURNS:
    Nothing

*/

void SetCdRomVol(short lvol, short rvol)
{
    CdWrite(CD_CDAUXL_REG, (~lvol & 0x7f) >> 2);
    CdWrite(CD_CDAUXR_REG, (~rvol & 0x7f) >> 2);
    return;
}


/*
  WORD GetDmaCount(void);

  This function returns the DMA controller count value for the
  CoDec DMA channel.

  INPUTS:
    None.

  RETURNS:
    16-bit DMA count value, ffffh to 0000h.
*/

WORD GetDmaCount(void)
{
    WORD     count0, count1;

    _disable();
    outp(DmacRegP->clrff, 0x00);
    count0 = inp(DmacRegP->count);
    count0 |= inp(DmacRegP->count) << 8;
    count1 = inp(DmacRegP->count);
    count1 |= inp(DmacRegP->count) << 8;
    _enable();

    if( (BYTE) count1 != (BYTE) count0 )
        return count1;
    else
        return count0;
}


/****************************************************************************
 INTERNAL DRIVER FUNCTIONS
****************************************************************************/


/*
  short GaRead(WORD rnum);

  This function is used to read the indirect addressed registers in the
  Ensoniq Soundscape gate array.

  INPUTS:
    rnum  - the numner of the indirect register to be read

  RETURNS:
    the contents of the indirect register are returned

*/

short GaRead(WORD rnum)
{
    outp(BasePort + GA_ADDR_OFF, rnum);
    return inp(BasePort + GA_DATA_OFF);
}


/*
  short GaWrite(WORD rnum, short value);

  This function is used to write the indirect addressed registers in the
  Ensoniq Soundscape gate array.

  INPUTS:
    rnum   - the numner of the indirect register to be read
    value  - the byte value to be written to the indirect register

  RETURNS:
    Nothing
*/

void GaWrite(WORD rnum, short value)
{
    outp(BasePort + GA_ADDR_OFF, rnum);
    outp(BasePort + GA_DATA_OFF, value);
    return;
}


/*
  short CdRead(WORD rnum);

  This function is used to read the indirect addressed registers in the
  AD-1848 or compatible CODEC. It will preserve the special function bits
  in the upper-nibble of the indirect address register.

  INPUTS:
    rnum  - the numner of the indirect register to be read

  RETURNS:
    the contents of the indirect register are returned

*/

short CdRead(WORD rnum)
{
    outp(WavePort + CD_ADDR_OFF,
        (inp(WavePort + CD_ADDR_OFF) & 0xf0) | rnum);
    return inp(WavePort + CD_DATA_OFF);
}


/*
  short CdWrite(WORD rnum, short value);

  This function is used to write the indirect addressed registers in the
  AD-1848 or compatible CODEC. It will preserve the special function bits
  in the upper-nibble of the indirect address register.

  INPUTS:
    rnum   - the numner of the indirect register to be read
    value  - the byte value to be written to the indirect register

  RETURNS:
    Nothing
*/

void CdWrite(WORD rnum, short value)
{
    outp(WavePort + CD_ADDR_OFF,
        (inp(WavePort + CD_ADDR_OFF) & 0xf0) | rnum);
    outp(WavePort + CD_DATA_OFF, value);

    return;
}


/*
  short GetConfigEntry(char *dest, char *entry, FILE *fp);

  This function parses a file (SNDSCAPE.INI) for a left-hand string and,
  if found, writes its associated right-hand value to a destination buffer.
  This function is case-insensitive.

  INPUTS:
    fp  - a file pointer to the open SNDSCAPE.INI config file
    dst - the destination buffer pointer
    lhp - a pointer to the right-hand string

  RETURNS:
    0   - if successful
    -1  - if the right-hand string is not found or has no equate
*/

short GetConfigEntry(char *dest, char *entry, FILE *fp)
{
    char     static str[83];
    char     static tokstr[33];
    char    *p;

    /* make a local copy of the entry, upper-case it */
    strcpy(tokstr, entry);
    strupr(tokstr);

    /* rewind the file and try to find it ... */
    rewind(fp);
    for( ;; )
    {
        /* get the next string from the file */
        fgets(str, 83, fp);
        if( feof(fp) )
            return -1;

        /* properly terminate the string */
        for( p = str; *p != '\0'; ++p )
        {
            if( *p == ' ' || *p == '\t' || *p == 0x0a || *p == 0x0d )
            {
                *p = '\0';
                break;
            }
        }

        /* see if it's an 'equate' string; if so, zero the '=' */
        if( !(p = strchr(str, '=')) )
            continue;
        *p = '\0';

        /* upper-case the current string and test it */
        strupr(str);
        if( strcmp(str, tokstr) )
            continue;

        /* it's our string - copy the right-hand value to buffer */
        for( p = str + strlen(str) + 1; (*dest++ = *p++) != '\0'; )
            ;
        break;
    }

    return 0;
}


#ifdef USE_CODEC_IRQ
/*
  The Wave ISR

  This ISR sets the global next-buffer pointer based on the DMA controller
  count at the time of the interrupt.
*/

void interrupt WaveIsr()
{
    /* verify PIC in-service reg for IRQs 7 and 15 */
    if( (WaveIrq & 0x07) == 0x07 )
    {
        outp(PicBase, 0x0b);
        inp(PicBase);
        if( !(inp(PicBase) & 0x80) )
            return;
    }

    /* if the CoDec is interrupting ... */
    if( inp(WavePort + CD_STATUS_OFF) & 0x01 )
    {

        /* set the next-buffer to the next buffer half to fill */
        if( GetDmaCount() < BUFFERSIZE/2 )
            NextBuffer = DmaBuffer;
        else
            NextBuffer = DmaBuffer + BUFFERSIZE/2;

        /* clear the CODEC interrupt */
        outp(WavePort + CD_STATUS_OFF, 0x00);
    }

    /* clear the PC interrupt controller */
    if(WaveIrq >= 8)
        outp(0xa0, 0x20);
    outp(0x20, 0x20);

    return;
}
#endif


--------------7E1E274D67D--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019