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

📄 pdsocket.cpp

📁 SBC2410 WinCE 5.0 BSP.绝大多数驱动已经调通。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:  

Abstract:

    Platform dependent PCMCIA initialization functions

Notes: 
--*/
#include <windows.h>
#include <types.h>
#include <socksv2.h>
#include <memory.h>
#include <ceddk.h>
#include <nkintr.h>

#include "PDSocket.h"

//////////////////////////////////////////////////////////////////////////

//#define PCMCIA_DRIVER_KEY TEXT("Drivers\\PCMCIA")
#define FN_SYSINTR_VALUE_NAME TEXT("FnSysIntr")
#define FN_IRQ_VALUE_NAME TEXT("FnIrq")
#define FORCE_FN_SYSINTR_NAME TEXT("ForceFnSysIntr")
#define CONTROLLER_FN_INT_VALUE_NAME TEXT("ControllerFnInt")
#define CSC_SYSINTR_VALUE_NAME TEXT("CSCSysIntr")
#define CSC_IRQ_VALUE_NAME TEXT("CSCIrq")
#define POLLING_MODE_NAME TEXT("PollingMode")
#define POLL_TIMEOUT_NAME TEXT("PollTimeout")
#define DISABLE_SOCKET_NAME TEXT("DisableSocket")
#define CSC_INTERRUPT_DELAY_NAME TEXT("CSCInterruptDelay")

#define CHIPSET_ID_CNT 32
#define CHIPSET_ID_LEN ((CHIPSET_ID_CNT * 9) + 1)

const SS_POWER_ENTRY CPcmciaCardSocket::m_rgPowerEntries[NUM_POWER_ENTRIES] =
{
    { 0,    PWR_SUPPLY_VCC | PWR_SUPPLY_VPP1 | PWR_SUPPLY_VPP2 },
    { 33,   PWR_SUPPLY_VCC                                     },
    { 50,   PWR_SUPPLY_VCC | PWR_SUPPLY_VPP1 | PWR_SUPPLY_VPP2 },
    { 120,                   PWR_SUPPLY_VPP1 | PWR_SUPPLY_VPP2 }
};
DWORD CPcmciaCardSocket::ms_dwSocketLastIndex = 1;

CPcmciaCardSocket::CPcmciaCardSocket( CPcmciaBusBridge* pBridge )
{
    m_pBridge = pBridge;
    m_dwSocketIndex = 0;
    while( m_dwSocketIndex == 0 )
    {
        m_dwSocketIndex = ( DWORD )
                          InterlockedIncrement( ( LONG * ) &ms_dwSocketLastIndex ); 
        //Make it is it does not exist.
        CPcmciaCardSocket* pSocket = GetSocket( ( HANDLE ) m_dwSocketIndex );
        if( pSocket != NULL )
        {
            // Duplicated , Retry.
            m_dwSocketIndex = 0;
            pSocket->DeRef();
        }
    }

    DEBUGCHK( m_pBridge );
    while( m_pBridge->LockOwner( 1000 ) != TRUE )
    {
        DEBUGCHK( FALSE );
    }
    DEBUGMSG( ZONE_INIT,
              ( TEXT( "CARDBUS: CPcmciaCardSocket (Socket=%d) Created\r\n" ),
                GetSocketHandle() ) );
}

CPcmciaCardSocket::~CPcmciaCardSocket()
{
    m_pBridge->ReleaseOwner();
    DEBUGMSG( ZONE_INIT,
              ( TEXT( "CARDBUS: CPcmciaCardSocket (Socket=%d) Deleted\r\n" ),
                GetSocketHandle() ) );
}

