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

📄 io_apic_32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				}				case MP_BUS_PCI: /* PCI pin */				{					trigger = default_PCI_trigger(idx);					break;				}				case MP_BUS_MCA: /* MCA pin */				{					trigger = default_MCA_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:		{			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;			/*			 * For MPS mode, so far only needed by ES7000 platform			 */			if (ioapic_renumber_irq)				irq = ioapic_renumber_irq(apic, irq);			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]) {				apic_printk(APIC_VERBOSE, KERN_DEBUG						"disabling PIRQ%d\n", pin-16);			} else {				irq = pirq_entries[pin-16];				apic_printk(APIC_VERBOSE, 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. */static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };static int __assign_irq_vector(int irq){	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;	int vector, offset;	BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);	if (irq_vector[irq] > 0)		return irq_vector[irq];	vector = current_vector;	offset = current_offset;next:	vector += 8;	if (vector >= FIRST_SYSTEM_VECTOR) {		offset = (offset + 1) % 8;		vector = FIRST_DEVICE_VECTOR + offset;	}	if (vector == current_vector)		return -ENOSPC;	if (test_and_set_bit(vector, used_vectors))		goto next;	current_vector = vector;	current_offset = offset;	irq_vector[irq] = vector;	return vector;}static int assign_irq_vector(int irq){	unsigned long flags;	int vector;	spin_lock_irqsave(&vector_lock, flags);	vector = __assign_irq_vector(irq);	spin_unlock_irqrestore(&vector_lock, flags);	return vector;}static struct irq_chip ioapic_chip;#define IOAPIC_AUTO	-1#define IOAPIC_EDGE	0#define IOAPIC_LEVEL	1static void ioapic_register_intr(int irq, int vector, unsigned long trigger){	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||	    trigger == IOAPIC_LEVEL) {		irq_desc[irq].status |= IRQ_LEVEL;		set_irq_chip_and_handler_name(irq, &ioapic_chip,					 handle_fasteoi_irq, "fasteoi");	} else {		irq_desc[irq].status &= ~IRQ_LEVEL;		set_irq_chip_and_handler_name(irq, &ioapic_chip,					 handle_edge_irq, "edge");	}	set_intr_gate(vector, interrupt[irq]);}static 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;	apic_printk(APIC_VERBOSE, 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) {				apic_printk(APIC_VERBOSE, KERN_DEBUG						" IO-APIC (apicid-pin) %d-%d",						mp_ioapics[apic].mpc_apicid,						pin);				first_notcon = 0;			} else				apic_printk(APIC_VERBOSE, ", %d-%d",					mp_ioapics[apic].mpc_apicid, pin);			continue;		}		if (!first_notcon) {			apic_printk(APIC_VERBOSE, " not connected.\n");			first_notcon = 1;		}		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);		__ioapic_write_entry(apic, pin, entry);		spin_unlock_irqrestore(&ioapic_lock, flags);	}	}	if (!first_notcon)		apic_printk(APIC_VERBOSE, " not connected.\n");}/* * Set up the 8259A-master output pin: */static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector){	struct IO_APIC_route_entry entry;	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].chip = &ioapic_chip;	set_irq_handler(0, handle_edge_irq);	/*	 * Add it to the IO-APIC irq-routing table:	 */	ioapic_write_entry(apic, pin, entry);	enable_8259A_irq(0);}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;	if (apic_verbosity == APIC_QUIET)		return; 	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);	printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.bits.entries);	printk(KERN_DEBUG ".......     : PRQ implemented: %X\n", reg_01.bits.PRQ);	printk(KERN_DEBUG ".......     : IO APIC version: %04X\n", reg_01.bits.version);	/*	 * 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);	}	/*	 * 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);	}	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;		entry = ioapic_read_entry(apic, i);		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		);	}	}	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;		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;}#if 0static void print_APIC_bitfield (int base){	unsigned int v;	int i, j;	if (apic_verbosity == APIC_QUIET)		return;	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){	unsigned int v, ver, maxlvt;	if (apic_verbosity == APIC_QUIET)		return;	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",		smp_processor_id(), hard_smp_processor_id());	v = apic_read(APIC_ID);	printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, GET_APIC_ID(v));	v = apic_read(APIC_LVR);	printk(KERN_INFO "... APIC VERSION: %08x\n", v);	ver = GET_APIC_VERSION(v);	maxlvt = lapic_get_maxlvt();	v = apic_read(APIC_TASKPRI);	printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);	if (APIC_INTEGRATED(ver)) {			/* !82489DX */		v = apic_read(APIC_ARBPRI);		printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,			v & APIC_ARBPRI_MASK);		v = apic_read(APIC_PROCPRI);		printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);	}	v = apic_read(APIC_EOI);	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);	v = apic_read(APIC_RRR);	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);	v = apic_read(APIC_LDR);	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);	v = apic_read(APIC_DFR);	printk(KERN_DEBUG "... APIC DFR: %08x\n", v);	v = apic_read(APIC_SPIV);	printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);	printk(KERN_DEBUG "... APIC ISR field:\n");	print_APIC_bitfield(APIC_ISR);	printk(KERN_DEBUG "... APIC TMR field:\n");	print_APIC_bitfield(APIC_TMR);	printk(KERN_DEBUG "... APIC IRR field:\n");	print_APIC_bitfield(APIC_IRR);	if (APIC_INTEGRATED(ver)) {		/* !82489DX */		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */			apic_write(APIC_ESR, 0);		v = apic_read(APIC_ESR);		printk(KERN_DEBUG "... APIC ESR: %08x\n", v);	}	v = apic_read(APIC_ICR);	printk(KERN_DEBUG "... APIC ICR: %08x\n", v);	v = apic_read(APIC_ICR2);	printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);	v = apic_read(APIC_LVTT);	printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);	if (maxlvt > 3) {                       /* PC is LVT#4. */		v = apic_read(APIC_LVTPC);		printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v);	}	v = apic_read(APIC_LVT0);	printk(KERN_DEBUG "... APIC LVT0: %08x\n", v);

⌨️ 快捷键说明

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