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

📄 iosapic.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * }	 */	writel(IOSAPIC_VERSION, addr + IOSAPIC_REG_SELECT);	return readl(IOSAPIC_WINDOW + addr);}/* * if the given vector is already owned by other, *  assign a new vector for the other and make the vector available */static void __initiosapic_reassign_vector (int vector){	int new_vector;	if (iosapic_intr_info[vector].rte_index >= 0 || iosapic_intr_info[vector].addr	    || iosapic_intr_info[vector].gsi_base || iosapic_intr_info[vector].dmode	    || iosapic_intr_info[vector].polarity || iosapic_intr_info[vector].trigger)	{		new_vector = ia64_alloc_vector();		printk(KERN_INFO "Reassigning vector %d to %d\n", vector, new_vector);		memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],		       sizeof(struct iosapic_intr_info));		memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));		iosapic_intr_info[vector].rte_index = -1;	}}static voidregister_intr (unsigned int gsi, int vector, unsigned char delivery,	       unsigned long polarity, unsigned long trigger){	irq_desc_t *idesc;	struct hw_interrupt_type *irq_type;	int rte_index;	int index;	unsigned long gsi_base;	char *iosapic_address;	index = find_iosapic(gsi);	if (index < 0) {		printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi);		return;	}	iosapic_address = iosapic_lists[index].addr;	gsi_base = iosapic_lists[index].gsi_base;	rte_index = gsi - gsi_base;	iosapic_intr_info[vector].rte_index = rte_index;	iosapic_intr_info[vector].polarity = polarity;	iosapic_intr_info[vector].dmode    = delivery;	iosapic_intr_info[vector].addr     = iosapic_address;	iosapic_intr_info[vector].gsi_base = gsi_base;	iosapic_intr_info[vector].trigger  = trigger;	if (trigger == IOSAPIC_EDGE)		irq_type = &irq_type_iosapic_edge;	else		irq_type = &irq_type_iosapic_level;	idesc = irq_desc(vector);	if (idesc->handler != irq_type) {		if (idesc->handler != &no_irq_type)			printk(KERN_WARNING "%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 trigger){	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, trigger);	printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",	       gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),	       (trigger == IOSAPIC_EDGE ? "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(). */int __initiosapic_register_platform_intr (u32 int_type, unsigned int gsi,				int iosapic_vector, u16 eid, u16 id,				unsigned long polarity, unsigned long trigger){	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_CPE_VECTOR;		delivery = IOSAPIC_LOWEST_PRIORITY;		break;	      default:		printk(KERN_ERR "%s: invalid interrupt type (%d)\n", __FUNCTION__,			int_type);		return -1;	}	register_intr(gsi, vector, delivery, polarity, trigger);	printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",	       int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),	       (trigger == IOSAPIC_EDGE ? "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(). */void __initiosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,			  unsigned long polarity, unsigned long trigger){	int vector;	unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;	vector = isa_irq_to_vector(isa_irq);	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);	DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",	    isa_irq, gsi,	    polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "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 vector;	unsigned int gsi;	if (pci_pin_to_gsi(segment, bus, slot, pci_pin, &gsi) < 0) {		printk(KERN_ERR "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) {		/* allocate a vector for this interrupt line */		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, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);		DBG("PCI: (%02x:%02x:%02x INT%c) -> GSI 0x%x -> vector %d\n",		    segment, bus, slot, 'A' + pci_pin, gsi, vector);	}	return vector;}void __initiosapic_system_init (int system_pcat_compat){	int vector;	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)		iosapic_intr_info[vector].rte_index = -1;	/* mark as unused */	pcat_compat = system_pcat_compat;	if (pcat_compat) {		/*		 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support		 * enabled.		 */		printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);		outb(0xff, 0xA1);		outb(0xff, 0x21);	}}void __initiosapic_init (unsigned long phys_addr, unsigned int gsi_base){	int num_rte;	unsigned int isa_irq, ver;	char *addr;	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].gsi_base = gsi_base;	iosapic_lists[num_iosapic].num_rte = num_rte;	num_iosapic++;	printk(KERN_INFO "  IOSAPIC v%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) {		/*		 * 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)			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);	}}/* * 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(KERN_INFO "%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(KERN_INFO "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(KERN_ERR "%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 + -