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

📄 io_apic.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				case MP_BUS_EISA: /* EISA pin */				{					trigger = default_EISA_trigger(idx);					break;				}				case MP_BUS_PCI: /* PCI pin */				{					trigger = default_PCI_trigger(idx);					break;				}				case MP_BUS_MCA: /* MCA pin */				{					trigger = default_MCA_trigger(idx);					break;				}				case MP_BUS_NEC98: /* NEC 98 pin */				{					trigger = default_NEC98_trigger(idx);					break;				}				default:				{					printk(KERN_WARNING "broken BIOS!!\n");					trigger = 1;					break;				}			}			break;		}		case 1: /* edge */		{			trigger = 0;			break;		}		case 2: /* reserved */		{			printk(KERN_WARNING "broken BIOS!!\n");			trigger = 1;			break;		}		case 3: /* level */		{			trigger = 1;			break;		}		default: /* invalid */		{			printk(KERN_WARNING "broken BIOS!!\n");			trigger = 0;			break;		}	}	return trigger;}static inline int irq_polarity(int idx){	return MPBIOS_polarity(idx);}static inline int irq_trigger(int idx){	return MPBIOS_trigger(idx);}static int pin_2_irq(int idx, int apic, int pin){	int irq, i;	int bus = mp_irqs[idx].mpc_srcbus;	/*	 * Debugging check, we are in big trouble if this message pops up!	 */	if (mp_irqs[idx].mpc_dstirq != pin)		printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");	switch (mp_bus_id_to_type[bus])	{		case MP_BUS_ISA: /* ISA pin */		case MP_BUS_EISA:		case MP_BUS_MCA:		case MP_BUS_NEC98:		{			irq = mp_irqs[idx].mpc_srcbusirq;			break;		}		case MP_BUS_PCI: /* PCI pin */		{			/*			 * PCI IRQs are mapped in order			 */			i = irq = 0;			while (i < apic)				irq += nr_ioapic_registers[i++];			irq += pin;			if ((!apic) && (irq < 16)) 				irq += 16;			break;		}		default:		{			printk(KERN_ERR "unknown bus type %d.\n",bus); 			irq = 0;			break;		}	}	/*	 * PCI IRQ command line redirection. Yes, limits are hardcoded.	 */	if ((pin >= 16) && (pin <= 23)) {		if (pirq_entries[pin-16] != -1) {			if (!pirq_entries[pin-16]) {				printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16);			} else {				irq = pirq_entries[pin-16];				printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n",						pin-16, irq);			}		}	}	return irq;}static inline int IO_APIC_irq_trigger(int irq){	int apic, idx, pin;	for (apic = 0; apic < nr_ioapics; apic++) {		for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {			idx = find_irq_entry(apic,pin,mp_INT);			if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))				return irq_trigger(idx);		}	}	/*	 * nonexistent IRQs are edge default	 */	return 0;}/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };#ifdef CONFIG_PCI_MSIint assign_irq_vector(int irq)#elseint __init assign_irq_vector(int irq)#endif{	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;	BUG_ON(irq >= NR_IRQ_VECTORS);	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)		return IO_APIC_VECTOR(irq);next:	current_vector += 8;	if (current_vector == SYSCALL_VECTOR)		goto next;	if (current_vector >= FIRST_SYSTEM_VECTOR) {		offset++;		if (!(offset%8))			return -ENOSPC;		current_vector = FIRST_DEVICE_VECTOR + offset;	}	vector_irq[current_vector] = irq;	if (irq != AUTO_ASSIGN)		IO_APIC_VECTOR(irq) = current_vector;	return current_vector;}static struct hw_interrupt_type ioapic_level_type;static struct hw_interrupt_type ioapic_edge_type;#define IOAPIC_AUTO	-1#define IOAPIC_EDGE	0#define IOAPIC_LEVEL	1static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger){	if (use_pci_vector() && !platform_legacy_irq(irq)) {		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||				trigger == IOAPIC_LEVEL)			irq_desc[vector].handler = &ioapic_level_type;		else			irq_desc[vector].handler = &ioapic_edge_type;		set_intr_gate(vector, interrupt[vector]);	} else	{		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||				trigger == IOAPIC_LEVEL)			irq_desc[irq].handler = &ioapic_level_type;		else			irq_desc[irq].handler = &ioapic_edge_type;		set_intr_gate(vector, interrupt[irq]);	}}void __init setup_IO_APIC_irqs(void){	struct IO_APIC_route_entry entry;	int apic, pin, idx, irq, first_notcon = 1, vector;	unsigned long flags;	printk(KERN_DEBUG "init IO_APIC IRQs\n");	for (apic = 0; apic < nr_ioapics; apic++) {	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {		/*		 * add it to the IO-APIC irq-routing table:		 */		memset(&entry,0,sizeof(entry));		entry.delivery_mode = INT_DELIVERY_MODE;		entry.dest_mode = INT_DEST_MODE;		entry.mask = 0;				/* enable IRQ */		entry.dest.logical.logical_dest = 					cpu_mask_to_apicid(TARGET_CPUS);		idx = find_irq_entry(apic,pin,mp_INT);		if (idx == -1) {			if (first_notcon) {				printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);				first_notcon = 0;			} else				printk(", %d-%d", mp_ioapics[apic].mpc_apicid, pin);			continue;		}		entry.trigger = irq_trigger(idx);		entry.polarity = irq_polarity(idx);		if (irq_trigger(idx)) {			entry.trigger = 1;			entry.mask = 1;		}		irq = pin_2_irq(idx, apic, pin);		/*		 * skip adding the timer int on secondary nodes, which causes		 * a small but painful rift in the time-space continuum		 */		if (multi_timer_check(apic, irq))			continue;		else			add_pin_to_irq(irq, apic, pin);		if (!apic && !IO_APIC_IRQ(irq))			continue;		if (IO_APIC_IRQ(irq)) {			vector = assign_irq_vector(irq);			entry.vector = vector;			ioapic_register_intr(irq, vector, IOAPIC_AUTO);					if (!apic && (irq < 16))				disable_8259A_irq(irq);		}		spin_lock_irqsave(&ioapic_lock, flags);		io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));		io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));		spin_unlock_irqrestore(&ioapic_lock, flags);	}	}	if (!first_notcon)		printk(" not connected.\n");}/* * Set up the 8259A-master output pin: */void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector){	struct IO_APIC_route_entry entry;	unsigned long flags;	memset(&entry,0,sizeof(entry));	disable_8259A_irq(0);	/* mask LVT0 */	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);	/*	 * We use logical delivery to get the timer IRQ	 * to the first CPU.	 */	entry.dest_mode = INT_DEST_MODE;	entry.mask = 0;					/* unmask IRQ now */	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);	entry.delivery_mode = INT_DELIVERY_MODE;	entry.polarity = 0;	entry.trigger = 0;	entry.vector = vector;	/*	 * The timer IRQ doesn't have to know that behind the	 * scene we have a 8259A-master in AEOI mode ...	 */	irq_desc[0].handler = &ioapic_edge_type;	/*	 * Add it to the IO-APIC irq-routing table:	 */	spin_lock_irqsave(&ioapic_lock, flags);	io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));	io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));	spin_unlock_irqrestore(&ioapic_lock, flags);	enable_8259A_irq(0);}static inline void UNEXPECTED_IO_APIC(void){}void __init print_IO_APIC(void){	int apic, i;	union IO_APIC_reg_00 reg_00;	union IO_APIC_reg_01 reg_01;	union IO_APIC_reg_02 reg_02;	union IO_APIC_reg_03 reg_03;	unsigned long flags; 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);	for (i = 0; i < nr_ioapics; i++)		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",		       mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);	/*	 * We are a bit conservative about what we expect.  We have to	 * know about every hardware change ASAP.	 */	printk(KERN_INFO "testing the IO APIC.......................\n");	for (apic = 0; apic < nr_ioapics; apic++) {	spin_lock_irqsave(&ioapic_lock, flags);	reg_00.raw = io_apic_read(apic, 0);	reg_01.raw = io_apic_read(apic, 1);	if (reg_01.bits.version >= 0x10)		reg_02.raw = io_apic_read(apic, 2);	if (reg_01.bits.version >= 0x20)		reg_03.raw = io_apic_read(apic, 3);	spin_unlock_irqrestore(&ioapic_lock, flags);	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);	if (reg_00.bits.ID >= get_physical_broadcast())		UNEXPECTED_IO_APIC();	if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)		UNEXPECTED_IO_APIC();	printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);	if (	(reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */		(reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */		(reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */		(reg_01.bits.entries != 0x1f) && /* dual Xeon boards */		(reg_01.bits.entries != 0x22) && /* bigger Xeon boards */		(reg_01.bits.entries != 0x2E) &&		(reg_01.bits.entries != 0x3F)	)		UNEXPECTED_IO_APIC();	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);	if (	(reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */		(reg_01.bits.version != 0x10) && /* oldest IO-APICs */		(reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */		(reg_01.bits.version != 0x13) && /* Xeon IO-APICs */		(reg_01.bits.version != 0x20)    /* Intel P64H (82806 AA) */	)		UNEXPECTED_IO_APIC();	if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)		UNEXPECTED_IO_APIC();	/*	 * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,	 * but the value of reg_02 is read as the previous read register	 * value, so ignore it if reg_02 == reg_01.	 */	if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {		printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);		printk(KERN_DEBUG ".......     : arbitration: %02X\n", reg_02.bits.arbitration);		if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)			UNEXPECTED_IO_APIC();	}	/*	 * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02	 * or reg_03, but the value of reg_0[23] is read as the previous read	 * register value, so ignore it if reg_03 == reg_0[12].	 */	if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&	    reg_03.raw != reg_01.raw) {		printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);		printk(KERN_DEBUG ".......     : Boot DT    : %X\n", reg_03.bits.boot_DT);		if (reg_03.bits.__reserved_1)			UNEXPECTED_IO_APIC();	}	printk(KERN_DEBUG ".... IRQ redirection table:\n");	printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"			  " Stat Dest Deli Vect:   \n");	for (i = 0; i <= reg_01.bits.entries; i++) {		struct IO_APIC_route_entry entry;		spin_lock_irqsave(&ioapic_lock, flags);		*(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);		*(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);		spin_unlock_irqrestore(&ioapic_lock, flags);		printk(KERN_DEBUG " %02x %03X %02X  ",			i,			entry.dest.logical.logical_dest,			entry.dest.physical.physical_dest		);		printk("%1d    %1d    %1d   %1d   %1d    %1d    %1d    %02X\n",			entry.mask,			entry.trigger,			entry.irr,			entry.polarity,			entry.delivery_status,			entry.dest_mode,			entry.delivery_mode,			entry.vector		);	}	}	if (use_pci_vector())		printk(KERN_INFO "Using vector-based indexing\n");	printk(KERN_DEBUG "IRQ to pin mappings:\n");	for (i = 0; i < NR_IRQS; i++) {		struct irq_pin_list *entry = irq_2_pin + i;		if (entry->pin < 0)			continue; 		if (use_pci_vector() && !platform_legacy_irq(i))			printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i));		else			printk(KERN_DEBUG "IRQ%d ", i);		for (;;) {			printk("-> %d:%d", entry->apic, entry->pin);			if (!entry->next)				break;			entry = irq_2_pin + entry->next;		}		printk("\n");	}	printk(KERN_INFO ".................................... done.\n");	return;}static void print_APIC_bitfield (int base){	unsigned int v;	int i, j;	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);	for (i = 0; i < 8; i++) {		v = apic_read(base + i*0x10);		for (j = 0; j < 32; j++) {			if (v & (1<<j))				printk("1");			else				printk("0");		}		printk("\n");	}}void /*__init*/ print_local_APIC(void * dummy){

⌨️ 快捷键说明

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