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

📄 pseries_pci.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 2 页
字号:
					res->end =   range.parent_addr + range.size - 1;#endif					res->parent = NULL;					res->sibling = NULL;					res->child = NULL;				}			  	break;			}		}		PPCDBG(PPCDBG_PHBINIT, "\tphb->io_base_phys   = 0x%lx\n", 		       phb->io_base_phys); 		PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%lx\n", 		       phb->pci_mem_offset); 		if (naca->interrupt_controller == IC_OPEN_PIC) {			int addr = root_addr_size_words * (index + 2) - 1;			openpic_setup_ISU(index, opprop[addr]); 		}		index++;	}	pci_devs_phb_init();	return 0;	 /*Success */}/****************************************************************** * * Allocate and partially initialize a structure to represent a PHB. * ******************************************************************/struct pci_controller *alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words){	struct pci_controller *phb;	unsigned int *ui_ptr = NULL, len;	struct reg_property64 reg_struct;	int *bus_range;	int *buid_vals;	PPCDBG(PPCDBG_PHBINIT, "alloc_phb: %s\n", dev->full_name); 	PPCDBG(PPCDBG_PHBINIT, "\tdev             = 0x%lx\n", dev); 	PPCDBG(PPCDBG_PHBINIT, "\tmodel           = 0x%lx\n", model); 	PPCDBG(PPCDBG_PHBINIT, "\taddr_size_words = 0x%lx\n", addr_size_words);   	/* Found a PHB, now figure out where his registers are mapped. */	ui_ptr = (unsigned int *) get_property(dev, "reg", &len);	if (ui_ptr == NULL) {		PPCDBG(PPCDBG_PHBINIT, "\tget reg failed.\n"); 		return(NULL);	}	if (addr_size_words == 1) {		reg_struct.address = ((struct reg_property32 *)ui_ptr)->address;		reg_struct.size    = ((struct reg_property32 *)ui_ptr)->size;	} else {		reg_struct = *((struct reg_property64 *)ui_ptr);	}	PPCDBG(PPCDBG_PHBINIT, "\treg_struct.address = 0x%lx\n", reg_struct.address);	PPCDBG(PPCDBG_PHBINIT, "\treg_struct.size    = 0x%lx\n", reg_struct.size); 	/***************************************************************	* Set chip specific data in the phb, including types & 	* register pointers.	***************************************************************/	/****************************************************************	* Python	***************************************************************/	if (strstr(model, "Python")) {		PPCDBG(PPCDBG_PHBINIT, "\tCreate python\n");	        phb = pci_alloc_pci_controller("PHB PY",phb_type_python);		if (phb == NULL) return NULL;	       		phb->cfg_addr = (volatile unsigned long *) 			ioremap(reg_struct.address + 0xf8000, PAGE_SIZE);		PPCDBG(PPCDBG_PHBINIT, "\tcfg_addr_r = 0x%lx\n", 		       reg_struct.address + 0xf8000);		PPCDBG(PPCDBG_PHBINIT, "\tcfg_addr_v = 0x%lx\n", 		       phb->cfg_addr);		phb->cfg_data = (char*)(phb->cfg_addr + 0x02);       		phb->phb_regs = (volatile unsigned long *) 			ioremap(reg_struct.address + 0xf7000, PAGE_SIZE);		/* Python's register file is 1 MB in size. */		phb->chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 					 0x100000); 		/* 		 * Firmware doesnt always clear this bit which is critical		 * for good performance - Anton		 */		{			volatile u32 *tmp, i;#define PRG_CL_RESET_VALID 0x00010000			tmp = (u32 *)((unsigned long)phb->chip_regs + 0xf6030);			if (*tmp & PRG_CL_RESET_VALID) {				printk("Python workaround: ");				*tmp &= ~PRG_CL_RESET_VALID;				/*				 * We must read it back for changes to				 * take effect				 */				i = *tmp;				printk("reg0: %x\n", i);			}		}	/***************************************************************	* Speedwagon	***************************************************************/	} else if (strstr(model, "Speedwagon")) {		PPCDBG(PPCDBG_PHBINIT, "\tCreate speedwagon\n");	        phb = pci_alloc_pci_controller("PHB SW",phb_type_speedwagon);		if (phb == NULL) return NULL;		if (_machine == _MACH_pSeries) {			phb->cfg_addr = (volatile unsigned long *) 			  ioremap(reg_struct.address + 0x140, PAGE_SIZE);			phb->cfg_data = (char*)(phb->cfg_addr - 0x02); /* minus is correct */			phb->phb_regs = (volatile unsigned long *) 			  ioremap(reg_struct.address, PAGE_SIZE);			/* Speedwagon's register file is 1 MB in size. */			phb->chip_regs = ioremap(reg_struct.address & ~(0xfffffUL),						 0x100000); 			PPCDBG(PPCDBG_PHBINIT, "\tmapping chip_regs from 0x%lx -> 0x%lx\n", 			       reg_struct.address & 0xfffff, phb->chip_regs);		} else {			phb->cfg_addr = NULL;			phb->cfg_data = NULL; 			phb->phb_regs = NULL;			phb->chip_regs = NULL;		}		phb->local_number = ((reg_struct.address >> 12) & 0xf) - 0x8;	/***************************************************************	* Trying to build a known just gets the code in trouble.	***************************************************************/	} else { 		PPCDBG(PPCDBG_PHBINIT, "\tUnknown PHB Type!\n");		printk("PCI: Unknown Phb Type!\n");		return NULL;	}	bus_range = (int *) get_property(dev, "bus-range", &len);	if (bus_range == NULL || len < 2 * sizeof(int)) {		PPCDBG(PPCDBG_PHBINIT, "Can't get bus-range for %s\n", dev->full_name);		kfree(phb);		return(NULL);	}	/***************************************************************	* Finished with the initialization	***************************************************************/	phb->first_busno =  bus_range[0];	phb->last_busno  =  bus_range[1];	phb->arch_data   = dev;	phb->ops = &rtas_pci_ops;	buid_vals = (int *) get_property(dev, "ibm,fw-phb-id", &len);	if (buid_vals == NULL || len < 2 * sizeof(int)) {		phb->buid = 0;	} else {		/* Big bus system.  These systems start new bus numbers under		 * each phb.  Until pci domains are standard, we depend on a		 * patch which makes bus numbers ints and we shift the phb		 * number into the upper bits.		 */		struct pci_bus check;		if (sizeof(check.number) == 1 || sizeof(check.primary) == 1 ||		    sizeof(check.secondary) == 1 || sizeof(check.subordinate) == 1) {			udbg_printf("pSeries_pci:  this system has large bus numbers and the kernel was not\n"			      "built with the patch that fixes include/linux/pci.h struct pci_bus so\n"			      "number, primary, secondary and subordinate are ints.\n");			panic("pSeries_pci:  this system has large bus numbers and the kernel was not\n"			      "built with the patch that fixes include/linux/pci.h struct pci_bus so\n"			      "number, primary, secondary and subordinate are ints.\n");		}		phb->buid = (((unsigned long)buid_vals[0]) << 32UL) |			(((unsigned long)buid_vals[1]) & 0xffffffff);		phb->first_busno += (phb->global_number << 8);		phb->last_busno += (phb->global_number << 8);	}	/* Dump PHB information for Debug */	PPCDBGCALL(PPCDBG_PHBINIT,dumpPci_Controller(phb) );	return phb;}void fixup_resources(struct pci_dev *dev){ 	int i; 	struct pci_controller *phb = PCI_GET_PHB_PTR(dev);#ifdef CONFIG_PPC_EEH	struct device_node *dn;	unsigned long eeh_disable_bit;	/* Add IBM loc code (slot) as a prefix to the device names for service */	dn = pci_device_to_OF_node(dev);	if (dn) {		char *loc_code = get_property(dn, "ibm,loc-code", 0);		if (loc_code) {			int loc_len = strlen(loc_code);			if (loc_len < sizeof(dev->name)) {				memmove(dev->name+loc_len+1, dev->name, sizeof(dev->name)-loc_len-1);				memcpy(dev->name, loc_code, loc_len);				dev->name[loc_len] = ' ';				dev->name[sizeof(dev->name)-1] = '\0';			}		}	}	if (is_eeh_configured(dev)) {		eeh_disable_bit = 0;		printk("PCI: eeh configured for %s %s\n", dev->slot_name, dev->name);		if (eeh_set_option(dev, EEH_ENABLE) != 0) {			printk("PCI: failed to enable eeh for %s %s\n", dev->slot_name, dev->name);			eeh_disable_bit = EEH_TOKEN_DISABLED;		}	} else {		/* Assume device is by default EEH_DISABLE'd */		printk("PCI: eeh NOT configured for %s %s\n", dev->slot_name, dev->name);		eeh_disable_bit = EEH_TOKEN_DISABLED;	}#endif	PPCDBG(PPCDBG_PHBINIT, "fixup_resources:\n"); 	PPCDBG(PPCDBG_PHBINIT, "\tphb                 = 0x%016LX\n", phb); 	PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_io_offset  = 0x%016LX\n", phb->pci_io_offset); 	PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%016LX\n", phb->pci_mem_offset); 	PPCDBG(PPCDBG_PHBINIT, "\tdev->name   = %s\n", dev->name);	PPCDBG(PPCDBG_PHBINIT, "\tdev->vendor:device = 0x%04X : 0x%04X\n", dev->vendor, dev->device);	if (phb == NULL)		return; 	for (i = 0; i <  DEVICE_COUNT_RESOURCE; ++i) {		PPCDBG(PPCDBG_PHBINIT, "\tdevice %x.%x[%d] (flags %x) [%lx..%lx]\n",			    dev->bus->number, dev->devfn, i,			    dev->resource[i].flags,			    dev->resource[i].start,			    dev->resource[i].end);		if ((dev->resource[i].start == 0) && (dev->resource[i].end == 0)) {			continue;		}		if (dev->resource[i].flags & IORESOURCE_IO) {#ifdef CONFIG_PPC_EEH			unsigned int busno = dev->bus ? dev->bus->number : 0;			unsigned long size = dev->resource[i].end - dev->resource[i].start;			unsigned long addr = (unsigned long)__ioremap(dev->resource[i].start + phb->io_base_phys, size, _PAGE_NO_CACHE);			if (!addr)				panic("fixup_resources: ioremap failed!\n");			dev->resource[i].start = eeh_token(phb->global_number, busno, dev->devfn, addr) | eeh_disable_bit;			dev->resource[i].end = dev->resource[i].start + size;#else			unsigned long offset = (unsigned long)phb->io_base_virt;			dev->resource[i].start += offset;			dev->resource[i].end += offset;#endif			PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx .. %lx]\n",			       dev->resource[i].start, dev->resource[i].end);		} else if (dev->resource[i].flags & IORESOURCE_MEM) {			if (dev->resource[i].start == 0) {				/* Bogus.  Probably an unused bridge. */				dev->resource[i].end = 0;			} else {#ifdef CONFIG_PPC_EEH				unsigned int busno = dev->bus ? dev->bus->number : 0;				unsigned long size = dev->resource[i].end - dev->resource[i].start;				unsigned long addr = (unsigned long)__ioremap(dev->resource[i].start + phb->pci_mem_offset, size, _PAGE_NO_CACHE);				if (!addr)					panic("fixup_resources: ioremap failed!\n");				dev->resource[i].start = eeh_token(phb->global_number, busno, dev->devfn, addr) | eeh_disable_bit;				dev->resource[i].end = dev->resource[i].start + size;#else				dev->resource[i].start += phb->pci_mem_offset;				dev->resource[i].end += phb->pci_mem_offset;#endif			}			PPCDBG(PPCDBG_PHBINIT, "\t\t-> now [%lx..%lx]\n",			       dev->resource[i].start, dev->resource[i].end);		} else {			continue;		} 		/* zap the 2nd function of the winbond chip */ 		if (dev->resource[i].flags & IORESOURCE_IO 		    && dev->bus->number == 0 && dev->devfn == 0x81) 			dev->resource[i].flags &= ~IORESOURCE_IO; 	}}   static void check_s7a(void){	struct device_node *root;	char *model;	root = find_path_device("/");	if (root) {		model = get_property(root, "model", NULL);		if (model && !strcmp(model, "IBM,7013-S7A"))			s7a_workaround = 1;	}}void __initpSeries_pcibios_fixup(void){	struct pci_dev *dev;	PPCDBG(PPCDBG_PHBINIT, "pSeries_pcibios_fixup: start\n");	pci_assign_all_busses = 0;	check_s7a();		pci_for_each_dev(dev) {		pci_read_irq_line(dev);		PPCDBGCALL(PPCDBG_PHBINIT, dumpPci_Dev(dev) );	}	if (naca->interrupt_controller == IC_PPC_XIC) {		xics_isa_init(); 	}}/***********************************************************************  * pci_find_hose_for_OF_device * * This function finds the PHB that matching device_node in the  * OpenFirmware by scanning all the pci_controllers. *  ***********************************************************************/struct pci_controller*pci_find_hose_for_OF_device(struct device_node *node){	while (node) {		struct pci_controller *hose;		for (hose=hose_head;hose;hose=hose->next)			if (hose->arch_data == node)				return hose;		node=node->parent;	}	return NULL;}/***********************************************************************  * ppc64_pcibios_init *   * Chance to initialize and structures or variable before PCI Bus walk. *   ***********************************************************************/void pSeries_pcibios_init(void){	PPCDBG(PPCDBG_PHBINIT, "\tppc64_pcibios_init Entry.\n"); 	if (get_property(find_path_device("/rtas"),"ibm,fw-phb-id",NULL) != NULL) {		PPCDBG(PPCDBG_PHBINIT, "\tFound: ibm,fw-phb-id\n"); 		Pci_Large_Bus_System = 1;	}}/* * This is called very early before the page table is setup. */void pSeries_pcibios_init_early(void){	ppc_md.pcibios_read_config_byte = rtas_read_config_byte;	ppc_md.pcibios_read_config_word = rtas_read_config_word;	ppc_md.pcibios_read_config_dword = rtas_read_config_dword;	ppc_md.pcibios_write_config_byte = rtas_write_config_byte;	ppc_md.pcibios_write_config_word = rtas_write_config_word;	ppc_md.pcibios_write_config_dword = rtas_write_config_dword;}/************************************************************************//* Get a char* of the device physical location(U0.3-P1-I8)              *//* See the Product Topology in the RS/6000 Architecture.                *//************************************************************************/int device_Location(struct pci_dev *PciDev, char *BufPtr){	struct device_node *DevNode = (struct device_node *)PciDev->sysdata;	return sprintf(BufPtr,"PCI: Bus%3d, Device%3d, Vendor %04X, Location %-12s",		       PciDev->bus->number,		       PCI_SLOT(PciDev->devfn),		       PciDev->vendor,		       (char*)get_property(DevNode,"ibm,loc-code",0));}/************************************************************************//* Set the slot reset line to the state passed in.                      *//* This is the platform specific for code for the pci_reset_device      *//* function.                                                            *//************************************************************************/int pci_set_reset(struct pci_dev *PciDev, int state){	return -1;}

⌨️ 快捷键说明

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