⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcmb_smp.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
//==========================================================================
//
//      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 configuration

CYG_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;

/*------------------------------------------------------------------------*/

// Statics

static 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 + -