File:  [WindowsNT SDKs] / q_a / samples / ddk / detect / deteisa.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:30:32 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/*++

Copyright (c) 1992  Microsoft Corporation

Module Name:

    deteisa.c

Abstract:

    This is the main file for the autodetection DLL for all the EISA adapters
    which MS is shipping with Windows NT.


--*/

#include <ntddk.h>
#include <ntddnetd.h>

#include <windef.h>
#include <winerror.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "detect.h"


//  Prototype "borrowed" from WINUSER.H
extern int WINAPIV wsprintfW(LPWSTR, LPCWSTR, ...);
//  Prototype "borrowed" from WINBASE.H
VOID WINAPI Sleep( DWORD dwMilliseconds );

//
// Individual card detection routines
//


//
// Helper functions
//

ULONG
FindEisaCard(
    IN  ULONG AdapterNumber,
    IN  ULONG BusNumber,
    IN  BOOLEAN First,
    IN  ULONG CompressedId,
    OUT PULONG Confidence
    );

#ifdef WORKAROUND

UCHAR EisaFirstTime = 1;

//
// List of all the adapters supported in this file, this cannot be > 256
// because of the way tokens are generated.
//
//
// NOTE : If you change the index of an adapter, be sure the change it in
// EisaQueryCfgHandler(), EisaFirstNextHandler() and EisaVerifyCfgHandler() as
// well!
//

static ADAPTER_INFO Adapters[] = {

    {
        1000,
        L"NE3200",
        L"SLOTNUMBER 1 100 ",
        NULL,
        999

    },

    {
        1100,
        L"DEC422",
        L"SLOTNUMBER 1 100 ",
        NULL,
        999

    },

    {
        1200,
        L"P1990",
        L"SLOTNUMBER 1 100 ",
        NULL,
        999

    },

    {
        1300,
        L"NETFLX",
        L"SLOTNUMBER 1 100 ",
        NULL,
        999

    },

    {
        1400,
        L"CPQTOK",
        L"SLOTNUMBER 1 100 ",
        NULL,
        999

    }
};

#else

//
// List of all the adapters supported in this file, this cannot be > 256
// because of the way tokens are generated.
//
//
// NOTE : If you change the index of an adapter, be sure the change it in
// EisaQueryCfgHandler(), EisaFirstNextHandler() and EisaVerifyCfgHandler() as
// well!
//

static ADAPTER_INFO Adapters[] = {

    {
        1000,
        L"NE3200",
        L"SLOTNUMBER\0001\000100\0",
        NULL,
        999

    },

    {
        1100,
        L"DEC422",
        L"SLOTNUMBER\0001\000100\0",
        NULL,
        999

    },

    {
        1200,
        L"P1990",
        L"SLOTNUMBER\0001\000100\0",
        NULL,
        999

    },

    {
        1300,
        L"NETFLEX",
        L"SLOTNUMBER\0001\000100\0",
        NULL,
        999

    },

    {
        1400,
        L"CPQTOK",
        L"SLOTNUMBER\0001\000100\0",
        NULL,
        999

    }

};

#endif

//
// Structure for holding state of a search
//

typedef struct _SEARCH_STATE {

    ULONG SlotNumber;

} SEARCH_STATE, *PSEARCH_STATE;


//
// This is an array of search states.  We need one state for each type
// of adapter supported.
//

static SEARCH_STATE SearchStates[sizeof(Adapters) / sizeof(ADAPTER_INFO)] = {0};


//
// Structure for holding a particular adapter's complete information
//
typedef struct _EISA_ADAPTER {

    LONG CardType;
    INTERFACE_TYPE InterfaceType;
    ULONG BusNumber;
    ULONG SlotNumber;

} EISA_ADAPTER, *PEISA_ADAPTER;


extern
LONG
EisaIdentifyHandler(
    IN LONG Index,
    IN WCHAR * Buffer,
    IN LONG BuffSize
    )

