1 /* 2 * <Insert copyright here : it must be BSD-like so everyone can use it> 3 * 4 * Author: Erich Boleyn <erich (at) 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