STATUS CPcmciaCardSocket::GetPowerEntry( PDWORD pdwNumOfEnery,
                                         PSS_POWER_ENTRY pPowerEntry )
{
    STATUS status = CERR_BAD_ARGS;
    if( pdwNumOfEnery != NULL && pPowerEntry != NULL )
    {
        DWORD dwNumOfCopied = min( *pdwNumOfEnery, NUM_POWER_ENTRIES );
        if( dwNumOfCopied != 0 )
        {
            memcpy( pPowerEntry,
                    m_rgPowerEntries,
                    dwNumOfCopied * sizeof( SS_POWER_ENTRY ) );
            *pdwNumOfEnery = dwNumOfCopied;
            status = CERR_SUCCESS;
        }
    }
    return status;
}

UINT16 CPcmciaCardSocket::GetSocketNo()
{
    return m_pBridge->GetSocketNo();
};

CPcmciaBusBridge::CPcmciaBusBridge( LPCTSTR RegPath ) : CPCCardBusBridgeBase( RegPath ),
                                                        CMiniThread( 0,
                                                                     TRUE )
{
    m_dwFnIrq = -1;
    m_fPCICCritSecInitialized = false;
    m_pCardBusResource = NULL;
    m_hISTEvent = NULL;
    m_uSocketNum = ( WORD ) - 1;
    m_pCardSocket = NULL;
    m_fPowerCycleEvent = FALSE;
    m_fCardInjectEvent = FALSE;
    m_fPollingMode = TRUE;
	m_dwCSCInterruptDelay = 0;
};


CPcmciaBusBridge::~CPcmciaBusBridge()
{
    // Terminate IST
    m_bTerminated = TRUE;
    if( m_hISTEvent )
    {
        SetEvent( m_hISTEvent );
        ThreadTerminated( 1000 );
        if( !m_fPollingMode )
        {
            InterruptDisable( m_dwCSCSysIntr );
        }
        CloseHandle( m_hISTEvent );
    };

    if( m_uSocketNum != ( UINT16 ) - 1 )
    {
        GetSocketNumberFromCS( FALSE );
        m_uSocketNum = ( UINT16 ) - 1;
    }

    RemovePcmciaCardSocket();

    if( m_pCardBusResource != NULL )
    {
        delete  m_pCardBusResource;
    }
    if( m_fPCICCritSecInitialized )
    {
        DeleteCriticalSection( &m_PCICCritSec );
    }
}

BOOL CPcmciaBusBridge::InstallIsr()
{
    UINT8 tmp;

    //
    // Disable interrupts
    //
    WritePCICRegister( REG_INTERRUPT_AND_GENERAL_CONTROL, 0 );

	// Management int -> edge triggering(PULSE), System int -> LEVEL triggering 
    WritePCICRegister( REG_GENERAL_CONTROL, MISC1_VCC_33|MISC1_PM_IRQ|MISC1_SPK_ENABLE );
    UINT8 bPat = ReadPCICRegister( REG_GENERAL_CONTROL );
	// 25Mhz_bypass,low_power_dynamic,IRQ12=drive_LED
	WritePCICRegister( REG_GLOBAL_CONTROL, MISC2_LOW_POWER_MODE|MISC2_LED_ENABLE);

	// before configuring timing register, FIFO should be cleared.
	WritePCICRegister( REG_FIFO_CTRL, FIFO_EMPTY_WRITE);    //Flush FIFO

	//default access time is 300ns
	WritePCICRegister( REG_SETUP_TIMING0, 5);                   //80ns(no spec)
	WritePCICRegister( REG_CMD_TIMING0, 20);                  //320ns(by spec,25Mhz clock)
	WritePCICRegister( REG_RECOVERY_TIMING0, 5);                   //80ns(no spec)

	//default access time is 300ns
	WritePCICRegister( REG_SETUP_TIMING1, 2);                   //80ns(no spec)
	WritePCICRegister( REG_CMD_TIMING1, 8);                   //320ns(by spec,25Mhz clock)
	WritePCICRegister( REG_RECOVERY_TIMING1, 2);                   //80ns(no spec)

    if( !m_fPollingMode )
    {
        // PD6710 specific code to enable CSC interrupt (routed to -INTR)
        tmp = CFG_CARD_DETECT_ENABLE | CFG_READY_ENABLE;
        WritePCICRegister( REG_STATUS_CHANGE_INT_CONFIG, tmp );

        // Enable Manage Interrupt
        tmp = ReadPCICRegister( REG_INTERRUPT_AND_GENERAL_CONTROL );
        tmp |= INT_ENABLE_MANAGE_INT;
        WritePCICRegister( REG_INTERRUPT_AND_GENERAL_CONTROL, tmp );
    }
    else
    {
        WritePCICRegister( REG_STATUS_CHANGE_INT_CONFIG, 0 );
    }

    // CreateIST Event
    m_hISTEvent = CreateEvent( 0, FALSE, FALSE, NULL );

    if( !m_fPollingMode )
    {
        // Run IST
        BOOL r = InterruptInitialize( m_dwCSCSysIntr, m_hISTEvent, 0, 0 );
        ASSERT( r );
    }

    return TRUE;
}

