isapnp.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 689 行 · 第 1/2 页

C
689
字号
/* -*-C-*-
 *
 * $Revision: 1.2 $
 *   $Author: kwelton $
 *     $Date: 2000/03/16 02:55:56 $
 *
 * 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.
 *
 * Copyright (c) 1995, 1996, 1997, 1998  Microsoft Corporation
 * Copyright (c) 1999, 2000 ARM Limited
 * All Rights Reserved
 */
#define WINCEMACRO 1

#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <rio.h>
#include <platform.h>

//
// Plug and Play Card Control Registers
//
#define SET_READ_DATA_PORT          0x00
#define SERIAL_ISOLATION_PORT       0x01
#define CONFIG_CONTROL_PORT         0x02
#define WAKE_CSN_PORT               0x03
#define SET_CSN_PORT                0x06

//
// Config Control command
//
#define CONTROL_WAIT_FOR_KEY        0x02
#define CONTROL_RESET_CSN           0x04

#define NUMBER_CARD_ID_BYTES        9
#define NUMBER_CARD_ID_BITS         (NUMBER_CARD_ID_BYTES * 8)
#define CHECKSUMED_BITS             64
#define LFSR_SEED                   0x6A
#define ISOLATION_TEST_BYTE_1       0x55
#define ISOLATION_TEST_BYTE_2       0xAA

#define PNP_ISA_IO_BASE             ((PUCHAR)0)
#define PNP_ADDRESS_PORT            0x279
#define PNP_WRITE_DATA_PORT         0xA79
#define PNP_READ_DATA_PORT          0x203

#define _outp(value, address)       IO_WRITE(address, value)
#define _inp(address)               IO_READ(address)
#define pnpWriteAddress(data)       _outp((USHORT)PNP_ADDRESS_PORT, \
                                          (UCHAR)(data))
#define pnpWriteData(data)          _outp((USHORT)PNP_WRITE_DATA_PORT, \
                                          (UCHAR)(data))
#define pnpReadData()               _inp((USHORT)PNP_READ_DATA_PORT)

CRITICAL_SECTION    g_csISAConfig;

BOOL   g_bISAInitialized = FALSE;
USHORT g_usISAReadPort;
UCHAR  g_ucISANumberCSNs;


UCHAR PnPReadRegister(PUCHAR pIOSpace, UCHAR ucRegNo);
void PnPWriteRegister(PUCHAR pIOSpace, UCHAR ucRegNo, UCHAR ucValue);
void PnPSendInitiationKey(PUCHAR pIOSpace);
void PnPSetWaitForKey(PUCHAR pIOSpace);
void PnPWake(PUCHAR pIOSpace, UCHAR ucCSN);
void PnPReadSerialId(PUCHAR pIOSpace, PUCHAR ucSerialId);
int PnPReadResourceData(PUCHAR pIOSpace, PUCHAR ucResourceData,
                        int iDataSize);

int PnPGetLogicalDeviceInfo(PUCHAR ucResourceData, int iDataSize,
                            PISA_PNP_LOGICAL_DEVICE_INFO pDeviceInfo);

void SC_Sleep(DWORD);

/**********************************************************************/