/*++

Routine Description:

    This routine returns information about the netcards supported by
    this file.

Arguments:

    Index -  The index of the netcard being address.  The first
    cards information is at index 1000, the second at 1100, etc.

    Buffer - Buffer to store the result into.

    BuffSize - Number of bytes in Buffer

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/


{
    LONG NumberOfAdapters;
    LONG Code = Index % 100;
    LONG Length;
    LONG i;

    NumberOfAdapters = sizeof(Adapters) / sizeof(ADAPTER_INFO);

#ifdef WORKAROUND

    //
    // We need to convert unicode spaces into unicode NULLs.
    //

    if (EisaFirstTime) {

        EisaFirstTime = 0;

        for (i = 0; i < NumberOfAdapters; i++) {

            Length = UnicodeStrLen(Adapters[i].Parameters);

            for (; Length > 0; Length--) {

                if (Adapters[i].Parameters[Length] == L' ') {

                    Adapters[i].Parameters[Length] = UNICODE_NULL;

                }

            }

        }

    }

#endif

    Index = Index - Code;

    if (((Index / 100) - 10) < NumberOfAdapters) {

        //
        // Find the correct adapter ID
        //

        for (i=0; i < NumberOfAdapters; i++) {

            if (Adapters[i].Index == Index) {

                switch (Code) {

                    case 0:

                        //
                        // Find the string length
                        //

                        Length = UnicodeStrLen(Adapters[i].InfId);

                        Length ++;

                        if (BuffSize < Length) {

                            return(ERROR_INSUFFICIENT_BUFFER);

                        }

                        memcpy((PVOID)Buffer, Adapters[i].InfId, Length * sizeof(WCHAR));
                        break;

                    case 3:

                        //
                        // Maximum value is 1000
                        //

                        if (BuffSize < 5) {

                            return(ERROR_INSUFFICIENT_BUFFER);

                        }

                        wsprintfW((PVOID)Buffer, L"%d", Adapters[i].SearchOrder);

                        break;

                    default:

                        return(ERROR_INVALID_PARAMETER);

                }

                return(0);

            }

        }

        return(ERROR_INVALID_PARAMETER);

    }

    return(ERROR_NO_MORE_ITEMS);

}


extern
LONG
EisaFirstNextHandler(
    IN  LONG NetcardId,
    IN  INTERFACE_TYPE InterfaceType,
    IN  ULONG BusNumber,
    IN  BOOL First,
    OUT PVOID *Token,
    OUT LONG *Confidence
    )

/*++

Routine Description:

    This routine finds the instances of a physical adapter identified
    by the NetcardId.

Arguments:

    NetcardId -  The index of the netcard being address.  The first
    cards information is id 1000, the second id 1100, etc.

    InterfaceType - Microchannel

    BusNumber - The bus number of the bus to search.

    First - TRUE is we are to search for the first instance of an
    adapter, FALSE if we are to continue search from a previous stopping
    point.

    Token - A pointer to a handle to return to identify the found
    instance

    Confidence - A pointer to a long for storing the confidence factor
    that the card exists.

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/

{
    ULONG CompressedId;
    ULONG ReturnValue;

    if (InterfaceType != Eisa) {

        *Confidence = 0;
        return(0);

    }

    //
    // Get CompressedId
    //

    switch (NetcardId) {

        //
        // NE3200
        //

        case 1000:

            CompressedId = 0x07CC3A;
            break;

        //
        // DEC422
        //

        case 1100:

            CompressedId = 0x42A310;
            break;

        //
        // PROTEON 1990
        //

        case 1200:

            CompressedId = 0x604F42;
            break;

        //
        // NET FLEX
        //

        case 1300:

            CompressedId = 0x61110E;
            break;

        //
        // COMPAQ Jupiter board
        //

        case 1400:

            CompressedId = 0x60110E;
            break;

        default:

            return(ERROR_INVALID_PARAMETER);

    }

    //
    // Call FindFirst Routine
    //

    ReturnValue = FindEisaCard(
                        (ULONG)((NetcardId - 1000) / 100),
                        BusNumber,
                        (BOOLEAN)First,
                        CompressedId,
                        Confidence
                        );

    if (ReturnValue == 0) {

        //
        // In this module I use the token as follows: Remember that
        // the token can only be 2 bytes long (the low 2) because of
        // the interface to the upper part of this DLL.
        //
        //  The rest of the high byte is the the bus number.
        //  The low byte is the driver index number into Adapters.
        //
        // NOTE: This presumes that there are < 129 buses in the
        // system. Is this reasonable?
        //

        *Token = (PVOID)((BusNumber & 0x7F) << 8);

        *Token = (PVOID)(((ULONG)*Token) | ((NetcardId - 1000) / 100));

    }

    return(ReturnValue);

}

extern
LONG
EisaOpenHandleHandler(
    IN  PVOID Token,
    OUT PVOID *Handle
    )

/*++

Routine Description:

    This routine takes a token returned by FirstNext and converts it
    into a permanent handle.

Arguments:

    Token - The token.

    Handle - A pointer to the handle, so we can store the resulting
    handle.

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/

{
    PEISA_ADAPTER Adapter;
    LONG AdapterNumber;
    ULONG BusNumber;
    INTERFACE_TYPE InterfaceType;

    //
    // Get info from the token
    //

    InterfaceType = Eisa;

    BusNumber = (ULONG)(((ULONG)Token >> 8) & 0x7F);

    AdapterNumber = ((ULONG)Token) & 0xFF;

    //
    // Store information
    //

    Adapter = (PEISA_ADAPTER)DetectAllocateHeap(
                                 sizeof(EISA_ADAPTER)
                                 );

    if (Adapter == NULL) {

        return(ERROR_NOT_ENOUGH_MEMORY);

    }

    //
    // Copy across address
    //

    Adapter->SlotNumber = SearchStates[(ULONG)AdapterNumber].SlotNumber;
    Adapter->CardType = Adapters[AdapterNumber].Index;
    Adapter->InterfaceType = InterfaceType;
    Adapter->BusNumber = BusNumber;

    *Handle = (PVOID)Adapter;

    return(0);
}

LONG
EisaCreateHandleHandler(
    IN  LONG NetcardId,
    IN  INTERFACE_TYPE InterfaceType,
    IN  ULONG BusNumber,
    OUT PVOID *Handle
    )

/*++

Routine Description:

    This routine is used to force the creation of a handle for cases
    where a card is not found via FirstNext, but the user says it does
    exist.

Arguments:

    NetcardId - The id of the card to create the handle for.

    InterfaceType - Microchannel

    BusNumber - The bus number of the bus in the system.

    Handle - A pointer to the handle, for storing the resulting handle.

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/

{
    PEISA_ADAPTER Adapter;
    LONG NumberOfAdapters;
    LONG i;

    if (InterfaceType != Eisa) {

        return(ERROR_INVALID_PARAMETER);

    }

    NumberOfAdapters = sizeof(Adapters) / sizeof(ADAPTER_INFO);

    for (i=0; i < NumberOfAdapters; i++) {

        if (Adapters[i].Index == NetcardId) {

            //
            // Store information
            //

            Adapter = (PEISA_ADAPTER)DetectAllocateHeap(
                                         sizeof(EISA_ADAPTER)
                                         );

            if (Adapter == NULL) {

                return(ERROR_NOT_ENOUGH_MEMORY);

            }

            //
            // Copy across memory address
            //

            Adapter->SlotNumber = 1;
            Adapter->CardType = NetcardId;
            Adapter->InterfaceType = InterfaceType;
            Adapter->BusNumber = BusNumber;

            *Handle = (PVOID)Adapter;

            return(0);

        }

    }

    return(ERROR_INVALID_PARAMETER);
}

extern
LONG
EisaCloseHandleHandler(
    IN PVOID Handle
    )

/*++

Routine Description:

    This frees any resources associated with a handle.

Arguments:

   Handle - The handle.

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/

{
    DetectFreeHeap(Handle);

    return(0);
}

LONG
EisaQueryCfgHandler(
    IN  PVOID Handle,
    OUT WCHAR *Buffer,
    IN  LONG BuffSize
    )

/*++

Routine Description:

    This routine calls the appropriate driver's query config handler to
    get the parameters for the adapter associated with the handle.

Arguments:

    Handle - The handle.

    Buffer - The resulting parameter list.

    BuffSize - Length of the given buffer in WCHARs.

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/

{
    PEISA_ADAPTER Adapter = (PEISA_ADAPTER)(Handle);
    LONG OutputLengthLeft = BuffSize;
    LONG CopyLength;
    ULONG CompressedId;
    PVOID BusHandle;
    ULONG ReturnValue;
    ULONG Confidence;

    ULONG StartPointer = (ULONG)Buffer;

    if (Adapter->InterfaceType != Eisa) {

        return(ERROR_INVALID_PARAMETER);

    }

    //
    // Verify the SlotNumber
    //

    if (!GetEisaKey(Adapter->BusNumber, &BusHandle)) {

        return(ERROR_INVALID_PARAMETER);

    }

    if (!GetEisaCompressedId(
                 BusHandle,
                 Adapter->SlotNumber,
                 &CompressedId
                 )) {

        //
        // Fail
        //

        return(ERROR_INVALID_PARAMETER);

    }

    //
    // Verify ID
    //

    ReturnValue = ERROR_INVALID_PARAMETER;

    switch (Adapter->CardType) {

        //
        // NE3200
        //

        case 1000:

            if (CompressedId == 0x07CC3A) {

                ReturnValue = 0;

            } else {

                CompressedId = 0x07CC3A;

            }
            break;

        //
        // DEC422
        //

        case 1100:

            if (CompressedId == 0x42A310) {

                ReturnValue = 0;

            } else {

                CompressedId = 0x42A310;

            }
            break;

        //
        // PROTEON 1990
        //

        case 1200:

            if (CompressedId == 0x604F42) {

                ReturnValue = 0;

            } else {

                CompressedId = 0x604F42;

            }
            break;

        //
        // NET FLEX
        //

        case 1300:

            if (CompressedId == 0x61110E) {

                ReturnValue = 0;

            } else {

                CompressedId = 0x61110E;

            }
            break;

        //
        // COMPAQ Jupiter board
        //

        case 1400:

            if (CompressedId == 0x60110E) {

                ReturnValue = 0;

            } else {

                CompressedId = 0x60110E;

            }
            break;

        default:

            return(ERROR_INVALID_PARAMETER);

    }


    if (ReturnValue != 0) {

        //
        // Try to find it in another slot
        //

        ReturnValue = FindEisaCard(
                        Adapter->CardType,
                        Adapter->BusNumber,
                        TRUE,
                        CompressedId,
                        &Confidence
                        );

        if (Confidence != 100) {

            //
            // Confidence is not absolute -- we are out of here.
            //

            return(ERROR_INVALID_PARAMETER);

        }

        Adapter->SlotNumber = SearchStates[(ULONG)Adapter->CardType].SlotNumber;

    }

    //
    // Build resulting buffer
    //

    //
    // Put in SlotNumber
    //

    //
    // Copy in the title string
    //

    CopyLength = UnicodeStrLen(SlotNumberString) + 1;

    if (OutputLengthLeft < CopyLength) {

        return(ERROR_INSUFFICIENT_BUFFER);

    }

    memcpy((PVOID)Buffer,
           (PVOID)SlotNumberString,
           (CopyLength * sizeof(WCHAR))
           );

    Buffer = &(Buffer[CopyLength]);
    OutputLengthLeft -= CopyLength;

    //
    // Copy in the value
    //

    if (OutputLengthLeft < 8) {

        return(ERROR_INSUFFICIENT_BUFFER);

    }

    CopyLength = wsprintfW(Buffer,L"0x%x",(ULONG)(Adapter->SlotNumber));

    if (CopyLength < 0) {

        return(ERROR_INSUFFICIENT_BUFFER);

    }

    CopyLength++;  // Add in the \0

    Buffer = &(Buffer[CopyLength]);
    OutputLengthLeft -= CopyLength;

    //
    // Copy in final \0
    //

    if (OutputLengthLeft < 1) {

        return(ERROR_INSUFFICIENT_BUFFER);

    }

    CopyLength = (ULONG)Buffer - StartPointer;
    Buffer[CopyLength] = L'\0';

    return(0);
}

extern
LONG
EisaVerifyCfgHandler(
    IN PVOID Handle,
    IN WCHAR *Buffer
    )

/*++

Routine Description:

    This routine verifys that a given parameter list is complete and
    correct for the adapter associated with the handle.

Arguments:

    Handle - The handle.

    Buffer - The parameter list.

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/

{
    PEISA_ADAPTER Adapter = (PEISA_ADAPTER)(Handle);
    WCHAR *Place;
    ULONG CompressedId;
    ULONG SlotNumber;
    PVOID BusHandle;
    BOOLEAN Found;

    if (Adapter->InterfaceType != Eisa) {

        return(ERROR_INVALID_DATA);

    }

    //
    // Parse out the parameter.
    //

    //
    // Get the SlotNumber
    //

    Place = FindParameterString(Buffer, SlotNumberString);

    if (Place == NULL) {

        return(ERROR_INVALID_DATA);

    }

    Place += UnicodeStrLen(SlotNumberString) + 1;

    //
    // Now parse the thing.
    //

    ScanForNumber(Place, &SlotNumber, &Found);

    if (Found == FALSE) {

        return(ERROR_INVALID_DATA);

    }

    //
    // Verify the SlotNumber
    //

    if (!GetEisaKey(Adapter->BusNumber, &BusHandle)) {

        return(ERROR_INVALID_DATA);

    }

    if (!GetEisaCompressedId(
                 BusHandle,
                 SlotNumber,
                 &CompressedId
                 )) {

        //
        // Fail
        //

        return(ERROR_INVALID_DATA);

    }

    //
    // Verify ID
    //

    switch (Adapter->CardType) {

        //
        // NE3200
        //

        case 1000:

            if (CompressedId != 0x07CC3A) {

                return(ERROR_INVALID_DATA);

            }
            break;

        //
        // DEC422
        //

        case 1100:

            if (CompressedId != 0x42A310) {

                return(ERROR_INVALID_DATA);

            }
            break;

        //
        // PROTEON 1990
        //

        case 1200:

            if (CompressedId != 0x604F42) {

                return(ERROR_INVALID_DATA);

            }
            break;

        //
        // NET FLEX
        //

        case 1300:

            if (CompressedId != 0x61110E) {

                return(ERROR_INVALID_DATA);

            }
            break;

        //
        // COMPAQ Jupiter Board
        //

        case 1400:

            if (CompressedId != 0x60110E) {

                return(ERROR_INVALID_DATA);

            }
            break;

        default:

            return(ERROR_INVALID_DATA);

    }

    return(0);

}

extern
LONG
EisaQueryMaskHandler(
    IN  LONG NetcardId,
    OUT WCHAR *Buffer,
    IN  LONG BuffSize
    )

/*++

Routine Description:

    This routine returns the parameter list information for a specific
    network card.

Arguments:

    NetcardId - The id of the desired netcard.

    Buffer - The buffer for storing the parameter information.

    BuffSize - Length of Buffer in WCHARs.

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/

{
    WCHAR *Result;
    LONG Length;
    LONG NumberOfAdapters;
    LONG i;

    //
    // Find the adapter
    //

    NumberOfAdapters = sizeof(Adapters) / sizeof(ADAPTER_INFO);

    for (i=0; i < NumberOfAdapters; i++) {

        if (Adapters[i].Index == NetcardId) {

            Result = Adapters[i].Parameters;

            //
            // Find the string length (Ends with 2 NULLs)
            //

            for (Length=0; ; Length++) {

                if (Result[Length] == L'\0') {

                    ++Length;

                    if (Result[Length] == L'\0') {

                        break;

                    }

                }

            }

            Length++;

            if (BuffSize < Length) {

                return(ERROR_NOT_ENOUGH_MEMORY);

            }

            memcpy((PVOID)Buffer, Result, Length * sizeof(WCHAR));

            return(0);

        }

    }

    return(ERROR_INVALID_PARAMETER);

}

extern
LONG
EisaParamRangeHandler(
    IN  LONG NetcardId,
    IN  WCHAR *Param,
    OUT LONG *Values,
    OUT LONG *BuffSize
    )

/*++

Routine Description:

    This routine returns a list of valid values for a given parameter name
    for a given card.

Arguments:

    NetcardId - The Id of the card desired.

    Param - A WCHAR string of the parameter name to query the values of.

    Values - A pointer to a list of LONGs into which we store valid values
    for the parameter.

    BuffSize - At entry, the length of Values in LONGs.  At exit, the
    number of LONGs stored in Values.

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/

{

    *BuffSize = 0;
    return(0);

}

extern
LONG
EisaQueryParameterNameHandler(
    IN  WCHAR *Param,
    OUT WCHAR *Buffer,
    IN  LONG BufferSize
    )

/*++

Routine Description:

    Returns a localized, displayable name for a specific parameter.  All the
    parameters that this file uses are define by MS, so no strings are
    needed here.

Arguments:

    Param - The parameter to be queried.

    Buffer - The buffer to store the result into.

    BufferSize - The length of Buffer in WCHARs.

Return Value:

    ERROR_INVALID_PARAMETER -- To indicate that the MS supplied strings
    should be used.

--*/

