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

📄 pci.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	default:		return PCIBIOS_DEVICE_NOT_FOUND;	}	/*	 * Note: the caller has already checked that offset is	 * suitably aligned and that len is 1, 2 or 4.	 */	switch (len) {	case 1:		*val = in_8((u8 *)addr);		break;	case 2:		*val = in_le16((u16 *)addr);		break;	default:		*val = in_le32((u32 *)addr);		break;	}	return PCIBIOS_SUCCESSFUL;}static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,				     int offset, int len, u32 val){	struct pci_controller *hose;	unsigned long addr;	hose = pci_bus_to_host(bus);	if (hose == NULL)		return PCIBIOS_DEVICE_NOT_FOUND;	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);	if (!addr)		return PCIBIOS_DEVICE_NOT_FOUND;	switch (u3_ht_skip_device(hose, bus, devfn)) {	case 0:		break;	case 1:		return PCIBIOS_SUCCESSFUL;	default:		return PCIBIOS_DEVICE_NOT_FOUND;	}	/*	 * Note: the caller has already checked that offset is	 * suitably aligned and that len is 1, 2 or 4.	 */	switch (len) {	case 1:		out_8((u8 *)addr, val);		(void) in_8((u8 *)addr);		break;	case 2:		out_le16((u16 *)addr, val);		(void) in_le16((u16 *)addr);		break;	default:		out_le32((u32 *)addr, val);		(void) in_le32((u32 *)addr);		break;	}	return PCIBIOS_SUCCESSFUL;}static struct pci_ops u3_ht_pci_ops ={	u3_ht_read_config,	u3_ht_write_config};#endif /* CONFIG_PPC64 */#ifdef CONFIG_PPC32/* * For a bandit bridge, turn on cache coherency if necessary. * N.B. we could clean this up using the hose ops directly. */static void __init init_bandit(struct pci_controller *bp){	unsigned int vendev, magic;	int rev;	/* read the word at offset 0 in config space for device 11 */	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);	udelay(2);	vendev = in_le32(bp->cfg_data);	if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) +			PCI_VENDOR_ID_APPLE) {		/* read the revision id */		out_le32(bp->cfg_addr,			 (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);		udelay(2);		rev = in_8(bp->cfg_data);		if (rev != BANDIT_REVID)			printk(KERN_WARNING			       "Unknown revision %d for bandit\n", rev);	} else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);		return;	}	/* read the word at offset 0x50 */	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);	udelay(2);	magic = in_le32(bp->cfg_data);	if ((magic & BANDIT_COHERENT) != 0)		return;	magic |= BANDIT_COHERENT;	udelay(2);	out_le32(bp->cfg_data, magic);	printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");}/* * Tweak the PCI-PCI bridge chip on the blue & white G3s. */static void __init init_p2pbridge(void){	struct device_node *p2pbridge;	struct pci_controller* hose;	u8 bus, devfn;	u16 val;	/* XXX it would be better here to identify the specific	   PCI-PCI bridge chip we have. */	if ((p2pbridge = find_devices("pci-bridge")) == 0	    || p2pbridge->parent == NULL	    || strcmp(p2pbridge->parent->name, "pci") != 0)		return;	if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {		DBG("Can't find PCI infos for PCI<->PCI bridge\n");		return;	}	/* Warning: At this point, we have not yet renumbered all busses.	 * So we must use OF walking to find out hose	 */	hose = pci_find_hose_for_OF_device(p2pbridge);	if (!hose) {		DBG("Can't find hose for PCI<->PCI bridge\n");		return;	}	if (early_read_config_word(hose, bus, devfn,				   PCI_BRIDGE_CONTROL, &val) < 0) {		printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");		return;	}	val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;	early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);}/* * Some Apple desktop machines have a NEC PD720100A USB2 controller * on the motherboard. Open Firmware, on these, will disable the * EHCI part of it so it behaves like a pair of OHCI's. This fixup * code re-enables it ;) */static void __init fixup_nec_usb2(void){	struct device_node *nec;	for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {		struct pci_controller *hose;		u32 data, *prop;		u8 bus, devfn;		prop = (u32 *)get_property(nec, "vendor-id", NULL);		if (prop == NULL)			continue;		if (0x1033 != *prop)			continue;		prop = (u32 *)get_property(nec, "device-id", NULL);		if (prop == NULL)			continue;		if (0x0035 != *prop)			continue;		prop = (u32 *)get_property(nec, "reg", NULL);		if (prop == NULL)			continue;		devfn = (prop[0] >> 8) & 0xff;		bus = (prop[0] >> 16) & 0xff;		if (PCI_FUNC(devfn) != 0)			continue;		hose = pci_find_hose_for_OF_device(nec);		if (!hose)			continue;		early_read_config_dword(hose, bus, devfn, 0xe4, &data);		if (data & 1UL) {			printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n");			data &= ~1UL;			early_write_config_dword(hose, bus, devfn, 0xe4, data);			early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE,				nec->intrs[0].line);		}	}}static void __init setup_bandit(struct pci_controller *hose,				struct reg_property *addr){	hose->ops = &macrisc_pci_ops;	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);	init_bandit(hose);}static int __init setup_uninorth(struct pci_controller *hose,				 struct reg_property *addr){	pci_assign_all_buses = 1;	has_uninorth = 1;	hose->ops = &macrisc_pci_ops;	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);	/* We "know" that the bridge at f2000000 has the PCI slots. */	return addr->address == 0xf2000000;}#endif#ifdef CONFIG_PPC64static void __init setup_u3_agp(struct pci_controller* hose){	/* On G5, we move AGP up to high bus number so we don't need	 * to reassign bus numbers for HT. If we ever have P2P bridges	 * on AGP, we'll have to move pci_assign_all_busses to the	 * pci_controller structure so we enable it for AGP and not for	 * HT childs.	 * We hard code the address because of the different size of	 * the reg address cell, we shall fix that by killing struct	 * reg_property and using some accessor functions instead	 */	hose->first_busno = 0xf0;	hose->last_busno = 0xff;	has_uninorth = 1;	hose->ops = &macrisc_pci_ops;	hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);	hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);	u3_agp = hose;}static void __init setup_u3_ht(struct pci_controller* hose){	struct device_node *np = (struct device_node *)hose->arch_data;	int i, cur;	hose->ops = &u3_ht_pci_ops;	/* We hard code the address because of the different size of	 * the reg address cell, we shall fix that by killing struct	 * reg_property and using some accessor functions instead	 */	hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000,							   0x02000000);	/*	 * /ht node doesn't expose a "ranges" property, so we "remove"	 * regions that have been allocated to AGP. So far, this version of	 * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions	 * to /ht. We need to fix that sooner or later by either parsing all	 * child "ranges" properties or figuring out the U3 address space	 * decoding logic and then read its configuration register (if any).	 */	hose->io_base_phys = 0xf4000000;	hose->pci_io_size = 0x00400000;	hose->io_resource.name = np->full_name;	hose->io_resource.start = 0;	hose->io_resource.end = 0x003fffff;	hose->io_resource.flags = IORESOURCE_IO;	hose->pci_mem_offset = 0;	hose->first_busno = 0;	hose->last_busno = 0xef;	hose->mem_resources[0].name = np->full_name;	hose->mem_resources[0].start = 0x80000000;	hose->mem_resources[0].end = 0xefffffff;	hose->mem_resources[0].flags = IORESOURCE_MEM;	u3_ht = hose;	if (u3_agp == NULL) {		DBG("U3 has no AGP, using full resource range\n");		return;	}	/* We "remove" the AGP resources from the resources allocated to HT,	 * that is we create "holes". However, that code does assumptions	 * that so far happen to be true (cross fingers...), typically that	 * resources in the AGP node are properly ordered	 */	cur = 0;	for (i=0; i<3; i++) {		struct resource *res = &u3_agp->mem_resources[i];		if (res->flags != IORESOURCE_MEM)			continue;		/* We don't care about "fine" resources */		if (res->start >= 0xf0000000)			continue;		/* Check if it's just a matter of "shrinking" us in one		 * direction		 */		if (hose->mem_resources[cur].start == res->start) {			DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",			    cur, hose->mem_resources[cur].start,			    res->end + 1);			hose->mem_resources[cur].start = res->end + 1;			continue;		}		if (hose->mem_resources[cur].end == res->end) {			DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",			    cur, hose->mem_resources[cur].end,			    res->start - 1);			hose->mem_resources[cur].end = res->start - 1;			continue;		}		/* No, it's not the case, we need a hole */		if (cur == 2) {			/* not enough resources for a hole, we drop part			 * of the range			 */			printk(KERN_WARNING "Running out of resources"			       " for /ht host !\n");			hose->mem_resources[cur].end = res->start - 1;			continue;		}		cur++;		DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",		    cur-1, res->start - 1, cur, res->end + 1);		hose->mem_resources[cur].name = np->full_name;		hose->mem_resources[cur].flags = IORESOURCE_MEM;		hose->mem_resources[cur].start = res->end + 1;		hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;		hose->mem_resources[cur-1].end = res->start - 1;	}}#endif/* * We assume that if we have a G3 powermac, we have one bridge called * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, * if we have one or more bandit or chaos bridges, we don't have a MPC106. */static int __init add_bridge(struct device_node *dev){	int len;	struct pci_controller *hose;#ifdef CONFIG_PPC32	struct reg_property *addr;#endif	char *disp_name;	int *bus_range;	int primary = 1;	DBG("Adding PCI host bridge %s\n", dev->full_name);#ifdef CONFIG_PPC32	/* XXX fix this */	addr = (struct reg_property *) get_property(dev, "reg", &len);	if (addr == NULL || len < sizeof(*addr)) {		printk(KERN_WARNING "Can't use %s: no address\n",		       dev->full_name);		return -ENODEV;	}#endif	bus_range = (int *) get_property(dev, "bus-range", &len);	if (bus_range == NULL || len < 2 * sizeof(int)) {		printk(KERN_WARNING "Can't get bus-range for %s, assume"		       " bus 0\n", dev->full_name);	}	/* XXX Different prototypes, to be merged */#ifdef CONFIG_PPC64	hose = pcibios_alloc_controller(dev);#else	hose = pcibios_alloc_controller();#endif	if (!hose)		return -ENOMEM;	hose->arch_data = dev;	hose->first_busno = bus_range ? bus_range[0] : 0;	hose->last_busno = bus_range ? bus_range[1] : 0xff;	disp_name = NULL;#ifdef CONFIG_PPC64	if (device_is_compatible(dev, "u3-agp")) {		setup_u3_agp(hose);		disp_name = "U3-AGP";		primary = 0;	} else if (device_is_compatible(dev, "u3-ht")) {		setup_u3_ht(hose);		disp_name = "U3-HT";

⌨️ 快捷键说明

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