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

📄 pci_serv.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (pci_config_error)  /* check to see if the NMI handler during the config cycle */
		status = 1;  

	pci_config_cycle = 0; /* turn on exception handling after pci config cycle */

  if (old_abort_vec)
  {
      ((volatile unsigned *)0x20)[4] = old_abort_vec;
      old_abort_vec = 0;
      _flushICache();
  }

  if (status) return (ERROR);
  else return (OK);
}

extern void __ignore_abort(void);

/**************************************************************************
* sys_config_setup - this function sets up a PCI configuration cycle
*
* This function sets up either the primary or secondary outbound configuration
* cycle address register.  It is called by all the sys_*_config_* functions. 
*
*/
static int sys_config_setup(ULONG busno, ULONG devno, ULONG funcno, ULONG regno, UINT32 **pci_occ_addr, 
							UINT32 **pci_occ_data)
{
	
	/* First check the parameters for sanity */
	if ((busno > 255) || (devno > 31) || (funcno> 7) || (regno > 63)) return (ERROR);
	
	if (busno == primary_busno) 
	{
		*pci_occ_addr = (UINT32 *) POCCAR_ADDR;
		*pci_occ_data = (UINT32 *) POCCDR_ADDR;
	}
	else if (busno == secondary_busno) 
	{
		*pci_occ_addr = (UINT32 *) SOCCAR_ADDR;
		*pci_occ_data = (UINT32 *) SOCCDR_ADDR;
	}
	else if (busno <= bus0_lastbus)
	{
		*pci_occ_addr = (UINT32 *) POCCAR_ADDR;
		*pci_occ_data = (UINT32 *) POCCDR_ADDR;
	}
	else if (busno <= bus1_lastbus)
	{
		*pci_occ_addr = (UINT32 *) SOCCAR_ADDR;
		*pci_occ_data = (UINT32 *) SOCCDR_ADDR;
	}
	else return (ERROR);
	
	(void)pci_cycle_cleanup(busno);	/* start with clean slate */

	pci_config_cycle = 1; /* turn off exception handling during pci config cycle */

	if (old_abort_vec) {
	    printf("recursive config setup\n");
	    while (1);
	}

	old_abort_vec = ((volatile unsigned *)0x20)[4];
	((volatile unsigned *)0x20)[4] = (unsigned)__ignore_abort;
	_flushICache();

	pci_config_error = FALSE;

	/* turn off error messages which could be generated by non-existant devices */
	PRINT_OFF();

	if ((busno == PRIMARY_BUS_NUM) || (busno == SECONDARY_BUS_NUM))
	{
		/* set up the config access register for type 0 config cycles */
		**pci_occ_addr =
			(        
			(1 << ((devno & 0x1f) + 16)) |
			((funcno & 0x07) << 8)  |
			((regno & 0x3f) << 2)  |
			(0) );
    }
	else
	{
		/* set up the config access register for type 1 config cycles */
		**pci_occ_addr =
			(
			((busno & 0xff) << 16) |
			((devno & 0x1f) << 11) |
			((funcno& 0x07) << 8)  |
			((regno & 0x3f) << 2)  |
			(1) );
	}

	return (OK);
}

/**************************************************************************
* sys_read_config_byte - this function performs a PCI configuration cycle
*                        and returns a byte.
*
* This function will read a byte from config space on the PCI bus.  It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_read_config_byte (UINT32 busno, UINT32 devno, UINT32 funcno, UINT32 offset, UINT8 *data)
{
	UINT32 *pci_occ_data;
	UINT32 regno;
    UINT32 *pci_occ_addr;

	/* initialize here to keep compiler happy */
	pci_occ_addr = (UINT32 *) POCCAR_ADDR;
	pci_occ_data = (UINT32 *) POCCDR_ADDR;
	
	/* Register numbers are DWORD indexes */
	regno = offset / 0x4;

	/* Set up the cycle. */
	if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
		return (ERROR);

	/* Now do the read */
	*data = (UINT8)(((*pci_occ_data) >> ((offset % 0x4) * 8)) & 0xff);
	
	if (pci_cycle_cleanup (busno) == OK)
	{
		PRINT_ON();
		return (OK);
	}
	else
	{
		PRINT_ON();
		return (ERROR);
	}
}

/**************************************************************************
* sys_read_config_word - this function performs a PCI configuration cycle
*                        and returns a 16-bit word.
*
* This function will read a word from config space on the PCI bus.  It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_read_config_word (UINT32 busno, UINT32 devno, UINT32 funcno, UINT32 offset, UINT16 *data)
{
  UINT32 *pci_occ_data;
  UINT32 regno;
  UINT32 *pci_occ_addr;

	/* initialize here to keep compiler happy */
	pci_occ_addr = (UINT32 *) POCCAR_ADDR;
	pci_occ_data = (UINT32 *) POCCDR_ADDR;

	/* Offsets must be word-aligned */
	if (offset % 0x2) return (ERROR);
	
	/* Register numbers are DWORD indexes */
	regno = offset / 0x4;

	/* Set up the cycle. */
	if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK) return (ERROR);
	
	/* Now do the read */
	*data = (UINT16)(((*pci_occ_data) >> ((offset % 0x4) * 8)) & 0xffff);
	
	if (pci_cycle_cleanup(busno) == OK)
	{
		PRINT_ON();
		return (OK);
	}
	else
	{
		PRINT_ON();
		return (ERROR);
	}
}

