aboutsummaryrefslogtreecommitdiff
path: root/src/arch/i386/include/arch/smp/mpspec.h
blob: 32ed2d752acb4735c650a57337da080b646e067b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
#ifndef __ASM_MPSPEC_H
#define __ASM_MPSPEC_H

#if HAVE_MP_TABLE==1

/*
 * Structure definitions for SMP machines following the
 * Intel Multiprocessing Specification 1.1 and 1.4.
 */

/*
 * This tag identifies where the SMP configuration
 * information is. 
 */
 
#define SMP_MAGIC_IDENT	(('_'<<24)|('P'<<16)|('M'<<8)|'_')

/*
 * a maximum of 16 APICs with the current APIC ID architecture.
 */
#define MAX_APICS 16


#define SMP_FLOATING_TABLE_LEN sizeof(struct intel_mp_floating)

struct intel_mp_floating
{
	char mpf_signature[4];		/* "_MP_" 			*/
	unsigned long mpf_physptr;	/* Configuration table address	*/
	unsigned char mpf_length;	/* Our length (paragraphs)	*/
	unsigned char mpf_specification;/* Specification version	*/
	unsigned char mpf_checksum;	/* Checksum (makes sum 0)	*/
	unsigned char mpf_feature1;	/* Standard or configuration ? 	*/
	unsigned char mpf_feature2;	/* Bit7 set for IMCR|PIC	*/
	unsigned char mpf_feature3;	/* Unused (0)			*/
	unsigned char mpf_feature4;	/* Unused (0)			*/
	unsigned char mpf_feature5;	/* Unused (0)			*/
};

struct mp_config_table
{
	char mpc_signature[4];
#define MPC_SIGNATURE "PCMP"
	unsigned short mpc_length;	/* Size of table */
	char  mpc_spec;			/* 0x01 */
	char  mpc_checksum;
	char  mpc_oem[8];
	char  mpc_productid[12];
	unsigned long mpc_oemptr;	/* 0 if not present */
	unsigned short mpc_oemsize;	/* 0 if not present */
	unsigned short mpc_entry_count;
	unsigned long mpc_lapic;	/* APIC address */
	unsigned short mpe_length;	/* Extended Table size */
	unsigned char mpe_checksum;	/* Extended Table checksum */
	unsigned char reserved;
};

/* Followed by entries */

#define	MP_PROCESSOR	0
#define	MP_BUS		1
#define	MP_IOAPIC	2
#define	MP_INTSRC	3
#define	MP_LINTSRC	4

struct mpc_config_processor
{
	unsigned char mpc_type;
	unsigned char mpc_apicid;	/* Local APIC number */
	unsigned char mpc_apicver;	/* Its versions */
	unsigned char mpc_cpuflag;
#define MPC_CPU_ENABLED		1	/* Processor is available */
#define MPC_CPU_BOOTPROCESSOR	2	/* Processor is the BP */
	unsigned long mpc_cpufeature;		
#define MPC_CPU_STEPPING_MASK 0x0F
#define MPC_CPU_MODEL_MASK	0xF0
#define MPC_CPU_FAMILY_MASK	0xF00
	unsigned long mpc_featureflag;	/* CPUID feature value */
	unsigned long mpc_reserved[2];
};

struct mpc_config_bus
{
	unsigned char mpc_type;
	unsigned char mpc_busid;
	unsigned char mpc_bustype[6] __attribute((packed));
};

#define BUSTYPE_EISA	"EISA"
#define BUSTYPE_ISA	"ISA"
#define BUSTYPE_INTERN	"INTERN"	/* Internal BUS */
#define BUSTYPE_MCA	"MCA"
#define BUSTYPE_VL	"VL"		/* Local bus */
#define BUSTYPE_PCI	"PCI"
#define BUSTYPE_PCMCIA	"PCMCIA"

struct mpc_config_ioapic
{
	unsigned char mpc_type;
	unsigned char mpc_apicid;
	unsigned char mpc_apicver;
	unsigned char mpc_flags;
#define MPC_APIC_USABLE		0x01
	unsigned long mpc_apicaddr;
};

struct mpc_config_intsrc
{
	unsigned char mpc_type;
	unsigned char mpc_irqtype;
	unsigned short mpc_irqflag;
	unsigned char mpc_srcbus;
	unsigned char mpc_srcbusirq;
	unsigned char mpc_dstapic;
	unsigned char mpc_dstirq;
};

enum mp_irq_source_types {
	mp_INT = 0,
	mp_NMI = 1,
	mp_SMI = 2,
	mp_ExtINT = 3
};

#define MP_IRQ_POLARITY_DEFAULT	0x0
#define MP_IRQ_POLARITY_HIGH	0x1
#define MP_IRQ_POLARITY_LOW	0x3
#define MP_IRQ_POLARITY_MASK    0x3
#define MP_IRQ_TRIGGER_DEFAULT	0x0
#define MP_IRQ_TRIGGER_EDGE	0x4
#define MP_IRQ_TRIGGER_LEVEL	0xc
#define MP_IRQ_TRIGGER_MASK     0xc


