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

📄 pci_serv.c

📁 基于ecos的redboot
💻 C
📖 第 1 页 / 共 5 页
字号:
			{
				printf("Error reading Region 0 Base\n");
				return;
			}
			printf("PCI Region 0 Base     = 0x%08X\n",long_data);

			/* get Region 1 Base Address */
			offset = REGION1_BASE_OFFSET;
			if (sys_read_config_dword (busno,devno,function,offset,&long_data)
                == ERROR)
			{
				printf("Error reading Region 1 Base\n");
				return;
			}
			printf("PCI Region 1 Base     = 0x%08X\n",long_data);

			/* get Expansion ROM Base Address */
			offset = TYPE1_EXP_ROM_OFFSET;
			if (sys_read_config_dword (busno,devno,function,offset,&long_data)
                == ERROR)
			{
				printf("Error reading Expansion ROM Base\n");
				return;
			}
			printf("Expansion ROM Base    = 0x%08X\n",long_data);

		} /* end type 1 header */

    }
}

/* check if host of backplane */
int isHost()
{
	if (*BACKPLANE_DET_REG & BP_HOST_BIT)
		return TRUE;
	else
		return FALSE;
}




/*****************************************************************************
* sys_pci_device_initialization - initialize PCI I/O devices
*
* This function is responsible for initializing all PCI I/O devices for proper
* PCI operation.  All I/O devices are mapped into appropriate locations in the
* PCI address space (based on size and alignment requirements).  This function
* must ensure that no bus conflicts exist.  This function is also responsible
* for initializing cache line size, latency timer, DEVSEL# timing, and parity
* error response.  This function fills out the data structure which is passed
* in to it.  This function will return SUCCESSFUL if at least one I/O
* controller can be successfully configured.  This function will return ERROR
* if no I/O controllers can be initialized.
*
*/
void sys_pci_device_initialization (PCI_DATA* pci_data)
{   
	
	volatile int i;

	bus0_lastbus = PRIMARY_BUS_NUM;        /* last bus number behind bus 0 (primary bus ) */
    bus1_lastbus = SECONDARY_BUS_NUM;      /* last bus number behind bus 1 (secondary bus) */

	pci_data->num_devices = 0;	 /* total number of devices configured */
	pci_data->num_functions = 0; /* total number of functions configured */

	init_312_pci(); /* initialize the ATU, MU and bridge on the 80312 */

	if (isHost())
	{
	  /* If the IQ80310 board is connected to the backplane it has to initialize the Primary PCI bus */

      /* set PCI base addresses for primary bus */

	  memspace_ptr[PRIMARY_BUS_NUM] = PRIMARY_MEM_BASE;
	  memspace_limit[PRIMARY_BUS_NUM] = PRIMARY_MEM_LIMIT;

	  iospace_ptr[PRIMARY_BUS_NUM] = PRIMARY_IO_BASE;
	  iospace_limit[PRIMARY_BUS_NUM] = PRIMARY_IO_LIMIT;

	  PRINT_OFF();

	  /* Initialize Primary PCI bus */
	  sys_pci_bus_init (PRIMARY_BUS_NUM, PRIMARY_BUS_NUM, pci_data);
	}

	/* Initialization of the Secondary PCI bus */

    /* set PCI base addresses for secondary bus */

	memspace_ptr[SECONDARY_BUS_NUM] = SECONDARY_MEM_BASE;
	memspace_limit[SECONDARY_BUS_NUM] = SECONDARY_MEM_LIMIT;

	iospace_ptr[SECONDARY_BUS_NUM] = SECONDARY_IO_BASE;
	iospace_limit[SECONDARY_BUS_NUM] = SECONDARY_IO_LIMIT;

	PRINT_OFF();
    
	/* Initialize Secondary PCI bus */
	sys_pci_bus_init (SECONDARY_BUS_NUM, SECONDARY_BUS_NUM, pci_data);

	
	/* Set absolute last secondary bus */
	if (bus0_lastbus > bus1_lastbus)
	  lastbus = bus0_lastbus;	
	else
	  lastbus = bus1_lastbus;

	PRINT_OFF();

	/* before exiting, configure and enable FIQ and IRQ interrupts */
	
	_enableFiqIrq();  /* enable FIQ and IRQ interrupts in CP13 */
	
	config_ints();   /* configure interrupts */

	/* wait a while to clear out any unwanted NMI interrupts */
	for (i = 0; i < 100000; i++)
		;

	PRINT_ON();

	/* enable ECC single bit correction and multi-bit reporting
	   - initialization code only enables correction */
	*(volatile unsigned long *)ECCR_ADDR = 0x6;
}