/**************************************************************************
* sys_read_config_dword - this function performs a PCI configuration cycle
*                        and returns a 32-bit word.
*
* This function will read a dword from config space on the PCI bus.  It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_read_config_dword (
	UINT32 busno,
	UINT32 devno,
	UINT32 funcno,
	UINT32 offset,
	UINT32 *data
	)
{
	UINT32 *pci_occ_data;
	UINT32 regno;
	UINT32 *pci_occ_addr;

	/* initialize here to keep compiler happy */
	pci_occ_addr = (UINT32 *) POCCAR_ADDR;
	pci_occ_data = (UINT32 *) POCCDR_ADDR;

	/* Offsets must be dword-aligned */
	if (offset % 0x4) return (ERROR);
	
	/* Register numbers are DWORD indexes */
	regno = offset / 0x4; 

	/* Set up the cycle. */
	if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
		return (ERROR);

	/* Now do the read */
	*data = *pci_occ_data;
	
	if (pci_cycle_cleanup (busno) == OK)
	{
		PRINT_ON();
		return (OK);
	}
	else
	{
		PRINT_ON();
		return (ERROR);
	}
}

/**************************************************************************
* sys_write_config_byte - this function performs a PCI configuration cycle
*                         and writes a byte.
*
* This function will write a byte to config space on the PCI bus.  It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_write_config_byte (
	UINT32 busno,
	UINT32 devno,
	UINT32 funcno,
	UINT32 offset,
	UINT8 *data
	)
{
	UINT32 *pci_occ_data;
	UINT32 regno, temp;
    UINT32 *pci_occ_addr;
	UINT32 data_mask;

	/* initialize here to keep compiler happy */
	pci_occ_addr = (UINT32 *) POCCAR_ADDR;
	pci_occ_data = (UINT32 *) POCCDR_ADDR;
	
	/* Register numbers are DWORD indexes */
	regno = offset / 0x4;

	/* build mask for byte of interest */
	data_mask = ~(0x000000ff << ((offset % 0x4) * 8));

	/* Set up the cycle. */
	if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
		return (ERROR);

	/* set up 32-bit word, clear old data, OR in new data */
	temp = (UINT32)(((UINT32) *data) << ((offset % 0x4) * 8));
	*pci_occ_data &= data_mask;
	*pci_occ_data |= temp;
	
	if (pci_cycle_cleanup (busno) == OK)
	{
		PRINT_ON();
		return (OK);
	}
	else
	{
		PRINT_ON();
		return (ERROR);
	}
}

/**************************************************************************
* sys_write_config_word - this function performs a PCI configuration cycle
*                        and writes a 16-bit word.
*
* This function will write a word to config space on the PCI bus.  It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_write_config_word (
	UINT32 busno,
	UINT32 devno,
	UINT32 funcno,
	UINT32 offset,
	UINT16 *data
	)
{
	UINT32 *pci_occ_data;
	UINT32 regno, temp;
    UINT32 *pci_occ_addr;
	UINT32 data_mask;

	/* initialize here to keep compiler happy */
	pci_occ_addr = (UINT32 *) POCCAR_ADDR;
	pci_occ_data = (UINT32 *) POCCDR_ADDR;

	/* Offsets must be word-aligned */
	if (offset % 0x2) return (ERROR);
	
	/* Register numbers are DWORD indexes */
	regno = offset / 0x4;

    /* build mask for word of interest */
	data_mask= ~(0x0000ffff << ((offset % 0x4) * 8));

	/* Set up the cycle. */
	if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
		return (ERROR);

	/* set up 32-bit word */
	temp = (UINT32)(((UINT32) *data) << ((offset % 0x4) * 8));
    *pci_occ_data &= data_mask; 
	*pci_occ_data |= temp;
		
	if (pci_cycle_cleanup (busno) == OK)
	{
		PRINT_ON();
		return (OK);
	}
	else
	{
		PRINT_ON();
		return (ERROR);
	}
}

/**************************************************************************
* sys_write_config_dword - this function performs a PCI configuration cycle
*                        and writes a 32-bit word.
*
* This function will write a dword to config space on the PCI bus.  It is
* a user service intended to be called through the calls interface.
*/
ULONG sys_write_config_dword (
	UINT32 busno,
	UINT32 devno,
	UINT32 funcno,
	UINT32 offset,
	UINT32 *data
	)
{
	UINT32 *pci_occ_data;
	UINT32 regno;
    UINT32 *pci_occ_addr;

	/* initialize here to keep compiler happy */
	pci_occ_addr = (UINT32 *) POCCAR_ADDR;
	pci_occ_data = (UINT32 *) POCCDR_ADDR;

	/* Offsets must be dword-aligned */
	if (offset % 0x4) return (ERROR);
	
	/* Register numbers are DWORD indexes */
	regno = offset / 0x4; 

	/* Set up the cycle. */
	if (sys_config_setup (busno, devno, funcno, regno, &pci_occ_addr, &pci_occ_data) != OK)
		return (ERROR);

	/* Now do the write */
	*pci_occ_data = *data;
	
	if (pci_cycle_cleanup (busno) == OK)
	{
		PRINT_ON();
		return (OK);
	}
	else
	{
		PRINT_ON();
		return (ERROR);
	}
}

/******************************************************************************
* sys_find_pci_device - find a PCI device based on Vendor ID and Device ID
*
* This function returns the location of PCI devices that have a specific
* Device ID and Vendor ID.  Given a Vendor ID, Device ID, and an Index, the
* function returns the Bus Number, Device Number, and Function Number of the
* Nth Device/Function whose Vendor ID and Device ID match the input parameters.
*
* Calling software can find all devices having the same Vendor ID and Device ID
* by making successive calls to this function starting with the index set to 0,
* and incrementing the index until the function returns DEVICE_NOT_FOUND.  A
* return value of BAD_VENDOR_ID indicates that the Vendor ID value passed had
* a value of all 1's.
*
*/
STATUS sys_find_pci_device (int vendor_id, int device_id, int index, PCI_DEVICE_LOCATION *devloc)
{
	int found;

⌨️ 快捷键说明

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