{
    return(ERROR_INVALID_PARAMETER);
}

ULONG
FindEisaCard(
    IN  ULONG AdapterNumber,
    IN  ULONG BusNumber,
    IN  BOOLEAN First,
    IN  ULONG CompressedId,
    OUT PULONG Confidence
    )

/*++

Routine Description:

    This routine finds the instances of a physical adapter identified
    by the CompressedId.

Arguments:

    AdapterNumber - The index into the global array of adapters for the card.

    BusNumber - The bus number of the bus to search.

    First - TRUE is we are to search for the first instance of an
    adapter, FALSE if we are to continue search from a previous stopping
    point.

    CompressedId - The EISA Compressed Id of the card.

    Confidence - A pointer to a long for storing the confidence factor
    that the card exists.

Return Value:

    0 if nothing went wrong, else the appropriate WINERROR.H value.

--*/

{
    PVOID BusHandle;
    ULONG TmpCompressedId;

    if (First) {

        SearchStates[AdapterNumber].SlotNumber = 1;

    } else {

        SearchStates[AdapterNumber].SlotNumber++;

    }

    if (!GetEisaKey(BusNumber, &BusHandle)) {

        return(ERROR_INVALID_PARAMETER);

    }

    while (TRUE) {

        if (!GetEisaCompressedId(BusHandle,
                         SearchStates[AdapterNumber].SlotNumber,
                         &TmpCompressedId)) {

            *Confidence = 0;
            return(0);

        }

        if (CompressedId == TmpCompressedId) {

            *Confidence = 100;
            return(0);

        }

        SearchStates[AdapterNumber].SlotNumber++;

    }

    DeleteEisaKey(BusHandle);

}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.