⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 igs5050snd.c

📁 zinc60t22.tar.gz:zinc在tornado2.2.x下的补丁
💻 C
字号:
/* igs5050Snd.c - IGST 5050 Sound Support Module *//* Copyright 2000 - 2003 Wind River Systems, Inc. *//*modification history--------------------01g,18jun03,jlb  Updated to Tornado 2.201f,18oct01,jlb  Obtain PCI memory base from BSP (SPR 69996)01e,19jul01,msr  Added uglMemAccessCheck() call to test mem access.01d,14jun01,rfm  Added BSP API support for MIPS3201c,18dec00,jlb  Return ERROR when device already open01b,11sep00,jlb  Use soundcard.h verses sound.h01a,14mar00,jlb  written*//* DESCRIPTIONThis file provides the audio device driver for the IGS5050 graphics/audiodevice.  This driver is specifically written for the IGS5050 demonstrationboard developed by IGS Technologies, Inc.  It operates the audio processorin conjunction with the AC97 codec.   *//* includes */#include "vxWorks.h"#include "errno.h"#include "fcntl.h"#include "intLib.h"#include "ioLib.h"#include "iosLib.h"#include "iv.h"#include "logLib.h"#include "lstLib.h"#include "semLib.h"#include "stdlib.h"#include "string.h"#include "taskLib.h"#include "selectLib.h"#include "cacheLib.h"#include "sysLib.h"#include "drv/pci/pciConfigLib.h"#include "ugl/audio/soundcard.h"#include "ugl/driver/audio/igsAudio.h"#include "ugl/driver/audio/ac97.h"#include "ugl/ugl.h"#define INT_VEC_GET(irq)    (0x20 + irq)LOCAL int DrvNum;/* Forward declarations *//* Driver implementation functions */static int igsSndOpen (SND_DEV *pDev, char *fileName, int flags, int mode);static int igsSndClose (int devId);static int igsSndRead (int devId, char *buffer, int maxbytes);static int igsSndWrite (int devId, char *buffer, int nbytes);static int igsSndIoctl (int devId, int function, int arg);/* Interrupt handler */static void audioInterrupt (SND_DEV *pDev);/* Utility functions */int igsDspInit (SND_DEV *pDev);DSP_FD * igsDspOpen (SND_DEV *pDev);int igsMixerInit (SND_DEV *pDev);MIXER_FD * igsMixerOpen (SND_DEV *pDev);#ifdef USE_BSP_APIint igsAudioIsaRegBase;#endif/******************************************************************************* igsSndDevCreate - create the IGS audio driver device ** This routine creates the audio device for the IGS-5050. The inputs for* creation of the audio device are generic and is meant to cover all  audio* driver situations.  For this driver, all of the input parameters are not* used.  The following parameters are used:**\is*\i <devName>*   Provides the name of the device that is to be created.  The name must*   be in the format "/name", for example /sound.*\i <channel>*   The channel that is to be used on the audio processor.*\ie** RETURNS: OK when device successfully created; otherwise ERROR** ERRNO: N/A** SEE ALSO: */STATUS igsSndDevCreate     (    char *devName,              /* name of device */    int channel,                /* hardware channel to use */    int instance,               /* instance of the board */    int intLevel,               /* interrupt level (not used) */    int intVec,                 /* interrupt vector (not used - from PCI header) */    int dma8,                   /* DMA channel for 16 bit (not used) */    int dma16                   /* DMA channel for 8 bit (not used( */    )    {    SND_DEV *pDev;    DEV_HDR * pHdr;    char *pName;    UINT32 val;#ifdef USE_BSP_API    WINDML_DEVICE * pWindMLDev;#else    int busno, devno, funcno;    UINT32 baseAdrs;    UINT8 intLine;    int size;#endif    /* if device is already present, do not create again */    pHdr = iosDevFind (devName, &pName);    if ((pHdr != NULL) && (strcmp (devName, pHdr->name) == 0))        return (OK);#ifdef USE_BSP_API    if ((pWindMLDev = sysWindMLDevGet(WINDML_AUDIO_DEVICE, 0, VENDOR_PCI_TVIA, 				DEVICE_ID_TVIA_5050_AUDIO)) == UGL_NULL)	{	return(ERROR);	}    val = WINDML_IO_ENABLE | WINDML_MEM_ENABLE;    sysWindMLDevCtrl(pWindMLDev, WINDML_ACCESS_MODE_SET, &val);#else /* USE_BSP_API */    /* Locate the device on the PCI bus */    if (pciFindDevice (IGS_VENDOR_ID, IGS5000_DEVICE_ID, instance,                         &busno, &devno, &funcno) != OK)         return (ERROR);    /* Device found, obtain the base address and interrupt */    if (uglPCIAddressGet (busno, devno, funcno, PCI_CFG_BASE_ADDRESS_0,                          (char *)&baseAdrs, &size) != OK)        return (ERROR);    if (uglMemAccessCheck ("IGS-5050 Audio", (char *)baseAdrs, size) !=         UGL_STATUS_OK)        return (ERROR);    pciConfigInByte (busno, devno, funcno, PCI_CFG_DEV_INT_LINE,                         &intLine);#endif /* USE_BSP_API */    /* Get audio control structure */    pDev = (SND_DEV *)malloc (sizeof(SND_DEV));    bzero ((char *)pDev, sizeof(SND_DEV));#ifdef USE_BSP_API    /* Get the PCI base address */    sysWindMLDevCtrl(pWindMLDev, WINDML_PCI_MEMBASE_GET, &val);    pDev->pBaseIOAdrs = (UINT8 *)pWindMLDev->pPhysBaseAdrs0;    pDev->devSem = semBCreate (SEM_Q_FIFO, SEM_FULL);    pDev->intSem = semBCreate (SEM_Q_FIFO, SEM_FULL);    pDev->mode = O_RDONLY;    pDev->channel = channel;    pDev->pWindMLDev = pWindMLDev;    pDev->pciMembase = val;    igsAudioIsaRegBase = (int)pWindMLDev->pRegBase;    /* Enable Linear mode for PCI access */    igsOut(GR_INDEX, 0x33);    if ((igsIn(GR_DATA) & 8) == 0)	{	val = igsIn(GR_DATA) | 8;	igsOut(GR_DATA, val);	}#else /* USE_BSP_API */    pDev->pBaseIOAdrs = (UINT8 *)baseAdrs;    pDev->irq    = intLine;    pDev->devSem = semBCreate (SEM_Q_FIFO, SEM_FULL);    pDev->intSem = semBCreate (SEM_Q_FIFO, SEM_FULL);    pDev->mode = O_RDONLY;    pDev->channel = channel;    /* Enable Linear mode for PCI access */    igsOut(GR_INDEX, 0x33);    if ((igsIn(GR_DATA) & 8) == 0)	{	val = igsIn(GR_DATA) | 8;	igsOut(GR_DATA, val);	}#endif /* USE_BSP_API */    /* Install the driver */    DrvNum = iosDrvInstall (NULL, NULL, igsSndOpen, igsSndClose,                            igsSndRead, igsSndWrite, igsSndIoctl);    /* hook in select processing */    selWakeupListInit (&pDev->selList);    /* Initialize the DSP */    igsDspInit (pDev);    /* Initialize the mixer */    igsMixerInit (pDev);    if (iosDevAdd (&pDev->devHdr, devName, DrvNum) == ERROR)        {        free ((char *)pDev);        return(ERROR);        }    /* Disable interrupts */    sndIgsAddrEngIntDisable (pDev->pBaseIOAdrs);    sndIgsAudioOut32 (pDev->pBaseIOAdrs, AUDSTOP, 0xffffffff);    sndIgsAudioOut32 (pDev->pBaseIOAdrs, AINTEN, 0);    sndIgsAudioOut32 (pDev->pBaseIOAdrs, AINT0, 0xffffffff);#ifdef USE_BSP_API    sysWindMLIntConnect(pWindMLDev, audioInterrupt, (int)pDev);    sysWindMLIntEnable(pDev->pWindMLDev);#else /* USE_BSP_API */    /* Attach interrupt handler and enable interrupts */    intConnect (INUM_TO_IVEC (INT_VEC_GET (pDev->irq)), audioInterrupt,                 (int)pDev);    sysIntEnablePIC (pDev->irq);#endif /* USE_BSP_API */    return(OK);    }/******************************************************************************* igsSndOpen - open an IGS audio device ** This routine opens an audio device for the IGS-5050. The following* audio devices may be opened /xxxx/dsp and /xxxx/mixer.** RETURNS: device control structure when successfully opened; otherwise*       ERROR** ERRNO: N/A** SEE ALSO: */static int igsSndOpen     (    SND_DEV *pDev,              /* device control structure */     char *fileName,             /* sub-device to open */    int flags,                  /* open flags */    int mode                    /* open mode */    )    {    SND_FD *pSnd = (SND_FD *)ERROR;    /* wait for device to become available */    if (semTake (pDev->devSem, 30 * sysClkRateGet()))        errno = S_ioLib_DEVICE_ERROR;    else        {        if (strcmp (fileName, "/dsp") == 0)            {            /* open the DSP */            DSP_FD *pDsp;                pDsp = igsDspOpen (pDev);            if (pDsp != (DSP_FD *)ERROR)                {                pDev->pDsp = pDsp;                        pSnd = (SND_FD *)pDsp;                }            }        else if(strcmp (fileName, "/mixer") == 0)            {            /* open the mixer */            MIXER_FD *pMixer;                pMixer = igsMixerOpen (pDev);            if (pMixer != (MIXER_FD *)ERROR)                {                pDev->pMixer = pMixer;                        pSnd = (SND_FD *)pMixer;                }            }        else            errno = ENODEV;        }    semGive (pDev->devSem);    return ((int)pSnd);    }/******************************************************************************* igsSndClose - close an IGS audio device ** This routine closes an audio device for the IGS-5050.** RETURNS: OK when device closed; otherwise ERROR** ERRNO: N/A** SEE ALSO: */static int igsSndClose     (    int  devId                  /* device control structure */    )    {    SND_FD *pSnd = (SND_FD *)devId;    return(pSnd->fdClose (devId));    }/******************************************************************************* igsSndRead - read from an IGS audio device ** This routine reads from the audio device for the IGS-5050.** RETURNS: number of bytes read** ERRNO: N/A** SEE ALSO: */static int igsSndRead     (    int devId,              /* device control structure */    char *buffer,           /* location to store read data */    int maxbytes            /* number of bytes to read */    )    {    SND_FD *pSnd = (SND_FD *)devId;    if (pSnd->fdRead == NULL)        {        errno = S_ioLib_UNKNOWN_REQUEST;        return(ERROR);        }    else        return(pSnd->fdRead (devId, buffer, maxbytes));    }/******************************************************************************* igsSndWrite - write to an IGS audio device ** This routine writes to the audio device for the IGS-5050.** RETURNS: Number of bytes written** ERRNO: N/A** SEE ALSO: */static int igsSndWrite     (    int devId,              /* device control structure */    char *buffer,           /* location of data buffer */    int nbytes              /* number of bytes to output */    )    {    SND_FD *pSnd = (SND_FD *)devId;    if (pSnd->fdWrite == NULL)        {        errno = S_ioLib_UNKNOWN_REQUEST;        return(ERROR);        }    else        return(pSnd->fdWrite (devId, buffer, nbytes));    }/******************************************************************************* igsSndIoctl - handle IOCTL for an IGS audio device ** This routine handles ioctls to the audio device for the IGS-5050.** RETURNS: OK when operation was successful; otherwise ERROR** ERRNO: N/A** SEE ALSO: */static int igsSndIoctl     (    int devId,              /* device control structure */     int function,           /* function to perform */    int arg                 /* function argument */    )    {    SND_FD *pSnd = (SND_FD *)devId;    if (pSnd->fdIoctl == NULL)        {        errno = S_ioLib_UNKNOWN_REQUEST;        return(ERROR);        }    else        return(pSnd->fdIoctl (devId, function, arg));    }/******************************************************************************* audioInterrupt - audio interrupt handler ** This routine processes audio interrupts for the IGS-5050.** RETURNS: N/A** ERRNO: N/A** SEE ALSO: */static void audioInterrupt     (    SND_DEV *pDev               /* device control structure */    )    {    UINT8     GRIndex;    UINT8     GRData;    UINT32    aint0;     UINT32    misint0;    UINT32    cspf;    DSP_FD *pDsp = (DSP_FD *)pDev->pDsp;    /* Save the current GR index */    GRIndex  = igsIn(GR_INDEX);    /* Get interrupt status */    igsOut(GR_INDEX, 0x1A);    GRData   = igsIn(GR_DATA);    igsOut(GR_INDEX, GRIndex);    /* Is it audio specific interrupt? */    if (!(GRData & 0x04))        return;    /* yes, get the address interrupt status */    aint0 = sndIgsAudioIn32 (pDev->pBaseIOAdrs, AINT0);    /* get the miscellaneous interrupt & status and mask out the     * interrupt status bits       */      misint0  = sndIgsAudioIn32 (pDev->pBaseIOAdrs, MISCINT0);    misint0 &= 0x010000FF;    /* any interrupt pending? */    if (misint0 == 0)        return;    /* if address engine interrupt, then get current sample position */    if (misint0 & ADDRESS_IRQ) 	{        cspf = sndIgsAudioIn32 (pDev->pBaseIOAdrs, CSPF);	}    else        {        logMsg ("IGS interrupt ???? \n",0,0,0,0,0,0);        return;        }    /* identify buffer that was emptied and signal writer */    if (cspf & aint0)	{        pDsp->buf1Empty = TRUE;	}    else	{        pDsp->buf2Empty = TRUE;	}    /* Wakeup any pending task */    semGive (pDev->intSem);    selWakeupAll (&pDev->selList, SELWRITE);    /* If no buffer available, turn off output */    if ((pDsp->buf1Empty) && (pDsp->buf2Empty))        {        pDev->mode &= ~DSP_PLAY;        sndIgsAddrEngIntDisable (pDev->pBaseIOAdrs);        sndIgsAudioOut32 (pDev->pBaseIOAdrs, AUDSTOP, aint0);	sndIgsAudioOut32 (pDev->pBaseIOAdrs, AINTEN, ~aint0);	sndIgsAudioOut32 (pDev->pBaseIOAdrs, AINT0, aint0);        }    else        /* Reset interrupt */        sndIgsAudioOut32 (pDev->pBaseIOAdrs, AINT0, aint0);    /* Increment interrupt counter */    pDev->intCount++;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -