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

📄 iosapic.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 2 页
字号:
	       unsigned int gsi_base, char *iosapic_address){	irq_desc_t *idesc;	struct hw_interrupt_type *irq_type;	int rte_index;	rte_index = gsi - gsi_base;	iosapic_intr_info[vector].rte_index = rte_index;	iosapic_intr_info[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;	iosapic_intr_info[vector].dmode    = delivery;	/*	 * In override, it may not provide addr/gsi_base.  GSI is enough to	 * locate iosapic addr, gsi_base and rte_index by examining	 * gsi_base and num_rte of registered iosapics (tbd)	 */#ifndef	OVERRIDE_DEBUG	if (iosapic_address) {		iosapic_intr_info[vector].addr = iosapic_address;		iosapic_intr_info[vector].gsi_base = gsi_base;	}#else	if (iosapic_address) {		if (iosapic_intr_info[vector].addr && (iosapic_intr_info[vector].addr != iosapic_address))			printk("WARN: %s: diff IOSAPIC ADDRESS for GSI 0x%x, vector %d\n",			       __FUNCTION__, gsi, vector);		iosapic_intr_info[vector].addr = iosapic_address;		if (iosapic_intr_info[vector].gsi_base && (iosapic_intr_info[vector].gsi_base != gsi_base)) {			printk("WARN: %s: diff GSI base 0x%x for GSI 0x%x, vector %d\n",			       __FUNCTION__, gsi_base, gsi, vector);		}		iosapic_intr_info[vector].gsi_base = gsi_base;	} else if (!iosapic_intr_info[vector].addr)		printk("WARN: %s: invalid override for GSI 0x%x, vector %d\n",		       __FUNCTION__, gsi, vector);#endif	if (edge_triggered) {		iosapic_intr_info[vector].trigger = IOSAPIC_EDGE;		irq_type = &irq_type_iosapic_edge;	} else {		iosapic_intr_info[vector].trigger = IOSAPIC_LEVEL;		irq_type = &irq_type_iosapic_level;	}	idesc = irq_desc(vector);	if (idesc->handler != irq_type) {		if (idesc->handler != &no_irq_type)			printk("%s: changing vector %d from %s to %s\n",			       __FUNCTION__, vector, idesc->handler->typename,			       irq_type->typename);		idesc->handler = irq_type;	}}/* * ACPI can describe IOSAPIC interrupts via static tables and namespace * methods.  This provides an interface to register those interrupts and * program the IOSAPIC RTE. */intiosapic_register_intr (unsigned int gsi,		       unsigned long polarity, unsigned long edge_triggered,		       unsigned int gsi_base, char *iosapic_address){	int vector;	unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;	vector = gsi_to_vector(gsi);	if (vector < 0)		vector = ia64_alloc_vector();	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,		      polarity, edge_triggered, gsi_base, iosapic_address);	printk("GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",	       gsi, (polarity ? "high" : "low"),	       (edge_triggered ? "edge" : "level"), dest, vector);	/* program the IOSAPIC routing table */	set_rte(vector, dest);	return vector;}/* * ACPI calls this when it finds an entry for a platform interrupt. * Note that the irq_base and IOSAPIC address must be set in iosapic_init(). */intiosapic_register_platform_intr (u32 int_type, unsigned int gsi,				int iosapic_vector, u16 eid, u16 id,				unsigned long polarity, unsigned long edge_triggered,				unsigned int gsi_base, char *iosapic_address){	unsigned char delivery;	int vector;	unsigned int dest = ((id << 8) | eid) & 0xffff;	switch (int_type) {	      case ACPI_INTERRUPT_PMI:		vector = iosapic_vector;		/*		 * since PMI vector is alloc'd by FW(ACPI) not by kernel,		 * we need to make sure the vector is available		 */		iosapic_reassign_vector(vector);		delivery = IOSAPIC_PMI;		break;	      case ACPI_INTERRUPT_INIT:		vector = ia64_alloc_vector();		delivery = IOSAPIC_INIT;		break;	      case ACPI_INTERRUPT_CPEI:		vector = IA64_PCE_VECTOR;		delivery = IOSAPIC_LOWEST_PRIORITY;		break;	      default:		printk("%s: invalid interrupt type (%d)\n", __FUNCTION__,			int_type);		return -1;	}	register_intr(gsi, vector, delivery, polarity,		      edge_triggered, gsi_base, iosapic_address);	printk("PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",	       int_type, gsi, (polarity ? "high" : "low"),	       (edge_triggered ? "edge" : "level"), dest, vector);	/* program the IOSAPIC routing table */	set_rte(vector, dest);	return vector;}/* * ACPI calls this when it finds an entry for a legacy ISA IRQ override. * Note that the gsi_base and IOSAPIC address must be set in iosapic_init(). */voidiosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,			  unsigned long polarity, unsigned long edge_triggered){	int index, vector;	unsigned int gsi_base;	char *addr;	unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;	index = find_iosapic(gsi);	if (index < 0) {		printk("ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n", isa_irq, gsi);		return;	}	vector = isa_irq_to_vector(isa_irq);	addr = iosapic_lists[index].addr;	gsi_base = iosapic_lists[index].gsi_base;	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered,		      gsi_base, addr);	DBG("ISA: IRQ %u -> GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",	    isa_irq, global_vector,	    polarity ? "high" : "low", edge_triggered ? "edge" : "level",	    dest, vector);	/* program the IOSAPIC routing table */	set_rte(vector, dest);}/* * Map PCI pin to the corresponding GSI. * If no such mapping exists, return -1. */static intpci_pin_to_gsi (int segment, int bus, int slot, int pci_pin, unsigned int *gsi){	struct pci_vector_struct *r;	for (r = pci_irq.route; r < pci_irq.route + pci_irq.num_routes; r++)		if (r->segment == segment && r->bus == bus &&		    (r->pci_id >> 16) == slot && r->pin == pci_pin) {			*gsi = r->irq;			return 0;		}	return -1;}/* * Map PCI pin to the corresponding IA-64 interrupt vector.  If no such mapping exists, * try to allocate a new vector.  If it fails, return -1. */static intpci_pin_to_vector (int segment, int bus, int slot, int pci_pin){	int index, vector;	int gsi_base, pcat_compat;	char *addr;	unsigned int gsi;	if (pci_pin_to_gsi(segment, bus, slot, pci_pin, &gsi) < 0) {		printk("PCI: no interrupt route for %02x:%02x:%02x pin %c\n",			segment, bus, slot, 'A' + pci_pin);		return -1;	}	vector = gsi_to_vector(gsi);	if (vector < 0) {		/* we should allocate a vector for this interrupt line */		index = find_iosapic(gsi);		if (index < 0) {			printk("PCI: GSI 0x%x has no IOSAPIC mapping\n", gsi);			return -1;		}		addr = iosapic_lists[index].addr;		gsi_base = iosapic_lists[index].gsi_base;		pcat_compat = iosapic_lists[index].pcat_compat;		if (pcat_compat && (gsi < 16))			vector = isa_irq_to_vector(gsi);		else {			/* new GSI; allocate a vector for it */			vector = ia64_alloc_vector();		}		register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,			      0, 0, gsi_base, addr);		DBG("PCI: (%02x:%02x:%02x:%02x INT%c) -> GSI 0x%x -> vector %d\n",		    segment, bus, slot, 'A' + pci_pin, gsi, vector);	}	return vector;}void __devinitiosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat){	int num_rte, vector;	unsigned int isa_irq, ver;	char *addr;	static int first_time = 1;	if (first_time) {		first_time = 0;		for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)			iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */	}	if (pcat_compat) {		/*		 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support		 * enabled.		 */		printk("%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);		outb(0xff, 0xA1);		outb(0xff, 0x21);	}	addr = ioremap(phys_addr, 0);	ver = iosapic_version(addr);	/*	 * The MAX_REDIR register holds the highest input pin	 * number (starting from 0).	 * We add 1 so that we can use it for number of pins (= RTEs)	 */	num_rte = ((ver >> 16) & 0xff) + 1;	iosapic_lists[num_iosapic].addr = addr;	iosapic_lists[num_iosapic].pcat_compat = pcat_compat;	iosapic_lists[num_iosapic].gsi_base = gsi_base;	iosapic_lists[num_iosapic].num_rte = num_rte;	num_iosapic++;	printk("IOSAPIC: version %x.%x, address 0x%lx, GSIs 0x%x-0x%x\n",	       (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);	if ((gsi_base == 0) && pcat_compat) {		unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;		/*		 * Map the legacy ISA devices into the IOSAPIC data.  Some of these may		 * get reprogrammed later on with data from the ACPI Interrupt Source		 * Override table.		 */		for (isa_irq = 0; isa_irq < 16; ++isa_irq) {			vector = isa_irq_to_vector(isa_irq);			register_intr(isa_irq, vector, IOSAPIC_LOWEST_PRIORITY,				     /* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */				     1, 1, gsi_base, addr);			DBG("ISA: IRQ %u -> GSI 0x%x (high,edge) -> CPU 0x%04x vector %d\n",			    isa_irq, isa_irq, dest, vector);			/* program the IOSAPIC routing table: */			set_rte(vector, dest);		}	}}/* * Set allocated interrupt vector to dev->irq and * program IOSAPIC to deliver interrupts */voidiosapic_fixup_pci_interrupt (struct pci_dev *dev){	int segment;	unsigned char pci_pin;	int vector;	unsigned int dest;	struct hw_interrupt_type *irq_type;	irq_desc_t *idesc;	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pci_pin);	if (pci_pin) {		pci_pin--; /* interrupt pins are numberd starting from 1 */		segment = PCI_SEGMENT(dev);		vector = pci_pin_to_vector(segment, dev->bus->number, PCI_SLOT(dev->devfn), pci_pin);		if (vector < 0 && dev->bus->parent) {			/* go back to the bridge */			struct pci_dev *bridge = dev->bus->self;			if (bridge) {				/* allow for multiple bridges on an adapter */				do {					/* do the bridge swizzle... */					pci_pin = (pci_pin + PCI_SLOT(dev->devfn)) % 4;					vector = pci_pin_to_vector(segment,								   bridge->bus->number,								   PCI_SLOT(bridge->devfn),								   pci_pin);				} while (vector < 0 && (bridge = bridge->bus->self));			}			if (vector >= 0)				printk(KERN_WARNING				       "PCI: using PPB (%s INT%c) to get vector %d\n",				       dev->slot_name, 'A' + pci_pin,				       vector);			else				printk(KERN_WARNING				       "PCI: Couldn't map irq for (%s INT%c)\n",				       dev->slot_name, 'A' + pci_pin);		}		if (vector >= 0) {			dev->irq = vector;			irq_type = &irq_type_iosapic_level;			idesc = irq_desc(vector);			if (idesc->handler != irq_type) {				if (idesc->handler != &no_irq_type)					printk("%s: changing vector %d from %s to %s\n",					       __FUNCTION__, vector,					       idesc->handler->typename,					       irq_type->typename);				idesc->handler = irq_type;			}#ifdef CONFIG_SMP			/*			 * For platforms that do not support interrupt redirect			 * via the XTP interface, we can round-robin the PCI			 * device interrupts to the processors			 */			if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {				static int cpu_index = 0;				dest = cpu_physical_id(cpu_index) & 0xffff;				cpu_index++;				if (cpu_index >= smp_num_cpus)					cpu_index = 0;			} else {				/*				 * Direct the interrupt vector to the current cpu,				 * platform redirection will distribute them.				 */				dest = (ia64_get_lid() >> 16) & 0xffff;			}#else			/* direct the interrupt vector to the running cpu id */			dest = (ia64_get_lid() >> 16) & 0xffff;#endif			printk("PCI->APIC IRQ transform: (%s INT%c) -> CPU 0x%04x vector %d\n",			       dev->slot_name, 'A' + pci_pin, dest, vector);			set_rte(vector, dest);		}	}}voidiosapic_pci_fixup (int phase){	struct	pci_dev	*dev;	if (phase == 0) {		if (0 != acpi_get_prt(&pci_irq.route, &pci_irq.num_routes)) {			printk("%s: acpi_get_prt failed\n", __FUNCTION__);		}		return;	}	if (phase != 1)		return;	pci_for_each_dev(dev) {		/* fixup dev->irq and program IOSAPIC */		iosapic_fixup_pci_interrupt(dev);		/*		 * Nothing to fixup		 * Fix out-of-range IRQ numbers		 */		if (dev->irq >= IA64_NUM_VECTORS)			dev->irq = 15;	/* Spurious interrupts */	}}

⌨️ 快捷键说明

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