/*****************************************************************************
* sys_pci_bus_init - initialize PCI I/O devices
*
* This function is responsible for initializing all PCI I/O devices for proper 
* PCI operation.  All I/O devices are mapped into appropriate locations in the
* PCI address space (based on size and alignment requirements).  This function 
* must ensure that no bus conflicts exist.  This function is also responsible 
* for initializing cache line size, latency timer, DEVSEL# timing, and parity
* error response.  This function fills out the data structure which is passed
* in to it.  This function will return SUCCESSFUL if at least one I/O 
* controller can be successfully configured.  This function will return ERROR 
* if no I/O controllers can be initialized.
*/
static void sys_pci_bus_init(UINT bus, UINT root_bus, PCI_DATA* pci_data)
{
	UINT   device, function;
	USHORT vendor, device_id;
	UINT   regno;
	ULONG  regvalue;
	USHORT regshort;
	UCHAR  regchar;
	UCHAR  intpin, intline;
	UINT   line;
	UCHAR  header_type;
	ULONG  rom_enabled;
	UINT   base_addr_reg_start;
	UINT   base_addr_reg_end;
	UINT   exp_rom_baseaddr;
	int	   multifunction;

/* bridge initialization variables */
	ULONG class_code;
	UINT  secondary_bus_number;
	UCHAR iospace_type;
	UCHAR data_byte;
	USHORT data_word;
	ULONG membase, iobase;
	ULONG memlimit, iolimit;
	int no_memory, no_io;

#ifdef DEBUG_PCI
	printf ("Configuring PCI Bus %d.\n", bus);
	printf ("PCI Root Bus %d.\n", root_bus);
	PRINT_OFF();
#endif

for (device = 0; device <= MAX_DEVICE_NUMBER; device++)
{
#ifdef DEBUG_PCI
	printf ("\nConfiguring device %d.\n\n", device);
#endif
	
	/* assume non-multifunction device at start */
	multifunction = FALSE;		
	
	for (function = 0; function < MAX_FUNCTION_NUMBER; function ++)
	{

#ifdef DEBUG_PCI
		printf ("Configuring function %d.\n", function);
#endif	  
	  /* To determine whether a device is installed in a particular slot, */
	  /* we attempt to read the vendor ID from that slot.  If there's     */
	  /* nothing there, the bridge should return 0xffff (and signal a     */
	  /* master abort).  Otherwise, there is something there and we need  */
	  /* to configure it.                                                 */
	  if ((sys_read_config_word(bus, device, function, VENDOR_ID_OFFSET, &vendor) == ERROR) || (vendor == 0xffff)) 
		{
	   	/* This means no device found */
#ifdef DEBUG_PCI
			printf ("\nNo device.\n");
#endif
			break;		/* Go on to the next device */
		}

	  /* We'll only get here if we got a real device/function */
		
		/* Count the number of devices */
		if (function == 0) (pci_data->num_devices)++;
		
		/* Count the number of functions */
		(pci_data->num_functions)++;

#ifdef DEBUG_PCI
		printf ("Vendor:  %x\n", vendor);
#endif

	  /* Read the Device ID */
		sys_read_config_word (bus,device,function,DEVICE_ID_OFFSET,&device_id);

#ifdef DEBUG_PCI
		printf("\n");
		printf("Configuring PCI Bus   : %d\n", bus);
		printf("            PCI Device: %d\n", device);
		printf("            Vendor Id : 0x%08X\n", vendor);
		printf("            Device Id : 0x%08X\n", device_id);
#endif

	  /* Read the Configuration Header Type to determine configuration */
	  if (sys_read_config_byte (bus,device,function,HEADER_TYPE_OFFSET,&header_type)== ERROR) continue;

		/* determine if multifunction device */
		if ((header_type & MULTIFUNCTION_DEVICE) && (function == 0))
		{
#ifdef DEBUG_PCI
			printf ("Multifunction Device Found...\n");
#endif
			multifunction = TRUE;
		}

		/* strip off multifunction device indicator bit */
		header_type &= 0x7f;

		switch (header_type)
		{
			case STANDARD_HEADER:
		    base_addr_reg_start = 0x10;	/* Base Address Reg. Start Offset      */
		    base_addr_reg_end =	0x24;	/* Base Address Reg. End Offset        */
		    exp_rom_baseaddr = 0x30;	/* Expansion ROM Base Addr. Reg Offset */
		    break;

			case PCITOPCI_HEADER:
		    base_addr_reg_start = 0x10;	/* Base Address Reg. Start Offset      */
		    base_addr_reg_end =	0x14;	/* Base Address Reg. End Offset        */
		    exp_rom_baseaddr = 0x38;	/* Expansion ROM Base Addr. Reg Offset */
		    break;

			default:
		    printf ("Header Type Not Supported, 0x%02X\n", header_type);
		    continue;	/* skip over device */
		    break;
		}

		/* We cycle through the base registers, first writing out all  */
		/* ones to the register, then reading it back to determine the */
		/* requested size in either I/O or memory space.  Then we      */
		/* align the top of memory or i/o space pointer, write it to   */
		/* the register, and increment it.  I say we so you won't feel */
		/* excluded.                                                   */
		for (regno = base_addr_reg_start; regno <= base_addr_reg_end; regno += 4) 
		{	
		
			/* Write out all 1's to the base register, then read it back */
			regvalue = 0xffffffff;
			sys_write_config_dword(bus,device,function,regno,(UINT32*)&regvalue);
			sys_read_config_dword (bus,device,function,regno,(UINT32*)&regvalue);

			/* Some number of the lower bits of regvalue will be clear */
			/* indicating a don't care position.  The more clear bits, */
			/* the larger the requested mapping space. */

			if (regvalue == 0)				/* ...this reg not used. */
				;

			/*---------------------------------------------------------*/
			/* I/O space mapping                                       */
			/*---------------------------------------------------------*/
			else if ((regvalue & 3) == 1) /* ...this is I/O space */
			{	
				ULONG requested_size;

				/* Align iospace_ptr for the requested size.  All bit */
				/* positions clear in regvalue must be clear in       */
				/* iospace_ptr. */
				requested_size = ~(regvalue & 0xfffffffe);

#ifdef DEBUG_PCI
				printf ("Configuration for I/O space...\n");
				printf ("Size request:  %x; ", requested_size);
				printf ("IOspace_ptr:   %x\n", iospace_ptr[root_bus]);
#endif

				/* check to make sure that there is enought iospace left to grant */
				if ((iospace_ptr[root_bus] + requested_size) > iospace_limit[root_bus])
				{
					printf ("\nPCI Configuration ERROR: Out of I/O Space on Bus %d!\n", bus);
					printf ("  No I/O Space Allocated to Device %d, Function %d.\n", device, function);
					return;
				}

				/* Align the space pointer if necessary */
				if (iospace_ptr[root_bus] & requested_size) 
				{
					iospace_ptr[root_bus] &= ~requested_size;
					iospace_ptr[root_bus] += requested_size + 1;
				}
#ifdef DEBUG_PCI
				printf("Adjusted I/O Space Ptr:  %x\n", iospace_ptr[root_bus]);
	    		printf("       I/O Space Size : 0x%08X\n", requested_size);
	    		printf("       I/O Space Base : 0x%08X\n", iospace_ptr[root_bus]);
#endif				/* Write out the adjusted iospace pointer. */
				
				sys_write_config_dword (bus,device,function,regno,(UINT32*)&iospace_ptr[root_bus]);

				/* Update space pointer */
				iospace_ptr[root_bus] += requested_size + 1;
			}

			/*---------------------------------------------------------*/
			/* Memory space mapping                                    */
			/*---------------------------------------------------------*/
			else if ((regvalue & 1) == 0)  /* ...this is memory space */
			{
				ULONG requested_size;

				/* Type is encoded in bits 1 and 2 */
				/* 64 bit space (10) is an error for the moment, as is */
				/* the reserved value, 11. */
				if (regvalue & 0x4)	
				{
					printf ("Type error in base register.\n");
					break;
				}

				/* Align memspace_ptr for the requested size.  All bit */
				/* positions clear in regvalue must be clear in        */
				/* memspace_ptr. */
				requested_size = ~(regvalue & 0xfffffff0);

#ifdef DEBUG_PCI
				printf ("Configuration for memory space.\n");
				printf ("Size request:  %x; ", requested_size);
				printf ("Membase_ptr:  %x\n", memspace_ptr[root_bus]);
#endif
				
							
				/* check to make sure that there is enough memspace left to grant */
				if ((memspace_ptr[root_bus] + requested_size) > memspace_limit[root_bus])
				{
					printf ("\nPCI Configuration ERROR: Out of Memory Space on Bus %d!\n", bus);					
					printf ("  No Memory Space Allocated to Device %d, Function %d.\n", device, function);					
					printf ("Root Bus = %d, Memory Ptr = 0x%08X, Requested Size = 0x%08X, Memory Limit = 0x%08X\n",					
								 root_bus, memspace_ptr[root_bus], requested_size, memspace_limit[root_bus]);					
	
					return;
				}
					
				if (memspace_ptr[root_bus] & requested_size) 
				{
					memspace_ptr[root_bus] &= ~requested_size;
					memspace_ptr[root_bus] += requested_size + 1;
				}

#ifdef DEBUG_PCI
				printf ("Adjusted Membase_ptr:  %x\n", memspace_ptr[root_bus]);
	    		printf("    Memory Space Size : 0x%08X\n", requested_size);
	    		printf("    Memory Space Base : 0x%08X\n", memspace_ptr[root_bus]);
#endif
				/* Write out the adjusted memory pointer */
				sys_write_config_dword (bus,device,function,regno,(UINT32*)&memspace_ptr[root_bus]);
				memspace_ptr[root_bus] += requested_size + 1;
			}	
		}
		
		/*-------------------------------------------------------------*/
		/* Expansion ROM mapping                                       */
		/* The expansion ROM is handled in the same way as the other   */
		/* PCI base registers.  If the lowest bit in this register is  */
		/* set, memory-mapped accesses are not possible, since the ROM */
		/* is active.  (Only one decoder).                             */
		/*-------------------------------------------------------------*/

		/* Store the state of the ROM enabled bit so we can restore it */
		sys_read_confi

⌨️ 快捷键说明

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