#ifdef DEBUG
VOID CPcmciaBusBridge::DumpAllRegisters()
{
    DEBUGMSG( ZONE_FUNCTION, ( TEXT( "Dumping all PCIC registers\r\n" ) ) );
    for( UINT8 nRegNum = 0; nRegNum < 0x40; nRegNum++ )
    {
        UINT8 val;
		if( nRegNum == REG_CARD_STATUS_CHANGE )
			val = -1;
		else
			val = ReadPCICRegister( nRegNum );
        DEBUGMSG( ZONE_FUNCTION,
                  ( TEXT( "%02x: %02x\r\n" ), nRegNum, val ) );
    }
    DEBUGMSG( ZONE_FUNCTION, ( TEXT( "Dump completed.\r\n" ) ) );
}
#endif

//
// Function to set the PCIC index register
//
VOID CPcmciaBusBridge::PCICIndex( UINT8  register_num )
{
    WRITE_PORT_UCHAR( m_PCICIndex, ( UINT8 )( register_num ) );
}

//
// Function to write to the PCIC data register
//
VOID CPcmciaBusBridge::PCICDataWrite( UINT8 value )
{
    WRITE_PORT_UCHAR( m_PCICData, value );
}

//
// Function to read the PCIC data register
//
UINT8 CPcmciaBusBridge::PCICDataRead( VOID )
{
    return READ_PORT_UCHAR( m_PCICData );
}


//
// Verify the PCIC's REG_CHIP_REVISION
//
// This bit of code looks in the 82365 chip revision register (PCIC index 0)
// to see if a valid 82365 is in the system.  The original code only
// recognized the 83h silicon revision.  This indicates REV C silicon from
// Intel.  However, Intel also had a very popular rev B version, and that's
// what the integrated PCMCIA controller on the AMD ElanSC400 emulated.  The
// silicon revision register for that version returned 82h.
//
BOOL CPcmciaBusBridge::IsValidPCICSig( void )
{
    switch( m_vRevision = ReadPCICRegister( REG_CHIP_REVISION ) )
    {
      case 0x82:
      case 0x83:
      case 0x84:
        // for newer chip - can handle 3.3v
        DEBUGMSG( 1,
                  ( TEXT( "PCMCIA:IsValidPCICSig Valid CHIP_REVISION detected = 0x%x at 0x%x\r\n" ),
                    m_vRevision,
                    m_PCICIndex ) );
        return TRUE;
    }
    DEBUGMSG( 1,
              ( TEXT( "PCMCIA:IsValidPCICSig Invalid CHIP_REVISION = 0x%x at 0x%x!!!\r\n" ),
                m_vRevision,
                m_PCICIndex ) );
    return FALSE;
}

