| /* |
| * <Insert copyright here : it must be BSD-like so everyone can use it> |
| * |
| * Author: Erich Boleyn <erich@uruk.org> http://www.uruk.org/~erich/ |
| * |
| * Header file implementing Intel MultiProcessor Specification (MPS) |
| * version 1.1 and 1.4 SMP hardware control for Intel Architecture CPUs, |
| * with hooks for running correctly on a standard PC without the hardware. |
| * |
| * This file was created from information in the Intel MPS version 1.4 |
| * document, order number 242016-004, which can be ordered from the |
| * Intel literature center. |
| */ |
| |
| #ifndef _SMP_IMPS_H |
| #define _SMP_IMPS_H |
| |
| /* make sure "apic.h" is included */ |
| #ifndef _APIC_H |
| #error Must include "apic.h" before "smp-imps.h" |
| #endif /* !_APIC_H */ |
| |
| /* |
| * Defines used. |
| */ |
| |
| #ifdef IMPS_DEBUG |
| #define IMPS_DEBUG_PRINT(x) KERNEL_PRINT(x) |
| #else /* !IMPS_DEBUG */ |
| #define IMPS_DEBUG_PRINT(x) |
| #endif /* !IMPS_DEBUG */ |
| |
| #define IMPS_MAX_CPUS APIC_BROADCAST_ID |
| |
| /* |
| * Defines representing limitations on values usable in different |
| * situations. This mostly depends on whether the APICs are old |
| * (82489DX) or new (SIO or Pentium/Pentium Pro integrated APICs). |
| * |
| * NOTE: It appears that the APICs must either be all old or all new, |
| * or broadcasts won't work right. |
| * NOTE #2: Given that, the maximum ID which can be sent to predictably |
| * is 14 for new APICs and 254 for old APICs. So, this all implies that |
| * a maximum of 15 processors is supported with the new APICs, and a |
| * maximum of 255 processors with the old APICs. |
| */ |
| |
| #define IMPS_APIC_ID(x) \ |
| ( imps_any_new_apics ? APIC_NEW_ID(x) : APIC_OLD_ID(x) ) |
| |
| /* |
| * This is the value that must be in the "sig" member of the MP |
| * Floating Pointer Structure. |
| */ |
| #define IMPS_FPS_SIGNATURE ('_' | ('M'<<8) | ('P'<<16) | ('_'<<24)) |
| #define IMPS_FPS_IMCRP_BIT 0x80 |
| #define IMPS_FPS_DEFAULT_MAX 7 |
| |
| /* |
| * This is the value that must be in the "sig" member of the MP |
| * Configuration Table Header. |
| */ |
| #define IMPS_CTH_SIGNATURE ('P' | ('C'<<8) | ('M'<<16) | ('P'<<24)) |
| |
| /* |
| * These are the "type" values for Base MP Configuration Table entries. |
| */ |
| #define IMPS_FLAG_ENABLED 1 |
| #define IMPS_BCT_PROCESSOR 0 |
| #define IMPS_CPUFLAG_BOOT 2 |
| #define IMPS_BCT_BUS 1 |
| #define IMPS_BCT_IOAPIC 2 |
| #define IMPS_BCT_IO_INTERRUPT 3 |
| #define IMPS_BCT_LOCAL_INTERRUPT 4 |
| #define IMPS_INT_INT 0 |
| #define IMPS_INT_NMI 1 |
| #define IMPS_INT_SMI 2 |
| #define IMPS_INT_EXTINT 3 |
| |
| |
| /* |
| * Typedefs and data item definitions done here. |
| */ |
| |
| typedef struct imps_fps imps_fps; /* MP floating pointer structure */ |
| typedef struct imps_cth imps_cth; /* MP configuration table header */ |
| typedef struct imps_processor imps_processor; |
| typedef struct imps_bus imps_bus; |
| typedef struct imps_ioapic imps_ioapic; |
| typedef struct imps_interrupt imps_interrupt; |
| |
| |
| /* |
| * Data structures defined here |
| */ |
| |
| /* |
| * MP Floating Pointer Structure (fps) |
| * |
| * Look at page 4-3 of the MP spec for the starting definitions of |
| * this structure. |
| */ |
| struct imps_fps |
| { |
| unsigned sig; |
| imps_cth *cth_ptr; |
| unsigned char length; |
| unsigned char spec_rev; |
| unsigned char checksum; |
| unsigned char feature_info[5]; |
| }; |
| |
| /* |
| * MP Configuration Table Header (cth) |
| * |
| * Look at page 4-5 of the MP spec for the starting definitions of |
| * this structure. |
| */ |
| struct imps_cth |
| { |
| unsigned sig; |
| unsigned short base_length; |
| unsigned char spec_rev; |
| unsigned char checksum; |
| char oem_id[8]; |
| char prod_id[12]; |
| unsigned oem_table_ptr; |
| unsigned short oem_table_size; |
| unsigned short entry_count; |
| unsigned lapic_addr; |
| unsigned short extended_length; |
| unsigned char extended_checksum; |
| char reserved[1]; |
| }; |
| |
| /* |
| * Base MP Configuration Table Types. They are sorted according to |
| * type (i.e. all of type 0 come first, etc.). Look on page 4-6 for |
| * the start of the descriptions. |
| */ |
| |
| struct imps_processor |
| { |
| unsigned char type; /* must be 0 */ |
| unsigned char apic_id; |
| unsigned char apic_ver; |
| unsigned char flags; |
| unsigned signature; |
| unsigned features; |
| char reserved[8]; |
| }; |
| |
| struct imps_bus |
| { |
| unsigned char type; /* must be 1 */ |
| unsigned char id; |
| char bus_type[6]; |
| }; |
| |
| struct imps_ioapic |
| { |
| unsigned char type; /* must be 2 */ |
| unsigned char id; |
| unsigned char ver; |
| unsigned char flags; |
| unsigned addr; |
| }; |
| |
| struct imps_interrupt |
| { |
| unsigned char type; /* must be 3 or 4 */ |
| unsigned char int_type; |
| unsigned short flags; |
| unsigned char source_bus_id; |
| unsigned char source_bus_irq; |
| unsigned char dest_apic_id; |
| unsigned char dest_apic_intin; |
| }; |
| |
| |
| /* |
| * Exported globals here. |
| */ |
| |
| /* |
| * "imps_any_new_apics" is non-zero if any of the APICS (local or I/O) |
| * are *not* an 82489DX. This is useful to determine if more than 15 |
| * CPUs can be supported (true if zero). |
| */ |
| extern int imps_any_new_apics; |
| |
| /* |
| * "imps_enabled" is non-zero if the probe sequence found IMPS |
| * information and was successful. |
| */ |
| extern int imps_enabled; |
| |
| /* |
| * This contains the local APIC hardware address. |
| */ |
| extern unsigned imps_lapic_addr; |
| |
| /* |
| * This represents the number of CPUs found. |
| */ |
| extern int imps_num_cpus; |
| |
| /* |
| * These map from virtual cpu numbers to APIC id's and back. |
| */ |
| extern unsigned char imps_cpu_apic_map[IMPS_MAX_CPUS]; |
| extern unsigned char imps_apic_cpu_map[IMPS_MAX_CPUS]; |
| |
| |
| /* |
| * This is the primary function for probing for Intel MPS 1.1/1.4 |
| * compatible hardware and BIOS information. While probing the CPUs |
| * information returned from the BIOS, this also starts up each CPU |
| * and gets it ready for use. |
| * |
| * Call this during the early stages of OS startup, before memory can |
| * be messed up. |
| * |
| * Returns 1 if IMPS information was found and is valid, else 0. |
| */ |
| |
| int imps_probe(void); |
| |
| |
| /* |
| * Defines that use variables |
| */ |
| |
| #define IMPS_LAPIC_READ(x) (*((volatile unsigned *) (imps_lapic_addr+(x)))) |
| #define IMPS_LAPIC_WRITE(x, y) \ |
| (*((volatile unsigned *) (imps_lapic_addr+(x))) = (y)) |
| |
| #endif /* !_SMP_IMPS_H */ |
| |