1 /*
2  *  <Insert copyright here : it must be BSD-like so everyone can use it>
3  *
4  *  Author:  Erich Boleyn  <erich@uruk.org>   http://www.uruk.org/~erich/
5  *
6  *  Header file implementing Intel MultiProcessor Specification (MPS)
7  *  version 1.1 and 1.4 SMP hardware control for Intel Architecture CPUs,
8  *  with hooks for running correctly on a standard PC without the hardware.
9  *
10  *  This file was created from information in the Intel MPS version 1.4
11  *  document, order number 242016-004, which can be ordered from the
12  *  Intel literature center.
13  */
14 
15 #ifndef _SMP_IMPS_H
16 #define _SMP_IMPS_H
17 
18 /* make sure "apic.h" is included */
19 #ifndef _APIC_H
20 #error		Must include "apic.h" before "smp-imps.h"
21 #endif /* !_APIC_H */
22 
23 /*
24  *  Defines used.
25  */
26 
27 #ifdef IMPS_DEBUG
28 #define IMPS_DEBUG_PRINT(x)  KERNEL_PRINT(x)
29 #else /* !IMPS_DEBUG */
30 #define IMPS_DEBUG_PRINT(x)
31 #endif /* !IMPS_DEBUG */
32 
33 #define IMPS_MAX_CPUS			APIC_BROADCAST_ID
34 
35 /*
36  *  Defines representing limitations on values usable in different
37  *  situations.  This mostly depends on whether the APICs are old
38  *  (82489DX) or new (SIO or Pentium/Pentium Pro integrated APICs).
39  *
40  *  NOTE:  It appears that the APICs must either be all old or all new,
41  *    or broadcasts won't work right.
42  *  NOTE #2:  Given that, the maximum ID which can be sent to predictably
43  *    is 14 for new APICs and 254 for old APICs.  So, this all implies that
44  *    a maximum of 15 processors is supported with the new APICs, and a
45  *    maximum of 255 processors with the old APICs.
46  */
47 
48 #define IMPS_APIC_ID(x)							\
49   ( imps_any_new_apics ? APIC_NEW_ID(x) : APIC_OLD_ID(x) )
50 
51 /*
52  *  This is the value that must be in the "sig" member of the MP
53  *  Floating Pointer Structure.
54  */
55 #define IMPS_FPS_SIGNATURE	('_' | ('M'<<8) | ('P'<<16) | ('_'<<24))
56 #define IMPS_FPS_IMCRP_BIT	0x80
57 #define IMPS_FPS_DEFAULT_MAX	7
58 
59 /*
60  *  This is the value that must be in the "sig" member of the MP
61  *  Configuration Table Header.
62  */
63 #define IMPS_CTH_SIGNATURE	('P' | ('C'<<8) | ('M'<<16) | ('P'<<24))
64 
65 /*
66  *  These are the "type" values for Base MP Configuration Table entries.
67  */
68 #define		IMPS_FLAG_ENABLED	1
69 #define IMPS_BCT_PROCESSOR		0
70 #define		IMPS_CPUFLAG_BOOT	2
71 #define IMPS_BCT_BUS			1
72 #define IMPS_BCT_IOAPIC			2
73 #define IMPS_BCT_IO_INTERRUPT		3
74 #define IMPS_BCT_LOCAL_INTERRUPT	4
75 #define		IMPS_INT_INT		0
76 #define		IMPS_INT_NMI		1
77 #define		IMPS_INT_SMI		2
78 #define		IMPS_INT_EXTINT		3
79 
80 
81 /*
82  *  Typedefs and data item definitions done here.
83  */
84 
85 typedef struct imps_fps imps_fps;	/* MP floating pointer structure */
86 typedef struct imps_cth imps_cth;	/* MP configuration table header */
87 typedef struct imps_processor imps_processor;
88 typedef struct imps_bus imps_bus;
89 typedef struct imps_ioapic imps_ioapic;
90 typedef struct imps_interrupt imps_interrupt;
91 
92 
93 /*
94  *  Data structures defined here
95  */
96 
97 /*
98  *  MP Floating Pointer Structure (fps)
99  *
100  *  Look at page 4-3 of the MP spec for the starting definitions of
101  *  this structure.
102  */
103 struct imps_fps
104   {
105     unsigned sig;
106     imps_cth *cth_ptr;
107     unsigned char length;
108     unsigned char spec_rev;
109     unsigned char checksum;
110     unsigned char feature_info[5];
111   };
112 
113 /*
114  *  MP Configuration Table Header  (cth)
115  *
116  *  Look at page 4-5 of the MP spec for the starting definitions of
117  *  this structure.
118  */
119 struct imps_cth
120   {
121     unsigned sig;
122     unsigned short base_length;
123     unsigned char spec_rev;
124     unsigned char checksum;
125     char oem_id[8];
126     char prod_id[12];
127     unsigned oem_table_ptr;
128     unsigned short oem_table_size;
129     unsigned short entry_count;
130     unsigned lapic_addr;
131     unsigned short extended_length;
132     unsigned char extended_checksum;
133     char reserved[1];
134   };
135 
136 /*
137  *  Base MP Configuration Table Types.  They are sorted according to
138  *  type (i.e. all of type 0 come first, etc.).  Look on page 4-6 for
139  *  the start of the descriptions.
140  */
141 
142 struct imps_processor
143   {
144     unsigned char type;		/* must be 0 */
145     unsigned char apic_id;
146     unsigned char apic_ver;
147     unsigned char flags;
148     unsigned signature;
149     unsigned features;
150     char reserved[8];
151   };
152 
153 struct imps_bus
154   {
155     unsigned char type;		/* must be 1 */
156     unsigned char id;
157     char bus_type[6];
158   };
159 
160 struct imps_ioapic
161   {
162     unsigned char type;		/* must be 2 */
163     unsigned char id;
164     unsigned char ver;
165     unsigned char flags;
166     unsigned addr;
167   };
168 
169 struct imps_interrupt
170   {
171     unsigned char type;		/* must be 3 or 4 */
172     unsigned char int_type;
173     unsigned short flags;
174     unsigned char source_bus_id;
175     unsigned char source_bus_irq;
176     unsigned char dest_apic_id;
177     unsigned char dest_apic_intin;
178   };
179 
180 
181 /*
182  *  Exported globals here.
183  */
184 
185 /*
186  *  This is the primary function for probing for Intel MPS 1.1/1.4
187  *  compatible hardware and BIOS information.  While probing the CPUs
188  *  information returned from the BIOS, this also starts up each CPU
189  *  and gets it ready for use.
190  *
191  *  Call this during the early stages of OS startup, before memory can
192  *  be messed up.
193  *
194  *  Returns 1 if IMPS information was found and is valid, else 0.
195  */
196 
197 int imps_probe (void);
198 
199 
200 /*
201  *  Defines that use variables
202  */
203 
204 #define IMPS_LAPIC_READ(x)  (*((volatile unsigned *) (imps_lapic_addr+(x))))
205 #define IMPS_LAPIC_WRITE(x, y)   \
206    (*((volatile unsigned *) (imps_lapic_addr+(x))) = (y))
207 
208 #endif /* !_SMP_IMPS_H */
209