//
// Function to get the initial settings from the registry
//
// NOTE: lpRegPath is assumed to be under HKEY_LOCAL_MACHINE
//
// Returns ERROR_SUCCESS on success or a Win32 error code on failure
//
DWORD CPcmciaBusBridge::GetRegistryConfig()
{
    DWORD dwRet = 1;
    DWORD dwSize, dwType, dwData;

    // get the PCMCIA windows configuration
    if( !LoadWindowsSettings() )
    {
        dwRet = ERROR_INVALID_DATA;
        goto grc_fail;
    }

    // get the polling mode value
    dwSize = sizeof( DWORD );
    if( !RegQueryValueEx( POLLING_MODE_NAME,
                          &dwType,
                          ( PUCHAR ) & dwData,
                          &dwSize ) )
    {
        m_fPollingMode = FALSE; // RegQueryValueEx failed, default to FALSE
    }
    else
    {
        m_fPollingMode = dwData ? TRUE : FALSE;
    }

    // get the function interrupt routing configuration

    // Get the controller function interrupt number
    dwSize = sizeof( DWORD );
    if( RegQueryValueEx( CONTROLLER_FN_INT_VALUE_NAME,
                          &dwType,
                          ( PUCHAR ) & dwData,
                          &dwSize ) )
    {
        m_dwControllerFnIntNo = dwData;
    }
    else
    {
        dwRet = FALSE;
        goto grc_fail;
    }

    // Get the function interrupt SYSINTR or IRQ value

    // First try to get the IRQ value
    dwSize = sizeof( DWORD );
    if( RegQueryValueEx( FN_IRQ_VALUE_NAME,
                        &dwType,
                        ( PUCHAR ) & dwData,
                        &dwSize ) )
    {
        m_dwFnSysIntr = SYSINTR_UNDEFINED;
        m_dwFnIrq = dwData;

        // check if we should automatically convert the IRQ to SYSINTR value
        dwSize = sizeof( DWORD );
        if( RegQueryValueEx( FORCE_FN_SYSINTR_NAME,
                              &dwType,
                              ( PUCHAR ) & dwData,
                              &dwSize ) )
        {
            if( dwData )
            {
                // Convert the interrupt to a logical sysintr value.
                if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_dwFnIrq, sizeof(DWORD), &m_dwFnSysIntr, sizeof(DWORD), NULL))
                {
                    RETAILMSG(1, (TEXT("PCMCIA: Failed to obtain function interrupt information!\r\n")));
                    m_dwFnSysIntr = SYSINTR_UNDEFINED;
                    dwRet = ERROR_INVALID_DATA;
                    goto grc_fail;
                }
                m_dwFnIrq = -1;
            }
        }
    }
    else
    {
        // IRQ value was not specified, try to get the SYSINTR value
        dwSize = sizeof( DWORD );
        if( RegQueryValueEx( FN_SYSINTR_VALUE_NAME,
                              &dwType,
                              ( PUCHAR ) & dwData,
                              &dwSize ) )
        {
            m_dwFnSysIntr = dwData;
            m_dwFnIrq = -1;
        }
        else
        {
            RETAILMSG(1, (TEXT("PCMCIA: Failed to obtain function interrupt information!\r\n")));
            dwRet = ERROR_INVALID_DATA;
            goto grc_fail;
        }
    }

    // get card status change interrupt routing configuration
    m_dwCSCSysIntr = SYSINTR_UNDEFINED;

    dwSize = sizeof( DWORD );
    if( RegQueryValueEx( CSC_SYSINTR_VALUE_NAME,
                            &dwType,
                            ( PUCHAR ) & dwData,
                            &dwSize ) )
    {
        m_dwCSCSysIntr = dwData;
    }
    else
    {
        dwSize = sizeof( DWORD );
        if( !RegQueryValueEx( CSC_IRQ_VALUE_NAME,
                                &dwType,
                                ( PUCHAR ) & dwData,
                                &dwSize ) )
        {
            m_fPollingMode = TRUE;
        }
        else
        {
            // Convert the interrupt to a logical sysintr value.
            if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwData, sizeof(DWORD), &m_dwCSCSysIntr, sizeof(DWORD), NULL))
            {
                RETAILMSG(1, (TEXT("PCMCIA: Failed to obtain sysintr value for CSC interrupt.\r\n")));
                m_dwCSCSysIntr = SYSINTR_UNDEFINED;
                m_fPollingMode = TRUE;
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -