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

📄 pciiomaplib.c

📁 ixp1200EB vxworks pci BSP
💻 C
📖 第 1 页 / 共 3 页
字号:
		    *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);
    }


/*******************************************************************************
*
* 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	offset,		/* offset into the configuration space */
    char * pData	/* data read from the offset */
    )
    {
    int	retval = 0;
    int	key;
    int n;
    UINT32 w;

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

    key = intLock ();				/* mutual exclusion start */

    switch (pciConfigMech)
	{
	case PCI_MECHANISM_1:
	    PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
		          (offset & 0xfc) | 0x80000000);
	    retval = PCI_IN_BYTE (pciConfigAddr1 + (offset & 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) |
				  (offset & 0xfc));
	    PCI_OUT_BYTE (pciConfigAddr0, 0);
	    retval >>= (offset & 0x03) * 8;
	    break;

	case PCI_MECHANISM_3:
	    /*
	     * There are reports of hardware (both target and bridge)
	     * that do not cope well with non-32-bit-aligned accesses,
	     * particularly non-32-bit-word accesses. We may be overreacting
	     * here, but restricting all the accesses to 32-bits should be
	     * safer. Efficiency should not be an issue during PCI
	     * configuration. In any case, this code is in the BSP and can be
	     * changed, if required.
	     */

	    n = offset % 4;

	    IDSEL(busNo, deviceNo);		/* Setup IDSEL Lines */

	    w = PCI_IN_LONG (((busNo == 0) ? pciConfigAddr0 : pciConfigAddr1) |
			MAKE_CFG_ADDR(busNo, deviceNo, funcNo, (offset & ~3)));
	    retval = (w >> (8 * n)) & 0xFF;

	    CLR_IDSEL;				/* Clear IDSEL Lines */
	    break;

	default:
	    break;
	}

    intUnlock (key);				/* mutual exclusion stop */

    *pData = (char)retval;

    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	offset,		/* offset into the configuration space */
    short * pData	/* data read from the offset */
    )
    {
    int	retval = 0;
    int	key;
    int n;
    UINT32 w;

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

    key = intLock ();				/* mutual exclusion start */

    switch (pciConfigMech)
	{
	case PCI_MECHANISM_1:
	    PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
		          (offset & 0xfc) | 0x80000000);
	    retval = PCI_IN_WORD (pciConfigAddr1 + (offset & 0x2));
	    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) |
				  (offset & 0xfc));
	    PCI_OUT_BYTE (pciConfigAddr0, 0);
	    retval >>= (offset & 0x02) * 8;
	    break;

	case PCI_MECHANISM_3:
	    n = offset % 4;

	    IDSEL(busNo, deviceNo);		/* Setup IDSEL Lines */

	    w = PCI_IN_LONG (((busNo == 0) ? pciConfigAddr0 : pciConfigAddr1) |
		MAKE_CFG_ADDR(busNo, deviceNo, funcNo, (offset & ~3)));
	    retval = (w >> (8 * n)) & 0xFFFF;

	    CLR_IDSEL;				/* Clear IDSEL Lines */
	    break;

	default:
	    break;
	}

    intUnlock (key);				/* mutual exclusion stop */

    *pData = retval;

    return (OK);
    }

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

STATUS pciConfigInLong
    (
    int	busNo,		/* bus number */
    int	deviceNo,	/* device number */
    int	funcNo,		/* function number */
    int	offset,		/* offset into the configuration space */
    int * pData		/* data read from the offset */
    )
    {
    int		 key;
    volatile int retval = 0;
    FAST int	 ix;

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

    key = intLock ();				/* mutual exclusion start */

    switch (pciConfigMech)
	{
	case PCI_MECHANISM_1:
	    PCI_OUT_LONG (pciConfigAddr0, pciPack (busNo, deviceNo, funcNo) |
		          (offset & 0xfc) | 0x80000000);
            for (ix = 0; ix < PCI_DELAY; ++ix)  /* XXXmas */
                ;
	    retval = PCI_IN_LONG (pciConfigAddr1);
	    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) |
				  (offset & 0xfc));
	    PCI_OUT_BYTE (pciConfigAddr0, 0);
	    break;

	case PCI_MECHANISM_3:
	    IDSEL(busNo, deviceNo);		/* Setup IDSEL Lines */
	    retval =
		PCI_IN_LONG (((busNo == 0) ? pciConfigAddr0 : pciConfigAddr1) |
			MAKE_CFG_ADDR(busNo, deviceNo, funcNo, offset));
	    CLR_IDSEL;				/* Clear IDSEL Lines */
	    break;

	default:
	    break;
	}

    intUnlock (key);				/* mutual exclusion stop */

    *pData = retval;

    return (OK);
    }


/*******************************************************************************
*
* pciConfigOutByte - write one byte to the PCI configuration space
*
* This routine writes one byte to the PCI configuration space.
*

⌨️ 快捷键说明

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