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

📄 pmac_pci.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
			 (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)			 + (offset & ~3));	} else {		/* See pci_read_config_byte */		out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);	}	udelay(2);	out_le16((volatile unsigned short *)(bp->cfg_data + (offset & 3)), val);	return PCIBIOS_SUCCESSFUL;}__pmacint pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,				    unsigned char offset, unsigned int val){	struct bridge_data *bp;	if (bus > max_bus || (bp = bridges[bus]) == 0)		return PCIBIOS_DEVICE_NOT_FOUND;	if ((offset & 3) != 0)		return PCIBIOS_BAD_REGISTER_NUMBER;	if (bus == bp->bus_number) {		if (dev_fn < (11 << 3))			return PCIBIOS_DEVICE_NOT_FOUND;		out_le32(bp->cfg_addr,			 (1UL << (dev_fn >> 3)) + ((dev_fn & 7) << 8)			 + offset);	} else {		/* See pci_read_config_byte */		out_le32(bp->cfg_addr, (bus << 16) + (dev_fn << 8) + (offset & ~3) + 1);	}	udelay(2);	out_le32((volatile unsigned int *)bp->cfg_data, val);	return PCIBIOS_SUCCESSFUL;}#define GRACKLE_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \				 | (((o) & ~3) << 24))int grackle_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,				     unsigned char offset, unsigned char *val){	struct bridge_data *bp;	*val = 0xff;	if (bus > max_bus || (bp = bridges[bus]) == 0)		return PCIBIOS_DEVICE_NOT_FOUND;	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));	*val = in_8(bp->cfg_data + (offset & 3));	return PCIBIOS_SUCCESSFUL;}int grackle_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,				     unsigned char offset, unsigned short *val){	struct bridge_data *bp;	*val = 0xffff;	if (bus > max_bus || (bp = bridges[bus]) == 0)		return PCIBIOS_DEVICE_NOT_FOUND;	if ((offset & 1) != 0)		return PCIBIOS_BAD_REGISTER_NUMBER;	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));	*val = in_le16((volatile unsigned short *)(bp->cfg_data + (offset&3)));	return PCIBIOS_SUCCESSFUL;}int grackle_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,				      unsigned char offset, unsigned int *val){	struct bridge_data *bp;	*val = 0xffffffff;	if (bus > max_bus || (bp = bridges[bus]) == 0)		return PCIBIOS_DEVICE_NOT_FOUND;	if ((offset & 3) != 0)		return PCIBIOS_BAD_REGISTER_NUMBER;	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));	*val = in_le32((volatile unsigned int *)bp->cfg_data);	return PCIBIOS_SUCCESSFUL;}int grackle_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,				      unsigned char offset, unsigned char val){	struct bridge_data *bp;	if (bus > max_bus || (bp = bridges[bus]) == 0)		return PCIBIOS_DEVICE_NOT_FOUND;	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));	out_8(bp->cfg_data + (offset & 3), val);	return PCIBIOS_SUCCESSFUL;}int grackle_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,				      unsigned char offset, unsigned short val){	struct bridge_data *bp;	if (bus > max_bus || (bp = bridges[bus]) == 0)		return PCIBIOS_DEVICE_NOT_FOUND;	if ((offset & 1) != 0)		return PCIBIOS_BAD_REGISTER_NUMBER;	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));	out_le16((volatile unsigned short *)(bp->cfg_data + (offset&3)), val);	return PCIBIOS_SUCCESSFUL;}int grackle_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,				    unsigned char offset, unsigned int val){	struct bridge_data *bp;	if (bus > max_bus || (bp = bridges[bus]) == 0)		return PCIBIOS_DEVICE_NOT_FOUND;	if ((offset & 1) != 0)		return PCIBIOS_BAD_REGISTER_NUMBER;	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));	out_le32((volatile unsigned int *)bp->cfg_data, val);	return PCIBIOS_SUCCESSFUL;}/* * For a bandit bridge, turn on cache coherency if necessary. * N.B. we can't use pcibios_*_config_* here because bridges[] * is not initialized yet. */static void __init init_bandit(struct bridge_data *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((volatile unsigned int *)bp->cfg_data);	if (vendev == (BANDIT_DEVID << 16) + APPLE_VENDID) {		/* 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 at %p\n",			       rev, bp->io_base);	} else if (vendev != (BANDIT_DEVID_2 << 16) + APPLE_VENDID) {		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);		return;	}	/* 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 at %p\n",		       rev, bp->io_base);	/* read the word at offset 0x50 */	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);	udelay(2);	magic = in_le32((volatile unsigned int *)bp->cfg_data);	if ((magic & BANDIT_COHERENT) != 0)		return;	magic |= BANDIT_COHERENT;	udelay(2);	out_le32((volatile unsigned int *)bp->cfg_data, magic);	printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %p\n",	       bp->io_base);}#define GRACKLE_PICR1_STG		0x00000040#define GRACKLE_PICR1_LOOPSNOOP		0x00000010/* N.B. this is called before bridges is initialized, so we can't   use grackle_pcibios_{read,write}_config_dword. */static inline void grackle_set_stg(struct bridge_data *bp, int enable){	unsigned int val;	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));	val = in_le32((volatile unsigned int *)bp->cfg_data);	val = enable? (val | GRACKLE_PICR1_STG) :		(val & ~GRACKLE_PICR1_STG);	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));	out_le32((volatile unsigned int *)bp->cfg_data, val);}static inline void grackle_set_loop_snoop(struct bridge_data *bp, int enable){	unsigned int val;	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));	val = in_le32((volatile unsigned int *)bp->cfg_data);	val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :		(val & ~GRACKLE_PICR1_LOOPSNOOP);	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));	out_le32((volatile unsigned int *)bp->cfg_data, val);}void __init pmac_find_bridges(void){	int bus;	struct bridge_data *bridge;	bridge_list = 0;	max_bus = 0;	add_bridges(find_devices("bandit"));	add_bridges(find_devices("chaos"));	add_bridges(find_devices("pci"));	bridges = (struct bridge_data **)		alloc_bootmem((max_bus + 1) * sizeof(struct bridge_data *));	memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *));	for (bridge = bridge_list; bridge != NULL; bridge = bridge->next)		for (bus = bridge->bus_number; bus <= bridge->max_bus; ++bus)			bridges[bus] = bridge;}/* * 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 void __init add_bridges(struct device_node *dev){	int *bus_range;	int len;	struct bridge_data *bp;	struct reg_property *addr;	for (; dev != NULL; dev = dev->next) {		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);			continue;		}		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\n",			       dev->full_name);			continue;		}		if (bus_range[1] == bus_range[0])			printk(KERN_INFO "PCI bus %d", bus_range[0]);		else			printk(KERN_INFO "PCI buses %d..%d", bus_range[0],			       bus_range[1]);		printk(" controlled by %s at %x\n", dev->name, addr->address);		if (device_is_compatible(dev, "uni-north")) {			int i = uninorth_count++;			uninorth_bridges[i].cfg_addr = ioremap(addr->address + 0x800000, 0x1000);			uninorth_bridges[i].cfg_data = ioremap(addr->address + 0xc00000, 0x1000);			uninorth_bridges[i].node = dev;			uninorth_bridges[i].iobase_phys = addr->address;			/* is 0x10000 enough for io space ? */			uninorth_bridges[i].iobase = (void *)ioremap(addr->address, 0x10000);			/* XXX This is the bridge with the PCI expansion bus. This is also the			 * address of the bus that will receive type 1 config accesses and io			 * accesses. Appears to be correct for iMac DV and G4 Sawtooth too.			 * That means that we cannot do io cycles on the AGP bus nor the internal			 * ethernet/fw bus. Fortunately, they appear not to be needed on iMac DV			 * and G4 neither.			 */			if (addr->address == 0xf2000000)				uninorth_default = i;			else				continue;		}				bp = (struct bridge_data *) alloc_bootmem(sizeof(*bp));		if (device_is_compatible(dev, "uni-north")) {			bp->cfg_addr = 0;			bp->cfg_data = 0;			bp->io_base = uninorth_bridges[uninorth_count-1].iobase;			bp->io_base_phys = uninorth_bridges[uninorth_count-1].iobase_phys;		} else if (strcmp(dev->name, "pci") == 0) {			/* XXX assume this is a mpc106 (grackle) */			bp->cfg_addr = (volatile unsigned int *)				ioremap(0xfec00000, 0x1000);			bp->cfg_data = (volatile unsigned char *)				ioremap(0xfee00000, 0x1000);			bp->io_base_phys = 0xfe000000;                        bp->io_base = (void *) ioremap(0xfe000000, 0x20000);                        if (machine_is_compatible("AAPL,PowerBook1998"))                        	grackle_set_loop_snoop(bp, 1);#if 0 			/* Disabled for now, HW problems ??? */			grackle_set_stg(bp, 1);#endif		} else {			/* a `bandit' or `chaos' bridge */			bp->cfg_addr = (volatile unsigned int *)				ioremap(addr->address + 0x800000, 0x1000);			bp->cfg_data = (volatile unsigned char *)				ioremap(addr->address + 0xc00000, 0x1000);			bp->io_base_phys = addr->address;			bp->io_base = (void *) ioremap(addr->address, 0x10000);		}		if (isa_io_base == 0)			isa_io_base = (unsigned long) bp->io_base;		bp->bus_number = bus_range[0];		bp->max_bus = bus_range[1];		bp->next = bridge_list;		bp->node = dev;		bridge_list = bp;		if (bp->max_bus > max_bus)			max_bus = bp->max_bus;		if (strcmp(dev->name, "bandit") == 0)			init_bandit(bp);	}}/* Recursively searches any node that is of type PCI-PCI bridge. Without * this, the old code would miss children of P2P bridges and hence not * fix IRQ's for cards located behind P2P bridges. * - Ranjit Deshpande, 01/20/99 */void __initfix_intr(struct device_node *node, struct pci_dev *dev){	unsigned int *reg, *class_code;	for (; node != 0;node = node->sibling) {		class_code = (unsigned int *) get_property(node, "class-code", 0);		if(class_code && (*class_code >> 8) == PCI_CLASS_BRIDGE_PCI)			fix_intr(node->child, dev);		reg = (unsigned int *) get_property(node, "reg", 0);		if (reg == 0 || ((reg[0] >> 8) & 0xff) != dev->devfn)			continue;		/* this is the node, see if it has interrupts */		if (node->n_intrs > 0) 			dev->irq = node->intrs[0].line;		break;	}}void __initpmac_pcibios_fixup(void){	struct pci_dev *dev;		/*	 * FIXME: This is broken: We should not assign IRQ's to IRQless	 *	  devices (look at PCI_INTERRUPT_PIN) and we also should	 *	  honor the existence of multi-function devices where	 *	  different functions have different interrupt pins. [mj]	 */	pci_for_each_dev(dev)	{		/*		 * Open Firmware often doesn't initialize the,		 * PCI_INTERRUPT_LINE config register properly, so we		 * should find the device node and se if it has an		 * AAPL,interrupts property.		 */		struct bridge_data *bp = bridges[dev->bus->number];		unsigned char pin;					if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||		    !pin)			continue; /* No interrupt generated -> no fixup */		/* We iterate all instances of uninorth for now */			if (uninorth_count && dev->bus->number == 0) {			int i;			for (i=0;i<uninorth_count;i++)				fix_intr(uninorth_bridges[i].node->child, dev);		} else                	fix_intr(bp->node->child, dev);	}}void __initpmac_setup_pci_ptrs(void){	struct device_node* np;	np = find_devices("pci");	if (np != 0)	{		if (device_is_compatible(np, "uni-north"))		{			/* looks like an Core99 powermac */			set_config_access_method(uni);		} else		{			/* looks like a G3 powermac */			set_config_access_method(grackle);		}	} else	{		set_config_access_method(pmac);	}		ppc_md.pcibios_fixup = pmac_pcibios_fixup;}

⌨️ 快捷键说明

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