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

📄 pciiomaplib.c

📁 ATMEL920T的BSP及ETH等已经设备驱动程序
💻 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 + -