mpparse.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,165 行 · 第 1/3 页

C
1,165
字号
	char oem[10];	int count=sizeof(*mpc);	unsigned char *mpt=((unsigned char *)mpc)+count;	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {		printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n",			*(u32 *)mpc->mpc_signature);		return 0;	}	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {		printk(KERN_ERR "SMP mptable: checksum error!\n");		return 0;	}	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {		printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",			mpc->mpc_spec);		return 0;	}	if (!mpc->mpc_lapic) {		printk(KERN_ERR "SMP mptable: null local APIC address!\n");		return 0;	}	memcpy(oem,mpc->mpc_oem,8);	oem[8]=0;	printk(KERN_INFO "OEM ID: %s ",oem);	memcpy(str,mpc->mpc_productid,12);	str[12]=0;	printk("Product ID: %s ",str);	mps_oem_check(mpc, oem, str);	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);	/* 	 * Save the local APIC address (it might be non-default) -- but only	 * if we're not using ACPI.	 */	if (!acpi_lapic)		mp_lapic_addr = mpc->mpc_lapic;	/*	 *	Now process the configuration blocks.	 */	mpc_record = 0;	while (count < mpc->mpc_length) {		switch(*mpt) {			case MP_PROCESSOR:			{				struct mpc_config_processor *m=					(struct mpc_config_processor *)mpt;				/* ACPI may have already provided this data */				if (!acpi_lapic)					MP_processor_info(m);				mpt += sizeof(*m);				count += sizeof(*m);				break;			}			case MP_BUS:			{				struct mpc_config_bus *m=					(struct mpc_config_bus *)mpt;				MP_bus_info(m);				mpt += sizeof(*m);				count += sizeof(*m);				break;			}			case MP_IOAPIC:			{				struct mpc_config_ioapic *m=					(struct mpc_config_ioapic *)mpt;				MP_ioapic_info(m);				mpt+=sizeof(*m);				count+=sizeof(*m);				break;			}			case MP_INTSRC:			{				struct mpc_config_intsrc *m=					(struct mpc_config_intsrc *)mpt;				MP_intsrc_info(m);				mpt+=sizeof(*m);				count+=sizeof(*m);				break;			}			case MP_LINTSRC:			{				struct mpc_config_lintsrc *m=					(struct mpc_config_lintsrc *)mpt;				MP_lintsrc_info(m);				mpt+=sizeof(*m);				count+=sizeof(*m);				break;			}			default:			{				count = mpc->mpc_length;				break;			}		}		++mpc_record;	}	clustered_apic_check();	if (!num_processors)		printk(KERN_ERR "SMP mptable: no processors registered!\n");	return num_processors;}static int __init ELCR_trigger(unsigned int irq){	unsigned int port;	port = 0x4d0 + (irq >> 3);	return (inb(port) >> (irq & 7)) & 1;}static void __init construct_default_ioirq_mptable(int mpc_default_type){	struct mpc_config_intsrc intsrc;	int i;	int ELCR_fallback = 0;	intsrc.mpc_type = MP_INTSRC;	intsrc.mpc_irqflag = 0;			/* conforming */	intsrc.mpc_srcbus = 0;	intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;	intsrc.mpc_irqtype = mp_INT;	/*	 *  If true, we have an ISA/PCI system with no IRQ entries	 *  in the MP table. To prevent the PCI interrupts from being set up	 *  incorrectly, we try to use the ELCR. The sanity check to see if	 *  there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can	 *  never be level sensitive, so we simply see if the ELCR agrees.	 *  If it does, we assume it's valid.	 */	if (mpc_default_type == 5) {		printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");		if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))			printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n");		else {			printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");			ELCR_fallback = 1;		}	}	for (i = 0; i < 16; i++) {		switch (mpc_default_type) {		case 2:			if (i == 0 || i == 13)				continue;	/* IRQ0 & IRQ13 not connected */			/* fall through */		default:			if (i == 2)				continue;	/* IRQ2 is never connected */		}		if (ELCR_fallback) {			/*			 *  If the ELCR indicates a level-sensitive interrupt, we			 *  copy that information over to the MP table in the			 *  irqflag field (level sensitive, active high polarity).			 */			if (ELCR_trigger(i))				intsrc.mpc_irqflag = 13;			else				intsrc.mpc_irqflag = 0;		}		intsrc.mpc_srcbusirq = i;		intsrc.mpc_dstirq = i ? i : 2;		/* IRQ0 to INTIN2 */		MP_intsrc_info(&intsrc);	}	intsrc.mpc_irqtype = mp_ExtINT;	intsrc.mpc_srcbusirq = 0;	intsrc.mpc_dstirq = 0;				/* 8259A to INTIN0 */	MP_intsrc_info(&intsrc);}static inline void __init construct_default_ISA_mptable(int mpc_default_type){	struct mpc_config_processor processor;	struct mpc_config_bus bus;	struct mpc_config_ioapic ioapic;	struct mpc_config_lintsrc lintsrc;	int linttypes[2] = { mp_ExtINT, mp_NMI };	int i;	/*	 * local APIC has default address	 */	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;	/*	 * 2 CPUs, numbered 0 & 1.	 */	processor.mpc_type = MP_PROCESSOR;	/* Either an integrated APIC or a discrete 82489DX. */	processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;	processor.mpc_cpuflag = CPU_ENABLED;	processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |				   (boot_cpu_data.x86_model << 4) |				   boot_cpu_data.x86_mask;	processor.mpc_featureflag = boot_cpu_data.x86_capability[0];	processor.mpc_reserved[0] = 0;	processor.mpc_reserved[1] = 0;	for (i = 0; i < 2; i++) {		processor.mpc_apicid = i;		MP_processor_info(&processor);	}	bus.mpc_type = MP_BUS;	bus.mpc_busid = 0;	switch (mpc_default_type) {		default:			printk("???\n");			printk(KERN_ERR "Unknown standard configuration %d\n",				mpc_default_type);			/* fall through */		case 1:		case 5:			memcpy(bus.mpc_bustype, "ISA   ", 6);			break;		case 2:		case 6:		case 3:			memcpy(bus.mpc_bustype, "EISA  ", 6);			break;		case 4:		case 7:			memcpy(bus.mpc_bustype, "MCA   ", 6);	}	MP_bus_info(&bus);	if (mpc_default_type > 4) {		bus.mpc_busid = 1;		memcpy(bus.mpc_bustype, "PCI   ", 6);		MP_bus_info(&bus);	}	ioapic.mpc_type = MP_IOAPIC;	ioapic.mpc_apicid = 2;	ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;	ioapic.mpc_flags = MPC_APIC_USABLE;	ioapic.mpc_apicaddr = 0xFEC00000;	MP_ioapic_info(&ioapic);	/*	 * We set up most of the low 16 IO-APIC pins according to MPS rules.	 */	construct_default_ioirq_mptable(mpc_default_type);	lintsrc.mpc_type = MP_LINTSRC;	lintsrc.mpc_irqflag = 0;		/* conforming */	lintsrc.mpc_srcbusid = 0;	lintsrc.mpc_srcbusirq = 0;	lintsrc.mpc_destapic = MP_APIC_ALL;	for (i = 0; i < 2; i++) {		lintsrc.mpc_irqtype = linttypes[i];		lintsrc.mpc_destapiclint = i;		MP_lintsrc_info(&lintsrc);	}}static struct intel_mp_floating *mpf_found;/* * Scan the memory blocks for an SMP configuration block. */void __init get_smp_config (void){	struct intel_mp_floating *mpf = mpf_found;	/*	 * ACPI supports both logical (e.g. Hyper-Threading) and physical 	 * processors, where MPS only supports physical.	 */	if (acpi_lapic && acpi_ioapic) {		printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n");		return;	}	else if (acpi_lapic)		printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");	printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);	if (mpf->mpf_feature2 & (1<<7)) {		printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");		pic_mode = 1;	} else {		printk(KERN_INFO "    Virtual Wire compatibility mode.\n");		pic_mode = 0;	}	/*	 * Now see if we need to read further.	 */	if (mpf->mpf_feature1 != 0) {		printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);		construct_default_ISA_mptable(mpf->mpf_feature1);	} else if (mpf->mpf_physptr) {		/*		 * Read the physical hardware table.  Anything here will		 * override the defaults.		 */		if (!smp_read_mpc(phys_to_virt(mpf->mpf_physptr))) {			smp_found_config = 0;			printk(KERN_ERR "BIOS bug, MP table errors detected!...\n");			printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n");			return;		}		/*		 * If there are no explicit MP IRQ entries, then we are		 * broken.  We set up most of the low 16 IO-APIC pins to		 * ISA defaults and hope it will work.		 */		if (!mp_irq_entries) {			struct mpc_config_bus bus;			printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");			bus.mpc_type = MP_BUS;			bus.mpc_busid = 0;			memcpy(bus.mpc_bustype, "ISA   ", 6);			MP_bus_info(&bus);			construct_default_ioirq_mptable(0);		}	} else		BUG();	printk(KERN_INFO "Processors: %d\n", num_processors);	/*	 * Only use the first configuration found.	 */}static int __init smp_scan_config (unsigned long base, unsigned long length){	unsigned long *bp = phys_to_virt(base);	struct intel_mp_floating *mpf;	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);	if (sizeof(*mpf) != 16)		printk("Error: MPF size\n");	while (length > 0) {		mpf = (struct intel_mp_floating *)bp;		if ((*bp == SMP_MAGIC_IDENT) &&			(mpf->mpf_length == 1) &&			!mpf_checksum((unsigned char *)bp, 16) &&			((mpf->mpf_specification == 1)				|| (mpf->mpf_specification == 4)) ) {			smp_found_config = 1;			printk(KERN_INFO "found SMP MP-table at %08lx\n",						virt_to_phys(mpf));			reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);			if (mpf->mpf_physptr) {				/*				 * We cannot access to MPC table to compute				 * table size yet, as only few megabytes from				 * the bottom is mapped now.				 * PC-9800's MPC table places on the very last				 * of physical memory; so that simply reserving				 * PAGE_SIZE from mpg->mpf_physptr yields BUG()				 * in reserve_bootmem.				 */				unsigned long size = PAGE_SIZE;				unsigned long end = max_low_pfn * PAGE_SIZE;				if (mpf->mpf_physptr + size > end)					size = end - mpf->mpf_physptr;				reserve_bootmem(mpf->mpf_physptr, size);			}			mpf_found = mpf;			return 1;		}		bp += 4;		length -= 16;	}	return 0;}

⌨️ 快捷键说明

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