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

📄 pciiomaplib.c

📁 vxworks for Sam2410 bsp NoNet
💻 C
📖 第 1 页 / 共 3 页
字号:
**/STATUS pciIomapLibInit    (    int mechanism,	/* configuration mechanism: 1, 2 or 3 */    int addr0,		/* config-addr-reg / CSE-reg */    int addr1,		/* config-data-reg / Forward-reg */    int addr2		/* none            / Base-address */    )    {    int ix;    if (pciLibInitStatus != NONE)	return (pciLibInitStatus);    switch (mechanism)	{	case PCI_MECHANISM_1:	case PCI_MECHANISM_2:	case PCI_MECHANISM_3:	    pciConfigMech	= mechanism;	    pciConfigAddr0	= addr0;	    pciConfigAddr1	= addr1;	    pciConfigAddr2	= addr2;	    pciLibInitStatus	= OK;	    break;	default:    	    pciLibInitStatus	= ERROR;	    break;	}    for (ix = 0; ix < PCI_IRQ_LINES; ix++)        dllInit (&pciIntList[ix]);    return (pciLibInitStatus);    }/********************************************************************************* pciFindDevice - find the nth device with the given device & vendor ID** This routine finds the nth device with the given device & vendor ID.** RETURNS: OK or ERROR if the deviceId and vendorId didn't match.**/STATUS pciFindDevice    (    int    vendorId,	/* vendor ID */    int    deviceId,	/* device ID */    int    index,	/* desired instance of device */    int *  pBusNo,	/* bus number */    int *  pDeviceNo,	/* device number */    int *  pFuncNo	/* function number */    )    {    STATUS status = ERROR;    BOOL   cont   = TRUE;    int    busNo;    int    deviceNo;    int    funcNo;    UINT16 device;    UINT16 vendor;    UINT8  header;    UINT32 devClass;    int    is_a_multi_function_device = 0;    if (pciLibInitStatus != OK)        cont = FALSE;    for (busNo = 0; cont == TRUE && busNo < PCI_MAX_BUS; busNo++)        for (deviceNo = 0; cont == TRUE && deviceNo < 31; ++deviceNo)	    {	    is_a_multi_function_device = 0;            for (funcNo = 0; cont == TRUE && funcNo < PCI_MAX_FUNC; funcNo++)		{		if ( (funcNo != 0) && !is_a_multi_function_device)		   continue;		pciConfigInWord (busNo, deviceNo, funcNo, PCI_CFG_VENDOR_ID,				 (short *) &vendor);		/* If nonexistent device, skip to next (PCI_NOTFITTED)*/		if (vendor == 0xFFFF)		    break;		pciConfigInByte(busNo, deviceNo, funcNo, PCI_CFG_HEADER_TYPE,				&header);		if (funcNo == 0)		    {		    is_a_multi_function_device = ((header & 0x80) != 0);		    }		pciConfigInWord(busNo, deviceNo, funcNo, PCI_CFG_DEVICE_ID,				(short *) &device);		if ((vendor == (UINT16)vendorId) &&		    (device == (UINT16)deviceId) &&		    (index-- == 0))		    {		      pciConfigInLong (busNo, deviceNo, funcNo,		      		       PCI_CFG_REVISION, (int *) &devClass);		      devClass = (devClass & 0xFFFFFF00) >> 8;		      if ( (devClass >> 16) == 0x06) {			/* BRIDGE... */		      }		    *pBusNo	= busNo;		    *pDeviceNo	= deviceNo;		    *pFuncNo	= funcNo;		    status	= OK;		    /* terminate all loops */		    cont	= FALSE;		    continue;		    }		}	    }    return (status);    }/********************************************************************************* pciFindClass - find the nth occurence of a device by PCI class code.** This routine finds the nth device with the given 24-bit PCI class code* (class subclass prog_if).** RETURNS: OK or ERROR if the class didn't match.**/STATUS pciFindClass    (    int    classCode,	/* 24-bit class code */    int	   index,	/* desired instance of device */    int *  pBusNo,	/* bus number */    int *  pDeviceNo,	/* device number */    int *  pFuncNo	/* function number */    )    {    STATUS status = ERROR;    BOOL   cont   = TRUE;    int    busNo;    int    deviceNo;    int    funcNo;    int    classCodeReg;    char   header;    if (pciLibInitStatus != OK)        cont = FALSE;    for (busNo = 0; cont == TRUE && busNo < PCI_MAX_BUS; busNo++)        for (deviceNo = 0;	     cont == TRUE && deviceNo < ((busNo == 0) ? PCI_MAX_DEV : 16);	     ++deviceNo)            for (funcNo = 0; cont == TRUE && funcNo < PCI_MAX_FUNC; funcNo++)		{#if (PCI_MAX_DEV > 31) && (PCI_MAX_FUNC > 7)		/* avoid a special bus cycle */		if ((deviceNo == 0x1f) && (funcNo == 0x07))		    continue;#endif		pciConfigInLong (busNo, deviceNo, funcNo, PCI_CFG_REVISION,				 &classCodeReg);		/* If nonexistent device, skip to next */		if (((UINT32)classCodeReg == 0xFFFFFFFF) && (funcNo == 0))		    break;		if ((((classCodeReg >> 8) & 0x00ffffff) == classCode) &&		    (index-- == 0))		    {		    *pBusNo	= busNo;		    *pDeviceNo	= deviceNo;		    *pFuncNo	= funcNo;		    status	= OK;		    /* terminate all loops */		    cont 	= FALSE;		    continue;		    }		/* goto next if current device is single function */		pciConfigInByte (busNo, deviceNo, funcNo, PCI_CFG_HEADER_TYPE,				 &header);		if ((header & PCI_HEADER_MULTI_FUNC) != PCI_HEADER_MULTI_FUNC &&		    funcNo == 0)		    break;		}    return (status);    }/******************************************************************************** pciDevConfig - configure a device on a PCI bus** This routine configures a device that is on a Peripheral Component* Interconnect (PCI) bus by writing to the configuration header of the* selected device.* It first disables the device by clearing the command register in the* configuration header.  It then sets the I/O and/or memory space base* address registers, the latency timer value and the cache line size.* Finally, it re-enables the device by loading the command register with* the specified command.** NOTE: This routine is designed for Type 0 PCI Configuration Headers ONLY.*       It is NOT usable for configuring, for example, a PCI-to-PCI bridge.** RETURNS: OK always.*/STATUS pciDevConfig    (    int		pciBusNo,		/* PCI bus number */    int		pciDevNo,		/* PCI device number */    int		pciFuncNo,		/* PCI function number */    ULONG       devIoBaseAdrs,          /* device IO base address */    ULONG       devMemBaseAdrs,         /* device memory base address */    ULONG       command                 /* command to issue */    )    {    INT32       ix;    UINT32      tmp32;    /*     * Disable device by clearing its command register field in its     * configuration header.     */    pciConfigOutWord (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_COMMAND, 0);    /*     *  Due to system constraints, this is a partial implementation     *  of enabling the Base Address Registers (BARs).     *  It is hoped that all PCI devices only require at most one     *  I/O space and/or one memory space.     *  If not, this code will re-allocate the device's memory to     *  each BAR implemented.  Sounds like future trouble!     */    for (ix = PCI_CFG_BASE_ADDRESS_0; ix <= PCI_CFG_BASE_ADDRESS_5; ix+=4)        {        /* Write all f's and read back value */        pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo, ix, 0xffffffff);        pciConfigInLong  (pciBusNo, pciDevNo, pciFuncNo, ix, (int *) &tmp32);        /* BAR implemented? */        if (tmp32 == 0)           {           /*            * No! According to the spec, BARs must be implemented            * in sequence starting at BAR 0.  So, all done.            */           break;           }        if (tmp32 & 0x1)	   {	   /* I/O space requested, set specified I/O space base address */           pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo, ix,			     devIoBaseAdrs | 0x1);	   }        else           {	   /* Memory space required, set specified base address */           pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo, ix,			     devMemBaseAdrs & ~0x1);           }        }    /* Configure Latency Timer */    pciConfigOutByte (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_LATENCY_TIMER,		      0xFF);    /* Enable the device's capabilities as specified */    pciConfigOutWord (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_COMMAND,  		      (UINT16)command);    return (OK);    }/********************************************************************************* pciPack - pack parameters for the Configuration Address Register** This routine packs three parameters into one integer for accessing the* Configuration Address Register** RETURNS: packed integer**/LOCAL int pciPack    (    int	busNo,		/* bus number */    int	deviceNo,	/* device number */    int	funcNo		/* function number */    )    {    return (((busNo    << 16) & 0x00ff0000) |	    ((deviceNo << 11) & 0x0000f800) |	    ((funcNo   << 8)  & 0x00000700));    }/********************************************************************************* pciSpecialCycle - generate a special cycle with a message** This routine generates a special cycle with a message.** RETURNS: OK or ERROR if this library is not initialized.**/STATUS pciSpecialCycle    (    int	busNo,		/* bus number */    int message		/* data on AD[31:0] during the special cycle */    )    {    int deviceNo	= 0x0000001f;    int funcNo		= 0x00000007;    int key;    if (pciLibInitStatus != OK)        return (ERROR);    /* mutual exclusion start */    key = intLock();    switch (pciConfigMech)	{	case PCI_MECHANISM_1:	    PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |		          0x80000000);	    PCI_OUT_LONG (pciConfigAddr1, message);	    break;	case PCI_MECHANISM_2:	    PCI_OUT_BYTE (pciConfigAddr0, 0xff);	    PCI_OUT_BYTE (pciConfigAddr1, 0x00);	    PCI_OUT_LONG ((pciConfigAddr2 | ((deviceNo & 0x000f) << 8)),			  message);	    PCI_OUT_BYTE (pciConfigAddr0, 0);	    break;	default:	    break;	}    /* mutual exclusion stop */    intUnlock(key);    return (OK);    }/********************************************************************************* pciInt - interrupt handler for shared PCI interrupt.** This routine executes multiple interrupt handlers for a PCI interrupt.* Each interrupt handler must check the device dependent interrupt status bit* to determine the source of the interrupt, since it simply execute all* interrupt handlers in the link list.** RETURNS: N/A**/VOID pciInt    (    int irq		/* IRQ associated to the PCI interrupt */    )    {    PCI_INT_RTN *pRtn;    for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[irq]); pRtn != NULL;	 pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node))	(* pRtn->routine) (pRtn->parameter);    }/********************************************************************************* pciIntConnect - connect the interrupt handler to the PCI interrupt.** This routine connects an interrupt handler to the PCI interrupt line(A - D).* Link list is created if multiple handlers are assigned to the single PCI* interrupt.** RETURNS: OK or ERROR if the interrupt handler cannot be built.**/STATUS pciIntConnect    (    VOIDFUNCPTR *vector,        /* interrupt vector to attach to     */    VOIDFUNCPTR routine,        /* routine to be called              */    int parameter               /* parameter to be passed to routine */    )    {    int irq = IVEC_TO_INUM ((int)vector) - INT_NUM_IRQ0;    PCI_INT_RTN *pRtn;    int oldLevel;    if (pciLibInitStatus != OK)	return (ERROR);    pRtn = (PCI_INT_RTN *)malloc (sizeof (PCI_INT_RTN));    if (pRtn == NULL)	return (ERROR);    pRtn->routine   = routine;    pRtn->parameter = parameter;    oldLevel = intLock ();			/* LOCK INTERRUPT */    dllAdd (&pciIntList[irq], &pRtn->node);    intUnlock (oldLevel);			/* UNLOCK INTERRUPT */    return (OK);    }/********************************************************************************* pciIntDisconnect - disconnect the interrupt handler from the PCI interrupt.** This routine disconnects the interrupt handler from the PCI interrupt line.** RETURNS: OK or ERROR if the interrupt handler cannot be removed.**/STATUS pciIntDisconnect    (    VOIDFUNCPTR *vector,        /* interrupt vector to attach to     */    VOIDFUNCPTR routine         /* routine to be called              */    )    {    int irq = IVEC_TO_INUM ((int)vector) - INT_NUM_IRQ0;    PCI_INT_RTN *pRtn;    int oldLevel;    if (pciLibInitStatus != OK)	return (ERROR);    for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[irq]); pRtn != NULL;	 pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node))	{	if (pRtn->routine == routine)	    {	    oldLevel = intLock ();			/* LOCK INTERRUPT */	    dllRemove (&pciIntList[irq], &pRtn->node);	    intUnlock (oldLevel);			/* UNLOCK INTERRUPT */	    free ((char *)pRtn);	    return (OK);	    }	}    return (ERROR);    }#endif /* defined(INCLUDE_PCI) */

⌨️ 快捷键说明

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