struct mpc_config_lintsrc
{
	unsigned char mpc_type;
	unsigned char mpc_irqtype;
	unsigned short mpc_irqflag;
	unsigned char mpc_srcbusid;
	unsigned char mpc_srcbusirq;
	unsigned char mpc_destapic;	
#define MP_APIC_ALL	0xFF
	unsigned char mpc_destapiclint;
};

/*
 *	Default configurations
 *
 *	1	2 CPU ISA 82489DX
 *	2	2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining
 *	3	2 CPU EISA 82489DX
 *	4	2 CPU MCA 82489DX
 *	5	2 CPU ISA+PCI
 *	6	2 CPU EISA+PCI
 *	7	2 CPU MCA+PCI
 */

#define MAX_IRQ_SOURCES 128
#define MAX_MP_BUSSES 32
enum mp_bustype {
	MP_BUS_ISA,
	MP_BUS_EISA,
	MP_BUS_PCI,
	MP_BUS_MCA
};

/* Followed by entries */

#define	MPE_SYSTEM_ADDRESS_SPACE	0x80
#define	MPE_BUS_HIERARCHY		0x81
#define	MPE_COMPATIBILITY_ADDRESS_SPACE	0x82

struct mp_exten_config {
	unsigned char mpe_type;
	unsigned char mpe_length;
};

typedef struct mp_exten_config *mpe_t;

struct mp_exten_system_address_space {
	unsigned char mpe_type;
	unsigned char mpe_length;
	unsigned char mpe_busid;
	unsigned char mpe_address_type;
#define ADDRESS_TYPE_IO       0
#define ADDRESS_TYPE_MEM      1
#define ADDRESS_TYPE_PREFETCH 2
	unsigned int  mpe_address_base_low;
	unsigned int  mpe_address_base_high;
	unsigned int  mpe_address_length_low;
	unsigned int  mpe_address_length_high;
};

struct mp_exten_bus_hierarchy {
	unsigned char mpe_type;
	unsigned char mpe_length;
	unsigned char mpe_busid;
	unsigned char mpe_bus_info;
#define BUS_SUBTRACTIVE_DECODE 1
	unsigned char mpe_parent_busid;
	unsigned char reserved[3];
};

struct mp_exten_compatibility_address_space {
	unsigned char mpe_type;
	unsigned char mpe_length;
	unsigned char mpe_busid;
	unsigned char mpe_address_modifier;
#define ADDRESS_RANGE_SUBTRACT 1
#define ADDRESS_RANGE_ADD      0
	unsigned int  mpe_range_list;
#define RANGE_LIST_IO_ISA	0	
	/* X100 - X3FF
	 * X500 - X7FF
	 * X900 - XBFF
	 * XD00 - XFFF
	 */
#define RANGE_LIST_IO_VGA	1
	/* X3B0 - X3BB
	 * X3C0 - X3DF
	 * X7B0 - X7BB
	 * X7C0 - X7DF
	 * XBB0 - XBBB
	 * XBC0 - XBDF
	 * XFB0 - XFBB
	 * XFC0 - XCDF
	 */
};

/* Default local apic addr */
#define LAPIC_ADDR 0xFEE00000

void *smp_next_mpc_entry(struct mp_config_table *mc);
void *smp_next_mpe_entry(struct mp_config_table *mc);

void smp_write_processor(struct mp_config_table *mc,
	unsigned char apicid, unsigned char apicver,
	unsigned char cpuflag, unsigned int cpufeature,
	unsigned int featureflag);
void smp_write_processors(struct mp_config_table *mc);
void smp_write_bus(struct mp_config_table *mc,
	unsigned char id, unsigned char *bustype);
void smp_write_ioapic(struct mp_config_table *mc,
	unsigned char id, unsigned char ver, 
	unsigned long apicaddr);
void smp_write_intsrc(struct mp_config_table *mc,
	unsigned char irqtype, unsigned short irqflag,
	unsigned char srcbus, unsigned char srcbusirq,
	unsigned char dstapic, unsigned char dstirq);
void smp_write_lintsrc(struct mp_config_table *mc,
	unsigned char irqtype, unsigned short irqflag,
	unsigned char srcbusid, unsigned char srcbusirq,
	unsigned char destapic, unsigned char destapiclint);
void smp_write_address_space(struct mp_config_table *mc,
	unsigned char busid, unsigned char address_type,
	unsigned int address_base_low, unsigned int address_base_high,
	unsigned int address_length_low, unsigned int address_length_high);
void smp_write_bus_hierarchy(struct mp_config_table *mc,
	unsigned char busid, unsigned char bus_info,
	unsigned char parent_busid);
void smp_write_compatibility_address_space(struct mp_config_table *mc,
	unsigned char busid, unsigned char address_modifier,
	unsigned int range_list);
unsigned char smp_compute_checksum(void *v, int len);
void *smp_write_floating_table(unsigned long addr);
unsigned long write_smp_table(unsigned long addr);

#else /* HAVE_MP_TABLE */
#if 0
static inline 
unsigned long write_smp_table(unsigned long addr)
{
	return addr;
}
#endif
#define write_smp_table(addr)	(addr)
#endif /* HAVE_MP_TABLE */

#endif