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
85typedef struct imps_fps imps_fps;	/* MP floating pointer structure */
86typedef struct imps_cth imps_cth;	/* MP configuration table header */
87typedef struct imps_processor imps_processor;
88typedef struct imps_bus imps_bus;
89typedef struct imps_ioapic imps_ioapic;
90typedef 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 */
103struct 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 */
119struct 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
142struct 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
153struct imps_bus
154  {
155    unsigned char type;		/* must be 1 */
156    unsigned char id;
157    char bus_type[6];
158  };
159
160struct 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
169struct 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
197int 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