📄 pcmb_smp.c
字号:
//==========================================================================//// pcmb_smp.c//// HAL SMP implementation////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): nickg// Contributors: nickg// Date: 2001-08-03// Purpose: HAL SMP implementation// Description: This file contains SMP support functions.////####DESCRIPTIONEND####////========================================================================*/#include <pkgconf/hal.h>#include <pkgconf/hal_i386.h>#include <pkgconf/hal_i386_pcmb.h>#ifdef CYGPKG_HAL_SMP_SUPPORT#ifdef CYGPKG_KERNEL#include <pkgconf/kernel.h>#endif#include <cyg/infra/cyg_type.h> // Base types#include <cyg/infra/cyg_trac.h> // tracing macros#include <cyg/infra/cyg_ass.h> // assertion macros#include <cyg/infra/diag.h>#include <cyg/hal/hal_intr.h>#include <cyg/hal/hal_io.h>#include <cyg/hal/hal_smp.h>// ------------------------------------------------------------------------// Debugging/diagnostic controls// Setting this to 1 causes the parsing of the MP structures and the// initialization of the APIC and IOAPIC to be reported on the// diagnostic channel.#define SHOW_DIAGNOSTICS 0// Setting this to 1 causes various things to be displayed on the PC// screen during normal operation. These are mostly for my own use,// and may be somewhat obscure to anyone else.#define SCREEN_DIAGNOSTICS 0#if SCREEN_DIAGNOSTICS==0#undef PC_WRITE_SCREEN#undef PC_WRITE_SCREEN_8#undef PC_WRITE_SCREEN_16#undef PC_WRITE_SCREEN_32#define PC_WRITE_SCREEN( pos, ch )#define PC_WRITE_SCREEN_8( pos, val )#define PC_WRITE_SCREEN_16( pos, val )#define PC_WRITE_SCREEN_32( pos, val )#endif// ------------------------------------------------------------------------static int streq( const char *s1, const char *s2 ){ while( *s1 == *s2 && *s1 && *s2 ) s1++,s2++; return !(*s2-*s1);}/*------------------------------------------------------------------------*/// MP FPS structure:#define MP_FPS_SIGNATURE 0#define MP_FPS_MPCT 4#define MP_FPS_LENGTH 8#define MP_FPS_REV 9#define MP_FPS_CSUM 10#define MP_FPS_FEATURE1 11#define MP_FPS_FEATURE2 12#define MP_FPS_FEATURE3 13#define MP_FPS_FEATURE4 14#define MP_FPS_FEATURE5 15#define MP_FPS_SIZE 16#define MP_FPS_SIGNATURE_VALUE 0x5f504d5f/*------------------------------------------------------------------------*/// MP config table structure// Header structure:#define MPCT_HDR_SIGNATURE 0#define MPCT_HDR_LENGTH 4#define MPCT_HDR_REV 6#define MPCT_HDR_CHECKSUM 7#define MPCT_HDR_OEM_ID 8#define MPCT_HDR_PROD_ID 16#define MPCT_HDR_OEM_TAB 28#define MPCT_HDR_OEM_TAB_SIZE 32#define MPCT_HDR_ENTRY_COUNT 34#define MPCT_HDR_LOCAL_APIC 36#define MPCT_HDR_XTAB_LENGTH 40#define MPCT_HDR_XTAB_CHECKSUM 42#define MPCT_HDR_SIZE 44#define MPCT_HDR_SIGNATURE_VAL 0x504d4350#define MPCT_ENTRY_TYPE_PROCESSOR 0#define MPCT_ENTRY_TYPE_BUS 1#define MPCT_ENTRY_TYPE_IOAPIC 2#define MPCT_ENTRY_TYPE_INTERRUPT_IO 3#define MPCT_ENTRY_TYPE_INTERRUPT_LOCAL 4#define MPCT_ENTRY_PROC_TYPE 0#define MPCT_ENTRY_PROC_APIC_ID 1#define MPCT_ENTRY_PROC_APIC_VER 2#define MPCT_ENTRY_PROC_CPU_FLAGS 3#define MPCT_ENTRY_PROC_CPU_SIGNATURE 4#define MPCT_ENTRY_PROC_FEATURE_FLAGS 8#define MPCT_ENTRY_PROC_RESERVED0 12#define MPCT_ENTRY_PROC_RESERVED1 16#define MPCT_ENTRY_PROC_SIZE 20#define MPCT_ENTRY_BUS_TYPE 0#define MPCT_ENTRY_BUS_ID 1#define MPCT_ENTRY_BUS_TYPE_STRING 2#define MPCT_ENTRY_BUS_SIZE 8#define MPCT_ENTRY_IOAPIC_TYPE 0#define MPCT_ENTRY_IOAPIC_ID 1#define MPCT_ENTRY_IOAPIC_VER 2#define MPCT_ENTRY_IOAPIC_FLAGS 3#define MPCT_ENTRY_IOAPIC_ADDRESS 4#define MPCT_ENTRY_IOAPIC_SIZE 8#define MPCT_ENTRY_IOINT_TYPE 0#define MPCT_ENTRY_IOINT_INT_TYPE 1#define MPCT_ENTRY_IOINT_FLAGS 2#define MPCT_ENTRY_IOINT_SOURCE_BUS 4#define MPCT_ENTRY_IOINT_SOURCE_IRQ 5#define MPCT_ENTRY_IOINT_DEST_APIC 6#define MPCT_ENTRY_IOINT_DEST_INT 7#define MPCT_ENTRY_IOINT_SIZE 8#define MPCT_ENTRY_LOCINT_TYPE 0#define MPCT_ENTRY_LOCINT_INT_TYPE 1#define MPCT_ENTRY_LOCINT_FLAGS 2#define MPCT_ENTRY_LOCINT_SOURCE_BUS 4#define MPCT_ENTRY_LOCINT_SOURCE_IRQ 5#define MPCT_ENTRY_LOCINT_DEST_APIC 6#define MPCT_ENTRY_LOCINT_DEST_INT 7#define MPCT_ENTRY_LOCINT_SIZE 8/*------------------------------------------------------------------------*/// Exported SMP configurationCYG_ADDRESS cyg_hal_smp_local_apic;CYG_ADDRESS cyg_hal_smp_io_apic;CYG_WORD32 cyg_hal_smp_cpu_count = 0;CYG_BYTE cyg_hal_smp_cpu_flags[HAL_SMP_CPU_MAX];CYG_BYTE cyg_hal_isa_bus_id = 0xff;CYG_BYTE cyg_hal_isa_bus_irq[16];CYG_BYTE cyg_hal_pci_bus_id = 0xff;CYG_BYTE cyg_hal_pci_bus_irq[4];HAL_SPINLOCK_TYPE cyg_hal_ioapic_lock;/*------------------------------------------------------------------------*/// Staticsstatic CYG_ADDRESS mp_fps;static CYG_ADDRESS mpct;/*------------------------------------------------------------------------*/static CYG_WORD32 mp_checksum(CYG_BYTE *p, CYG_WORD32 len){ CYG_WORD32 sum = 0; while (len--) sum += *p++; return sum & 0xFF;}/*------------------------------------------------------------------------*/static cyg_bool cyg_hal_scan_smp_config( CYG_ADDRESS base, CYG_ADDRWORD size ){#if SHOW_DIAGNOSTICS diag_printf("Scan for MP struct: %08x..%08x\n",base,base+size);#endif while( size > 0 ) { CYG_WORD32 sig; HAL_READMEM_UINT32( base, sig ); if( sig == MP_FPS_SIGNATURE_VALUE ) { CYG_BYTE val8; // We have a candidate for the floating structure#if SHOW_DIAGNOSTICS diag_printf("MP_FPS candidate found at %08x\n",base);#endif HAL_READMEM_UINT8( base+MP_FPS_LENGTH, val8 ); if( val8 != 1 ) break; HAL_READMEM_UINT8( base+MP_FPS_REV, val8 ); if( val8 != 1 && val8 != 4 ) break; if( mp_checksum( (CYG_BYTE *)base, MP_FPS_SIZE ) != 0 ) break; mp_fps = base; HAL_READMEM_UINT32( base+MP_FPS_MPCT, mpct );#if SHOW_DIAGNOSTICS diag_printf("MPCT at %08x\n",mpct);#endif return 1; } base += 16; size -= 16; } return 0;}/*------------------------------------------------------------------------*/static cyg_bool cyg_hal_find_smp_config( void ){ // check bottom 1k if( cyg_hal_scan_smp_config(0x00000, 0x00400 ) ) return 1; // check top 1k of RAM if( cyg_hal_scan_smp_config(0x9fc00, 0x00400 ) ) return 1; // check BIOS ROM if( cyg_hal_scan_smp_config(0xf0000, 0x10000 ) ) return 1; }/*------------------------------------------------------------------------*/static cyg_bool cyg_hal_parse_smp_config( void ){ CYG_WORD32 val32; CYG_WORD16 val16; CYG_BYTE val8; int i; #if SHOW_DIAGNOSTICS { diag_printf("FPS address: %08x\n",mp_fps); HAL_READMEM_UINT32( mp_fps+MP_FPS_SIGNATURE, val32); diag_printf("FPS signature: %08x\n",val32); HAL_READMEM_UINT32( mp_fps+MP_FPS_MPCT, val32); diag_printf("FPS MPCT address: %08x\n",val32); HAL_READMEM_UINT8( mp_fps+MP_FPS_LENGTH, val8); diag_printf("FPS length: %02x\n",val8); HAL_READMEM_UINT8( mp_fps+MP_FPS_REV, val8); diag_printf("FPS spec rev: %02x\n",val8); HAL_READMEM_UINT8( mp_fps+MP_FPS_CSUM, val8); diag_printf("FPS checksum: %02x\n",val8); for( i = 0; i < 5; i++ ) { HAL_READMEM_UINT8( mp_fps+MP_FPS_FEATURE1, val8); diag_printf("FPS feature byte %d: %02x\n",i,val8); } }#endif if( mpct ) { HAL_READMEM_UINT32( mpct+MPCT_HDR_SIGNATURE, val32); if( val32 != MPCT_HDR_SIGNATURE_VAL ) return 0; HAL_READMEM_UINT16( mpct+MPCT_HDR_LENGTH, val16); if( mp_checksum( (CYG_BYTE *)mpct, val16 ) != 0 ) return 0; #if SHOW_DIAGNOSTICS { char id[13]; diag_printf("MPCT address: %08x\n",mpct); HAL_READMEM_UINT32( mpct+MPCT_HDR_SIGNATURE, val32); diag_printf("MPCT signature: %08x\n",val32); HAL_READMEM_UINT16( mpct+MPCT_HDR_LENGTH, val16); diag_printf("MPCT length: %04x\n",val16); HAL_READMEM_UINT8( mpct+MPCT_HDR_REV, val8); diag_printf("MPCT spec rev: %02x\n",val8); HAL_READMEM_UINT8( mpct+MPCT_HDR_CHECKSUM, val8); diag_printf("MPCT checksum: %02x\n",val8); for( i = 0; i < 8; i++ ) { HAL_READMEM_UINT8( mpct+MPCT_HDR_OEM_ID+i, val8); id[i] = val8; } id[i] = 0; diag_printf("MPCT OEM Id: %s\n",id); for( i = 0; i < 12; i++ ) { HAL_READMEM_UINT8( mpct+MPCT_HDR_PROD_ID+i, val8); id[i] = val8; } id[i] = 0; diag_printf("MPCT Product Id: %s\n",id); HAL_READMEM_UINT32( mpct+MPCT_HDR_OEM_TAB, val32); diag_printf("MPCT OEM table: %08x\n",val32); HAL_READMEM_UINT16( mpct+MPCT_HDR_OEM_TAB_SIZE, val16); diag_printf("MPCT OEM table size: %04x\n",val16); HAL_READMEM_UINT16( mpct+MPCT_HDR_ENTRY_COUNT, val16); diag_printf("MPCT entry count: %04x\n",val16); HAL_READMEM_UINT32( mpct+MPCT_HDR_LOCAL_APIC, val32); diag_printf("MPCT local APIC: %08x\n",val32); HAL_READMEM_UINT16( mpct+MPCT_HDR_XTAB_LENGTH, val16); diag_printf("MPCT extended table length: %04x\n",val16); HAL_READMEM_UINT8( mpct+MPCT_HDR_XTAB_CHECKSUM, val8); diag_printf("MPCT extended table checksum: %02x\n",val8); }#endif // Extract the data we need from the structure HAL_READMEM_UINT32( mpct+MPCT_HDR_LOCAL_APIC, cyg_hal_smp_local_apic); // now parse the base table, looking for processor and IOAPIC entries. { CYG_WORD16 entries; CYG_ADDRESS entry = mpct + MPCT_HDR_SIZE; HAL_READMEM_UINT16( mpct+MPCT_HDR_ENTRY_COUNT, entries);#if SHOW_DIAGNOSTICS diag_printf("\nBase table:\n");#endif while( entries-- ) { CYG_BYTE type; HAL_READMEM_UINT8( entry, type ); switch( type ) { case MPCT_ENTRY_TYPE_PROCESSOR:#if SHOW_DIAGNOSTICS diag_printf(" Processor\n"); HAL_READMEM_UINT8( entry+MPCT_ENTRY_PROC_APIC_ID, val8 ); diag_printf(" APIC ID: %02x\n",val8); HAL_READMEM_UINT8( entry+MPCT_ENTRY_PROC_APIC_VER, val8 ); diag_printf(" APIC Version: %02x\n",val8); HAL_READMEM_UINT8( entry+MPCT_ENTRY_PROC_CPU_FLAGS, val8 ); diag_printf(" CPU Flags: %02x\n",val8); HAL_READMEM_UINT8( entry+MPCT_ENTRY_PROC_CPU_SIGNATURE, val32 ); diag_printf(" CPU Signature: %08x\n",val32); HAL_READMEM_UINT8( entry+MPCT_ENTRY_PROC_FEATURE_FLAGS, val32 ); diag_printf(" Feature flags: %08x\n",val32);#endif { CYG_BYTE cpuid; // Index CPUs by their APIC IDs HAL_READMEM_UINT8( entry+MPCT_ENTRY_PROC_APIC_ID, cpuid ); // Get flags for this CPU. HAL_READMEM_UINT8(entry+MPCT_ENTRY_PROC_CPU_FLAGS, cyg_hal_smp_cpu_flags[cpuid]); cyg_hal_smp_cpu_count++; // count another CPU } entry += MPCT_ENTRY_PROC_SIZE; break; case MPCT_ENTRY_TYPE_BUS: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -