Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

3959 lines
81 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
detwd.c
Abstract:
This is the main file for the autodetection DLL for all the wdlan.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"
#include "detwd.h"
//
// Individual card detection routines
//
//
// Helper functions
//
VOID
WdGetBoardId(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PULONG BoardIdMask
);
BOOLEAN
WdCardAt(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PUCHAR Interrupt,
OUT PULONG MemoryAddress,
OUT PULONG MemoryLength
);
VOID
WdCardCopyDownBuffer(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
IN ULONG MemoryBaseAddress,
IN PUCHAR Buffer,
IN ULONG Length
);
BOOLEAN
CheckForWdAddress(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress
);
VOID
CardGetBaseInfo(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PULONG BoardIdMask
);
VOID
CardGetEepromInfo(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PULONG BoardIdMask
);
VOID
CardGetEepromRamSize(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
IN ULONG Bid,
OUT PULONG RamSize
);
VOID
CardGetRamSize(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
IN ULONG RevNumber,
IN ULONG Bid,
OUT PULONG RamSize
);
VOID
WdCardSetup(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
IN ULONG MemoryBaseAddress,
IN ULONG Bid,
OUT UCHAR *NetworkAddress
);
BOOLEAN
CheckFor585(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
ULONG IoBaseAddress
);
#ifdef WORKAROUND
UCHAR WdFirstTime = 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
// WdQueryCfgHandler() and WdVerifyCfgHandler() as well!
//
static ADAPTER_INFO Adapters[] = {
{
1000,
L"SMCISA",
L"IRQ 1 90 IRQTYPE 2 100 IOADDR 1 100 IOADDRLENGTH 2 100 MEMADDR 1 100 MEMADDRLENGTH 2 100 ",
NULL,
400
}
};
#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
// WdQueryCfgHandler() and WdVerifyCfgHandler() as well!
//
static ADAPTER_INFO Adapters[] = {
{
1000,
L"SMCISA",
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"100\0"
L"MEMADDRLENGTH\0"
L"2\0"
L"100\0",
NULL,
400
}
};
#endif
//
// Structure for holding state of a search
//
typedef struct _SEARCH_STATE
{
ULONG IoBaseAddress;
UCHAR Interrupt;
ULONG MemoryAddress;
ULONG MemoryLength;
}
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 _WD_ADAPTER
{
LONG CardType;
INTERFACE_TYPE InterfaceType;
ULONG BusNumber;
ULONG IoBaseAddress;
UCHAR Interrupt;
ULONG MemoryAddress;
ULONG MemoryLength;
}
WD_ADAPTER,
*PWD_ADAPTER;
extern
LONG
WdIdentifyHandler(
IN LONG lIndex,
IN WCHAR * pwchBuffer,
IN LONG cwchBuffSize
)
/*++
Routine Description:
This routine returns information about the netcards supported by
this file.
Arguments:
lIndex - The index of the netcard being address. The first
cards information is at index 1000, the second at 1100, etc.
pwchBuffer - Buffer to store the result into.
cwchBuffSize - Number of bytes in pwchBuffer
Return Value:
0 if nothing went wrong, else the appropriate WINERROR.H value.
--*/
{
LONG NumberOfAdapters;
LONG Code = lIndex % 100;
LONG Length;
LONG i;
NumberOfAdapters = sizeof(Adapters) / sizeof(ADAPTER_INFO);
#ifdef WORKAROUND
if (WdFirstTime) {
WdFirstTime = 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
lIndex = lIndex - Code;
if (((lIndex / 100) - 10) < NumberOfAdapters) {
for (i=0; i < NumberOfAdapters; i++) {
if (Adapters[i].Index == lIndex) {
switch (Code) {
case 0:
//
// Find the string length
//
Length = UnicodeStrLen(Adapters[i].InfId);
Length ++;
if (cwchBuffSize < Length) {
return(ERROR_INSUFFICIENT_BUFFER);
}
memcpy((PVOID)pwchBuffer, Adapters[i].InfId, Length * sizeof(WCHAR));
break;
case 3:
//
// Maximum value is 1000
//
if (cwchBuffSize < 5) {
return(ERROR_INSUFFICIENT_BUFFER);
}
wsprintf((PVOID)pwchBuffer, L"%d", Adapters[i].SearchOrder);
break;
default:
return(ERROR_INVALID_PARAMETER);
}
return(0);
}
}
return(ERROR_INVALID_PARAMETER);
}
return(ERROR_NO_MORE_ITEMS);
}
extern
LONG WdFirstNextHandler(
IN LONG lNetcardId,
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN BOOL fFirst,
OUT PVOID *ppvToken,
OUT LONG *lConfidence
)
/*++
Routine Description:
This routine finds the instances of a physical adapter identified
by the NetcardId.
Arguments:
lNetcardId - 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.
fFirst - 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.
ppvToken - A pointer to a handle to return to identify the found
instance
lConfidence - 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.
--*/
{
NETDTECT_RESOURCE Resource;
if ((InterfaceType != Isa) && (InterfaceType != Eisa))
{
*lConfidence = 0;
return(0);
}
if (lNetcardId != 1000)
{
*lConfidence = 0;
return(ERROR_INVALID_PARAMETER);
}
//
// If fFirst, reset search state
//
if (fFirst)
{
SearchStates[0].IoBaseAddress = 0x200;
}
else if (SearchStates[0].IoBaseAddress < 0x400)
{
SearchStates[0].IoBaseAddress += 0x20;
}
while (SearchStates[0].IoBaseAddress < 0x400)
{
if (WdCardAt(
InterfaceType,
BusNumber,
SearchStates[0].IoBaseAddress,
&SearchStates[0].Interrupt,
&SearchStates[0].MemoryAddress,
&SearchStates[0].MemoryLength))
{
break;
}
SearchStates[0].IoBaseAddress += 0x20;
}
if (SearchStates[0].IoBaseAddress == 0x400)
{
*lConfidence = 0;
return(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)
{
*ppvToken = (PVOID)0x8000;
}
else
{
*ppvToken = (PVOID)0x0;
}
*ppvToken = (PVOID)(((ULONG)*ppvToken) | ((BusNumber & 0x7F) << 8));
*ppvToken = (PVOID)(((ULONG)*ppvToken) | 0); // index
*lConfidence = 100;
return(0);
}
extern
LONG
WdOpenHandleHandler(
IN PVOID pvToken,
OUT PVOID *ppvHandle
)
/*++
Routine Description:
This routine takes a token returned by FirstNext and converts it
into a permanent handle.
Arguments:
Token - The token.
ppvHandle - 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.
--*/
{
PWD_ADAPTER Handle;
LONG AdapterNumber;
ULONG BusNumber;
INTERFACE_TYPE InterfaceType;
//
// Get info from the token
//
if (((ULONG)pvToken) & 0x8000)
{
InterfaceType = Isa;
}
else
{
InterfaceType = Eisa;
}
BusNumber = (ULONG)(((ULONG)pvToken >> 8) & 0x7F);
AdapterNumber = ((ULONG)pvToken) & 0xFF;
//
// Store information
//
Handle = (PWD_ADAPTER)DetectAllocateHeap(sizeof(WD_ADAPTER));
if (Handle == NULL)
{
return(ERROR_NOT_ENOUGH_MEMORY);
}
//
// Copy across address
//
Handle->IoBaseAddress = SearchStates[(ULONG)AdapterNumber].IoBaseAddress;
Handle->CardType = Adapters[AdapterNumber].Index;
Handle->InterfaceType = InterfaceType;
Handle->BusNumber = BusNumber;
*ppvHandle = (PVOID)Handle;
return(0);
}
LONG
WdCreateHandleHandler(
IN LONG lNetcardId,
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
OUT PVOID *ppvHandle
)
/*++
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:
lNetcardId - The id of the card to create the handle for.
InterfaceType - Isa or Eisa.
BusNumber - The bus number of the bus in the system.
ppvHandle - A pointer to the handle, for storing the resulting handle.
Return Value:
0 if nothing went wrong, else the appropriate WINERROR.H value.
--*/
{
PWD_ADAPTER Handle;
LONG NumberOfAdapters;
LONG i;
NETDTECT_RESOURCE Resource;
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 == lNetcardId)
{
//
// Store information
//
Handle = (PWD_ADAPTER)DetectAllocateHeap(sizeof(WD_ADAPTER));
if (Handle == NULL)
{
return(ERROR_NOT_ENOUGH_MEMORY);
}
//
// Copy across memory address
//
Handle->IoBaseAddress = 0x200;
Handle->Interrupt = 3;
Handle->MemoryAddress = 0;
Handle->CardType = lNetcardId;
Handle->InterfaceType = InterfaceType;
Handle->BusNumber = BusNumber;
Resource.InterfaceType = InterfaceType;
Resource.BusNumber = BusNumber;
Resource.Type = NETDTECT_PORT_RESOURCE;
Resource.Value = 0x200;
Resource.Length = 0x20;
Resource.Flags = 0;
DetectTemporaryClaimResource(&Resource);
Resource.Type = NETDTECT_PORT_RESOURCE;
Resource.Value = 3;
Resource.Length = 0;
DetectTemporaryClaimResource(&Resource);
*ppvHandle = (PVOID)Handle;
return(0);
}
}
return(ERROR_INVALID_PARAMETER);
}
extern
LONG
WdCloseHandleHandler(
IN PVOID pvHandle
)
/*++
Routine Description:
This frees any resources associated with a handle.
Arguments:
pvHandle - The handle.
Return Value:
0 if nothing went wrong, else the appropriate WINERROR.H value.
--*/
{
DetectFreeHeap(pvHandle);
return(0);
}
LONG
WdQueryCfgHandler(
IN PVOID pvHandle,
OUT WCHAR *pwchBuffer,
IN LONG cwchBuffSize
)
/*++
Routine Description:
This routine calls the appropriate driver's query config handler to
get the parameters for the adapter associated with the handle.
Arguments:
pvHandle - The handle.
pwchBuffer - The resulting parameter list.
cwchBuffSize - Length of the given buffer in WCHARs.
Return Value:
0 if nothing went wrong, else the appropriate WINERROR.H value.
--*/
{
PWD_ADAPTER Adapter = (PWD_ADAPTER)(pvHandle);
NTSTATUS NtStatus;
LONG OutputLengthLeft = cwchBuffSize;
LONG CopyLength;
ULONG StartPointer = (ULONG)pwchBuffer;
if ((Adapter->InterfaceType != Isa) && (Adapter->InterfaceType != Eisa))
{
return(ERROR_INVALID_PARAMETER);
}
//
// First put in memory addr
//
if (Adapter->MemoryAddress == 0)
{
goto SkipMemory;
}
//
// Now the amount of memory
//
if (Adapter->MemoryLength == 0)
{
goto SkipMemory;
}
//
// Copy in the title string
//
CopyLength = UnicodeStrLen(MemAddrString) + 1;
if (OutputLengthLeft < CopyLength)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
RtlMoveMemory((PVOID)pwchBuffer,
(PVOID)MemAddrString,
(CopyLength * sizeof(WCHAR)));
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
//
// Copy in the value
//
if (OutputLengthLeft < 8)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength = wsprintf(pwchBuffer,L"0x%x", Adapter->MemoryAddress);
if (CopyLength < 0)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength++; // Add in the \0
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
//
// Copy in the title string
//
CopyLength = UnicodeStrLen(MemLengthString) + 1;
if (OutputLengthLeft < CopyLength)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
RtlMoveMemory((PVOID)pwchBuffer,
(PVOID)MemLengthString,
(CopyLength * sizeof(WCHAR)));
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
//
// Copy in the value
//
if (OutputLengthLeft < 8)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength = wsprintf(pwchBuffer,L"0x%x", Adapter->MemoryLength);
if (CopyLength < 0)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength++; // Add in the \0
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
SkipMemory:
//
// Now the IoBaseAddress
//
//
// Copy in the title string
//
CopyLength = UnicodeStrLen(IoAddrString) + 1;
if (OutputLengthLeft < CopyLength)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
RtlMoveMemory((PVOID)pwchBuffer,
(PVOID)IoAddrString,
(CopyLength * sizeof(WCHAR)));
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
//
// Copy in the value
//
if (OutputLengthLeft < 6)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength = wsprintf(pwchBuffer,L"0x%x",Adapter->IoBaseAddress);
if (CopyLength < 0)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength++; // Add in the \0
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
//
// Copy in the title string
//
CopyLength = UnicodeStrLen(IoLengthString) + 1;
if (OutputLengthLeft < CopyLength)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
RtlMoveMemory((PVOID)pwchBuffer,
(PVOID)IoLengthString,
(CopyLength * sizeof(WCHAR)));
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
//
// Copy in the value
//
if (OutputLengthLeft < 5)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength = wsprintf(pwchBuffer,L"0x20");
if (CopyLength < 0)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength++; // Add in the \0
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
if (Adapter->Interrupt == 0)
{
goto SkipIrq;
}
//
// Copy in the title string (IRQ)
//
CopyLength = UnicodeStrLen(IrqString) + 1;
if (OutputLengthLeft < CopyLength)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
RtlMoveMemory((PVOID)pwchBuffer,
(PVOID)IrqString,
(CopyLength * sizeof(WCHAR)));
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
//
// Copy in the value
//
if (OutputLengthLeft < 3)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength = wsprintf(pwchBuffer,L"%d", Adapter->Interrupt);
if (CopyLength < 0)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength++; // Add in the \0
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
//
// Copy in the title string (IRQTYPE)
//
CopyLength = UnicodeStrLen(IrqTypeString) + 1;
if (OutputLengthLeft < CopyLength)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
RtlMoveMemory((PVOID)pwchBuffer,
(PVOID)IrqTypeString,
(CopyLength * sizeof(WCHAR)));
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
//
// Copy in the value
//
if (OutputLengthLeft < 2)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
//
// 0 == latched, all the cards here are ISA cards -- which are
// latched cards.
//
CopyLength = wsprintf(pwchBuffer,L"0");
if (CopyLength < 0)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength++; // Add in the \0
pwchBuffer = &(pwchBuffer[CopyLength]);
OutputLengthLeft -= CopyLength;
SkipIrq:
//
// Copy in final \0
//
if (OutputLengthLeft < 1)
{
return(ERROR_INSUFFICIENT_BUFFER);
}
CopyLength = (ULONG)pwchBuffer - StartPointer;
((PUCHAR)StartPointer)[CopyLength] = L'\0';
return(0);
}
extern
LONG
WdVerifyCfgHandler(
IN PVOID pvHandle,
IN WCHAR *pwchBuffer
)
/*++
Routine Description:
This routine verifys that a given parameter list is complete and
correct for the adapter associated with the handle.
Arguments:
pvHandle - The handle.
pwchBuffer - The parameter list.
Return Value:
0 if nothing went wrong, else the appropriate WINERROR.H value.
--*/
{
PWD_ADAPTER Adapter = (PWD_ADAPTER)(pvHandle);
WCHAR *Place;
BOOLEAN Found;
ULONG IoBaseAddress;
ULONG MemoryBaseAddress;
ULONG Interrupt;
NETDTECT_RESOURCE Resource;
if ((Adapter->InterfaceType != Isa) && (Adapter->InterfaceType != Eisa))
{
return(ERROR_INVALID_PARAMETER);
}
if (Adapter->CardType == 1000)
{
//
// Parse out the parameter.
//
//
// Get the IoBaseAddress
//
Place = FindParameterString(pwchBuffer, 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 MemoryBaseAddress
//
Place = FindParameterString(pwchBuffer, MemAddrString);
if (Place == NULL)
{
return(ERROR_INVALID_DATA);
}
Place += UnicodeStrLen(MemAddrString) + 1;
//
// Now parse the thing.
//
ScanForNumber(Place, &MemoryBaseAddress, &Found);
if (Found == FALSE)
{
return(ERROR_INVALID_DATA);
}
//
// Get the Interrupt
//
Place = FindParameterString(pwchBuffer, IrqString);
if (Place == NULL)
{
return(ERROR_INVALID_DATA);
}
Place += UnicodeStrLen(IrqString) + 1;
//
// Now parse the thing.
//
ScanForNumber(Place, &Interrupt, &Found);
if (Found == FALSE)
{
return(ERROR_INVALID_DATA);
}
}
else
{
//
// Error!
//
return(ERROR_INVALID_DATA);
}
if ((IoBaseAddress != Adapter->IoBaseAddress) ||
(Interrupt != Adapter->Interrupt) ||
(MemoryBaseAddress != Adapter->MemoryAddress))
{
UCHAR TempInterrupt;
ULONG TempMemoryAddress;
ULONG TempMemoryLength;
if (WdCardAt(
Adapter->InterfaceType,
Adapter->BusNumber,
IoBaseAddress,
&TempInterrupt,
&TempMemoryAddress,
&TempMemoryLength))
{
return(ERROR_INVALID_DATA);
}
if ((Interrupt != TempInterrupt) ||
(MemoryBaseAddress != TempMemoryAddress))
{
return(ERROR_INVALID_DATA);
}
Resource.InterfaceType = Adapter->InterfaceType;
Resource.BusNumber = Adapter->BusNumber;
Resource.Type = NETDTECT_PORT_RESOURCE;
Resource.Value = Adapter->IoBaseAddress;
Resource.Length = 0x20;
Resource.Flags = 0;
DetectFreeSpecificTemporaryResource(&Resource);
Resource.Value = IoBaseAddress;
DetectTemporaryClaimResource(&Resource);
Resource.Type = NETDTECT_IRQ_RESOURCE;
Resource.Value = Adapter->Interrupt;
Resource.Length = 0;
DetectFreeSpecificTemporaryResource(&Resource);
Resource.Value = Interrupt;
DetectTemporaryClaimResource(&Resource);
Resource.Type = NETDTECT_MEMORY_RESOURCE;
Resource.Value = Adapter->MemoryAddress;
Resource.Length = Adapter->MemoryLength;
DetectFreeSpecificTemporaryResource(&Resource);
Resource.Value = TempMemoryAddress;
Resource.Length = TempMemoryLength;
DetectTemporaryClaimResource(&Resource);
Adapter->IoBaseAddress = IoBaseAddress;
Adapter->Interrupt = TempInterrupt;
Adapter->MemoryAddress = TempMemoryAddress;
Adapter->MemoryLength = TempMemoryLength;
}
return(0);
}
extern
LONG WdQueryMaskHandler(
IN LONG lNetcardId,
OUT WCHAR *pwchBuffer,
IN LONG cwchBuffSize
)
/*++
Routine Description:
This routine returns the parameter list information for a specific
network card.
Arguments:
lNetcardId - The id of the desired netcard.
pwchBuffer - The buffer for storing the parameter information.
cwchBuffSize - Length of pwchBuffer 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 == lNetcardId) {
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 (cwchBuffSize < Length) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
memcpy((PVOID)pwchBuffer, Result, Length * sizeof(WCHAR));
return(0);
}
}
return(ERROR_INVALID_PARAMETER);
}
extern
LONG
WdParamRangeHandler(
IN LONG lNetcardId,
IN WCHAR *pwchParam,
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:
lNetcardId - The Id of the card desired.
pwchParam - 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 IoBaseAddress
//
if (memcmp(pwchParam, IoAddrString, (UnicodeStrLen(IoAddrString) + 1) * sizeof(WCHAR)) == 0) {
//
// Is there enough space
//
if (*plBuffSize < 16) {
*plBuffSize = 0;
return(ERROR_INSUFFICIENT_BUFFER);
}
plValues[0] = 0x300;
plValues[1] = 0x220;
plValues[2] = 0x240;
plValues[3] = 0x260;
plValues[4] = 0x280;
plValues[5] = 0x2A0;
plValues[6] = 0x2C0;
plValues[7] = 0x2E0;
plValues[8] = 0x200;
plValues[9] = 0x320;
plValues[10] = 0x340;
plValues[11] = 0x360;
plValues[12] = 0x380;
plValues[13] = 0x3A0;
plValues[14] = 0x3C0;
plValues[15] = 0x3E0;
*plBuffSize = 16;
return(0);
} else if (memcmp(pwchParam, IrqString, (UnicodeStrLen(IrqString) + 1) * sizeof(WCHAR)) == 0) {
//
// Is there enough space
//
if (*plBuffSize < 14) {
*plBuffSize = 0;
return(ERROR_INSUFFICIENT_BUFFER);
}
plValues[0] = 3;
plValues[1] = 2;
plValues[2] = 4;
plValues[3] = 5;
plValues[4] = 6;
plValues[5] = 7;
plValues[6] = 8;
plValues[7] = 9;
plValues[8] = 10;
plValues[9] = 11;
plValues[10] = 12;
plValues[11] = 13;
plValues[12] = 14;
plValues[13] = 15;
*plBuffSize = 14;
return(0);
} else if (memcmp(pwchParam, MemAddrString, (UnicodeStrLen(MemAddrString) + 1) * sizeof(WCHAR)) == 0) {
UCHAR i;
//
// Is there enough space
//
if (*plBuffSize < 128) {
*plBuffSize = 0;
return(ERROR_INSUFFICIENT_BUFFER);
}
plValues[0] = 0x00;
for (i=1; i < 128; i++) {
plValues[i] = plValues[i-1] + 0x2000;
}
//
// Setup default value
//
plValues[0] = 0xD0000;
for (i=1; i < 128; i++) {
if (plValues[i] == 0xD0000) {
plValues[i] = 0x0;
break;
}
}
*plBuffSize = 128;
return(0);
}
return(ERROR_INVALID_PARAMETER);
}
extern
LONG WdQueryParameterNameHandler(
IN WCHAR *pwchParam,
OUT WCHAR *pwchBuffer,
IN LONG cwchBufferSize
)
/*++
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:
pwchParam - The parameter to be queried.
pwchBuffer - The buffer to store the result into.
cwchBufferSize - The length of pwchBuffer in WCHARs.
Return Value:
ERROR_INVALID_PARAMETER -- To indicate that the MS supplied strings
should be used.
--*/
{
return(ERROR_INVALID_PARAMETER);
}
BOOLEAN
WdCardAt(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PUCHAR Interrupt,
OUT PULONG MemoryAddress,
OUT PULONG MemoryLength
)
/*++
Routine Description:
This routine checks for the instance of a SMC/Wd card at the Io
location given. This is done by checking for the card signature
in memory. The memory location is found by reading the ports.
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
Return Value:
TRUE if a card is found, else FALSE.
--*/
{
NTSTATUS NtStatus;
ULONG TempBoardId = 0;
UCHAR InterruptNumber = 0;
ULONG Bid;
UCHAR IdByte;
UCHAR RegValue, RegValue2;
UCHAR RevNumber = 0;
ULONG RamAddr = 0;
ULONG RamSize = 0;
UCHAR ReadBuffer[15];
HANDLE TrapHandle;
UCHAR InterruptList[6];
UCHAR ResultList[6];
ULONG Length, i;
NETDTECT_RESOURCE Resource;
static UCHAR TestBuffer[] = "Test String";
#if DBG
DbgPrint("WdCardAt entered: IoBaseAddress = 0x%.4X.\n", IoBaseAddress);
#endif
if (DetectCheckPortUsage(InterfaceType,
BusNumber,
IoBaseAddress,
0x20) != STATUS_SUCCESS)
{
return(FALSE);
}
if (!CheckFor8390(InterfaceType, BusNumber, IoBaseAddress + WD_690_CR))
{
#if DBG
DbgPrint("WdCardAt: This is not an 8390 CHIP.\n");
#endif
return(FALSE);
}
if (!CheckForWdAddress(InterfaceType, BusNumber, IoBaseAddress))
{
#if DBG
DbgPrint("WdCardAt: Check for address failed.\n");
#endif
return(FALSE);
}
//
// Get the board ID and check for an unsupported SMC card.
//
WdGetBoardId(InterfaceType, BusNumber, IoBaseAddress, &TempBoardId);
if (TempBoardId == 0)
{
return(FALSE);
}
Resource.InterfaceType = InterfaceType;
Resource.BusNumber = BusNumber;
Resource.Type = NETDTECT_PORT_RESOURCE;
Resource.Value = IoBaseAddress;
Resource.Length = 0x20;
Resource.Flags = 0;
DetectTemporaryClaimResource(&Resource);
//
// Get MemorySize
//
WdGetBoardId(InterfaceType,
BusNumber,
IoBaseAddress,
&Bid);
NtStatus = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_ID_BYTE,
&IdByte);
if (NtStatus != STATUS_SUCCESS)
{
return(FALSE);
}
RevNumber = IdByte & WD_BOARD_REV_MASK;
RevNumber >>= 1;
if (RevNumber >= 3)
{
CardGetEepromRamSize(
InterfaceType,
BusNumber,
IoBaseAddress,
Bid,
&RamSize);
}
else
{
CardGetRamSize(
InterfaceType,
BusNumber,
IoBaseAddress,
RevNumber,
Bid,
&RamSize);
}
//
// For card with no interface chip we have to find a suitable
// location for the memory address and then we can find the
// interrupt number.
//
if (!(Bid & INTERFACE_CHIP))
{
//
// Search for a memory location
//
for (RamAddr = 0xC0000; RamAddr < 0xE0000; RamAddr += 0x2000)
{
//
// Verify memory address
//
NtStatus = DetectCheckMemoryUsage(
InterfaceType,
BusNumber,
RamAddr,
0x2000);
if (NtStatus == STATUS_SUCCESS)
{
//
// Set up MSR
//
RegValue = (((UCHAR)(((PUSHORT)RamAddr) + 2) << 3) |
(UCHAR)(RamAddr >> 13));
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + CNFG_MSR_583,
(UCHAR)(RegValue | (UCHAR)0x40));
if (NtStatus != STATUS_SUCCESS)
{
continue;
}
//
// Write test string to memory
//
NtStatus = DetectWriteMappedMemory(
InterfaceType,
BusNumber,
RamAddr,
strlen(TestBuffer) + 1,
TestBuffer);
if (NtStatus != STATUS_SUCCESS)
{
continue;
}
//
// Read it back
//
NtStatus = DetectReadMappedMemory(
InterfaceType,
BusNumber,
RamAddr,
strlen(TestBuffer) + 1,
ReadBuffer);
if (NtStatus != STATUS_SUCCESS)
{
continue;
}
//
// Are they the same?
//
Length = strlen(TestBuffer) + 1;
if (memcmp(ReadBuffer, TestBuffer, Length) != 0)
{
continue;
}
break;
}
}
//
// Did we find a suitable spot?
//
if (RamAddr == 0xE0000)
{
//
// Abort (pro-choice?)
//
RamAddr = 0;
}
//
// Verify Interrupt
//
InterruptList[0] = 3;
InterruptList[1] = 2;
InterruptList[2] = 4;
InterruptList[3] = 5;
InterruptList[4] = 6;
InterruptList[5] = 7;
//
// Set the interrupt trap -- we are checking the interrupt number now
//
NtStatus = DetectSetInterruptTrap(
InterfaceType,
BusNumber,
&TrapHandle,
InterruptList,
6);
if (NtStatus == STATUS_SUCCESS)
{
UCHAR NetworkAddress[6];
//
// CardSetup
//
WdCardSetup(
InterfaceType,
BusNumber,
IoBaseAddress,
RamAddr,
Bid,
NetworkAddress);
//
// Create an interrupt
//
Send8390Packet(
InterfaceType,
BusNumber,
IoBaseAddress + 0x10,
RamAddr,
WdCardCopyDownBuffer,
NetworkAddress);
//
// Check which one went off
//
NtStatus = DetectQueryInterruptTrap(TrapHandle, ResultList, 6);
//
// Remove interrupt trap
//
NtStatus = DetectRemoveInterruptTrap(TrapHandle);
if (NtStatus != STATUS_SUCCESS)
{
return(FALSE);
}
for (i = 0; i < 6; i++)
{
if ((ResultList[i] == 1) || (ResultList[i] == 2))
{
if (InterruptNumber == 0)
{
InterruptNumber = InterruptList[i];
}
else
{
//
// Error! Two interrupts reported
//
InterruptNumber = 0;
break;
}
}
}
}
}
else
{
//
// Get58xRamBase();
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return(FALSE);
}
RegValue &= 0x3F;
if ((Bid & INTERFACE_CHIP_MASK) == INTERFACE_5X3_CHIP)
{
RegValue |= 0x40;
RamAddr = (ULONG)RegValue << 13;
}
else
{
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + CNFG_LAAR_584,
&RegValue2);
if (NtStatus != STATUS_SUCCESS)
{
return(FALSE);
}
RegValue2 &= CNFG_LAAR_MASK;
RegValue2 <<= 3;
RegValue2 |= ((RegValue & 0x38) >> 3);
RamAddr = ((ULONG)RegValue2 << 16) + (((ULONG)(RegValue & 0x7)) << 13);
}
//
// Get58xIrq();
//
RegValue = 0;
if ((Bid & INTERFACE_CHIP_MASK) != INTERFACE_5X3_CHIP)
{
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + CNFG_ICR_583,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return(FALSE);
}
RegValue &= CNFG_ICR_IR2_584;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + CNFG_IRR_583,
&RegValue2);
if (NtStatus != STATUS_SUCCESS)
{
return(FALSE);
}
RegValue2 &= CNFG_IRR_IRQS;
RegValue2 >>= 5;
if (RegValue2 == 0)
{
if (RegValue == 0)
{
InterruptNumber = 2;
}
else
{
InterruptNumber = 10;
}
}
else if (RegValue2 == 1)
{
if (RegValue == 0)
{
InterruptNumber = 3;
}
else
{
InterruptNumber = 11;
}
}
else if (RegValue2 == 2)
{
if (RegValue == 0)
{
if (Bid & ALTERNATE_IRQ_BIT)
{
InterruptNumber = 5;
}
else
{
InterruptNumber = 4;
}
}
else
{
InterruptNumber = 15;
}
}
else if (RegValue2 == 3)
{
if (RegValue == 0)
{
InterruptNumber = 7;
}
else
{
InterruptNumber = 4;
}
}
}
if ((RamAddr != 0) && (RamSize != 0))
{
//
// Acquire the memory resource...
//
*MemoryAddress = RamAddr;
*MemoryLength = RamSize;
Resource.Type = NETDTECT_MEMORY_RESOURCE;
Resource.Value = RamAddr;
Resource.Length = RamSize;
DetectTemporaryClaimResource(&Resource);
}
if (InterruptNumber != 0)
{
Resource.Type = NETDTECT_MEMORY_RESOURCE;
Resource.Value = InterruptNumber;
Resource.Length = 0;
DetectTemporaryClaimResource(&Resource);
*Interrupt = InterruptNumber;
}
return(TRUE);
}
VOID
WdGetBoardId(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PULONG BoardIdMask
)
/*++
Routine Description:
This routine will determine which WD80xx card is installed and set the
BoardIdMask to the feature bits.
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
BoardIdMask - The resulting board id.
Return:
none.
--*/
{
UCHAR IdByte;
UINT RevNumber;
NTSTATUS NtStatus;
//
// Init mask.
//
*BoardIdMask = 0;
//
// GetBoardRevNumber();
//
NtStatus = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_ID_BYTE,
&IdByte);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
RevNumber = (IdByte & WD_BOARD_REV_MASK) >> 1;
#if DBG
DbgPrint("WdGetBoardId: RevNumber = 0x%.8X.\n", RevNumber);
#endif
//
// Check rev is valid.
//
if (RevNumber == 0)
{
*BoardIdMask = 0;
return;
}
//
// GetBaseInfo();
//
CardGetBaseInfo(InterfaceType, BusNumber, IoBaseAddress, BoardIdMask);
//
// GetMediaType();
//
if (IdByte & WD_MEDIA_TYPE_BIT)
{
*BoardIdMask |= ETHERNET_MEDIA;
}
else
{
ULONG i;
ULONG Address;
UCHAR CheckSum = 0, TempChar;
Address = IoBaseAddress + 8;
for (i = 0; i < 8; i++, Address++)
{
NtStatus = DetectReadPortUchar(
InterfaceType,
BusNumber,
Address,
&TempChar);
if ( NtStatus != STATUS_SUCCESS )
{
*BoardIdMask = 0;
return;
}
CheckSum += TempChar;
}
//
// If this is TOKENRING then our driver won't work.
//
if ( CheckSum == 0xEE )
{
#if DBG
DbgPrint("WdGetBoardId: Media type is TOKENRING.\n");
#endif
*BoardIdMask = 0;
return;
}
if (RevNumber != 1)
{
*BoardIdMask |= TWISTED_PAIR_MEDIA;
}
else
{
*BoardIdMask |= STARLAN_MEDIA;
}
}
//
// if (RevNumber >= 2) then
// GetIdByteInfo();
//
if (RevNumber >= 2)
{
//
// For two cards this bit means use alternate IRQ
//
if (IdByte & WD_SOFT_CONFIG_BIT)
{
if (((*BoardIdMask & WD8003EB) == WD8003EB) ||
((*BoardIdMask & WD8003W) == WD8003W))
{
*BoardIdMask |= ALTERNATE_IRQ_BIT;
}
}
}
//
// if (RevNumber >= 3) then
// AddFeatureBits(EEPROM_OVERRIDE, 584_CHIP, EXTRA_EEPROM_OVERRIDE);
// GetEepromInfo(BaseAddr, Mca, RevNumber, EEPromBoardIdMask);
// AddFeatureBits(EEPromBoardIdMask);
// else
// GetRamSize();
//
if (RevNumber >= 3)
{
ULONG EEPromMask;
if ( !CheckFor585(InterfaceType, BusNumber, IoBaseAddress) )
{
*BoardIdMask &= (WD_584_ID_EEPROM_OVERRIDE | WD_584_EXTRA_EEPROM_OVERRIDE);
*BoardIdMask |= INTERFACE_584_CHIP;
}
else
{
//
// The adapter is a 585, 790, or a 795. None of the
// adapters work with our driver.
//
#if DBG
DbgPrint("WdGetBoardId: This is a 585, 790, or 795.\n");
#endif
*BoardIdMask = 0;
return;
}
CardGetEepromInfo(InterfaceType, BusNumber, IoBaseAddress, &EEPromMask);
*BoardIdMask |= EEPromMask;
}
//
// if (RevNumber >= 4) then
// AddFeatureBits(ADVANCED_FEATURES);
//
if (RevNumber >= 4)
{
*BoardIdMask |= ADVANCED_FEATURES;
}
}
VOID
CardGetBaseInfo(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PULONG BoardIdMask
)
/*++
Routine Description:
This routine will get the following information about the card:
Is there an interface chip,
Are some registers aliased,
Is the board 16 bit,
Is the board in a 16 bit slot.
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
BoardIdMask - The resulting board id.
Return:
none.
--*/
{
UCHAR RegValue;
UCHAR SaveValue;
UCHAR TmpValue;
ULONG Register;
NTSTATUS NtStatus;
BOOLEAN ExistsAnInterfaceChip = FALSE;
//
// Does there exist and interface chip?
//
//
// Get original value
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_7,
&SaveValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Put something into chip (if it exists).
//
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_7,
0x35);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Swamp bus with something else.
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Read from chip
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_7,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Was the value saved on the chip??
//
if (RegValue == 0x35)
{
//
// Try it again just for kicks.
//
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_7,
0x3A);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Swamp bus with something else.
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Read from chip
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_7,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Was the value saved on the chip??
//
if (RegValue == 0x3A)
{
ExistsAnInterfaceChip = TRUE;
}
}
//
// Write back original value.
//
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_7,
SaveValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
//
// if (BoardUsesAliasing(BaseAddr)) then
//
// return;
//
for (Register = WD_REG_1; Register < WD_REG_6; Register++)
{
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + Register,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + Register + WD_LAN_OFFSET,
&SaveValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
if (RegValue != SaveValue)
{
break;
}
}
if (Register == WD_REG_6)
{
//
// Check register 7
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + Register,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + Register + WD_LAN_OFFSET,
&SaveValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
}
if (RegValue == SaveValue)
{
return;
}
//
//
// if (ExistsAnInterfaceChip) then
//
// AddFeatureBits(INTERFACE_CHIP);
//
// else
//
// if (BoardIs16Bit(BaseAddr)) then
//
// AddFeatureBits(BOARD_16BIT);
//
// if (InA16BitSlot(BaseAddr)) then
//
// AddFeatureBits(SLOT_16BIT);
//
//
//
//
if (ExistsAnInterfaceChip)
{
*BoardIdMask |= INTERFACE_CHIP;
}
else
{
//
// Save original value.
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&SaveValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Now flip 16 bit value and write it back.
//
RegValue = (SaveValue & (UCHAR)WD_SIXTEEN_BIT);
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
(UCHAR)(SaveValue ^ WD_SIXTEEN_BIT));
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Swamp bus with something else.
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress,
&TmpValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// Read back value.
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&TmpValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
if ((UCHAR)(TmpValue & (UCHAR)WD_SIXTEEN_BIT) == (UCHAR)RegValue)
{
//
// If the flip stayed, we have a 16 bit chip.
//
//
// Put back orginal value.
//
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
(UCHAR)(SaveValue & 0xFE));
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
*BoardIdMask |= BOARD_16BIT;
}
else
{
//
// Put back original value.
//
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
SaveValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
}
}
}
VOID
CardGetEepromInfo(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
OUT PULONG BoardIdMask
)
/*++
Routine Description:
This routine will get the following information about the card:
Bus type,
Bus size,
Media type,
IRQ - primary or alternate,
RAM size
In this case All other information in the top 16 bits of the BoardIdMask
are zeroed and replaced with these values since EEProm values are
overriding old values.
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
BoardIdMask - Returns the feature mask of the installed board.
Return:
none.
--*/
{
UCHAR RegValue;
NTSTATUS NtStatus;
//
// *BoardIdMask = 0;
//
*BoardIdMask = 0;
//
// RecallEEPromData();
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
RegValue &= WD_584_ICR_MASK;
RegValue |= WD_584_OTHER_BIT;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_3,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
RegValue &= WD_584_EAR_MASK;
RegValue |= WD_584_ENGR_PAGE;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_3,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
RegValue &= WD_584_ICR_MASK;
RegValue |= (WD_584_RLA | WD_584_OTHER_BIT);
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
while (RegValue & WD_584_RECALL_DONE)
{
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_584_EEPROM_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
//
// if (RamPaging) then
//
// AddFeatureBits(PAGED_RAM);
//
if ((RegValue & WD_584_EEPROM_PAGING_MASK) == WD_584_EEPROM_RAM_PAGING)
{
*BoardIdMask |= PAGED_RAM;
}
//
// if (RomPaging) then
//
// AddFeatureBits(PAGED_ROM);
//
if ((RegValue & WD_584_EEPROM_PAGING_MASK) == WD_584_EEPROM_ROM_PAGING)
{
*BoardIdMask |= PAGED_ROM;
}
//
// if (16BitBus) then
//
// AddFeatureBits(BOARD_16BIT);
//
// if (16BitSlot) then
//
// AddFeatureBits(SLOT_16BIT);
//
if ((RegValue & WD_584_EEPROM_BUS_SIZE_MASK) == WD_584_EEPROM_BUS_SIZE_16BIT)
{
*BoardIdMask |= BOARD_16BIT;
}
//
// if (StarLanMedia) then
//
// AddFeatureBits(STARLAN_MEDIA);
//
// else
//
// if (TpMedia) then
//
// AddFeatureBits(TWISTED_PAIR_MEDIA);
//
// else
//
// if (EwMedia) then
//
// AddFeatureBits(EW_MEDIA);
//
// else
//
// AddFeatureBits(ETHERNET_MEDIA);
//
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_584_EEPROM_0,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
if ((RegValue & WD_584_EEPROM_MEDIA_MASK) == WD_584_STARLAN_TYPE)
{
*BoardIdMask |= STARLAN_MEDIA;
}
else if ((RegValue & WD_584_EEPROM_MEDIA_MASK) == WD_584_TP_TYPE)
{
*BoardIdMask |= TWISTED_PAIR_MEDIA;
}
else if ((RegValue & WD_584_EEPROM_MEDIA_MASK) == WD_584_EW_TYPE)
{
*BoardIdMask |= EW_MEDIA;
}
else
{
*BoardIdMask |= ETHERNET_MEDIA;
}
//
// if (AlternateIrq) then AddFeatureBits(ALTERNATE_IRQ_BIT);
//
if ((RegValue & WD_584_EEPROM_IRQ_MASK) != WD_584_PRIMARY_IRQ)
{
*BoardIdMask |= ALTERNATE_IRQ_BIT;
}
//
// RecallLanAddressFromEEProm(NdisAdapterHandle, BaseAddr);
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
RegValue &= WD_584_ICR_MASK;
RegValue |= WD_584_OTHER_BIT;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_3,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
RegValue &= WD_584_EAR_MASK;
RegValue |= WD_584_EA6;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_3,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
RegValue &= WD_584_ICR_MASK;
RegValue |= WD_584_RLA;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
while (RegValue & WD_584_RECALL_DONE)
{
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
*BoardIdMask = 0;
return;
}
}
}
BOOLEAN
CheckForWdAddress(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress
)
/*++
Routine Description:
This routine will determine if the network address of the card is
(indeed) the SMC/WD prefix.
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
Return:
TRUE if it is an SMC/WD identification, else FALSE.
--*/
{
UCHAR Value;
NTSTATUS NtStatus;
NtStatus = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_LAN_0,
&Value);
if (NtStatus != STATUS_SUCCESS)
{
return(FALSE);
}
if (Value != 0x00)
{
return(FALSE);
}
NtStatus = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_LAN_1,
&Value);
if (NtStatus != STATUS_SUCCESS)
{
return(FALSE);
}
if (Value != 0x00)
{
return(FALSE);
}
NtStatus = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_LAN_2,
&Value);
if (NtStatus != STATUS_SUCCESS)
{
return(FALSE);
}
if (Value != 0xC0)
{
return(FALSE);
}
return(TRUE);
}
VOID
CardGetEepromRamSize(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
IN ULONG Bid,
OUT PULONG RamSize
)
/*++
Routine Description:
This routine will get the following information about the card:
RAM size
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
Bid - Board Id as returned by GetBoardId
RamSize - Amount of shared ram.
Return:
none.
--*/
{
UCHAR RegValue;
NTSTATUS NtStatus;
//
// InitValue
//
*RamSize = 0;
//
// RecallEEPromData();
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
RegValue &= WD_584_ICR_MASK;
RegValue |= WD_584_OTHER_BIT;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_3,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
RegValue &= WD_584_EAR_MASK;
RegValue |= WD_584_ENGR_PAGE;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_3,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
RegValue &= WD_584_ICR_MASK;
RegValue |= (WD_584_RLA | WD_584_OTHER_BIT);
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
while (RegValue & WD_584_RECALL_DONE)
{
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_584_EEPROM_0,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
//
// Get RAM Info
//
if ((RegValue & WD_584_EEPROM_RAM_SIZE_MASK) == WD_584_EEPROM_RAM_SIZE_8K)
{
*RamSize = 0x2000;
}
else
{
if ((RegValue & WD_584_EEPROM_RAM_SIZE_MASK) == WD_584_EEPROM_RAM_SIZE_16K)
{
if (!(Bid & BOARD_16BIT))
{
*RamSize = 0x4000;
}
else if (!(Bid & SLOT_16BIT))
{
*RamSize = 0x2000;
}
else
{
*RamSize = 0x4000;
}
}
else
{
if ((RegValue & WD_584_EEPROM_RAM_SIZE_MASK) ==
WD_584_EEPROM_RAM_SIZE_32K)
{
*RamSize = 0x8000;
}
else
{
if ((RegValue & WD_584_EEPROM_RAM_SIZE_MASK) ==
WD_584_EEPROM_RAM_SIZE_64K)
{
if (!(Bid & BOARD_16BIT))
{
*RamSize = 0x10000;
}
else
{
if (!(Bid & SLOT_16BIT))
{
*RamSize = 0x8000;
}
else
{
*RamSize = 0x10000;
}
}
}
else
{
*RamSize = 0x0;
}
}
}
}
//
// Restore EEPROM to initial state
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
RegValue &= WD_584_ICR_MASK;
RegValue |= WD_584_OTHER_BIT;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_3,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
RegValue &= WD_584_EAR_MASK;
RegValue |= WD_584_EA6;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_3,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
RegValue &= WD_584_ICR_MASK;
RegValue |= WD_584_RLA;
NtStatus = DetectWritePortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
while (RegValue & WD_584_RECALL_DONE)
{
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
}
}
VOID
CardGetRamSize(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
IN ULONG RevNumber,
IN ULONG Bid,
OUT PULONG RamSize
)
/*++
Routine Description:
This routine will get the following information about the card:
Ram size.
The card must have a RevNumber < 3 for this routine to work.
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
RevNumber - The revision number of the board.
Bid - The board id of the board.
RamSize - Amount of shared ram.
Return:
none.
--*/
{
UCHAR RegValue;
NTSTATUS NtStatus;
BOOLEAN Slot16Bit = TRUE;
*RamSize = 0;
//
// Check for a 16 bit slot...
//
if (Bid & BOARD_16BIT)
{
//
// Now check if it is a 16 bit slot....
//
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
if (!(RegValue & WD_SIXTEEN_BIT))
{
Slot16Bit = FALSE;
}
}
else
{
Slot16Bit = FALSE;
}
//
// if (RevNumber < 2) then
//
// if (16BitBus) then
//
// if (16BitSlot) then
//
// AddFeatureBits(RAM_SIZE_16K);
//
// else
//
// AddFeatureBits(RAM_SIZE_8K);
//
// else
//
// if (!HaveInterfaceChip) then
//
// AddFeatureBits(RAM_SIZE_UNKNOWN);
//
// else
//
// ReadFromChipRamSize();
// else
//
// switch (CardType)
//
// case WD8003E:
// case WD8003S:
// case WD8003WT:
// case WD8003W:
// case WD8003EB:
//
// if (CardSaysLargeRam) then
//
// AddFeatureBits(RAM_SIZE_32K);
//
// else
//
// AddFeatureBits(RAM_SIZE_8K);
//
// break;
//
// case MICROCHANNEL:
//
// if (CardSaysLargeRam) then
//
// AddFeatureBits(RAM_SIZE_64K);
//
// else
//
// AddFeatureBits(RAM_SIZE_16K);
//
// break;
//
// case WD8013EBT:
//
// if (16BitSlot) then
//
//
// if (CardSaysLargeRam) then
//
// AddFeatureBits(RAM_SIZE_64K);
//
// else
//
// AddFeatureBits(RAM_SIZE_16K);
//
// else
//
// if (CardSaysLargeRam) then
//
// AddFeatureBits(RAM_SIZE_32K);
//
// else
//
// AddFeatureBits(RAM_SIZE_8K);
//
// break;
//
// default:
//
// AddFeatureBits(RAM_SIZE_UNKNOWN);
//
if (RevNumber < 2)
{
if (Bid & BOARD_16BIT)
{
if (Slot16Bit)
{
*RamSize = 0x4000;
}
else
{
*RamSize = 0x2000;
}
}
else
{
if (!(Bid & INTERFACE_CHIP))
{
*RamSize = 0x2000;
}
else
{
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_1,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
if (RegValue & WD_MSB_583_BIT)
{
*RamSize = 0x8000;
}
else
{
*RamSize = 0x2000;
}
}
}
}
else
{
NtStatus = DetectReadPortUchar(InterfaceType,
BusNumber,
IoBaseAddress + WD_ID_BYTE,
&RegValue);
if (NtStatus != STATUS_SUCCESS)
{
return;
}
switch (Bid & STATIC_ID_MASK)
{
case WD8003E:
case WD8003S:
case WD8003WT:
case WD8003W:
case WD8003EB:
if (RegValue & WD_RAM_SIZE_BIT)
{
*RamSize = 0x8000;
}
else
{
*RamSize = 0x2000;
}
break;
case WD8013EBT:
if (Bid & SLOT_16BIT)
{
if (RegValue & WD_RAM_SIZE_BIT)
{
*RamSize = 0x10000;
}
else
{
*RamSize = 0x4000;
}
}
else
{
if (RegValue & WD_RAM_SIZE_BIT)
{
*RamSize = 0x8000;
}
else
{
*RamSize = 0x2000;
}
}
break;
default:
*RamSize = 0x2000;
}
}
}
VOID
WdCardCopyDownBuffer(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
IN ULONG MemoryBaseAddress,
IN PUCHAR Buffer,
IN ULONG Length
)
/*++
Routine Description:
This routine will copy down a buffer to the address given on the card.
Arguments:
InterfaceType - The type of bus, ISA or EISA.
BusNumber - The bus number in the system.
IoBaseAddress - The IO port address of the card.
MemoryBaseAddress - The destination of the buffer.
Buffer - The buffer to copy
Length - Number of bytes to copy to the card.
Return:
none.
--*/
{
DetectWriteMappedMemory(
InterfaceType,
BusNumber,
MemoryBaseAddress,
Length,
Buffer);
}
VOID
WdCardSetup(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN ULONG IoBaseAddress,
IN ULONG MemoryBaseAddress,
IN ULONG Bid,
OUT UCHAR *NetworkAddress
)
/*++
Routine Description:
This routine initializes the chip.
Arguments:
InterfaceType - Isa or Eisa.
BusNumber - The bus number of the bus in the system.
IoBaseAddress - The IoBaseAddress to check.
MemoryBaseAddress - The MemoryBaseAddress (if applicable) to copy a p
packet to for transmission.
Bid - The board id.
NetworkAddress - The network address of the machine (returned).
Return Value:
None.
--*/
{
ULONG i;
UCHAR SaveValue;
UCHAR RegValue;
NTSTATUS NtStatus;
LARGE_INTEGER Delay;
//
// Reset IC
//
NtStatus = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + CNFG_MSR_583,
&SaveValue);
RegValue = SaveValue | (UCHAR)0x80;
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + CNFG_MSR_583,
RegValue);
//
// Wait for reset to complete. (2 ms)
//
Delay.LowPart = 2000;
Delay.HighPart = 0;
NtDelayExecution(FALSE, &Delay);
//
// Put back original value
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + CNFG_MSR_583,
(UCHAR)(SaveValue & (UCHAR)(~0x80)));
//
// Enable Ram
//
RegValue = (((UCHAR)(((PUSHORT)MemoryBaseAddress) + 2) << 3) |
(UCHAR)(MemoryBaseAddress >> 13));
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + CNFG_MSR_583,
(UCHAR)(RegValue | (UCHAR)0x40));
//
// Load LAN Address
//
for (i = 0; i < 6; i++)
{
//
// Read from IC
//
NtStatus = DetectReadPortUchar(InterfaceType, BusNumber,
IoBaseAddress + 0x8 + i,
&(NetworkAddress[i]));
}
//
// Init NIC
//
//
// Maintain reset
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x10,
0x21);
//
// Reset Remote_byte_count registers
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x1A,
0);
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x1B,
0);
//
// Make sure reset is bit is set
//
NtStatus = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x17,
&RegValue);
if (!(RegValue & 0x80))
{
//
// Wait 1600 ms
//
Delay.LowPart = 1600000;
Delay.HighPart = 0;
NtDelayExecution(FALSE, &Delay);
}
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x1E,
0x40);
//
// Set Receive Config
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x1C,
0x0);
//
// loopback operation while setting up rings.
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x1D,
0x04);
//
// Write first Receive ring buffer number
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x11,
0x1);
//
// Write last Receive ring buffer number
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x12,
0x3);
//
// Write buffer number where the card cannot write beyond.
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x13,
0x2);
//
// Clear all interrupt status bits
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x17,
0xFF);
//
// Set Interrupt Mask
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x1F,
0xFF);
//
// Maintain reset and select page 1
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x10,
0x61);
//
// Write physical address
//
for (i = 0; i < 6; i++)
{
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x11 + i,
NetworkAddress[i]);
}
//
// Load next pointer.
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x17,
0x2);
//
// Normal operation
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x1D,
0x00);
//
// Start the chip
//
NtStatus = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x10,
0x22);
}
BOOLEAN
CheckFor585(
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
ULONG IoBaseAddress
)
/*++
Routine Description:
This routine will check for presence of 585/790/795 interface.
Arguments:
BaseAddr - The base address for I/O to the board.
Return:
FALSE, if not 585 nor 790 nor 795.
TRUE, if 585/790/795.
--*/
{
UCHAR RegValue, RegValue1, RegValue2;
UCHAR SavValue;
NTSTATUS Status;
Status = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_4,
&RegValue);
if ( Status != STATUS_SUCCESS )
{
return FALSE;
}
SavValue = RegValue;
RegValue &= 0xC3;
RegValue |= 0x80;
Status = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_4,
RegValue);
if ( Status != STATUS_SUCCESS )
{
return FALSE;
}
RegValue1 = RegValue2 = 0;
for (RegValue = 0; RegValue < 6; RegValue++)
{
Status = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x08 + RegValue,
&RegValue1);
if (Status != STATUS_SUCCESS)
{
return FALSE;
}
Status = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_4,
&RegValue2);
if ( Status != STATUS_SUCCESS )
{
return FALSE;
}
RegValue2 &= 0xC3;
RegValue2 ^= 0x80;
Status = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_4,
RegValue2);
if ( Status != STATUS_SUCCESS )
{
return FALSE;
}
Status = DetectReadPortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + 0x08 + RegValue,
&RegValue2);
if ( Status != STATUS_SUCCESS )
{
return FALSE;
}
if (RegValue1 != RegValue2)
{
break;
}
}
if (RegValue == 6)
{
Status = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_4,
SavValue);
return FALSE;
}
Status = DetectWritePortUchar(
InterfaceType,
BusNumber,
IoBaseAddress + WD_REG_4,
(UCHAR)(SavValue & 0xC3));
if ( Status != STATUS_SUCCESS )
{
return FALSE;
}
return TRUE;
}