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

📄 pci_serv.c

📁 移植到WLIT项目的redboot源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************** 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();#endiffor (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_config_dword (bus,device,function,exp_rom_baseaddr,(UINT32*)&regvalue);		rom_enabled = regvalue & 1;		/* Write out all 1's to the non-reserved bits of the base register, then read it back   */		regvalue = 0xffffffff;		sys_write_config_dword(bus,device,function,EXP_ROM_OFFSET,(UINT32*)&regvalue);		sys_read_config_dword (bus,device,function,EXP_ROM_OFFSET,(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 & 0xffff800) != 0)   /* No mapping if it's 0 */		{			ULONG requested_size;#ifdef DEBUG_PCI			printf ("Expansion ROM detected.\n");#endif			/* Expansion ROMs will map into memory space, so...	   */			/* Align memspace_ptr for the requested size.  All bit */			/* positions clear in regvalue must be clear in        */			/* memspace_ptr. */			requested_size = ~(regvalue & 0xfffff800);#ifdef DEBUG_PCI			printf ("Size request:  %x; ", requested_size);			printf ("Membase_ptr:  %x\n", memspace_ptr[root_bus]);#endif			/* check to make sure that there is enought 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 Expansion ROM Space Allocated to Device %d, Function %d.\n", device, function);				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("  Exp. ROM Space Size : 0x%08X\n", requested_size);			printf("  Exp. ROM Space Base : 0x%08X\n", memspace_ptr[root_bus]);#endif			/* Write out the adjusted memory pointer */			regvalue = memspace_ptr[root_bus] | rom_enabled;			sys_write_config_dword (bus,device

⌨️ 快捷键说明

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