VOID PnPIsolateCards(void)
{
    USHORT j;
    UCHAR  cardId[NUMBER_CARD_ID_BYTES];
    UCHAR  bit, bit7, checksum, byte1, byte2;
    ULONG  csn = 0;

    //
    // First send Initiation Key to all the PNP ISA cards to enable PnP auto-config
    // ports and put all cards in configuration mode.
    //

    PnPSendInitiationKey(NULL);

    //
    // Reset all Pnp ISA cards' CSN to 0 and return to wait-for-key state
    //

    pnpWriteAddress (CONFIG_CONTROL_PORT);
    pnpWriteData (CONTROL_WAIT_FOR_KEY | CONTROL_RESET_CSN);

    //
    // Delay 2 msec for cards to load initial configuration state.
    //

    SC_Sleep(2);

    //
    // Put cards into configuration mode to ready isolation process.
    // The hardware on each PnP Isa card expects 72 pairs of I/O read
    // access to the read data port.
    //

    PnPSendInitiationKey(NULL);

    //
    // Starting Pnp Isa card isolation process.
    //

    //
    // Send WAKE[CSN=0] to force all cards without CSN into isolation
    // state to set READ DATA PORT.
    //

    pnpWriteAddress(WAKE_CSN_PORT);
    pnpWriteData(0);

    //
    // Set read data port to current testing value.
    //

    pnpWriteAddress(SET_READ_DATA_PORT);
    pnpWriteData((UCHAR)(PNP_READ_DATA_PORT >> 2));

    //
    // Isolate one PnP ISA card until fail
    //

    while ( TRUE ) {

        //
        // Read serial isolation port to cause PnP cards in the isolation
        // state to compare one bit of the boards ID.
        //

        pnpWriteAddress(SERIAL_ISOLATION_PORT);

        //
        // We need to delay 1 msec prior to starting the first pair of isolation
        // reads and must wait 250usec between each subsequent pair of isolation
        // reads.  This delay gives the ISA cards time to access information from
        // possible very slow storage device.
        //

        SC_Sleep(1);

        memset(cardId, 0, NUMBER_CARD_ID_BYTES);
        checksum = LFSR_SEED;
        for ( j = 0; j < NUMBER_CARD_ID_BITS; j++ ) {

            //
            // Read card id bit by bit
            //

            byte1 = pnpReadData();
            byte2 = pnpReadData();
            bit = (byte1 == ISOLATION_TEST_BYTE_1) && (byte2 == ISOLATION_TEST_BYTE_2);
            cardId[j / 8] |= bit << (j % 8);
            if ( j < CHECKSUMED_BITS ) {

                //
                // Calculate checksum and only do it for the first 64 bits
                //

                bit7 = (((checksum & 2) >> 1) ^ (checksum & 1) ^ (bit)) << 7;
                checksum = (checksum >> 1) | bit7;
            }
            SC_Sleep(1);
        }

        //
        // Verify the card id we read is legitimate
        // First make sure checksum is valid.  Note zero checksum is considered valid.
        //

        if ( cardId[8] == 0 || checksum == cardId[8] ) {

            //
            // Next make sure cardId is not zero
            //

            byte1 = 0;
            for ( j = 0; j < NUMBER_CARD_ID_BYTES; j++ ) {
                byte1 |= cardId[j];
            }
            if ( byte1 != 0 ) {

                //
                // Make sure the vender EISA ID bytes are nonzero
                //

                if ( (cardId[0] & 0x7f) != 0 && cardId[1] != 0 ) {

                    pnpWriteAddress(SET_CSN_PORT);

                    pnpWriteData(++csn);

                    //
                    // Do Wake[CSN] command to put the newly isolated card to
                    // sleep state and other un-isolated cards to isolation
                    // state.
                    //

                    pnpWriteAddress(WAKE_CSN_PORT);
                    pnpWriteData(0);
                    continue;     // ... to isolate more cards ...
                }
            }
        }
        break;                // could not isolate more cards ...
    }

    //
    // Finaly put all cards into wait for key state.
    //

    pnpWriteAddress(CONFIG_CONTROL_PORT);
    pnpWriteData(CONTROL_WAIT_FOR_KEY);
    g_ucISANumberCSNs = (UCHAR) csn;
}

