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

📄 ip32-pci.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
字号:
/* * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2000, 2001 Keith M Wesolowski */#include <linux/kernel.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/types.h>#include <asm/pci.h>#include <asm/ip32/mace.h>#include <asm/ip32/crime.h>#include <asm/ip32/ip32_ints.h>#include <linux/delay.h>#undef DEBUG_MACE_PCI/* * O2 has up to 5 PCI devices connected into the MACE bridge.  The device * map looks like this: * * 0  aic7xxx 0 * 1  aic7xxx 1 * 2  expansion slot * 3  N/C * 4  N/C */#define chkslot(dev)							\do {									\	if ((dev)->bus->number > 0 || PCI_SLOT ((dev)->devfn) < 1	\	    || PCI_SLOT ((dev)->devfn) > 3)				\		return PCIBIOS_DEVICE_NOT_FOUND;			\} while (0)#define mkaddr(dev, where) \((((dev)->devfn & 0xffUL) << 8) | ((where) & 0xfcUL))void macepci_error (int irq, void *dev, struct pt_regs *regs);static int macepci_read_config_byte (struct pci_dev *dev, int where,				     u8 *val){	*val = 0xff;	chkslot (dev);	mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where));	*val = mace_read_8 (MACEPCI_CONFIG_DATA + ((where & 3UL) ^ 3UL));	return PCIBIOS_SUCCESSFUL;}static int macepci_read_config_word (struct pci_dev *dev, int where,				     u16 *val){	*val = 0xffff;	chkslot (dev);	if (where & 1)		return PCIBIOS_BAD_REGISTER_NUMBER; 	mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where));	*val = mace_read_16 (MACEPCI_CONFIG_DATA + ((where & 2UL) ^ 2UL));	return PCIBIOS_SUCCESSFUL;}static int macepci_read_config_dword (struct pci_dev *dev, int where,				      u32 *val){	*val = 0xffffffff;	chkslot (dev);	if (where & 3)		return PCIBIOS_BAD_REGISTER_NUMBER;	mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where));	*val = mace_read_32 (MACEPCI_CONFIG_DATA);	return PCIBIOS_SUCCESSFUL;}static int macepci_write_config_byte (struct pci_dev *dev, int where,				      u8 val){	chkslot (dev);	mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where));	mace_write_8 (MACEPCI_CONFIG_DATA + ((where & 3UL) ^ 3UL), val);	return PCIBIOS_SUCCESSFUL;}static int macepci_write_config_word (struct pci_dev *dev, int where,				      u16 val){	chkslot (dev);	if (where & 1)		return PCIBIOS_BAD_REGISTER_NUMBER;	mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where));	mace_write_16 (MACEPCI_CONFIG_DATA + ((where & 2UL) ^ 2UL), val);	return PCIBIOS_SUCCESSFUL;}static int macepci_write_config_dword (struct pci_dev *dev, int where,                                          u32 val){	chkslot (dev);	if (where & 3)		return PCIBIOS_BAD_REGISTER_NUMBER;	mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where));	mace_write_32 (MACEPCI_CONFIG_DATA, val);	return PCIBIOS_SUCCESSFUL;}static struct pci_ops macepci_ops = {	macepci_read_config_byte,	macepci_read_config_word,	macepci_read_config_dword,	macepci_write_config_byte,	macepci_write_config_word,	macepci_write_config_dword};struct pci_fixup pcibios_fixups[] = { { 0 } };void __init pcibios_init (void){	struct pci_dev *dev;	u32 start, size;	u16 cmd;	u32 base_io = 0x3000; /* The first i/o address to assign after SCSI */	u32 base_mem = 0x80100000; /* Likewise */	u32 rev = mace_read_32 (MACEPCI_REV);	int i;	printk ("MACE: PCI rev %d detected at %016lx\n", rev,		(u64) MACE_BASE + MACE_PCI);	/* These are *bus* addresses */	ioport_resource.start = 0;	ioport_resource.end = 0xffffffffUL;	iomem_resource.start = 0x80000000UL;	iomem_resource.end = 0xffffffffUL;	/* Clear any outstanding errors and enable interrupts */	mace_write_32 (MACEPCI_ERROR_ADDR, 0);	mace_write_32 (MACEPCI_ERROR_FLAGS, 0);	mace_write_32 (MACEPCI_CONTROL, 0xff008500);	crime_write_64 (CRIME_HARD_INT, 0UL);	crime_write_64 (CRIME_SOFT_INT, 0UL);	crime_write_64 (CRIME_INT_STAT, 0x000000000000ff00UL);	if (request_irq (MACE_PCI_BRIDGE_IRQ, macepci_error, 0,			 "MACE PCI error", NULL))		panic("PCI bridge can't get interrupt; can't happen.");	pci_scan_bus (0, &macepci_ops, NULL);#ifdef DEBUG_MACE_PCI	pci_for_each_dev (dev) {		printk ("Device: %d/%d/%d ARCS-assigned bus resource map\n",			dev->bus->number, PCI_SLOT (dev->devfn),			PCI_FUNC (dev->devfn));		for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {			if (dev->resource[i].start == 0)				continue;			printk ("%d: %016lx - %016lx (flags %04lx)\n",				i, dev->resource[i].start,				dev->resource[i].end, dev->resource[i].flags);		}	}#endif	/*	 * Assign sane resources to and enable all devices.  The requirement	 * for the SCSI controllers is well-known: a 256-byte I/O region	 * which we must assign, and a 1-page memory region which is	 * assigned by the system firmware.	 */	pci_for_each_dev (dev) {		switch (PCI_SLOT (dev->devfn)) {		case 1: /* SCSI bus 0 */			dev->resource[0].start = 0x1000UL;			dev->resource[0].end = 0x10ffUL;			break;		case 2: /* SCSI bus 1 */			dev->resource[0].start = 0x2000UL;			dev->resource[0].end = 0x20ffUL;			break;		default: /* Slots - I guess we have only 1 */			for (i=0; i < 6; i++) {				size = dev->resource[i].end					- dev->resource[i].start;				if (!size				    || !(dev->resource[i].flags					 & (IORESOURCE_IO|IORESOURCE_MEM))) {					dev->resource[i].start						= dev->resource[i].end = 0UL;					continue;				}				if (dev->resource[i].flags & IORESOURCE_IO) {					dev->resource[i].start = base_io;					base_io += PAGE_ALIGN (size);				} else {					dev->resource[i].start = base_mem;					base_mem += 0x100000UL;				}				dev->resource[i].end =					dev->resource[i].start + size;			}			break;		}		for (i=0; i < 6; i++) {			if (dev->resource[i].start == 0)				continue;			start = dev->resource[i].start;			if (dev->resource[i].flags & IORESOURCE_IO)				start |= 1;			pci_write_config_dword (dev,				PCI_BASE_ADDRESS_0 + (i << 2), (u32) start);		}		pci_write_config_byte (dev, PCI_CACHE_LINE_SIZE, 0x20);		pci_write_config_byte (dev, PCI_LATENCY_TIMER, 0x30);		pci_read_config_word (dev, PCI_COMMAND, &cmd);		cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SPECIAL | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY);		pci_write_config_word (dev, PCI_COMMAND, cmd);		pci_set_master (dev);	}        /*         * Fixup O2 PCI slot. Bad hack.         *//*        devtag = pci_make_tag(0, 0, 3, 0);        slot = macepci_conf_read(0, devtag, PCI_COMMAND_STATUS_REG);        slot |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE;        macepci_conf_write(0, devtag, PCI_COMMAND_STATUS_REG, slot);        slot = macepci_conf_read(0, devtag, PCI_MAPREG_START);        if (slot == 0xffffffe1)                macepci_conf_write(0, devtag, PCI_MAPREG_START, 0x00001000);        slot = macepci_conf_read(0, devtag, PCI_MAPREG_START + (2 << 2));        if ((slot & 0xffff0000) == 0) {                slot += 0x00010000;                macepci_conf_write(0, devtag, PCI_MAPREG_START + (2 << 2),                    0x00000000);        } */#ifdef DEBUG_MACE_PCI	printk ("Triggering PCI bridge interrupt...\n");	mace_write_32 (MACEPCI_ERROR_FLAGS, MACEPCI_ERROR_INTERRUPT_TEST);	pci_for_each_dev (dev) {		printk ("Device: %d/%d/%d final bus resource map\n",			dev->bus->number, PCI_SLOT (dev->devfn),			PCI_FUNC (dev->devfn));		for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {			if (dev->resource[i].start == 0)				continue;			printk ("%d: %016lx - %016lx (flags %04lx)\n",				i, dev->resource[i].start,				dev->resource[i].end, dev->resource[i].flags);		}	}#endif}/* * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of * the device (1-4 => A-D), tell what irq to use.  Note that we don't * in theory have slots 4 and 5, and we never normally use the shared * irqs.  I suppose a device without a pin A will thank us for doing it * right if there exists such a broken piece of crap. */static int __init macepci_map_irq (struct pci_dev *dev, u8 slot, u8 pin){	chkslot (dev);	if (pin == 0)		pin = 1;	switch (slot) {	case 1:		return MACEPCI_SCSI0_IRQ;	case 2:		return MACEPCI_SCSI1_IRQ;	case 3:		switch (pin) {		case 2:			return MACEPCI_SHARED0_IRQ;		case 3:			return MACEPCI_SHARED1_IRQ;		case 4:			return MACEPCI_SHARED2_IRQ;		case 1:		default:			return MACEPCI_SLOT0_IRQ;		}	case 4:		switch (pin) {		case 2:			return MACEPCI_SHARED2_IRQ;		case 3:			return MACEPCI_SHARED0_IRQ;		case 4:			return MACEPCI_SHARED1_IRQ;		case 1:		default:			return MACEPCI_SLOT1_IRQ;		}		return MACEPCI_SLOT1_IRQ;	case 5:		switch (pin) {		case 2:			return MACEPCI_SHARED1_IRQ;		case 3:			return MACEPCI_SHARED2_IRQ;		case 4:			return MACEPCI_SHARED0_IRQ;		case 1:		default:			return MACEPCI_SLOT2_IRQ;		}	default:		return 0;	}}/* * It's not entirely clear what this does in a system with no bridges. * In any case, bridges are not supported by Linux in O2. */static u8 __init macepci_swizzle (struct pci_dev *dev, u8 *pinp){	if (PCI_SLOT (dev->devfn) == 2)		*pinp = 2;	else		*pinp = 1;	return PCI_SLOT (dev->devfn);}/* All devices are enabled during initialization. */int pcibios_enable_device (struct pci_dev *dev){	return PCIBIOS_SUCCESSFUL;}char * __init pcibios_setup (char *str){	return str;}void __init pcibios_align_resource (void *data, struct resource *res,				    unsigned long size, unsigned long align){}void __init pcibios_update_resource (struct pci_dev *dev, struct resource *root,				     struct resource *res, int resource){}void __init pcibios_update_irq (struct pci_dev *dev, int irq){	pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);}void __init pcibios_fixup_bus (struct pci_bus *b){	pci_fixup_irqs (macepci_swizzle, macepci_map_irq);}/* XXX anybody know what this is supposed to do? */void __init pcibios_fixup_pbus_ranges(struct pci_bus * bus,				      struct pbus_set_ranges_data * ranges){	ranges->io_start -= bus->resource[0]->start;	ranges->io_end -= bus->resource[0]->start;	ranges->mem_start -= bus->resource[1]->start;	ranges->mem_end -= bus->resource[1]->start;}/* * Handle errors from the bridge.  This includes master and target aborts, * various command and address errors, and the interrupt test.  This gets * registered on the bridge error irq.  It's conceivable that some of these * conditions warrant a panic.  Anybody care to say which ones? */void macepci_error (int irq, void *dev, struct pt_regs *regs) {	u32 flags, error_addr;	char space;	flags = mace_read_32 (MACEPCI_ERROR_FLAGS);	error_addr = mace_read_32 (MACEPCI_ERROR_ADDR);	if (flags & MACEPCI_ERROR_MEMORY_ADDR)		space = 'M';	else if (flags & MACEPCI_ERROR_CONFIG_ADDR)		space = 'C';	else space = 'X';	if (flags & MACEPCI_ERROR_MASTER_ABORT) {		printk ("MACEPCI: Master abort at 0x%08x (%c)\n", error_addr,			space);		mace_write_32 (MACEPCI_ERROR_FLAGS, flags			       & ~MACEPCI_ERROR_MASTER_ABORT);	}	if (flags & MACEPCI_ERROR_TARGET_ABORT) {		printk ("MACEPCI: Target abort at 0x%08x (%c)\n", error_addr,			space);		mace_write_32 (MACEPCI_ERROR_FLAGS, flags			       & ~MACEPCI_ERROR_TARGET_ABORT);	}	if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) {		printk ("MACEPCI: Data parity error at 0x%08x (%c)\n",			error_addr, space);		mace_write_32 (MACEPCI_ERROR_FLAGS, flags			       & ~MACEPCI_ERROR_DATA_PARITY_ERR);	}	if (flags & MACEPCI_ERROR_RETRY_ERR) {		printk ("MACEPCI: Retry error at 0x%08x (%c)\n", error_addr,			space);		mace_write_32 (MACEPCI_ERROR_FLAGS, flags			       & ~MACEPCI_ERROR_RETRY_ERR);	}	if (flags & MACEPCI_ERROR_ILLEGAL_CMD) {		printk ("MACEPCI: Illegal command at 0x%08x (%c)\n",			error_addr, space);		mace_write_32 (MACEPCI_ERROR_FLAGS,			       flags & ~MACEPCI_ERROR_ILLEGAL_CMD);	}	if (flags & MACEPCI_ERROR_SYSTEM_ERR) {		printk ("MACEPCI: System error at 0x%08x (%c)\n",			error_addr, space);		mace_write_32 (MACEPCI_ERROR_FLAGS, flags			       & ~MACEPCI_ERROR_SYSTEM_ERR);	}	if (flags & MACEPCI_ERROR_PARITY_ERR) {		printk ("MACEPCI: Parity error at 0x%08x (%c)\n", error_addr,			space);		mace_write_32 (MACEPCI_ERROR_FLAGS, flags			       & ~MACEPCI_ERROR_PARITY_ERR);	}	if (flags & MACEPCI_ERROR_OVERRUN) {		printk ("MACEPCI: Overrun error at 0x%08x (%c)\n",			error_addr, space);		mace_write_32 (MACEPCI_ERROR_FLAGS, flags			       & ~MACEPCI_ERROR_OVERRUN);	}	if (flags & MACEPCI_ERROR_SIG_TABORT) {		printk ("MACEPCI: Signaled target abort (clearing)\n");		mace_write_32 (MACEPCI_ERROR_FLAGS, flags			       & ~MACEPCI_ERROR_SIG_TABORT);	}	if (flags & MACEPCI_ERROR_INTERRUPT_TEST) {		printk ("MACEPCI: Interrupt test triggered (clearing)\n");		mace_write_32 (MACEPCI_ERROR_FLAGS, flags			       & ~MACEPCI_ERROR_INTERRUPT_TEST);	}}unsigned __init int pcibios_assign_all_busses(void){	return 0;}

⌨️ 快捷键说明

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