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

📄 pciiomaplib.c

📁 ixp2400 bsp for vxworks
💻 C
📖 第 1 页 / 共 2 页
字号:
/* pciIomapLib.c - Support for PCI drivers *//* Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01b,22aug03,scm  bspcheck release test modifications...01a,27mar02,lagarwal  created from ixp1200eb_be*//*DESCRIPTIONThis library is PCI Revision 2.1 compliant.This module contains routines to support PCI bus mapped on IO address spacefor x86 and PowerPC architecture.  Functions in this library should not becalled from the interrupt level, except pciInt(), since it uses a mutualexclusion semaphore for consecutive register access.  The functions addressed here include:  - Initialize the library.  - Locate the device by deviceID and vendorID.  - Locate the device by classCode.  - Generate the special cycle.  - Access its configuration registers.  - Connect a shared interrupt handler.  - Disconnect a shared interrupt handler.  - Master shared interrupt handler.There are functions to access the IO address space.  In x86 architecture,they are sysInXXX() and sysOutXXX().  Macro PCI_IN_XXX() and PCI_OUT_XXX()are provided to use other IO address space functions.Shared PCI interrupt are supported by three functions: pciInt(),pciIntConnect(), pciIntDisconnect().  pciIntConnect() adds the specifiedinterrupt handler to the link list and pciIntDisconnect() removes it fromthe link list.  Master interrupt handler pciInt() executes these interrupthandlers in the link list for a PCI interrupt.  Each interrupt handler mustcheck the device dependent interrupt status bit to determine the source ofthe interrupt, since it simply execute all interrupt handlers in the linklist.  pciInt() should be attached by intConnect() function in the BSP initialization with its parameter. The parameter is an IRQ associated to the PCI interrupt.The maximum number of Type-1 Configuration Space buses supported in the 2.1Specifications is 256 (0x00 - 0xFF), far greater than most systems currentlysupport.  Most buses are numbered sequentially from 0.  An optional definecalled PCI_MAX_BUS may be declared in config.h to override the defaultdefinition of 256.  Similarly, the default number of devices and functionsmay be overriden by defining PCI_MAX_DEV and/or PCI_MAX_FUNC.  Note thatthe number of devices applies only to bus zero, all others being restrictedto 16 by the 2.1 spec.*/#if defined(INCLUDE_PCI)#include "vxWorks.h"#include "config.h"#include "dllLib.h"#include "sysLib.h"#include "stdio.h"#include "stdlib.h"#include "string.h"#include "intLib.h"#include "ixdp2400Misc.h"struct SPCfg spCfgOld, spCfgCpld;/* * We currently wish to include this from locally rather than from * there as that version is out-dated. However, as it has been included * in sysLib.c already, this will do no harm. */#include "drv/pci/pciIomapLib.h"#ifndef PCI_MAX_FUNC#  define PCI_MAX_FUNC	8#endif  /* PCI_MAX_FUNC *//* globals */STATUS	pciLibInitStatus = NONE;	/* initialization done */VOIDFUNCPTR	pciISRList[MAX_CPLD_INT];	/* list of int handlers */int	pciISRDataList[MAX_CPLD_INT];	/* list of parameters *//* locals */LOCAL int pciConfigAddr0;		/* config-addr-reg, CSE-reg*/LOCAL int pciConfigAddr1;		/* config-data-reg, forward-reg *//********************************************************************************* pciIomapLibInit - initialize the configuration access-method and addresses** This routine initializes the configuration access-method and addresses.** RETURNS:* OK, or ERROR if a mechanism is not 1, 2 or 3.**/STATUS pciIomapLibInit    (    int addr0,		/* config-addr-reg / CSE-reg */    int addr1		/* config-data-reg / Forward-reg */    )    {    int ix;    if (pciLibInitStatus != NONE)	return (pciLibInitStatus);	pciConfigAddr0	= addr0;	pciConfigAddr1	= addr1;	pciLibInitStatus	= OK;    for (ix = 0; ix < MAX_CPLD_INT; ix++)	{		pciISRList[ix] = 0;		pciISRDataList[ix] = 0;	}    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;    UINT32 device;    UINT32 vendor;    char   header;    if (pciLibInitStatus != OK)			/* sanity check */        cont = FALSE;    for (busNo = 0; cont == TRUE && busNo < PCI_MAX_BUS; busNo++)        for (deviceNo = 0;	     cont == TRUE && deviceNo < PCI_MAX_DEV;	     ++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_VENDOR_ID,				 &vendor);		/* If nonexistent device, skip to next */		if ((vendor == 0xFFFFFFFF) && (funcNo == 0))		    break;		device  = vendor >> 16;		device &= 0x0000FFFF;		vendor &= 0x0000FFFF;		if ((vendor == (UINT32)vendorId) &&		    (device == (UINT32)deviceId) &&		    (index-- == 0))		    {		    *pBusNo	= busNo;		    *pDeviceNo	= deviceNo;		    *pFuncNo	= funcNo;		    status	= OK;		    cont	= FALSE;	/* terminate all loops */		    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);    }/********************************************************************************* 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)			/* sanity check */        cont = FALSE;    for (busNo = 0; cont == TRUE && busNo < PCI_MAX_BUS; busNo++)        for (deviceNo = 0;	     cont == TRUE && deviceNo < PCI_MAX_DEV;	     ++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;		    cont 	= FALSE;	/* terminate all loops */		    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, &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;           }        /* I/O space requested? */        /* Yes, set specified I/O space base address  */        if (tmp32 & 0x1)           {           pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo, ix,			     devIoBaseAdrs | 0x1);           }        /* No, memory space required, set specified base address */        else           {           pciConfigOutLong (pciBusNo, pciDevNo, pciFuncNo, ix,			     devMemBaseAdrs & ~0x1);           }        }    /* Configure Cache Line Size Register */    pciConfigOutByte (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_CACHE_LINE_SIZE,		      PCI_CLINE_SZ);    /* Configure Latency Timer */    pciConfigOutByte (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_LATENCY_TIMER,		      PCI_LAT_TIMER);    /* Enable the device's capabilities as specified */    pciConfigOutWord (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_COMMAND,  		      (UINT16)command);    return (OK);    }static int clearMasterAbort(void){	UINT32 temp;	int err = 0;	temp = *(UINT32 *)(IXP2400_PCI_CONTROL);	if(temp & 0x120)	{		err = 1;		*(UINT32 *)(IXP2400_PCI_CONTROL) = temp;	}	temp = *(UINT32 *)(IXP2400_PCI_CMD_STAT);    if(temp & 0x20000000)	{		err = 1;#if A0_REV		while(temp & 0x20000000)		{			*(UINT32 *)(IXP2400_PCI_CMD_STAT) = temp;			temp = *(UINT32 *)(IXP2400_PCI_CMD_STAT);		}#else		*(UINT32 *)(IXP2400_PCI_CMD_STAT) = temp;#endif	}	return err;}/********************************************************************************* pciConfigInByte - read one byte from the PCI configuration space** This routine reads one byte from the PCI configuration space*

⌨️ 快捷键说明

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