mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3223 lines
60 KiB
3223 lines
60 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
detlance.c
|
|
|
|
Abstract:
|
|
|
|
This is the main file for the autodetection DLL for all the lance.sys
|
|
which MS is shipping with Windows NT.
|
|
|
|
Author:
|
|
|
|
Sean Selitrennikoff (SeanSe) October 1992.
|
|
|
|
Environment:
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include <windows.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "ntddnetd.h"
|
|
#include "detect.h"
|
|
|
|
|
|
//
|
|
// Individual card detection routines
|
|
//
|
|
|
|
LONG
|
|
De100FirstNext(
|
|
IN LONG NetcardId,
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN BOOL First,
|
|
OUT PVOID *Token,
|
|
OUT LONG *Confidence
|
|
);
|
|
|
|
|
|
LONG
|
|
DecEWFirstNext(
|
|
IN LONG NetcardId,
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN BOOL First,
|
|
OUT PVOID *Token,
|
|
OUT LONG *Confidence
|
|
);
|
|
|
|
LONG
|
|
De101FirstNext(
|
|
IN LONG NetcardId,
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN BOOL First,
|
|
OUT PVOID *Token,
|
|
OUT LONG *Confidence
|
|
);
|
|
|
|
LONG
|
|
DePCAFirstNext(
|
|
IN LONG NetcardId,
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN BOOL First,
|
|
OUT PVOID *Token,
|
|
OUT LONG *Confidence
|
|
);
|
|
|
|
|
|
#ifdef WORKAROUND
|
|
|
|
UCHAR LanceFirstTime = 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
|
|
// LanceQueryCfgHandler() and LanceVerifyCfgHandler() as well!
|
|
//
|
|
|
|
static ADAPTER_INFO Adapters[] = {
|
|
|
|
{
|
|
1000,
|
|
L"DEC100",
|
|
L"IRQ 1 90 IRQTYPE 2 100 IOADDR 1 100 IOADDRLENGTH 2 100 MEMADDR 1 75 MEMADDRLENGTH 2 100 ",
|
|
De100FirstNext,
|
|
700
|
|
|
|
},
|
|
|
|
{
|
|
1100,
|
|
L"DECETHERWORKSTURBO",
|
|
L"IRQ 1 90 IRQTYPE 2 100 IOADDR 1 100 IOADDRLENGTH 2 100 MEMADDR 1 75 MEMADDRLENGTH 2 100 ",
|
|
DecEWFirstNext,
|
|
700
|
|
|
|
},
|
|
{
|
|
1200,
|
|
L"DEC101",
|
|
L"IRQ 1 90 IRQTYPE 2 100 IOADDR 1 100 IOADDRLENGTH 2 100 MEMADDR 1 75 MEMADDRLENGTH 2 100 ",
|
|
De101FirstNext,
|
|
700
|
|
|
|
},
|
|
|
|
{
|
|
1300,
|
|
L"DECPC",
|
|
L"\0",
|
|
DePCAFirstNext,
|
|
701
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#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
|
|
// LanceQueryCfgHandler() and LanceVerifyCfgHandler() as well!
|
|
//
|
|
|
|
static ADAPTER_INFO Adapters[] = {
|
|
|
|
{
|
|
1000,
|
|
L"DEC100",
|
|
L"IRQ\0"
|
|
L"1\0"
|
|
L"90\0"
|
|
L"IRQTYPE\0"
|
|
L"2\0"
|
|
L"100\0"
|
|
L"IOADDR\0"
|
|
L"1\0"
|
|
L"100\0"
|
|
L"IOADDRLENGTH\0"
|
|
L"2\0"
|
|
L"100\0"
|
|
L"MEMADDR\0"
|
|
L"1\0"
|
|
L"75\0"
|
|
L"MEMADDRLENGTH\0"
|
|
L"2\0"
|
|
L"100\0",
|
|
De100FirstNext,
|
|
700
|
|
|
|
},
|
|
|
|
{
|
|
1100,
|
|
L"DECETHERWORKSTURBO",
|
|
L"IRQ\0"
|
|
L"1\0"
|
|
L"90\0"
|
|
L"IRQTYPE\0"
|
|
L"2\0"
|
|
L"100\0"
|
|
L"IOADDR\0"
|
|
L"1\0"
|
|
L"100\0"
|
|
L"IOADDRLENGTH\0"
|
|
L"2\0"
|
|
L"100\0"
|
|
L"MEMADDR\0"
|
|
L"1\0"
|
|
L"75\0"
|
|
L"MEMADDRLENGTH\0"
|
|
L"2\0"
|
|
L"100\0",
|
|
DecEWFirstNext,
|
|
700
|
|
|
|
},
|
|
|
|
{
|
|
1200,
|
|
L"DEC101",
|
|
L"IRQ\0"
|
|
L"1\0"
|
|
L"90\0"
|
|
L"IRQTYPE\0"
|
|
L"2\0"
|
|
L"100\0"
|
|
L"IOADDR\0"
|
|
L"1\0"
|
|
L"100\0"
|
|
L"IOADDRLENGTH\0"
|
|
L"2\0"
|
|
L"100\0"
|
|
L"MEMADDR\0"
|
|
L"1\0"
|
|
L"75\0"
|
|
L"MEMADDRLENGTH\0"
|
|
L"2\0"
|
|
L"100\0",
|
|
De101FirstNext,
|
|
700
|
|
|
|
},
|
|
|
|
{
|
|
1300,
|
|
L"DECPC",
|
|
L"\0",
|
|
DePCAFirstNext,
|
|
701
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
//
|
|
// Structure for holding state of a search
|
|
//
|
|
|
|
typedef struct _SEARCH_STATE {
|
|
|
|
PUCHAR MemoryAddress;
|
|
|
|
} 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};
|
|
|
|
static UCHAR CopyrightString[] = "COPYRIGHT DIGITAL EQUIPMENT";
|
|
#define LENGTH_OF_COPYRIGHT 30
|
|
|
|
|
|
//
|
|
// Structure for holding a particular adapter's complete information
|
|
//
|
|
typedef struct _LANCE_ADAPTER {
|
|
|
|
LONG CardType;
|
|
INTERFACE_TYPE InterfaceType;
|
|
ULONG BusNumber;
|
|
PUCHAR MemoryMappedBaseAddress;
|
|
ULONG IoBaseAddress;
|
|
UCHAR Interrupt;
|
|
BOOLEAN MemoryAcquired;
|
|
BOOLEAN IoAcquired;
|
|
BOOLEAN InterruptAcquired;
|
|
|
|
} LANCE_ADAPTER, *PLANCE_ADAPTER;
|
|
|
|
|
|
//
|
|
// Constant strings for parameters
|
|
//
|
|
|
|
static CHAR De100String[] = "DE100";
|
|
static CHAR De200String[] = "DE200";
|
|
static CHAR De201String[] = "DE201";
|
|
static CHAR De202String[] = "DE202";
|
|
static CHAR De101String[] = "DE101";
|
|
|
|
|
|
|
|
BOOLEAN
|
|
LanceHardwareDetails(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG IoBaseAddress
|
|
);
|
|
|
|
BOOLEAN
|
|
DecCardAt(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG MemoryAddress,
|
|
IN CHAR *DectectString
|
|
);
|
|
|
|
|
|
|
|
|
|
extern
|
|
LONG
|
|
LanceIdentifyHandler(
|
|
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
|
|
|
|
if (LanceFirstTime) {
|
|
|
|
LanceFirstTime = 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 adapter
|
|
//
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
wsprintf((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 LanceFirstNextHandler(
|
|
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 - Either Isa, or Eisa.
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
LONG ReturnValue;
|
|
LONG NumberOfAdapters;
|
|
LONG i;
|
|
|
|
if ((InterfaceType != Isa) &&
|
|
(InterfaceType != Eisa)) {
|
|
|
|
*Confidence = 0;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
NumberOfAdapters = sizeof(Adapters) / sizeof(ADAPTER_INFO);
|
|
|
|
for (i=0; i < NumberOfAdapters; i++) {
|
|
|
|
if (Adapters[i].Index == NetcardId) {
|
|
|
|
//
|
|
// Call FindFirst Routine
|
|
//
|
|
|
|
ReturnValue = (*(Adapters[i].FirstNext))(
|
|
i,
|
|
InterfaceType,
|
|
BusNumber,
|
|
First,
|
|
0,
|
|
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 high bit of the short is boolean for ISA (else, EISA).
|
|
// 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?
|
|
//
|
|
|
|
if (InterfaceType == Isa) {
|
|
|
|
*Token = (PVOID)0x8000;
|
|
|
|
} else {
|
|
|
|
*Token = (PVOID)0x0;
|
|
}
|
|
|
|
*Token = (PVOID)(((ULONG)*Token) | ((BusNumber & 0x7F) << 8));
|
|
|
|
*Token = (PVOID)(((ULONG)*Token) | i);
|
|
|
|
}
|
|
|
|
return(ReturnValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
extern
|
|
LONG
|
|
LanceOpenHandleHandler(
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLANCE_ADAPTER Adapter;
|
|
LONG AdapterNumber;
|
|
ULONG BusNumber;
|
|
INTERFACE_TYPE InterfaceType;
|
|
|
|
//
|
|
// Get info from the token
|
|
//
|
|
|
|
if (((ULONG)Token) & 0x8000) {
|
|
|
|
InterfaceType = Isa;
|
|
|
|
} else {
|
|
|
|
InterfaceType = Eisa;
|
|
|
|
}
|
|
|
|
BusNumber = (ULONG)(((ULONG)Token >> 8) & 0x7F);
|
|
|
|
AdapterNumber = ((ULONG)Token) & 0xFF;
|
|
|
|
//
|
|
// Store information
|
|
//
|
|
|
|
Adapter = (PLANCE_ADAPTER)DetectAllocateHeap(
|
|
sizeof(LANCE_ADAPTER)
|
|
);
|
|
|
|
if (Adapter == NULL) {
|
|
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
}
|
|
|
|
//
|
|
// Copy across memory address
|
|
//
|
|
|
|
Adapter->MemoryMappedBaseAddress = SearchStates[(ULONG)AdapterNumber].MemoryAddress -
|
|
0x10000;
|
|
Adapter->CardType = Adapters[AdapterNumber].Index;
|
|
Adapter->InterfaceType = InterfaceType;
|
|
Adapter->BusNumber = BusNumber;
|
|
Adapter->MemoryAcquired = FALSE;
|
|
Adapter->IoAcquired = FALSE;
|
|
Adapter->Interrupt = FALSE;
|
|
|
|
*Handle = (PVOID)Adapter;
|
|
|
|
return(0);
|
|
}
|
|
|
|
extern
|
|
LONG LanceCreateHandleHandler(
|
|
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 - Isa or Eisa.
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLANCE_ADAPTER Adapter;
|
|
LONG NumberOfAdapters;
|
|
LONG i;
|
|
|
|
if ((InterfaceType != Isa) &&
|
|
(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 = (PLANCE_ADAPTER)DetectAllocateHeap(
|
|
sizeof(LANCE_ADAPTER)
|
|
);
|
|
|
|
if (Adapter == NULL) {
|
|
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
}
|
|
|
|
//
|
|
// Copy across memory address
|
|
//
|
|
|
|
Adapter->MemoryMappedBaseAddress = SearchStates[i].MemoryAddress - 0x10000;
|
|
Adapter->CardType = NetcardId;
|
|
Adapter->InterfaceType = InterfaceType;
|
|
Adapter->BusNumber = BusNumber;
|
|
|
|
Adapter->MemoryAcquired = FALSE;
|
|
Adapter->IoAcquired = FALSE;
|
|
Adapter->Interrupt = FALSE;
|
|
|
|
*Handle = (PVOID)Adapter;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
extern
|
|
LONG
|
|
LanceCloseHandleHandler(
|
|
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
|
|
LanceQueryCfgHandler(
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)(Handle);
|
|
NTSTATUS NtStatus;
|
|
HANDLE TrapHandle;
|
|
BOOLEAN FoundIo = FALSE;
|
|
BOOLEAN FoundInterrupt = FALSE;
|
|
UCHAR i;
|
|
UCHAR InterruptList[6];
|
|
UCHAR ResultList[6];
|
|
ULONG InterruptListLength = 0;
|
|
ULONG IoBaseAddress = 0;
|
|
UCHAR InterruptNumber = 0;
|
|
LONG OutputLengthLeft = BuffSize;
|
|
LONG CopyLength;
|
|
USHORT Value;
|
|
NETDTECT_RESOURCE Resource;
|
|
ULONG StartPointer = (ULONG)Buffer;
|
|
|
|
if ((Adapter->InterfaceType != Isa) &&
|
|
(Adapter->InterfaceType != Eisa)) {
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
if (Adapter->CardType == 1400) {
|
|
|
|
//
|
|
// The DePCA has no parameters
|
|
//
|
|
|
|
if (BuffSize > 0) {
|
|
|
|
*Buffer = L'\0';
|
|
return(0);
|
|
|
|
} else {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Get the IoBaseAddress
|
|
//
|
|
if (!Adapter->IoAcquired)
|
|
{
|
|
switch(Adapter->CardType) {
|
|
|
|
//
|
|
// De100
|
|
// DecEW
|
|
// De101
|
|
//
|
|
case 1000:
|
|
case 1100:
|
|
case 1200:
|
|
|
|
if (DetectCheckPortUsage(Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
0x200,
|
|
0x10
|
|
) == STATUS_SUCCESS) {
|
|
|
|
if (!LanceHardwareDetails(Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
0x20C)) {
|
|
|
|
if ((DetectCheckPortUsage(Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
0x300,
|
|
0x10
|
|
) == STATUS_SUCCESS)
|
|
&&
|
|
(LanceHardwareDetails(Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
0x30C))) {
|
|
|
|
IoBaseAddress = (ULONG)0x300;
|
|
|
|
FoundIo = TRUE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IoBaseAddress = (ULONG)0x200;
|
|
|
|
FoundIo = TRUE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((DetectCheckPortUsage(Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
0x300,
|
|
0x10
|
|
) == STATUS_SUCCESS)
|
|
&&
|
|
(LanceHardwareDetails(Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
0x30C))) {
|
|
|
|
IoBaseAddress = (ULONG)0x300;
|
|
|
|
FoundIo = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
if (FoundIo == FALSE) {
|
|
|
|
goto BuildBuffer;
|
|
}
|
|
|
|
//
|
|
// Acquire the port.
|
|
//
|
|
Resource.InterfaceType = Adapter->InterfaceType;
|
|
Resource.BusNumber = Adapter->BusNumber;
|
|
Resource.Type = NETDTECT_PORT_RESOURCE;
|
|
Resource.Value = IoBaseAddress;
|
|
Resource.Length = 0x10;
|
|
Resource.Flags = 0;
|
|
|
|
DetectTemporaryClaimResource(&Resource);
|
|
|
|
Adapter->IoBaseAddress = IoBaseAddress;
|
|
Adapter->IoAcquired = TRUE;
|
|
}
|
|
else
|
|
{
|
|
FoundIo = TRUE;
|
|
IoBaseAddress = Adapter->IoBaseAddress;
|
|
}
|
|
|
|
//
|
|
// Get memory info. To do this call FindFirst routine.
|
|
//
|
|
if (!Adapter->MemoryAcquired)
|
|
{
|
|
Adapter->MemoryMappedBaseAddress = 0;
|
|
|
|
for (i=0; i < sizeof(Adapters) / sizeof(ADAPTER_INFO); i++) {
|
|
|
|
if (Adapters[i].Index == Adapter->CardType) {
|
|
ULONG Confidence;
|
|
ULONG ReturnValue;
|
|
|
|
ReturnValue = (*(Adapters[i].FirstNext))(
|
|
i,
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
TRUE,
|
|
0,
|
|
&Confidence
|
|
);
|
|
|
|
if ((ReturnValue == 0) && (Confidence == 100)) {
|
|
|
|
|
|
//
|
|
// Get the rest of the memory info.
|
|
// Guess that it is 64K aligned
|
|
//
|
|
Adapter->MemoryMappedBaseAddress =
|
|
(PUCHAR)((ULONG)(SearchStates[i].MemoryAddress - 0x10000) &
|
|
0xF0000
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Read amount of memory
|
|
//
|
|
|
|
NtStatus = DetectReadPortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress,
|
|
&Value
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
goto BuildBuffer;
|
|
|
|
}
|
|
|
|
if (Value & 0x20) {
|
|
|
|
//
|
|
// Definitely in 32K mode.
|
|
//
|
|
|
|
Adapter->MemoryMappedBaseAddress = (PUCHAR)((ULONG)Adapter->MemoryMappedBaseAddress |
|
|
0x8000);
|
|
}
|
|
|
|
Resource.Type = NETDTECT_MEMORY_RESOURCE;
|
|
Resource.Value = (ULONG)Adapter->MemoryMappedBaseAddress;
|
|
Resource.Length = (Resource.Value & 0x8000) ? 0x8000 : 0x10000;
|
|
|
|
DetectTemporaryClaimResource(&Resource);
|
|
Adapter->MemoryAcquired = TRUE;
|
|
}
|
|
|
|
//
|
|
// Get the interrupt number
|
|
//
|
|
if (Adapter->InterruptAcquired)
|
|
{
|
|
InterruptNumber = Adapter->Interrupt;
|
|
goto BuildBuffer;
|
|
}
|
|
|
|
switch(Adapter->CardType) {
|
|
|
|
//
|
|
// De100
|
|
// De101
|
|
//
|
|
case 1000:
|
|
case 1200:
|
|
|
|
InterruptList[0] = 2;
|
|
InterruptList[1] = 3;
|
|
InterruptList[2] = 4;
|
|
InterruptList[3] = 5;
|
|
InterruptList[4] = 7;
|
|
InterruptListLength = 5;
|
|
break;
|
|
|
|
//
|
|
// DecEW
|
|
//
|
|
|
|
case 1100:
|
|
|
|
InterruptList[0] = 5;
|
|
InterruptList[1] = 9;
|
|
InterruptList[2] = 10;
|
|
InterruptList[3] = 11;
|
|
InterruptList[4] = 12;
|
|
InterruptList[5] = 15;
|
|
InterruptListLength = 6;
|
|
break;
|
|
|
|
default:
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
//
|
|
// Set the interrupt trap
|
|
//
|
|
|
|
NtStatus = DetectSetInterruptTrap(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
&TrapHandle,
|
|
InterruptList,
|
|
InterruptListLength
|
|
);
|
|
|
|
if (NtStatus == STATUS_SUCCESS) {
|
|
|
|
//
|
|
// Create an interrupt
|
|
//
|
|
|
|
switch (Adapter->CardType) {
|
|
|
|
//
|
|
// De100
|
|
// DecEW
|
|
// De101
|
|
//
|
|
|
|
case 1000:
|
|
case 1100:
|
|
case 1200:
|
|
|
|
//
|
|
// Change to CSR0
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress + 0x6,
|
|
0x0
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
goto BuildBuffer;
|
|
|
|
}
|
|
|
|
//
|
|
// Write STOP bit
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress + 0x4,
|
|
0x4
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
goto BuildBuffer;
|
|
|
|
}
|
|
|
|
//
|
|
// Enable Interrupts in NICSR
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress,
|
|
0x2
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
goto BuildBuffer;
|
|
|
|
}
|
|
|
|
//
|
|
// Write INIT bit and INTERRUPT_ENABLE bit
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress + 0x4,
|
|
0x41
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
goto BuildBuffer;
|
|
|
|
}
|
|
|
|
Sleep(100);
|
|
|
|
//
|
|
// Write STOP bit
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
(ULONG)(IoBaseAddress + 0x4),
|
|
0x4
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
//
|
|
// Disable Interrupts in NICSR
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
(ULONG)(IoBaseAddress),
|
|
0x4
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Check which one went off
|
|
//
|
|
|
|
NtStatus = DetectQueryInterruptTrap(
|
|
TrapHandle,
|
|
ResultList,
|
|
InterruptListLength
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
goto BuildBuffer;
|
|
|
|
}
|
|
|
|
//
|
|
// Remove interrupt trap
|
|
//
|
|
|
|
NtStatus = DetectRemoveInterruptTrap(
|
|
TrapHandle
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
goto BuildBuffer;
|
|
|
|
}
|
|
|
|
//
|
|
// Search resulting buffer to find the right interrupt
|
|
//
|
|
|
|
for (i = 0; i < InterruptListLength; i++) {
|
|
|
|
if ((ResultList[i] == 1) || (ResultList[i] == 2)) {
|
|
|
|
if (FoundInterrupt) {
|
|
|
|
//
|
|
// Uh-oh, looks like interrupts on two different IRQs.
|
|
//
|
|
|
|
FoundInterrupt = FALSE;
|
|
goto BuildBuffer;
|
|
|
|
}
|
|
|
|
InterruptNumber = InterruptList[i];
|
|
FoundInterrupt = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Resource.Type = NETDTECT_IRQ_RESOURCE;
|
|
Resource.Value = InterruptNumber;
|
|
Resource.Length = 0;
|
|
|
|
DetectTemporaryClaimResource(&Resource);
|
|
|
|
Adapter->Interrupt = InterruptNumber;
|
|
Adapter->InterruptAcquired = TRUE;
|
|
|
|
BuildBuffer :
|
|
|
|
//
|
|
// Build resulting buffer
|
|
//
|
|
|
|
if (!FoundIo) {
|
|
|
|
//
|
|
// We found nothing...
|
|
//
|
|
|
|
//
|
|
// Copy in final \0
|
|
//
|
|
|
|
Buffer[0] = L'\0';
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// First put in memory addr
|
|
//
|
|
|
|
if (Adapter->MemoryMappedBaseAddress < (PUCHAR)0xC0000) {
|
|
|
|
goto SkipBaseAddr;
|
|
|
|
}
|
|
|
|
//
|
|
// Copy in the title string
|
|
//
|
|
|
|
CopyLength = UnicodeStrLen(MemAddrString) + 1;
|
|
|
|
if (OutputLengthLeft < CopyLength) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
RtlMoveMemory((PVOID)Buffer,
|
|
(PVOID)MemAddrString,
|
|
(CopyLength * sizeof(WCHAR))
|
|
);
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Copy in the value
|
|
//
|
|
|
|
if (OutputLengthLeft < 8) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength = wsprintf(Buffer,L"0x%x",(ULONG)(Adapter->MemoryMappedBaseAddress));
|
|
|
|
if (CopyLength < 0) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength++; // Add in the \0
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
SkipBaseAddr:
|
|
|
|
//
|
|
// Now the amount of memory
|
|
//
|
|
|
|
//
|
|
// Copy in the title string
|
|
//
|
|
|
|
CopyLength = UnicodeStrLen(MemLengthString) + 1;
|
|
|
|
if (OutputLengthLeft < CopyLength) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
RtlMoveMemory((PVOID)Buffer,
|
|
(PVOID)MemLengthString,
|
|
(CopyLength * sizeof(WCHAR))
|
|
);
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Copy in the value
|
|
//
|
|
|
|
if (OutputLengthLeft < 8) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
if ((ULONG)(Adapter->MemoryMappedBaseAddress) & 0x8000) {
|
|
|
|
CopyLength = wsprintf(Buffer,L"0x8000");
|
|
|
|
} else {
|
|
|
|
CopyLength = wsprintf(Buffer,L"0x10000");
|
|
|
|
}
|
|
|
|
if (CopyLength < 0) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength++; // Add in the \0
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Now the IoBaseAddress
|
|
//
|
|
|
|
//
|
|
// Copy in the title string
|
|
//
|
|
|
|
CopyLength = UnicodeStrLen(IoAddrString) + 1;
|
|
|
|
if (OutputLengthLeft < CopyLength) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
RtlMoveMemory((PVOID)Buffer,
|
|
(PVOID)IoAddrString,
|
|
(CopyLength * sizeof(WCHAR))
|
|
);
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Copy in the value
|
|
//
|
|
|
|
if (OutputLengthLeft < 6) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength = wsprintf(Buffer,L"0x%x",IoBaseAddress);
|
|
|
|
if (CopyLength < 0) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength++; // Add in the \0
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Copy in the title string
|
|
//
|
|
|
|
CopyLength = UnicodeStrLen(IoLengthString) + 1;
|
|
|
|
if (OutputLengthLeft < CopyLength) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
RtlMoveMemory((PVOID)Buffer,
|
|
(PVOID)IoLengthString,
|
|
(CopyLength * sizeof(WCHAR))
|
|
);
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Copy in the value
|
|
//
|
|
|
|
if (OutputLengthLeft < 5) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength = wsprintf(Buffer,L"0x10");
|
|
|
|
if (CopyLength < 0) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength++; // Add in the \0
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Now the interrupt (if we found it)
|
|
//
|
|
|
|
if (FoundInterrupt) {
|
|
|
|
//
|
|
// Copy in the title string
|
|
//
|
|
|
|
CopyLength = UnicodeStrLen(IrqString) + 1;
|
|
|
|
if (OutputLengthLeft < CopyLength) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
RtlMoveMemory((PVOID)Buffer,
|
|
(PVOID)IrqString,
|
|
(CopyLength * sizeof(WCHAR))
|
|
);
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Copy in the value
|
|
//
|
|
|
|
if (OutputLengthLeft < 3) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength = wsprintf(Buffer,L"%d",InterruptNumber);
|
|
|
|
if (CopyLength < 0) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength++; // Add in the \0
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Copy in the title string (IRQTYPE)
|
|
//
|
|
|
|
CopyLength = UnicodeStrLen(IrqTypeString) + 1;
|
|
|
|
if (OutputLengthLeft < CopyLength) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
RtlMoveMemory((PVOID)Buffer,
|
|
(PVOID)IrqTypeString,
|
|
(CopyLength * sizeof(WCHAR))
|
|
);
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
//
|
|
// Copy in the value
|
|
//
|
|
|
|
if (OutputLengthLeft < 2) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
//
|
|
// All card types in this detection are ISA cards,
|
|
// which are LATCHED (0 == latched)
|
|
//
|
|
CopyLength = wsprintf(Buffer,L"0");
|
|
|
|
if (CopyLength < 0) {
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
CopyLength++; // Add in the \0
|
|
|
|
Buffer = &(Buffer[CopyLength]);
|
|
OutputLengthLeft -= CopyLength;
|
|
|
|
}
|
|
|
|
//
|
|
// Copy in final \0
|
|
//
|
|
|
|
CopyLength = (ULONG)Buffer - StartPointer;
|
|
((PUCHAR)StartPointer)[CopyLength] = L'\0';
|
|
|
|
|
|
return(0);
|
|
}
|
|
|
|
extern
|
|
LONG
|
|
LanceVerifyCfgHandler(
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLANCE_ADAPTER Adapter = (PLANCE_ADAPTER)(Handle);
|
|
NTSTATUS NtStatus;
|
|
HANDLE TrapHandle;
|
|
BOOLEAN Found = FALSE;
|
|
|
|
UCHAR Interrupt;
|
|
ULONG MemoryAddress;
|
|
ULONG IoBaseAddress;
|
|
UCHAR Result;
|
|
USHORT Value;
|
|
|
|
WCHAR *Place;
|
|
CHAR *DetectString;
|
|
NETDTECT_RESOURCE Resource;
|
|
UINT i;
|
|
BOOLEAN FoundIo;
|
|
BOOLEAN FoundInterrupt;
|
|
UCHAR InterruptNumber;
|
|
UCHAR InterruptList[6];
|
|
UCHAR ResultList[6];
|
|
ULONG InterruptListLength = 0;
|
|
|
|
|
|
if ((Adapter->InterfaceType != Isa) &&
|
|
(Adapter->InterfaceType != Eisa)) {
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
|
|
}
|
|
|
|
if (Adapter->CardType != 1400)
|
|
{
|
|
//
|
|
// If not the DecPCA we need to parse out the parameters.
|
|
//
|
|
|
|
|
|
//
|
|
// Get the IoBaseAddress
|
|
//
|
|
|
|
Place = FindParameterString(Buffer, IoAddrString);
|
|
|
|
if (Place == NULL) {
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
|
|
}
|
|
|
|
Place += UnicodeStrLen(IoAddrString) + 1;
|
|
|
|
//
|
|
// Now parse the thing.
|
|
//
|
|
ScanForNumber(Place, &IoBaseAddress, &Found);
|
|
|
|
if (Found == FALSE) {
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Get the interrupt number
|
|
//
|
|
|
|
Place = FindParameterString(Buffer, IrqString);
|
|
|
|
if (Place == NULL) {
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
|
|
}
|
|
|
|
Place += UnicodeStrLen(IrqString) + 1;
|
|
|
|
//
|
|
// Now parse the thing.
|
|
//
|
|
|
|
ScanForNumber(Place, &MemoryAddress, &Found);
|
|
|
|
Interrupt = (UCHAR)MemoryAddress;
|
|
|
|
if (Found == FALSE) {
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
|
|
}
|
|
|
|
//
|
|
// Get the memory address
|
|
//
|
|
|
|
Place = FindParameterString(Buffer, MemAddrString);
|
|
|
|
if (Place == NULL) {
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
|
|
}
|
|
|
|
Place += UnicodeStrLen(MemAddrString) + 1;
|
|
|
|
//
|
|
// Now parse the thing.
|
|
//
|
|
|
|
ScanForNumber(Place, &MemoryAddress, &Found);
|
|
|
|
if (Found == FALSE) {
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set the DePCA values
|
|
//
|
|
MemoryAddress = 0xD0000;
|
|
IoBaseAddress = 0x200;
|
|
Interrupt = 5;
|
|
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
//
|
|
// Get the IoBaseAddress
|
|
//
|
|
if (!Adapter->IoAcquired)
|
|
{
|
|
|
|
if (DetectCheckPortUsage(Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress,
|
|
0x10) == STATUS_SUCCESS)
|
|
{
|
|
if (LanceHardwareDetails(Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress + 0xC))
|
|
{
|
|
FoundIo = TRUE;
|
|
}
|
|
}
|
|
|
|
if (FoundIo == FALSE)
|
|
{
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
//
|
|
// Acquire the port.
|
|
//
|
|
Resource.InterfaceType = Adapter->InterfaceType;
|
|
Resource.BusNumber = Adapter->BusNumber;
|
|
Resource.Type = NETDTECT_PORT_RESOURCE;
|
|
Resource.Value = IoBaseAddress;
|
|
Resource.Length = 0x10;
|
|
Resource.Flags = 0;
|
|
|
|
DetectTemporaryClaimResource(&Resource);
|
|
|
|
Adapter->IoBaseAddress = IoBaseAddress;
|
|
Adapter->IoAcquired = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (IoBaseAddress != Adapter->IoBaseAddress)
|
|
{
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get memory info. To do this call FindFirst routine.
|
|
//
|
|
if (!Adapter->MemoryAcquired)
|
|
{
|
|
|
|
Adapter->MemoryMappedBaseAddress = 0;
|
|
|
|
for (i = 0; i < sizeof(Adapters) / sizeof(ADAPTER_INFO); i++)
|
|
{
|
|
if (Adapters[i].Index == Adapter->CardType)
|
|
{
|
|
ULONG Confidence;
|
|
ULONG ReturnValue;
|
|
|
|
ReturnValue = (*(Adapters[i].FirstNext))(
|
|
i,
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
TRUE,
|
|
0,
|
|
&Confidence);
|
|
|
|
if ((ReturnValue == 0) && (Confidence == 100))
|
|
{
|
|
//
|
|
// Get the rest of the memory info.
|
|
// Guess that it is 64K aligned
|
|
//
|
|
Adapter->MemoryMappedBaseAddress =
|
|
(PUCHAR)((ULONG)(SearchStates[i].MemoryAddress - 0x10000) &
|
|
0xF0000);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Read amount of memory
|
|
//
|
|
DetectReadPortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress,
|
|
&Value);
|
|
|
|
if (Value & 0x20)
|
|
{
|
|
//
|
|
// Definitely in 32K mode.
|
|
//
|
|
Adapter->MemoryMappedBaseAddress = (PUCHAR)((ULONG)Adapter->MemoryMappedBaseAddress |
|
|
0x8000);
|
|
}
|
|
|
|
Resource.InterfaceType = Adapter->InterfaceType;
|
|
Resource.BusNumber = Adapter->BusNumber;
|
|
Resource.Type = NETDTECT_MEMORY_RESOURCE;
|
|
Resource.Value = (ULONG)Adapter->MemoryMappedBaseAddress;
|
|
Resource.Length = (Resource.Value & 0x8000) ? 0x8000 : 0x10000;
|
|
|
|
DetectTemporaryClaimResource(&Resource);
|
|
Adapter->MemoryAcquired = TRUE;
|
|
}
|
|
|
|
if (MemoryAddress != (ULONG)Adapter->MemoryMappedBaseAddress)
|
|
{
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
//
|
|
// Get the interrupt number
|
|
//
|
|
if (!Adapter->InterruptAcquired)
|
|
{
|
|
switch(Adapter->CardType)
|
|
{
|
|
//
|
|
// De100
|
|
// De101
|
|
//
|
|
case 1000:
|
|
case 1200:
|
|
|
|
InterruptList[0] = 2;
|
|
InterruptList[1] = 3;
|
|
InterruptList[2] = 4;
|
|
InterruptList[3] = 5;
|
|
InterruptList[4] = 7;
|
|
InterruptListLength = 5;
|
|
break;
|
|
|
|
//
|
|
// DecEW
|
|
//
|
|
|
|
case 1100:
|
|
|
|
InterruptList[0] = 5;
|
|
InterruptList[1] = 9;
|
|
InterruptList[2] = 10;
|
|
InterruptList[3] = 11;
|
|
InterruptList[4] = 12;
|
|
InterruptList[5] = 15;
|
|
InterruptListLength = 6;
|
|
break;
|
|
|
|
default:
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Set the interrupt trap
|
|
//
|
|
DetectSetInterruptTrap(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
&TrapHandle,
|
|
InterruptList,
|
|
InterruptListLength);
|
|
|
|
//
|
|
// Change to CSR0
|
|
//
|
|
DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress + 0x6,
|
|
0x0);
|
|
|
|
//
|
|
// Write STOP bit
|
|
//
|
|
DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress + 0x4,
|
|
0x4);
|
|
|
|
//
|
|
// Enable Interrupts in NICSR
|
|
//
|
|
DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress,
|
|
0x2);
|
|
|
|
//
|
|
// Write INIT bit and INTERRUPT_ENABLE bit
|
|
//
|
|
DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
IoBaseAddress + 0x4,
|
|
0x41);
|
|
|
|
Sleep(100);
|
|
|
|
//
|
|
// Write STOP bit
|
|
//
|
|
DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
(ULONG)(IoBaseAddress + 0x4),
|
|
0x4);
|
|
|
|
//
|
|
// Disable Interrupts in NICSR
|
|
//
|
|
DetectWritePortUshort(
|
|
Adapter->InterfaceType,
|
|
Adapter->BusNumber,
|
|
(ULONG)(IoBaseAddress),
|
|
0x4);
|
|
|
|
//
|
|
// Check which one went off
|
|
//
|
|
DetectQueryInterruptTrap(TrapHandle, ResultList, InterruptListLength);
|
|
|
|
//
|
|
// Remove interrupt trap
|
|
//
|
|
DetectRemoveInterruptTrap(TrapHandle);
|
|
|
|
//
|
|
// Search resulting buffer to find the right interrupt
|
|
//
|
|
for (i = 0; i < InterruptListLength; i++)
|
|
{
|
|
if ((ResultList[i] == 1) || (ResultList[i] == 2))
|
|
{
|
|
if (FoundInterrupt)
|
|
{
|
|
//
|
|
// Uh-oh, looks like interrupts on two different IRQs.
|
|
//
|
|
FoundInterrupt = FALSE;
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
InterruptNumber = InterruptList[i];
|
|
FoundInterrupt = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
Resource.InterfaceType = Adapter->InterfaceType;
|
|
Resource.BusNumber = Adapter->BusNumber;
|
|
Resource.Type = NETDTECT_IRQ_RESOURCE;
|
|
Resource.Value = InterruptNumber;
|
|
Resource.Length = 0;
|
|
|
|
DetectTemporaryClaimResource(&Resource);
|
|
|
|
Adapter->Interrupt = InterruptNumber;
|
|
}
|
|
|
|
if (Interrupt != Adapter->Interrupt)
|
|
{
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
extern
|
|
LONG LanceQueryMaskHandler(
|
|
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_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
memcpy((PVOID)Buffer, Result, Length * sizeof(WCHAR));
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
extern
|
|
LONG
|
|
LanceParamRangeHandler(
|
|
IN LONG NetcardId,
|
|
IN WCHAR *Param,
|
|
OUT LONG *plValues,
|
|
OUT LONG *plBuffSize
|
|
)
|
|
|
|
/*++
|
|
|
|
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.
|
|
|
|
plValues - A pointer to a list of LONGs into which we store valid values
|
|
for the parameter.
|
|
|
|
plBuffSize - At entry, the length of plValues in LONGs. At exit, the
|
|
number of LONGs stored in plValues.
|
|
|
|
Return Value:
|
|
|
|
0 if nothing went wrong, else the appropriate WINERROR.H value.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Do we want the IRQL
|
|
//
|
|
|
|
if (memcmp(Param, IrqString, (UnicodeStrLen(IrqString) + 1) * sizeof(WCHAR)) == 0) {
|
|
|
|
//
|
|
// Is there enough space
|
|
//
|
|
|
|
if (*plBuffSize < 6) {
|
|
|
|
*plBuffSize = 0;
|
|
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
//
|
|
// Find which card
|
|
//
|
|
|
|
switch (NetcardId) {
|
|
|
|
//
|
|
// De100
|
|
// De101
|
|
//
|
|
case 1000:
|
|
case 1200:
|
|
|
|
plValues[0] = 5;
|
|
plValues[1] = 3;
|
|
plValues[2] = 4;
|
|
plValues[3] = 2;
|
|
plValues[4] = 7;
|
|
*plBuffSize = 5;
|
|
break;
|
|
|
|
//
|
|
// DecEW
|
|
//
|
|
|
|
case 1100:
|
|
|
|
plValues[0] = 5;
|
|
plValues[1] = 9;
|
|
plValues[2] = 10;
|
|
plValues[3] = 11;
|
|
plValues[4] = 12;
|
|
plValues[5] = 15;
|
|
*plBuffSize = 6;
|
|
break;
|
|
|
|
default:
|
|
|
|
*plBuffSize = 0;
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Do we want the IoBaseAddress
|
|
//
|
|
|
|
if (memcmp(Param, IoAddrString, (UnicodeStrLen(IoAddrString) + 1) * sizeof(WCHAR)) == 0) {
|
|
|
|
//
|
|
// Is there enough space
|
|
//
|
|
|
|
if (*plBuffSize < 2) {
|
|
|
|
*plBuffSize = 0;
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
//
|
|
// Find which card
|
|
//
|
|
|
|
switch (NetcardId) {
|
|
|
|
//
|
|
// De100
|
|
// DecEW
|
|
// De101
|
|
//
|
|
|
|
case 1000:
|
|
case 1100:
|
|
case 1200:
|
|
|
|
plValues[0] = 0x300;
|
|
plValues[1] = 0x200;
|
|
*plBuffSize = 2;
|
|
break;
|
|
|
|
default:
|
|
|
|
*plBuffSize = 0;
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Do we want the MemoryBaseAddress
|
|
//
|
|
|
|
if (memcmp(Param, MemAddrString, (UnicodeStrLen(MemAddrString) + 1) * sizeof(WCHAR)) == 0) {
|
|
|
|
//
|
|
// Is there enough space
|
|
//
|
|
|
|
if (*plBuffSize < 6) {
|
|
|
|
*plBuffSize = 0;
|
|
return(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
}
|
|
|
|
//
|
|
// Find which card
|
|
//
|
|
|
|
switch (NetcardId) {
|
|
|
|
//
|
|
// De100
|
|
// DecEW
|
|
// De101
|
|
//
|
|
|
|
case 1000:
|
|
case 1100:
|
|
case 1200:
|
|
|
|
plValues[0] = 0xD0000;
|
|
plValues[1] = 0xC8000;
|
|
plValues[2] = 0xC0000;
|
|
plValues[3] = 0xD8000;
|
|
plValues[4] = 0xE0000;
|
|
plValues[5] = 0xE8000;
|
|
*plBuffSize = 6;
|
|
break;
|
|
|
|
default:
|
|
|
|
*plBuffSize = 0;
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
extern
|
|
LONG LanceQueryParameterNameHandler(
|
|
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);
|
|
}
|
|
|
|
BOOLEAN
|
|
DecCardAt(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG MemoryAddress,
|
|
IN CHAR *DetectString
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks for the instance of a Lance card at the memory
|
|
location given. This is done by checking for the DEC copyright
|
|
notice in ROM and then for the model name of the card.
|
|
|
|
Arguments:
|
|
|
|
InterfaceType - The type of bus, ISA or EISA.
|
|
|
|
BusNumber - The bus number in the system.
|
|
|
|
MemoryAddress - The address of the ROM space for the DEC card.
|
|
|
|
DetectString - The model name of the card to search for.
|
|
|
|
Return Value:
|
|
|
|
TRUE if a card is found, else FALSE.
|
|
|
|
--*/
|
|
|
|
{
|
|
UCHAR TmpBuffer[LENGTH_OF_COPYRIGHT];
|
|
LONG CopyrightLength;
|
|
LONG DetectLength;
|
|
NTSTATUS NtStatus;
|
|
|
|
CopyrightLength = strlen(CopyrightString);
|
|
DetectLength = strlen(DetectString);
|
|
|
|
NtStatus = DetectCheckMemoryUsage(
|
|
InterfaceType,
|
|
BusNumber,
|
|
MemoryAddress,
|
|
0x2000
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
//
|
|
// Read memory
|
|
//
|
|
|
|
NtStatus = DetectReadMappedMemory(
|
|
InterfaceType,
|
|
BusNumber,
|
|
MemoryAddress + 16,
|
|
CopyrightLength,
|
|
TmpBuffer
|
|
);
|
|
|
|
//
|
|
// Compare to copyright notice
|
|
//
|
|
|
|
if ((NtStatus == STATUS_SUCCESS) &&
|
|
(memcmp(TmpBuffer, CopyrightString, CopyrightLength) == 0)) {
|
|
|
|
//
|
|
// So far so good, now check for the specific card
|
|
//
|
|
|
|
//
|
|
// Read Memory
|
|
//
|
|
|
|
NtStatus = DetectReadMappedMemory(
|
|
InterfaceType,
|
|
BusNumber,
|
|
MemoryAddress + 6,
|
|
DetectLength,
|
|
TmpBuffer
|
|
);
|
|
|
|
//
|
|
// Compare
|
|
//
|
|
|
|
if ((NtStatus == STATUS_SUCCESS) &&
|
|
(memcmp(TmpBuffer, DetectString, DetectLength) == 0)) {
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
}
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
LONG
|
|
DecCardFirstNext(
|
|
IN LONG SearchStateIndex,
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN BOOL First,
|
|
IN CHAR *DetectString,
|
|
OUT LONG *Confidence
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine finds the instances of a physical adapter. This routine
|
|
handles the general (most typical) kind of Lance card.
|
|
|
|
Arguments:
|
|
|
|
SearchStateIndex - The index into SearchStates for the particular
|
|
adapter type we are searching for.
|
|
|
|
InterfaceType - Either Isa, or Eisa.
|
|
|
|
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.
|
|
|
|
DetectString - The model name of the adapter.
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
if (First) {
|
|
|
|
//
|
|
// Reset to beginning
|
|
//
|
|
|
|
SearchStates[SearchStateIndex].MemoryAddress = (PUCHAR)0xCC000;
|
|
|
|
}
|
|
|
|
while (SearchStates[SearchStateIndex].MemoryAddress != (PUCHAR)0xFC000) {
|
|
|
|
//
|
|
// Is there a card at the current address?
|
|
//
|
|
|
|
if (DecCardAt(InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(SearchStates[SearchStateIndex].MemoryAddress),
|
|
DetectString
|
|
)) {
|
|
|
|
//
|
|
// Found one!
|
|
//
|
|
|
|
*Confidence = 100;
|
|
|
|
//
|
|
// Move to next address for next time
|
|
//
|
|
|
|
SearchStates[SearchStateIndex].MemoryAddress += 0x10000;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Move to next address
|
|
//
|
|
|
|
SearchStates[SearchStateIndex].MemoryAddress += 0x10000;
|
|
|
|
}
|
|
|
|
*Confidence = 0;
|
|
|
|
return(0);
|
|
|
|
}
|
|
LONG
|
|
De100FirstNext(
|
|
IN LONG SearchStateIndex,
|
|
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 De100.
|
|
|
|
Arguments:
|
|
|
|
SearchStateIndex - The index in SearchStates for the De100 adapter.
|
|
|
|
InterfaceType - Either Isa, or Eisa.
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(Token);
|
|
|
|
return(DecCardFirstNext(SearchStateIndex,
|
|
InterfaceType,
|
|
BusNumber,
|
|
First,
|
|
De100String,
|
|
Confidence
|
|
)
|
|
);
|
|
}
|
|
LONG
|
|
DecEWFirstNext(
|
|
IN LONG SearchStateIndex,
|
|
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 Dec Etherworks Turbo Series.
|
|
|
|
Arguments:
|
|
|
|
SearchStateIndex - The index in SearchStates for the Dec EW adapters.
|
|
|
|
InterfaceType - Either Isa, or Eisa.
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
LONG ErrorCode;
|
|
UNREFERENCED_PARAMETER(Token);
|
|
|
|
ErrorCode = DecCardFirstNext(SearchStateIndex,
|
|
InterfaceType,
|
|
BusNumber,
|
|
First,
|
|
De200String,
|
|
Confidence
|
|
);
|
|
|
|
if ((ErrorCode == 0) && (*Confidence != 0)) {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
ErrorCode = DecCardFirstNext(SearchStateIndex,
|
|
InterfaceType,
|
|
BusNumber,
|
|
First,
|
|
De201String,
|
|
Confidence
|
|
);
|
|
|
|
if ((ErrorCode == 0) && (*Confidence != 0)) {
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
ErrorCode = DecCardFirstNext(SearchStateIndex,
|
|
InterfaceType,
|
|
BusNumber,
|
|
First,
|
|
De202String,
|
|
Confidence
|
|
);
|
|
|
|
return(ErrorCode);
|
|
|
|
}
|
|
LONG
|
|
De101FirstNext(
|
|
IN LONG SearchStateIndex,
|
|
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 De101.
|
|
|
|
Arguments:
|
|
|
|
SearchStateIndex - The index in SearchStates for the De101 adapter.
|
|
|
|
InterfaceType - Either Isa, or Eisa.
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(Token);
|
|
|
|
return(DecCardFirstNext(SearchStateIndex,
|
|
InterfaceType,
|
|
BusNumber,
|
|
First,
|
|
De101String,
|
|
Confidence
|
|
)
|
|
);
|
|
}
|
|
LONG
|
|
DePCAFirstNext(
|
|
IN LONG SearchStateIndex,
|
|
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 DePCA.
|
|
|
|
Arguments:
|
|
|
|
SearchStateIndex - The index in SearchStates for the DePCA adapter.
|
|
|
|
InterfaceType - Either Isa, or Eisa.
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
UCHAR Value;
|
|
HANDLE TrapHandle;
|
|
UCHAR Interrupt = 5;
|
|
NTSTATUS NtStatus;
|
|
|
|
UNREFERENCED_PARAMETER(Token);
|
|
|
|
if (!First) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
if (InterfaceType != Isa) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Check Memory base address
|
|
//
|
|
|
|
if (!DecCardAt(InterfaceType,
|
|
BusNumber,
|
|
0xDC000,
|
|
De100String
|
|
)) {
|
|
|
|
//
|
|
// Definitely not
|
|
//
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Check for the io base address
|
|
//
|
|
|
|
if (!LanceHardwareDetails(InterfaceType, BusNumber, 0x20C)) {
|
|
|
|
//
|
|
// Definitely not
|
|
//
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Check for the lan configuration register
|
|
//
|
|
|
|
NtStatus = DetectReadPortUchar(
|
|
InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(0x800),
|
|
&(Value)
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
if (Value == 0xFF) {
|
|
|
|
//
|
|
// No such port, definitely not.
|
|
//
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Check for the interrupt
|
|
//
|
|
|
|
//
|
|
// Set the interrupt trap -- we are checking the interrupt number now
|
|
//
|
|
|
|
NtStatus = DetectSetInterruptTrap(
|
|
InterfaceType,
|
|
BusNumber,
|
|
&TrapHandle,
|
|
&Interrupt,
|
|
1
|
|
);
|
|
|
|
if (NtStatus == STATUS_SUCCESS) {
|
|
|
|
//
|
|
// Check that it is available
|
|
//
|
|
|
|
NtStatus = DetectQueryInterruptTrap(
|
|
TrapHandle,
|
|
&Interrupt,
|
|
1
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
if (Interrupt == 3) {
|
|
|
|
//
|
|
// Remove interrupt trap
|
|
//
|
|
|
|
DetectRemoveInterruptTrap(
|
|
TrapHandle
|
|
);
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Create an interrupt
|
|
//
|
|
|
|
//
|
|
// Enable Interrupts in NICSR
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(0x200),
|
|
0x2
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Change to CSR0
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(0x206),
|
|
0x0
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Write STOP bit
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(0x204),
|
|
0x4
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Write INIT bit and INTERRUPT_ENABLE bit
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(0x204),
|
|
0x41
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
Sleep(100);
|
|
|
|
//
|
|
// Write STOP bit
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(0x204),
|
|
0x4
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
//
|
|
// Disable Interrupts in NICSR
|
|
//
|
|
|
|
NtStatus = DetectWritePortUshort(
|
|
InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(0x200),
|
|
0x4
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
return(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
//
|
|
// Check which one went off
|
|
//
|
|
|
|
NtStatus = DetectQueryInterruptTrap(
|
|
TrapHandle,
|
|
&Interrupt,
|
|
1
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Remove interrupt trap
|
|
//
|
|
|
|
NtStatus = DetectRemoveInterruptTrap(
|
|
TrapHandle
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Everything checks out
|
|
//
|
|
|
|
if ((Interrupt == 1) || (Interrupt == 2)) {
|
|
|
|
*Confidence = 100;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*Confidence = 0;
|
|
return(0);
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
LanceHardwareDetails(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG IoBaseAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks for a signature in a well known port address
|
|
|
|
Arguments:
|
|
|
|
InterfaceType - The type of the bus, EISA or Isa.
|
|
|
|
BusNumber - The number of the bus in the system.
|
|
|
|
IoBaseAddress - Address of port with the Lance signature.
|
|
|
|
Return Value:
|
|
|
|
TRUE - if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
UCHAR Signature[] = { 0xff, 0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa};
|
|
UCHAR BytesRead[8];
|
|
NTSTATUS NtStatus;
|
|
UINT ReadCount;
|
|
|
|
UINT Place;
|
|
|
|
//
|
|
// Reset E-PROM state
|
|
//
|
|
// To do this we first read from the E-PROM address until the
|
|
// specific signature is reached (then the next bytes read from
|
|
// the E-PROM address will be the ethernet address of the card).
|
|
//
|
|
|
|
|
|
|
|
//
|
|
// Read first part of the signature
|
|
//
|
|
|
|
for (Place=0; Place < 8; Place++){
|
|
|
|
NtStatus = DetectReadPortUchar(
|
|
InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(IoBaseAddress),
|
|
&(BytesRead[Place])
|
|
);
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ReadCount = 8;
|
|
|
|
//
|
|
// This advances to the front of the circular buffer.
|
|
//
|
|
|
|
while (ReadCount < 40) {
|
|
|
|
//
|
|
// Check if we have read the signature.
|
|
//
|
|
|
|
for (Place = 0; Place < 8; Place++){
|
|
|
|
if (BytesRead[Place] != Signature[Place]){
|
|
|
|
Place = 10;
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If we have read the signature, stop.
|
|
//
|
|
|
|
if (Place != 10){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// else, move all the bytes down one and read then
|
|
// next byte.
|
|
//
|
|
|
|
for (Place = 0; Place < 7; Place++){
|
|
|
|
BytesRead[Place] = BytesRead[Place+1];
|
|
|
|
}
|
|
|
|
NtStatus = DetectReadPortUchar(
|
|
InterfaceType,
|
|
BusNumber,
|
|
(ULONG)(IoBaseAddress),
|
|
&(BytesRead[7]));
|
|
|
|
if (NtStatus != STATUS_SUCCESS) {
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
ReadCount++;
|
|
}
|
|
|
|
|
|
if (ReadCount == 40){
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|