VOID ISAInitBusInfo(void)
{
    if ( g_bISAInitialized ) {
        return;
    }

    g_bISAInitialized = TRUE;

    InitializeCriticalSection(&g_csISAConfig);

    PnPIsolateCards();
    RETAILMSG(1, (TEXT("PnP ISA InitBusInfo : %d card(s) found\r\n"), g_ucISANumberCSNs));

    g_usISAReadPort = 0x203;
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
ULONG ISAGetBusDataByOffset(
                     IN ULONG BusNumber,
                     IN ULONG SlotNumber,
                     IN PVOID Buffer,
                     IN ULONG Offset,
                     IN ULONG Length
                     )
{
    UCHAR               ucCSNumber, ucLogicalDevice;
    UCHAR               ucSerialID[9];
    UCHAR               ucResourceData[2048];
    int                 iResourceLength;
    ULONG               ulReturn;

    if ( g_bISAInitialized == FALSE )
        ISAInitBusInfo();

    if ( g_ucISANumberCSNs == 0 || g_ucISANumberCSNs == ~0U ) {
        return (0);
    }

    ucCSNumber = (UCHAR)(SlotNumber >> 8);
    ucLogicalDevice = (UCHAR)SlotNumber;

    if ( ucCSNumber > g_ucISANumberCSNs || ucCSNumber == 0 ||
         (Offset == 0 && Length != sizeof(ISA_PNP_CONFIG)) ||
         (Offset == 1 && Length != sizeof(ISA_PNP_RESOURCES)) ||
         Offset > 1 ) {
        return (0);
    }

    EnterCriticalSection(&g_csISAConfig);

    PnPSendInitiationKey(PNP_ISA_IO_BASE);

    PnPWake(PNP_ISA_IO_BASE, ucCSNumber);

    if ( Offset == 0 ) {
        PISA_PNP_CONFIG     pPnPConfig = (PISA_PNP_CONFIG)Buffer;

        PnPReadSerialId(PNP_ISA_IO_BASE, ucSerialID);

        pPnPConfig->VendorID =
        ucSerialID[0] << 24 | ucSerialID[1] << 16 | ucSerialID[2] << 8 |
        ucSerialID[3];

        pPnPConfig->SerialNumber =
        ucSerialID[7] << 24 | ucSerialID[6] << 16 | ucSerialID[5] << 8 |
        ucSerialID[4];

        iResourceLength = PnPReadResourceData(
                                             PNP_ISA_IO_BASE, ucResourceData, sizeof(ucResourceData));

        pPnPConfig->NumberLogicalDevices = PnPGetLogicalDeviceInfo(
                                                                  ucResourceData, sizeof(ucResourceData),
                                                                  pPnPConfig->LogicalDeviceInfo);

        ulReturn = sizeof(ISA_PNP_CONFIG);
    } else {
        PISA_PNP_RESOURCES  pPnPResources = (PISA_PNP_RESOURCES)Buffer;
        int                 i;
        UCHAR               ucActive;

        PnPWriteRegister(PNP_ISA_IO_BASE, 0x07, ucLogicalDevice);

        ucActive = PnPReadRegister(PNP_ISA_IO_BASE, 0x30);

        if ( ucActive ) {
            pPnPResources->Flags = ISA_PNP_RESOURCE_FLAG_ACTIVE;

            for ( i = 0; i < 4; i++ ) {
                pPnPResources->Memory24Descriptors[i].MemoryBase =
                PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x40 + i * 8)) << 8;
                pPnPResources->Memory24Descriptors[i].MemoryBase |=
                (USHORT)PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x41 + i * 8));
                pPnPResources->Memory24Descriptors[i].MemoryControl =
                PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x42 + i * 8));
                pPnPResources->Memory24Descriptors[i].MemoryUpperLimit =
                (USHORT)(PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x43 + i * 8)) << 8);
                pPnPResources->Memory24Descriptors[i].MemoryUpperLimit |=
                (USHORT)PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x44 + i * 8));
            }

            for ( i = 0; i < 8; i++ ) {
                pPnPResources->IoPortDescriptors[i] =
                PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x60 + i * 2)) << 8;
                pPnPResources->IoPortDescriptors[i] |=
                PnPReadRegister(PNP_ISA_IO_BASE, (UCHAR)(0x61 + i * 2));
            }

            pPnPResources->IRQDescriptors[0].IRQLevel = PnPReadRegister(PNP_ISA_IO_BASE, 0x70);
            pPnPResources->IRQDescriptors[0].IRQType = PnPReadRegister(PNP_ISA_IO_BASE, 0x71);
            pPnPResources->IRQDescriptors[1].IRQLevel = PnPReadRegister(PNP_ISA_IO_BASE, 0x72);
            pPnPResources->IRQDescriptors[1].IRQType = PnPReadRegister(PNP_ISA_IO_BASE, 0x73);

⌨️ 快捷键说明

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