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

📄 pciiomaplib.c

📁 ge公司的dv4av4信号处理板的bsp源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* pciIomapLib.c - Support for PCI drivers */

/* Copyright 1984-1996 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*
modification history
--------------------
01h,15oct98,dat  SPR 9098, added iv.h and private/semLibP.h
01g,12jan97,hdn  changed variable name "vender" to "vendor".
01f,12jan97,hdn  changed variable name "class" to "classCodeReg".
01e,03dec96,hdn  added single/multi function check.
01d,16sep96,dat  made pciConfigMech global (for pciIomapShow).
01c,06aug96,hdn  added pciInt(), pciIntConnect() and pciIntDisconnect().
01b,14mar96,hdn  re-written.  changed parameters of the functions.
		 removed BIOS dependent codes.
01a,25feb95,bcs  written
*/


/*
DESCRIPTION

This library is PCI Revision 2.1 compliant.
This module contains routines to support PCI bus mapped on IO address space
for x86 and PowerPC architecture.  Functions in this library should not be
called from the interrupt level, except pciInt(), since it uses a mutual
exclusion 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 specified
interrupt handler to the link list and pciIntDisconnect() removes it from
the link list.  Master interrupt handler pciInt() executes these interrupt
handlers in the link list 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.  pciInt() should be attached by intConnect() function in the BSP 
initialization with its parameter. The parameter is an IRQ associated 
to the PCI interrupt.
*/

#include "vxWorks.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "intLib.h"
#include "sysLib.h"
#include "drv/pci/pciIomapLib.h"
#include "iv.h"
#include "private/semLibP.h"


/* defines */

#ifndef	PCI_IN_BYTE
#define PCI_IN_BYTE(x)		sysInByte (x)
#endif
#ifndef	PCI_IN_WORD
#define PCI_IN_WORD(x)		sysInWord (x)
#endif
#ifndef	PCI_IN_LONG
#define PCI_IN_LONG(x)		sysInLong (x)
#endif
#ifndef	PCI_OUT_BYTE
#define PCI_OUT_BYTE(x,y)	sysOutByte (x,y)
#endif
#ifndef	PCI_OUT_WORD
#define PCI_OUT_WORD(x,y)	sysOutWord (x,y)
#endif
#ifndef	PCI_OUT_LONG
#define PCI_OUT_LONG(x,y)	sysOutLong (x,y)
#endif


/* globals */

STATUS	pciLibInitStatus = NONE;	/* initialization done */
DL_LIST	pciIntList[PCI_IRQ_LINES];	/* link list of int handlers */
int	pciConfigMech = NONE;		/* 1=mechanism-1, 2=mechanism-2 */

/* locals */

LOCAL int pciConfigAddr0;		/* config-addr-reg, CSE-reg*/
LOCAL int pciConfigAddr1;		/* config-data-reg, forward-reg */
LOCAL int pciConfigAddr2;		/* not-used, base-addr */
LOCAL SEMAPHORE pciMuteSem;		/* mutual exclusion semaphore */


/*******************************************************************************
*
* pciIomapLibInit - initialize the configuration access-method and addresses
*
* This routine initializes the configuration access-method and addresses.
*
* Configuration mechanism one utilizes two 32-bit IO ports located at addresses
* 0x0cf8 and 0x0cfc. These two ports are:
*   - 32-bit configuration address port, at 0x0cf8
*   - 32-bit configuration data port, at 0x0cfc
* Accessing a PCI function's configuration port is two step process.
*   - Write the bus number, physical device number, function number and 
*     register number to the configuration address port.
*   - Perform an IO read from or an write to the configuration data port.
*
* Configuration mechanism two uses following two single-byte IO ports.
*   - Configuration space enable, or CSE, register, at 0x0cf8
*   - Forward register, at 0x0cfa
* To generate a PCI configuration transaction, the following actions are
* performed.
*   - Write the target bus number into the forward register.
*   - Write a one byte value to the CSE register at 0x0cf8.  The bit
*     pattern written to this register has three effects: disables the
*     generation of special cycles; enables the generation of configuration
*     transactions; specifies the target PCI functional device.
*   - Perform a one, two or four byte IO read or write transaction within
*     the IO range 0xc000 through 0xcfff.
*
* RETURNS:
* OK, or ERROR if a mechanism is not 1 or 2.
*
*/

STATUS pciIomapLibInit
    (
    int mechanism,	/* configuration mechanism: 1 or 2 */
    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:
	    pciConfigMech	= mechanism;
	    pciConfigAddr0	= addr0;
	    pciConfigAddr1	= addr1;
	    pciConfigAddr2	= addr2;
	    pciLibInitStatus	= OK;
	    break;

	default:
    	    pciLibInitStatus	= ERROR;
	    break;
	}

    semMInit (&pciMuteSem, SEM_Q_PRIORITY | SEM_DELETE_SAFE | 
	      SEM_INVERSION_SAFE);

    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;
    int busNo;
    int deviceNo;
    int funcNo;
    short device;
    short vendor;
    char header;

    if (pciLibInitStatus != OK)			/* sanity check */
        return (ERROR);

    for (busNo=0; busNo <= 0xff; busNo++)
        for (deviceNo=0; deviceNo <= 0x1f; deviceNo++)
            for (funcNo=0; funcNo <= 0x07; funcNo++)
		{
		/* avoid a special bus cycle */

		if ((deviceNo == 0x1f) && (funcNo == 0x07))
		    continue;

		pciConfigInWord (busNo, deviceNo, funcNo, PCI_CFG_VENDOR_ID,
				 &vendor);
		pciConfigInWord (busNo, deviceNo, funcNo, PCI_CFG_DEVICE_ID,
				 &device);
		if ((vendor == (short)vendorId) && 
		    (device == (short)deviceId) &&
		    (index-- == 0))
		    {
		    *pBusNo	= busNo;
		    *pDeviceNo	= deviceNo;
		    *pFuncNo	= funcNo;
		    status	= OK;
		    break;		/* terminate loop */
		    }

		/* goto next device if it is a single function device */

		pciConfigInByte (busNo, deviceNo, funcNo, PCI_CFG_HEADER_TYPE, 
				 &header);
		if ((header & PCI_HEADER_MULTI_FUNC) != PCI_HEADER_MULTI_FUNC)
		    break;
		}

    return (status);
    }

