]>
git.ipfire.org Git - ipfire-2.x.git/blob - src/hwinfo/src/smp/smp.c
2 [_Anarchy_(alan@lightning.swansea.uk.linux.org)] you should do one check
3 though - if the board seems to be SMP and the CPU in /proc/cpuinfo is non
4 intel dont install an SMP kernel - thats a dual pentium board with a cyrix
5 or similar single cpu in it
18 #define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')
20 struct intel_mp_floating
22 char mpf_signature
[4]; /* "_MP_" */
23 unsigned long mpf_physptr
; /* Configuration table address */
24 unsigned char mpf_length
; /* Our length (paragraphs) */
25 unsigned char mpf_specification
;/* Specification version */
26 unsigned char mpf_checksum
; /* Checksum (makes sum 0) */
27 unsigned char mpf_feature1
; /* Standard or configuration ? */
28 unsigned char mpf_feature2
; /* Bit7 set for IMCR|PIC */
29 unsigned char mpf_feature3
; /* Unused (0) */
30 unsigned char mpf_feature4
; /* Unused (0) */
31 unsigned char mpf_feature5
; /* Unused (0) */
34 struct mp_config_table
36 char mpc_signature
[4];
37 #define MPC_SIGNATURE "PCMP"
38 unsigned short mpc_length
; /* Size of table */
39 char mpc_spec
; /* 0x01 */
42 char mpc_productid
[12];
43 unsigned long mpc_oemptr
; /* 0 if not present */
44 unsigned short mpc_oemsize
; /* 0 if not present */
45 unsigned short mpc_oemcount
;
46 unsigned long mpc_lapic
; /* APIC address */
47 unsigned long reserved
;
50 /* Followed by entries */
52 #define MP_PROCESSOR 0
58 struct mpc_config_processor
60 unsigned char mpc_type
;
61 unsigned char mpc_apicid
; /* Local APIC number */
62 unsigned char mpc_apicver
; /* Its versions */
63 unsigned char mpc_cpuflag
;
64 #define CPU_ENABLED 1 /* Processor is available */
65 #define CPU_BOOTPROCESSOR 2 /* Processor is the BP */
66 unsigned long mpc_cpufeature
;
67 #define CPU_STEPPING_MASK 0x0F
68 #define CPU_MODEL_MASK 0xF0
69 #define CPU_FAMILY_MASK 0xF00
70 unsigned long mpc_featureflag
; /* CPUID feature value */
71 unsigned long mpc_reserved
[2];
76 unsigned char mpc_type
;
77 unsigned char mpc_busid
;
78 unsigned char mpc_bustype
[6] __attribute((packed
));
81 #define BUSTYPE_EISA "EISA"
82 #define BUSTYPE_ISA "ISA"
83 #define BUSTYPE_INTERN "INTERN" /* Internal BUS */
84 #define BUSTYPE_MCA "MCA"
85 #define BUSTYPE_VL "VL" /* Local bus */
86 #define BUSTYPE_PCI "PCI"
87 #define BUSTYPE_PCMCIA "PCMCIA"
89 /* We don't understand the others */
91 struct mpc_config_ioapic
93 unsigned char mpc_type
;
94 unsigned char mpc_apicid
;
95 unsigned char mpc_apicver
;
96 unsigned char mpc_flags
;
97 #define MPC_APIC_USABLE 0x01
98 unsigned long mpc_apicaddr
;
101 struct mpc_config_intsrc
103 unsigned char mpc_type
;
104 unsigned char mpc_irqtype
;
105 unsigned short mpc_irqflag
;
106 unsigned char mpc_srcbus
;
107 unsigned char mpc_srcbusirq
;
108 unsigned char mpc_dstapic
;
109 unsigned char mpc_dstirq
;
112 #define MP_INT_VECTORED 0
115 #define MP_INT_EXTINT 3
117 #define MP_IRQDIR_DEFAULT 0
118 #define MP_IRQDIR_HIGH 1
119 #define MP_IRQDIR_LOW 3
122 struct mpc_config_intlocal
124 unsigned char mpc_type
;
125 unsigned char mpc_irqtype
;
126 unsigned short mpc_irqflag
;
127 unsigned char mpc_srcbusid
;
128 unsigned char mpc_srcbusirq
;
129 unsigned char mpc_destapic
;
130 #define MP_APIC_ALL 0xFF
131 unsigned char mpc_destapiclint
;
136 * Default configurations
138 * 1 2 CPU ISA 82489DX
139 * 2 2 CPU EISA 82489DX no IRQ 8 or timer chaining
140 * 3 2 CPU EISA 82489DX
141 * 4 2 CPU MCA 82489DX
148 static int smp_found_config
=0;
151 * Checksum an MP configuration block.
154 static int mpf_checksum(unsigned char *mp
, int len
)
162 static int do_smp_scan_config(unsigned long *bp
, unsigned long length
)
164 struct intel_mp_floating
*mpf
;
167 if (sizeof(*mpf)!=16)
168 logMessage("Error: MPF size\n");
173 if (*bp
==SMP_MAGIC_IDENT
)
175 mpf
=(struct intel_mp_floating
*)bp
;
176 if (mpf
->mpf_length
==1 &&
177 !mpf_checksum((unsigned char *)bp
,16) &&
178 (mpf
->mpf_specification
== 1
179 || mpf
->mpf_specification
== 4) )
181 /*logMessage("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
182 if (mpf->mpf_feature2&(1<<7))
183 logMessage(" IMCR and PIC compatibility mode.\n");
185 logMessage(" Virtual Wire compatibility mode.\n");
198 static int smp_scan_config(int mem_fd
, unsigned long base
,
199 unsigned long length
)
208 p
=mmap(0, (length
+4095)&0xFFFFF000, PROT_READ
, MAP_SHARED
,
209 mem_fd
, (base
&0xFFFF0000));
212 /*logMessage("SMP Probe error: mmap: %s", strerror(errno));*/
215 do_smp_scan_config(p
+o
, length
-o
);
216 munmap(p
, (length
+4095)&0xFFFFF000);
220 static int intelDetectSMP(void)
224 mem_fd
=open("/dev/mem", O_RDONLY
);
228 /*logMessage("Error detecting SMP: /dev/mem: %s", strerror(errno));*/
232 * FIXME: Linux assumes you have 640K of base ram..
233 * this continues the error...
235 * 1) Scan the bottom 1K for a signature
236 * 2) Scan the top 1K of base RAM
237 * 3) Scan the 64K of bios
239 if (!smp_scan_config(mem_fd
, 0x0, 0x400) &&
240 !smp_scan_config(mem_fd
, 639*0x400,0x400) &&
241 !smp_scan_config(mem_fd
, 0xF0000,0x10000)) {
245 * If it is an SMP machine we should know now, unless the
246 * configuration is in an EISA/MCA bus machine with an
247 * extended bios data area.
249 * there is a real-mode segmented pointer pointing to the
250 * 4K EBDA area at 0x40E, calculate and scan it here.
252 * NOTE! There are Linux loaders that will corrupt the EBDA
253 * area, and as such this kind of SMP config may be less
254 * trustworthy, simply because the SMP table may have been
255 * stomped on during early boot. These loaders are buggy and
258 unsigned int address
;
260 address
= *(unsigned short *)phys_to_virt(0x40E);
262 smp_scan_config(mem_fd
, address
, 0x1000);
263 if (smp_found_config
)
264 /*logMessage("WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");*/
269 logMessage("Detected SMP capable motherboard\n");
271 logMessage("Detected non SMP capable motherboard\n");
273 return smp_found_config
;
278 static int isSMP
= -1;
283 return isSMP
= intelDetectSMP();
286 #endif /* __i386__ */