/*******************************************************************************
*
* pciFindClass - find the nth device with the given class(3 bytes).
*
* This routine finds the nth device with the given class(class subclass prog).
*
* RETURNS:
* OK, or ERROR if the class didn't match.
*
*/

STATUS pciFindClass
    (
    int	classCode,	/* class code */
    int	index,		/* desired instance of device */
    int * pBusNo,	/* bus number */
    int * pDeviceNo,	/* device number */
    int * pFuncNo	/* function number */
    )
    {
    STATUS status = ERROR;
    int busNo;
    int deviceNo;
    int funcNo;
    int classCodeReg;
    char header;

    if (pciLibInitStatus != OK)			/* sanity check */
        return (ERROR);

    for (busNo=0; busNo < 0xff; busNo++)
        for (deviceNo=0; deviceNo < 0x1f; deviceNo++)
            for (funcNo=0; funcNo < 0x07; funcNo++)
		{
		/* avoid a special bus cycle */

		if ((deviceNo == 0x1f) && (funcNo == 0x07))
		    continue;

		pciConfigInLong (busNo, deviceNo, funcNo, PCI_CFG_REVISION,
				 &classCodeReg);
		if ((((classCodeReg >> 8) & 0x00ffffff) == classCode) &&
		    (index-- == 0))
		    {
		    *pBusNo	= busNo;
		    *pDeviceNo	= deviceNo;
		    *pFuncNo	= funcNo;
		    status	= OK;
		    break;		/* terminate loop */
		    }

		/* goto next device if it is a single function device */

		pciConfigInByte (busNo, deviceNo, funcNo, PCI_CFG_HEADER_TYPE, 
				 &header);
		if ((header & PCI_HEADER_MULTI_FUNC) != PCI_HEADER_MULTI_FUNC)
		    break;
		}

    return (status);
    }

/*******************************************************************************
*
* 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));
    }

/*******************************************************************************
*
* pciConfigInByte - read one byte from the PCI configuration space
*
* This routine reads one byte from the PCI configuration space
*
* RETURNS:
* OK, or ERROR if this library is not initialized.
*
*/

STATUS pciConfigInByte
    (
    int	busNo,		/* bus number */
    int	deviceNo,	/* device number */
    int	funcNo,		/* function number */
    int	address,	/* address of the configuration space */
    char * pData	/* data read from the address */
    )
    {
#if 0
    int retval = 0;

    if (pciLibInitStatus != OK)			/* sanity check */
        return (ERROR);
#endif

    semTake (&pciMuteSem, WAIT_FOREVER);	/* mutual execlusion start */

#if 0
    switch (pciConfigMech)
	{
	case PCI_MECHANISM_1:
	    PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
		          (address & 0xfc) | 0x80000000);
	    retval = PCI_IN_BYTE (pciConfigAddr1 + (address & 0x3));
	    break;

	case PCI_MECHANISM_2:
	    PCI_OUT_BYTE (pciConfigAddr0, 0xf0 | (funcNo << 1));
	    PCI_OUT_BYTE (pciConfigAddr1, busNo);
	    retval = PCI_IN_LONG (pciConfigAddr2 | ((deviceNo & 0x000f) << 8) |
				  (address & 0xfc));
	    PCI_OUT_BYTE (pciConfigAddr0, 0);
	    retval >>= (address & 0x03) * 8;
	    break;

	default:
	    break;
	}
#else
    bslPciConfigRead8(busNo, deviceNo, funcNo, address, pData);
#endif

    semGive (&pciMuteSem);			/* mutual execlusion stop */

#if 0
    *pData = retval;
#endif

    return (OK);
    }

/*******************************************************************************
*
* pciConfigInWord - read one word from the PCI configuration space
*
* This routine reads one word from the PCI configuration space
*
* RETURNS:
* OK, or ERROR if this library is not initialized.
*
*/

STATUS pciConfigInWord
    (
    int	busNo,		/* bus number */
    int	deviceNo,	/* device number */
    int	funcNo,		/* function number */
    int	address,	/* address of the configuration space */
    short * pData	/* data read from the address */
    )
    {
#if 0
    int retval = 0;

    if (pciLibInitStatus != OK)			/* sanity check */
        return (ERROR);
#endif

    semTake (&pciMuteSem, WAIT_FOREVER);	/* mutual execlusion start */

#if 0
    switch (pciConfigMech)
	{
	case PCI_MECHANISM_1:
	    PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
		          (address & 0xfc) | 0x80000000);
	    retval = PCI_IN_WORD (pciConfigAddr1 + (address & 0x2));
	    break;

	case PCI_MECHANISM_2:

⌨️ 快捷键说明

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