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.
 
 
 
 
 
 

3393 lines
93 KiB

/***************************************************************************
*
* MADGE.C
*
* FastMAC Plus based NDIS3 miniport driver entry, initialisation and
* closedown module.
*
* Copyright (c) Madge Networks Ltd 1994
*
* COMPANY CONFIDENTIAL
*
* Created: PBA 21/06/1994
*
****************************************************************************/
#include <ndis.h>
#include "ftk_defs.h"
#include "ftk_extr.h"
#include "ftk_intr.h"
#include "mdgmport.upd"
#include "ndismod.h"
/*---------------------------------------------------------------------------
|
| Identification string for MVER.
|
---------------------------------------------------------------------------*/
char MVerString[] = MVER_STRING;
/*---------------------------------------------------------------------------
|
| Option strings for registry queries.
|
| There is a lot of fuss here to get the various strings defined in the
| correct way - those that are optional need to be defined in the parm.
| table as string constants, while those that are passed directly to the
| registry query functions need to be explicitly defined outside any
| structures.
|
|--------------------------------------------------------------------------*/
#define HIDDEN_OFFS 0x80
#define EmptyString NDIS_STRING_CONST("")
//
// These are the NT versions of the option strings.
//
#define IOAddrString NDIS_STRING_CONST("IoLocation")
#define IOBaseString NDIS_STRING_CONST("IoBaseAddress")
#define InterruptNumString NDIS_STRING_CONST("InterruptNumber")
#define DMAChanString NDIS_STRING_CONST("DmaChannel")
#define TxSlotNumString NDIS_STRING_CONST("TxSlots")
#define RxSlotNumString NDIS_STRING_CONST("RxSlots")
#define MaxFrameSizeString NDIS_STRING_CONST("MaxFrameSize")
#define CardBuffSizeString NDIS_STRING_CONST("CardBufferSize")
#define AlternateIoString NDIS_STRING_CONST("Alternate")
#define TestAndXIDString NDIS_STRING_CONST("TestAndXIDEnabled")
#define RxTxSlotsString NDIS_STRING_CONST("RxTxSlots")
#define ForceOpenString NDIS_STRING_CONST("ForceOpen")
#define Force4String NDIS_STRING_CONST("Force4")
#define Force16String NDIS_STRING_CONST("Force16")
#define SlotNumString NDIS_STRING_CONST("SlotNumber")
#define NoPciMmioString NDIS_STRING_CONST("NoMmio")
#define RingSpeedString NDIS_STRING_CONST("RingSpeed")
#define AdapterTypeString NDIS_STRING_CONST("AdapterType")
#define MmioAddrString NDIS_STRING_CONST("MemBase")
#define PlatformTypeString NDIS_STRING_CONST("PlatformType")
#define TransferTypeString NDIS_STRING_CONST("TransferType")
WCHAR PromModeString[] =
{ L'P' + HIDDEN_OFFS, L'r' + HIDDEN_OFFS, L'o' + HIDDEN_OFFS,
L'm' + HIDDEN_OFFS, L'i' + HIDDEN_OFFS, L's' + HIDDEN_OFFS,
L'c' + HIDDEN_OFFS, L'u' + HIDDEN_OFFS, L'o' + HIDDEN_OFFS,
L'u' + HIDDEN_OFFS, L's' + HIDDEN_OFFS, L'M' + HIDDEN_OFFS,
L'o' + HIDDEN_OFFS, L'd' + HIDDEN_OFFS, L'e' + HIDDEN_OFFS,
L'X' + HIDDEN_OFFS, 000 };
#define PromiscuousString { sizeof(PromModeString) - 2, \
sizeof(PromModeString), \
PromModeString }
//
// These strings are passed direct to NdisReadConfiguration.
//
STATIC NDIS_STRING BusTypeString = NDIS_STRING_CONST("BusType");
STATIC NDIS_STRING BusNumberString = NDIS_STRING_CONST("BusNumber");
STATIC NDIS_STRING IOAddressString = IOAddrString;
STATIC NDIS_STRING IOBaseAddrString = IOBaseString;
STATIC NDIS_STRING InterruptNumberString = InterruptNumString;
STATIC NDIS_STRING DMAChannelString = DMAChanString;
STATIC NDIS_STRING SlotNumberString = SlotNumString;
STATIC NDIS_STRING NoMmioString = NoPciMmioString;
STATIC NDIS_STRING AdapterString = AdapterTypeString;
STATIC NDIS_STRING MmioAddressString = MmioAddrString;
STATIC NDIS_STRING PlatformString = PlatformTypeString;
STATIC NDIS_STRING TransferModeString = TransferTypeString;
STATIC NDIS_STRING NullString = EmptyString;
/*---------------------------------------------------------------------------
|
| Optional parameter structure.
|
|--------------------------------------------------------------------------*/
//
// The Keyword parameters here use the #define's above, so the compiler is
// kept happy about string initialisers.
//
STATIC struct
{
MADGE_PARM_DEFINITION TxSlots;
MADGE_PARM_DEFINITION RxSlots;
MADGE_PARM_DEFINITION MaxFrameSize;
MADGE_PARM_DEFINITION CardBufferSize;
MADGE_PARM_DEFINITION PromiscuousMode;
MADGE_PARM_DEFINITION AlternateIo;
MADGE_PARM_DEFINITION TestAndXIDEnabled;
MADGE_PARM_DEFINITION RxTxSlots;
MADGE_PARM_DEFINITION ForceOpen;
MADGE_PARM_DEFINITION Force4;
MADGE_PARM_DEFINITION Force16;
MADGE_PARM_DEFINITION RingSpeed;
MADGE_PARM_DEFINITION NullParm;
}
MadgeParmTable =
{
{TxSlotNumString, 2, 32, {NdisParameterInteger, 0}},
{RxSlotNumString, 2, 32, {NdisParameterInteger, 0}},
{MaxFrameSizeString, 1024, 17839, {NdisParameterInteger, 4096}},
{CardBuffSizeString, 0, 0xFFFF, {NdisParameterInteger, 0}},
{PromiscuousString, 0, 1, {NdisParameterInteger, 0}},
{AlternateIoString, 0, 1, {NdisParameterInteger, 0}},
{TestAndXIDString, 0, 1, {NdisParameterInteger, 0}},
{RxTxSlotsString, 0, 5, {NdisParameterInteger, 2}},
{ForceOpenString, 0, 1, {NdisParameterInteger, 0}},
{Force4String, 0, 1, {NdisParameterInteger, 0}},
{Force16String, 0, 1, {NdisParameterInteger, 0}},
{RingSpeedString, 0, 2, {NdisParameterInteger, 0}},
{EmptyString}
};
/*---------------------------------------------------------------------------
|
| Name of the FastMAC Plus image file.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STRING FmpImageFileName = MADGE_FMP_NAME;
/*---------------------------------------------------------------------------
|
| List of PCI adapters in use.
|
---------------------------------------------------------------------------*/
STATIC struct
{
UINT BusNumber;
UINT SlotNumber;
}
PciSlotsUsedList[MAX_NUMBER_OF_ADAPTERS];
STATIC int
PciSlotsUsedCount = 0;
/****************************************************************************
*
* NDIS3 level adapter structure pointer table.
*
****************************************************************************/
/*---------------------------------------------------------------------------
|
| Function - MadgeReadRegistryForMC
|
| Parameters - wrapperConfigHandle -> Wrapper context handle.
| registryConfigHandle -> Already open registry query handle.
| ndisAdap -> Pointer to an NDIS3 level adapter
| structure.
|
| Purpose - Read configuration information for MC adapters out of
Ý the registry.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeReadRegistryForMC(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap
);
#pragma FTK_INIT_FUNCTION(MadgeReadRegistryForMC)
STATIC NDIS_STATUS
MadgeReadRegistryForMC(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap
)
{
static WORD mcaIrqMap[4] = { 0, 3, 9, 10};
static WORD mcaIoMap[8] = {0x0a20, 0x1a20, 0x2a20, 0x3a20,
0x0e20, 0x1e20, 0x2e20, 0x3e20};
NDIS_STATUS status;
PNDIS_CONFIGURATION_PARAMETER configParam;
UINT slotNumber;
NDIS_MCA_POS_DATA mcaData;
BYTE iOSelect;
//
// Note the information that is always true for MC adapters.
//
ndisAdap->NTCardBusType = NdisInterfaceMca;
ndisAdap->FTKCardBusType = ADAPTER_CARD_MC_BUS_TYPE;
ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
//
// MicroChannel is easy - the POS registers contain all the info
// we need, so read those and save the information.
//
NdisReadMcaPosInformation(
&status,
wrapperConfigHandle,
&slotNumber,
&mcaData
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
2,
readRegistry,
MADGE_ERRMSG_NO_MCA_POS
);
return status;
}
//
// Decode the Interrupt Number. Note: the FTK will throw
// IRQ 0 out as invalid.
//
ndisAdap->UsedInISR.InterruptNumber = mcaIrqMap[mcaData.PosData1 >> 6];
//
// NB: Arbitration Level 15 => PIO, which we do not allow -
// the FTK will throw this out as an invalid DMA channel.
// NB: We call it DmaChannel to be compatible with ISA cards.
//
ndisAdap->DmaChannel = (mcaData.PosData1 >> 1) & 0x0F;
//
// Build the IO Location select value from several sources.
//
iOSelect = (mcaData.PosData1 >> 5) & 0x01;
iOSelect |= (mcaData.PosData4 >> 4) & 0x02;
iOSelect |= (mcaData.PosData3 >> 0) & 0x04;
//
// NB: IO locations 0x2e20 and 0x3e20 are only valid for
// MC32 cards, but the .ADF file will have prevented them
// being set for MC16s.
//
ndisAdap->IoLocation1 = mcaIoMap[iOSelect];
ndisAdap->UsedInISR.InterruptMode = NdisInterruptLevelSensitive;
ndisAdap->UsedInISR.InterruptShared = TRUE;
ndisAdap->IORange1 = MC_IO_RANGE;
return NDIS_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------
|
| Function - MadgeReadRegistryForEISA
|
| Parameters - wrapperConfigHandle -> Wrapper context handle.
| registryConfigHandle -> Already open registry query handle.
| ndisAdap -> Pointer to an NDIS3 level adapter
| structure.
|
| Purpose - Read configuration information for an EISA adapter
Ý out of the registry.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeReadRegistryForEISA(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap
);
#pragma FTK_INIT_FUNCTION(MadgeReadRegistryForEISA)
STATIC NDIS_STATUS
MadgeReadRegistryForEISA(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap
)
{
NDIS_STATUS status;
PNDIS_CONFIGURATION_PARAMETER configParam;
UINT slotNumber;
NDIS_EISA_FUNCTION_INFORMATION eisaData;
//
// For Eisa bus systems, we could have an Isa card or an Eisa
// card - try to read the Eisa information, and if that fails
// MadgeReadRegistry will assume it is an Isa card instead.
//
NdisReadEisaSlotInformation(
&status,
wrapperConfigHandle,
&slotNumber,
&eisaData
);
if (status != NDIS_STATUS_SUCCESS)
{
return status;
}
//
// Note the information that is always true for EISA
// adapters.
//
ndisAdap->NTCardBusType = NdisInterfaceEisa;
ndisAdap->FTKCardBusType = ADAPTER_CARD_EISA_BUS_TYPE;
ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
//
// Got EISA configuration data - decode the relevant bits.
//
ndisAdap->IoLocation1 = slotNumber << 12;
//
// Get the Interrupt number from the NVRAM data - we know it
// is going to be the first Irq element in the Irq array
// because the card only uses one interrupt.
//
ndisAdap->UsedInISR.InterruptNumber =
eisaData.EisaIrq[0].ConfigurationByte.Interrupt;
ndisAdap->UsedInISR.InterruptMode = (NDIS_INTERRUPT_MODE)
(eisaData.EisaIrq[0].ConfigurationByte.LevelTriggered
? NdisInterruptLevelSensitive
: NdisInterruptLatched);
ndisAdap->UsedInISR.InterruptShared = (BOOLEAN)
eisaData.EisaIrq[0].ConfigurationByte.Shared;
//
// For EISA cards we don't care what the DMA setting is. So
// we leave it set to 0 forget about it.
//
ndisAdap->IORange1 = EISA_IO_RANGE;
ndisAdap->IoLocation2 = ndisAdap->IoLocation1 + EISA_IO_RANGE2_BASE;
ndisAdap->IORange2 = EISA_IO_RANGE2;
return NDIS_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------
|
| Function - MadgeReadRegistryForISA
|
| Parameters - wrapperConfigHandle -> Wrapper context handle.
| registryConfigHandle -> Already open registry query handle.
| ndisAdap -> Pointer to an NDIS3 level adapter
| structure.
Ý adapterType -> Adapter type.
|
| Purpose - Read configuration information for ISA adapters out
Ý of the registry.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeReadRegistryForISA(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap,
ULONG adapterType
);
#pragma FTK_INIT_FUNCTION(MadgeReadRegistryForISA)
STATIC NDIS_STATUS
MadgeReadRegistryForISA(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap,
ULONG adapterType
)
{
NDIS_STATUS status;
PNDIS_CONFIGURATION_PARAMETER configParam;
//
// Note the information that is always TRUE for ISA adapters.
//
ndisAdap->NTCardBusType = NdisInterfaceIsa;
//
// Do some adapter type specific setup. If we don't
// know what sort of adapter it is we'll assume it's
// an ATULA adapter so we are backwards compatible.
//
switch (adapterType)
{
case MADGE_ADAPTER_UNKNOWN:
case MADGE_ADAPTER_ATULA:
ndisAdap->FTKCardBusType = ADAPTER_CARD_ATULA_BUS_TYPE;
ndisAdap->IORange1 = ATULA_IO_RANGE;
ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
break;
case MADGE_ADAPTER_SMART16:
ndisAdap->FTKCardBusType = ADAPTER_CARD_SMART16_BUS_TYPE;
ndisAdap->IORange1 = SMART16_IO_RANGE;
ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
break;
case MADGE_ADAPTER_PCMCIA:
ndisAdap->FTKCardBusType = ADAPTER_CARD_PCMCIA_BUS_TYPE;
ndisAdap->IORange1 = PCMCIA_IO_RANGE;
ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
break;
case MADGE_ADAPTER_PNP:
ndisAdap->FTKCardBusType = ADAPTER_CARD_PNP_BUS_TYPE;
ndisAdap->IORange1 = PNP_IO_RANGE;
ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
break;
default:
return NDIS_STATUS_FAILURE;
}
//
// Get the IO location - must have this. First try
// "IoLocation" and then "IoBaseAddress".
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&IOAddressString,
NdisParameterHexInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&IOBaseAddrString,
NdisParameterHexInteger
);
}
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
2,
readRegistry,
MADGE_ERRMSG_NO_ISA_IO
);
return status;
}
ndisAdap->IoLocation1 = configParam->ParameterData.IntegerData;
//
// Er, slight hack here. We used to pretend that Smart16
// adapters were ATULA adapters. We now don't. So to
// be backwards compatible, if we have an unknown adapter
// with an IO base >= 0x4a20 and <= 0x6e20 we'll assume it's
// really a Smart16.
//
if (adapterType == MADGE_ADAPTER_UNKNOWN &&
ndisAdap->IoLocation1 >= 0x4a20 &&
ndisAdap->IoLocation1 <= 0x6e20)
{
adapterType = MADGE_ADAPTER_SMART16;
ndisAdap->FTKCardBusType = ADAPTER_CARD_SMART16_BUS_TYPE;
ndisAdap->IORange1 = SMART16_IO_RANGE;
ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
}
//
// Get the IRQ number - we must have this.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&InterruptNumberString,
NdisParameterInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
2,
readRegistry,
MADGE_ERRMSG_NO_ISA_IRQ
);
return status;
}
ndisAdap->UsedInISR.InterruptNumber =
configParam->ParameterData.IntegerData;
ndisAdap->UsedInISR.InterruptMode = NdisInterruptLatched;
ndisAdap->UsedInISR.InterruptShared = FALSE;
//
// Read the TransferType parameter and switch into PIO
// mode if specified.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&TransferModeString,
NdisParameterInteger
);
if (status == NDIS_STATUS_SUCCESS)
{
if (configParam->ParameterData.IntegerData == MADGE_PIO_MODE)
{
ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
}
}
//
// Get the DMA channel (PIO is specified as channel 0,
// multiprocessor safe PIO is specified as 0x8000). We
// don't need a DMA channel if the adapter isn't an ATULA so
// the only reason for reading the DMA channel for none
// ATULA adapters is to allow backwards compatability with old
// registry set ups that specify multiprocessor safe PIO
// with the DmaChannel == 0x8000. Using the DMA channel
// to specify PIO is retained for backwards compatibility
// the correct way is to set the TransferType parameter.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&DMAChannelString,
NdisParameterInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
ndisAdap->DmaChannel = 0;
}
else
{
ndisAdap->DmaChannel = configParam->ParameterData.IntegerData;
}
//
// Note if we should be using multiprocessor safe PIO.
//
if (ndisAdap->DmaChannel == 0x8000)
{
ndisAdap->DmaChannel = 0;
ndisAdap->UseMPSafePIO = TRUE;
}
//
// If we did not get a DMA channel then we must use PIO.
//
if (ndisAdap->DmaChannel == 0)
{
ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
}
return NDIS_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------
|
| Function - MadgeFindPciInfoForWin95
|
| Parameters - wrapperConfigHandle -> Wrapper context handle.
| registryConfigHandle -> Already open registry query handle.
| ndisAdap -> Pointer to an NDIS3 level adapter
| structure.
Ý pciSlotInfo -> Pointer to a buffer that will
Ý be filled with the configuration
Ý data for the adapter.
|
| Purpose - Read configuration information for PCI adapters out
Ý of the registry when running on Windows95. The slot
Ý containing the adapter is also found and the configuration
Ý data from the slot returned in the pciSlotInfo buffer.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeFindPciInfoForWin95(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap,
BYTE * pciSlotInfo
);
#pragma FTK_INIT_FUNCTION(MadgeFindPciInfoForWin95)
STATIC NDIS_STATUS
MadgeFindPciInfoForWin95(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap,
BYTE * pciSlotInfo
)
{
NDIS_STATUS status;
PNDIS_CONFIGURATION_PARAMETER configParam;
UINT i;
//
// Unfortunately Windows95 (M7) and NT handle PCI configuration
// in different ways. Under NT one has to read the slot
// configuration. Under Windows95 the resource information
// is faked up by the configuration manager and can be read
// directly from the wrapper.
//
//
// Get the IO location - must have this. First try
// "IoLocation" and then "IoBaseAddress".
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&IOAddressString,
NdisParameterHexInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&IOBaseAddrString,
NdisParameterHexInteger
);
}
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
2,
readRegistry,
MADGE_ERRMSG_NO_PCI_IO
);
return status;
}
ndisAdap->IoLocation1 = configParam->ParameterData.IntegerData;
//
// Get the IRQ number - we must have this.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&InterruptNumberString,
NdisParameterInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
2,
readRegistry,
MADGE_ERRMSG_NO_PCI_IRQ
);
return status;
}
ndisAdap->UsedInISR.InterruptNumber =
configParam->ParameterData.IntegerData;
//
// Get the MMIO base address - optional.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&MmioAddressString,
NdisParameterInteger
);
if (status == NDIS_STATUS_SUCCESS)
{
ndisAdap->MmioRawAddress =
configParam->ParameterData.IntegerData;
}
//
// We also need to know which slot the adapter is in so we can
// read and write configuration space directly. We'll search for
// a slot which contains a Madge adapter which the correct I/O
// location. As a side effect we'll store the configuration data
// for the slot in pciSlotInfo. Note: Under Windows 95 (build 490)
// NdisReadPciSlotInformation does appear to return the number
// of bytes read as it does under NT - not sure what it returns ...
//
ndisAdap->SlotNumber = PCI_FIND_ADAPTER;
for (i = 0; i < MAX_PCI_SLOTS; i++)
{
NdisReadPciSlotInformation(
ndisAdap->UsedInISR.MiniportHandle,
i,
0,
(VOID *) pciSlotInfo,
PCI_CONFIG_SIZE
);
if (PCI_VENDOR_ID(pciSlotInfo) == MADGE_PCI_VENDOR_ID &&
PCI_IO_BASE(pciSlotInfo) == ndisAdap->IoLocation1)
{
ndisAdap->SlotNumber = i;
break;
}
}
if (ndisAdap->SlotNumber == PCI_FIND_ADAPTER)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_DRIVER_FAILURE,
2,
readRegistry,
MADGE_ERRMSG_BAD_PCI_SLOTNUMBER
);
return NDIS_STATUS_FAILURE;
}
return NDIS_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------
Ý
Ý Function - MadgePciSlotUsed
Ý
Ý Parameters - busNumber -> Bus number containing the adapter.
Ý slotNumber -> Slot number containing the adapter.
Ý
Ý Purpose - Check if a PCI slot is already in use.
Ý
Ý Returns - TRUE if the slot is in use or FALSE if not.
Ý
Ý--------------------------------------------------------------------------*/
STATIC BOOLEAN
MadgePciSlotUsed(
UINT busNumber,
UINT slotNumber
);
#pragma FTK_INIT_FUNCTION(MadgePciSlotUsed)
STATIC BOOLEAN
MadgePciSlotUsed(
UINT busNumber,
UINT slotNumber
)
{
int i;
for (i = 0; i < PciSlotsUsedCount; i++)
{
if (PciSlotsUsedList[i].BusNumber == busNumber &&
PciSlotsUsedList[i].SlotNumber == slotNumber)
{
return TRUE;
}
}
return FALSE;
}
/*---------------------------------------------------------------------------
|
| Function - MadgeFindPciInfoForNt
|
| Parameters - wrapperConfigHandle -> Wrapper context handle.
| registryConfigHandle -> Already open registry query handle.
| ndisAdap -> Pointer to an NDIS3 level adapter
| structure.
Ý pciSlotInfo -> Pointer to a buffer that will
Ý be filled with the configuration
Ý data for the adapter.
|
| Purpose - Read configuration information for PCI adapters out
Ý of the registry when running on Windows95. The slot
Ý containing the adapter is also found and the configuration
Ý data from the slot returned in the pciSlotInfo buffer.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeFindPciInfoForNt(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap,
BYTE * pciSlotInfo
);
#pragma FTK_INIT_FUNCTION(MadgeFindPciInfoForNt)
STATIC NDIS_STATUS
MadgeFindPciInfoForNt(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap,
BYTE * pciSlotInfo
)
{
NDIS_STATUS status;
PNDIS_CONFIGURATION_PARAMETER configParam;
UINT slotNumber;
BOOLEAN pciSlotRead;
BOOLEAN useMmio;
UINT i;
PNDIS_RESOURCE_LIST pciResources;
PCM_PARTIAL_RESOURCE_DESCRIPTOR resDesc;
UINT busNumber;
//
// Unfortunately Windows95 (M7) and NT handle PCI configuration
// in different ways. Under NT one has to read the slot
// configuration. Under Windows95 the resource information
// is faked up by the configuration manager and can be read
// directly from the wrapper.
//
//
// Find out what the slot number is. This is in fact the
// PCI device number. Values 0 through 31 represent real
// slot numbers. 0xffff means we should search for the
// first unused Madge PCI adapter.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&SlotNumberString,
NdisParameterInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
2,
readRegistry,
MADGE_ERRMSG_NO_PCI_SLOTNUMBER
);
return status;
}
slotNumber = configParam->ParameterData.IntegerData;
pciSlotRead = FALSE;
//
// Read the bus number.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&BusNumberString,
NdisParameterInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
2,
readRegistry,
MADGE_ERRMSG_NO_PCI_SLOTNUMBER
);
return status;
}
busNumber = configParam->ParameterData.IntegerData;
//
// If the slot number is PCI_FIND_ADAPTER (0xffff) then we
// will attempt to search for the first Madge PCI adapter
// that is not already in use.
//
if (slotNumber == PCI_FIND_ADAPTER)
{
for (i = 0; !pciSlotRead && i < MAX_PCI_SLOTS; i++)
{
if (!MadgePciSlotUsed(busNumber, i))
{
//
// Extract the PCI configuration information from
// the slot.
//
status = NdisReadPciSlotInformation(
ndisAdap->UsedInISR.MiniportHandle,
i,
0,
(VOID *) pciSlotInfo,
PCI_CONFIG_SIZE
);
//
// Check if the slot contains a Madge adapter and
// break out of the loop if it does.
//
if (status == PCI_CONFIG_SIZE &&
PCI_VENDOR_ID(pciSlotInfo) == MADGE_PCI_VENDOR_ID)
{
slotNumber = i;
pciSlotRead = TRUE;
}
}
}
}
//
// Check if the slotNumber is valid. This will fail if the
// above adapter search failed.
//
if (slotNumber < 0 ||
slotNumber >= MAX_PCI_SLOTS ||
MadgePciSlotUsed(busNumber, slotNumber))
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_DRIVER_FAILURE,
2,
readRegistry,
MADGE_ERRMSG_BAD_PCI_SLOTNUMBER
);
return NDIS_STATUS_FAILURE;
}
//
// Note that the PCI slot is in use.
//
PciSlotsUsedList[PciSlotsUsedCount].BusNumber = busNumber;
PciSlotsUsedList[PciSlotsUsedCount].SlotNumber = slotNumber;
PciSlotsUsedCount++;
ndisAdap->SlotNumber = slotNumber;
//
// There two methods for getting the PCI configuration. One is
// to read it directly from the PCI configuration space. This
// works for Intel patforms where a PCI BIOS has configured
// all of the adapters at boot time. It does not work for
// none Intel platforms where the PCI devices are not
// configured at boot time. Unfortunately the call which
// provokes NT to configure a PCI device, NdisMPciAssignResources
// is not available in the NT 3.5 wrapper. So, until NT 3.51
// becomes dominant we must support both configuration methods.
//
//
// If we haven't already extracted the PCI configuration
// information from the slot and check that it is valid.
//
if (!pciSlotRead)
{
status = NdisReadPciSlotInformation(
ndisAdap->UsedInISR.MiniportHandle,
slotNumber,
0,
(VOID *) pciSlotInfo,
PCI_CONFIG_SIZE
);
if (status != PCI_CONFIG_SIZE ||
PCI_VENDOR_ID(pciSlotInfo) != MADGE_PCI_VENDOR_ID)
{
MadgePrint1("No Madge adapter in slot\n");
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_DRIVER_FAILURE,
2,
readRegistry,
MADGE_ERRMSG_BAD_PCI_SLOTNUMBER
);
return NDIS_STATUS_FAILURE;
}
}
//
// Call NdisMPciAssignResources for the specified slot to
// get the adapter configuration.
//
status = NdisMPciAssignResources(
ndisAdap->UsedInISR.MiniportHandle,
slotNumber,
&pciResources
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_DRIVER_FAILURE,
2,
readRegistry,
MADGE_ERRMSG_BAD_PCI_SLOTNUMBER
);
return NDIS_STATUS_FAILURE;
}
//
// Iterate through the returned resource list recording the values
// in the PCI configuration
//
for (i = 0; i < pciResources->Count; i++)
{
resDesc = &pciResources->PartialDescriptors[i];
switch (resDesc->Type)
{
case CmResourceTypeInterrupt:
ndisAdap->UsedInISR.InterruptNumber =
(ULONG) resDesc->u.Interrupt.Vector;
break;
case CmResourceTypePort:
ndisAdap->IoLocation1 =
(UINT) NdisGetPhysicalAddressLow(resDesc->u.Port.Start);
break;
case CmResourceTypeMemory:
ndisAdap->MmioRawAddress =
(DWORD) NdisGetPhysicalAddressLow(resDesc->u.Memory.Start);
break;
}
}
//
// On none-Intel platforms it's possible for the PCI adapter's I/O
// base to be greater than 0xffff. Since the FTK uses 16bit
// I/O locations we make a note of the I/O base in a 32bit cell
// that we can add in inside the I/O functions in sys_mem.c
//
#ifndef _M_IX86
ndisAdap->IoLocationBase = ndisAdap->IoLocation1;
ndisAdap->IoLocation1 = 0;
#endif
return NDIS_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------
|
| Function - MadgeReadRegistryForPCI
|
| Parameters - wrapperConfigHandle -> Wrapper context handle.
| registryConfigHandle -> Already open registry query handle.
| ndisAdap -> Pointer to an NDIS3 level adapter
| structure.
Ý platformType -> Type of platform: NT or Win95.
|
| Purpose - Read configuration information for PCI.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeReadRegistryForPCI(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap,
UINT platformType
);
#pragma FTK_INIT_FUNCTION(MadgeReadRegistryForPCI)
STATIC NDIS_STATUS
MadgeReadRegistryForPCI(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap,
UINT platformType
)
{
NDIS_STATUS status;
PNDIS_CONFIGURATION_PARAMETER configParam;
BYTE pciSlotInfo[PCI_CONFIG_SIZE];
BOOLEAN useMmio;
//
// Note the information that is always true for PCI adapters.
//
ndisAdap->NTCardBusType = NdisInterfacePci;
//
// Set up the fixed configuration information.
//
ndisAdap->UsedInISR.InterruptMode = NdisInterruptLevelSensitive;
ndisAdap->UsedInISR.InterruptShared = TRUE;
//
// We know need to find the PCI adapter and read in the configuration
// information for the slot. Unfortunatetly the method we have to use
// is different for NT and Win95.
//
if (platformType == MADGE_OS_WIN95)
{
status = MadgeFindPciInfoForWin95(
wrapperConfigHandle,
registryConfigHandle,
ndisAdap,
pciSlotInfo
);
}
else
{
status = MadgeFindPciInfoForNt(
wrapperConfigHandle,
registryConfigHandle,
ndisAdap,
pciSlotInfo
);
}
if (status != NDIS_STATUS_SUCCESS)
{
return status;
}
//
// Now we know we have a Madge PCI adapter of some sort but
// as yet we don't know what type. We'll work this out by
// looking at the device/revision ID in the slot's configuration
// data. At the same time we'll note the default transfer type
// for the adapter.
//
switch (PCI_REVISION(pciSlotInfo))
{
case MADGE_PCI_RAP1B_REVISION:
ndisAdap->FTKCardBusType = ADAPTER_CARD_PCI_BUS_TYPE;
ndisAdap->TransferMode = MMIO_DATA_TRANSFER_MODE;
ndisAdap->IORange1 = PCI_IO_RANGE;
break;
case MADGE_PCI_PCI2_REVISION:
ndisAdap->FTKCardBusType = ADAPTER_CARD_PCI2_BUS_TYPE;
ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
ndisAdap->IORange1 = PCI2_IO_RANGE;
break;
case MADGE_PCI_PCIT_REVISION:
ndisAdap->FTKCardBusType = ADAPTER_CARD_TI_PCI_BUS_TYPE;
ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
ndisAdap->IORange1 = SIF_IO_RANGE;
break;
default:
return NDIS_STATUS_FAILURE;
}
//
// Now we need to work out the transfer type. There are three
// things that affect the transfer type: the setting of
// the TransferType registry parameter, the setting of the
// NoMmio registry flag and whether we have been allocated any
// MMIO memory. Ideally we would just use the TransferType flag.
// The NoMmio flag is to preserve backwards compatibility with old
// registry set ups.
//
//
// Read the transfer type flag if possible.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&TransferModeString,
NdisParameterInteger
);
if (status == NDIS_STATUS_SUCCESS)
{
//
// Set the transfer type depending on the TransferType parameter
// and the adapter type.
//
if (configParam->ParameterData.IntegerData == MADGE_DMA_MODE)
{
if (ndisAdap->FTKCardBusType == ADAPTER_CARD_PCI2_BUS_TYPE ||
ndisAdap->FTKCardBusType == ADAPTER_CARD_TI_PCI_BUS_TYPE)
{
ndisAdap->TransferMode = DMA_DATA_TRANSFER_MODE;
}
}
if (configParam->ParameterData.IntegerData == MADGE_PIO_MODE)
{
ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
}
if (configParam->ParameterData.IntegerData == MADGE_MMIO_MODE)
{
if (ndisAdap->FTKCardBusType == ADAPTER_CARD_PCI_BUS_TYPE)
{
ndisAdap->TransferMode = MMIO_DATA_TRANSFER_MODE;
}
}
}
//
// To preserve backwards compatibility if we find the NoMmio flag
// set then switch to PIO mode.
//
if (ndisAdap->TransferMode == MMIO_DATA_TRANSFER_MODE)
{
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&NoMmioString,
NdisParameterInteger
);
if (status == NDIS_STATUS_SUCCESS)
{
if (configParam->ParameterData.IntegerData != 0)
{
ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
}
}
}
//
// If we are in MMIO mode then check that we were allocated some MMIO
// memory. If not switch to PIO mode.
//
if (ndisAdap->TransferMode == MMIO_DATA_TRANSFER_MODE)
{
if (ndisAdap->MmioRawAddress == 0)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MEMORY_CONFLICT,
2,
readRegistry,
MADGE_ERRMSG_BAD_PCI_MMIO
);
ndisAdap->TransferMode == PIO_DATA_TRANSFER_MODE;
}
}
return NDIS_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------
|
| Function - MadgeReadRegistry
|
| Parameters - wrapperConfigHandle -> Wrapper context handle.
| registryConfigHandle -> Already open registry query handle.
| ndisAdap -> Pointer to an NDIS3 level adapter
| structure.
|
| Purpose - Read configuration information out of the registry.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeReadRegistry(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap
);
#pragma FTK_INIT_FUNCTION(MadgeReadRegistry)
STATIC NDIS_STATUS
MadgeReadRegistry(
NDIS_HANDLE wrapperConfigHandle,
NDIS_HANDLE registryConfigHandle,
PMADGE_ADAPTER ndisAdap
)
{
NDIS_STATUS status;
PNDIS_CONFIGURATION_PARAMETER configParam;
MADGE_PARM_DEFINITION * pMadgeParmTable;
PVOID networkAddress;
ULONG networkAddressLength;
UINT adapterType;
UINT platformType;
//
// Try to read the OS platform type. If we don't find one then
// assume we are running on NT.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&PlatformString,
NdisParameterInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
platformType = MADGE_OS_NT;
}
else
{
platformType = configParam->ParameterData.IntegerData;
}
//
// Read the system bus type - that will give us a direction
// in which to search for further details.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&BusTypeString,
NdisParameterInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
2,
readRegistry,
MADGE_ERRMSG_NO_BUS_TYPE
);
return status;
}
ndisAdap->BusType = configParam->ParameterData.IntegerData;
//
// Originally we determined what sort of adapter we had based
// on the bus type returned by the configuration call to the
// wrapper. This works for NT but doesn't for Windows95 (M7)
// which seems to fail to identify a card as being in a PCI
// bus. We also cannot tell between the various sorts of ISA
// adapter now available. To fix this we look in the registry
// for an adapter type parameter. We use this and the bus type
// returned by the wrapper to work out where to start. We don't
// fail if we can't read an adapter type so that we will work with
// old registry set ups.
//
// Build 310 of Windows95 seems to return the native bus type of the
// PC. This means on a PCI machine we always get NdisInterfacePci.
// To get around this problem we will work out the bus type from
// the adapter type parameter if one is present.
//
// Unfortunately we can't just abandon the bus type de-multiplexing
// if we are to work with old NT registry set ups.
//
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&AdapterString,
NdisParameterInteger
);
if (status != NDIS_STATUS_SUCCESS)
{
adapterType = MADGE_ADAPTER_UNKNOWN;
}
else
{
adapterType = configParam->ParameterData.IntegerData;
}
switch (adapterType)
{
case MADGE_ADAPTER_ATULA:
case MADGE_ADAPTER_PCMCIA:
case MADGE_ADAPTER_PNP:
case MADGE_ADAPTER_SMART16:
ndisAdap->BusType = NdisInterfaceIsa;
break;
case MADGE_ADAPTER_EISA:
ndisAdap->BusType = NdisInterfaceEisa;
break;
case MADGE_ADAPTER_MC:
ndisAdap->BusType = NdisInterfaceMca;
break;
case MADGE_ADAPTER_PCI:
ndisAdap->BusType = NdisInterfacePci;
break;
default:
//
// We don't have a valid adapter type parameter so we'll
// just have to beleive the bus type the wrapper passed
// us.
//
break;
}
//
// Based on the determined Bus Type, try to find details of the card.
//
//
// Remember, all fields of the MADGE_ADAPTER structure were zeroed
// after the structure's allocation.
//
switch (ndisAdap->BusType)
{
case NdisInterfaceMca:
status = MadgeReadRegistryForMC(
wrapperConfigHandle,
registryConfigHandle,
ndisAdap
);
if (status != NDIS_STATUS_SUCCESS)
{
return status;
}
break;
case NdisInterfaceEisa:
//
// For Eisa bus systems, we could have an Isa card or an Eisa
// card - try to read the Eisa information, and if that fails
// assume it is an Isa card instead.
//
status = MadgeReadRegistryForEISA(
wrapperConfigHandle,
registryConfigHandle,
ndisAdap
);
if (status == NDIS_STATUS_SUCCESS)
{
break;
}
//
// Failed to read EISA data for this card, so it is unlikely
// to be one - try ISA instead - fall through.
//
case NdisInterfaceIsa:
status = MadgeReadRegistryForISA(
wrapperConfigHandle,
registryConfigHandle,
ndisAdap,
adapterType
);
if (status != NDIS_STATUS_SUCCESS)
{
return status;
}
break;
case NdisInterfacePci:
status = MadgeReadRegistryForPCI(
wrapperConfigHandle,
registryConfigHandle,
ndisAdap,
platformType
);
if (status != NDIS_STATUS_SUCCESS)
{
return status;
}
break;
default:
//
// Unsupported Bus Type, so return failure - no point being more
// explicit than that at the moment since any of the bits above
// could have failed too, and they do not return anything more
// meaningful either.
//
return NDIS_STATUS_FAILURE;
}
MadgePrint2("FTKCardBusType = %d\n", ndisAdap->FTKCardBusType);
MadgePrint2("SlotNumber = %d\n", ndisAdap->SlotNumber);
MadgePrint2("IoLocation1 = %lx\n", ndisAdap->IoLocation1);
MadgePrint2("MmioAddress = %lx\n", ndisAdap->MmioRawAddress);
MadgePrint2("InterruptNumber = %lx\n", ndisAdap->UsedInISR.InterruptNumber);
MadgePrint2("TransferMode = %d\n", ndisAdap->TransferMode);
MadgePrint2("DmaChannel = %d\n", ndisAdap->DmaChannel);
//
// To get here, we must have worked out the IO Address, IRQ number, DMA
// channel/arbitration level, and all the interrupt details. This just
// leaves the optional parameters for tuning the performance of the MAC
// code.
//
pMadgeParmTable = (MADGE_PARM_DEFINITION *) &MadgeParmTable;
while (!NdisEqualString(&pMadgeParmTable->Keyword, &NullString, TRUE))
{
NdisReadConfiguration(
&status,
&configParam,
registryConfigHandle,
&pMadgeParmTable->Keyword,
pMadgeParmTable->DefaultValue.ParameterType
);
if (status == NDIS_STATUS_SUCCESS)
{
//
// Did read something. Check bounds. We assume all are Integers.
//
if (configParam->ParameterData.IntegerData <
pMadgeParmTable->Minimum ||
configParam->ParameterData.IntegerData >
pMadgeParmTable->Maximum)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_DRIVER_FAILURE,
2,
readRegistry,
MADGE_ERRMSG_BAD_PARAMETER
);
pMadgeParmTable->ActualValue = pMadgeParmTable->DefaultValue;
}
else
{
pMadgeParmTable->ActualValue = *configParam;
}
}
else
{
//
// We didn't read anything, so use the default value.
//
pMadgeParmTable->ActualValue = pMadgeParmTable->DefaultValue;
}
pMadgeParmTable++;
}
//
// We have successfully read any optional keywords and none of them is
// too small or big. The other thing we need the registry for is the
// locally administered address, for which there is a specific NDIS call
//
NdisReadNetworkAddress(
&status,
&networkAddress,
&networkAddressLength,
registryConfigHandle
);
if (status == NDIS_STATUS_SUCCESS &&
networkAddressLength == TR_LENGTH_OF_ADDRESS)
{
//
// We read a valid length TR address, but if the
// top two bits are not "01", it is not legal.
//
if ((((BYTE *) networkAddress)[0] & 0xc0) == 0x40)
{
ndisAdap->OpeningNodeAddress =
*((NODE_ADDRESS *) networkAddress);
}
}
return NDIS_STATUS_SUCCESS;
}
/****************************************************************************
*
* Function - MadgeShutdown
*
* Parameters - context -> Adapter context.
*
* Purpose - Quickly shutdown the adapter.
*
* Returns - Nothing.
*
****************************************************************************/
VOID
MadgeShutdown(
NDIS_HANDLE context
)
{
MADGE_ADAPTER * ndisAdap;
ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(context);
MadgePrint1("MadgeShutdown called\n");
if (ndisAdap->TimerInitialized)
{
BOOLEAN timerOutstanding;
NdisMCancelTimer(&ndisAdap->WakeUpTimer, &timerOutstanding);
NdisMCancelTimer(&ndisAdap->CompletionTimer, &timerOutstanding);
ndisAdap->TimerInitialized = FALSE;
}
//
// Just call the FTK to shutdown the adapter.
//
if (ndisAdap->FtkInitialized)
{
rxtx_await_empty_tx_slots(ndisAdap->FtkAdapterHandle);
driver_remove_adapter(ndisAdap->FtkAdapterHandle);
ndisAdap->FtkInitialized = FALSE;
ndisAdap->AdapterRemoved = TRUE;
}
MadgePrint1("MadgeShutdown ended\n");
}
/*---------------------------------------------------------------------------
|
| Function - MadgeRegisterAdapter
|
| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter
| structure.
| wrapperConfigHandle -> Wrapper context handle.
|
| Purpose - Register an adapter instance with the NDIS3 wrapper.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeRegisterAdapter(
PMADGE_ADAPTER ndisAdap,
NDIS_HANDLE wrapperConfigHandle
);
#pragma FTK_INIT_FUNCTION(MadgeRegisterAdapter)
STATIC NDIS_STATUS
MadgeRegisterAdapter(
PMADGE_ADAPTER ndisAdap,
NDIS_HANDLE wrapperConfigHandle
)
{
NDIS_STATUS status;
BOOLEAN busMaster;
MadgePrint1("MadgeRegisterAdapter started\n");
//
// Register a shutdown handler with the wrapper.
//
NdisMRegisterAdapterShutdownHandler(
ndisAdap->UsedInISR.MiniportHandle,
ndisAdap,
MadgeShutdown
);
ndisAdap->ShutdownHandlerRegistered = TRUE;
//
// Register our attributes with the wrapper. These are our adapter
// context (i.e. a pointer to our adapter structure), whether we
// are a bus master device and our bus type.
//
busMaster = (ndisAdap->TransferMode == DMA_DATA_TRANSFER_MODE);
MadgePrint1("NdisMSetAttributes called\n");
MadgePrint2("busMaster = %d\n", (UINT) busMaster);
NdisMSetAttributes(
ndisAdap->UsedInISR.MiniportHandle,
(NDIS_HANDLE) ndisAdap,
busMaster,
ndisAdap->NTCardBusType
);
MadgePrint1("NdisMSetAttributes returned\n");
//
// Register our IO port usage.
//
MadgePrint1("NdisMRegisterIoPortRange called\n");
status = NdisMRegisterIoPortRange(
&ndisAdap->MappedIOLocation1,
ndisAdap->UsedInISR.MiniportHandle,
ndisAdap->IoLocation1 + ndisAdap->IoLocationBase,
ndisAdap->IORange1
);
MadgePrint1("NdisMRegisterIoPortRange returned\n");
MadgePrint2("MappedIORange1 = %x\n", (UINT) ndisAdap->MappedIOLocation1);
if (status != NDIS_STATUS_SUCCESS)
{
MadgePrint2("NdisMRegisterIoPortRange failed rc = %x\n", status);
return status;
}
ndisAdap->IORange1Initialized = TRUE;
//
// If we are using an EISA card then we have a second range of IO
// locations.
//
if (ndisAdap->IORange2 > 0)
{
MadgePrint1("NdisMRegisterIoPortRange called\n");
status = NdisMRegisterIoPortRange(
&ndisAdap->MappedIOLocation2,
ndisAdap->UsedInISR.MiniportHandle,
ndisAdap->IoLocation2 + ndisAdap->IoLocationBase,
ndisAdap->IORange2
);
MadgePrint1("NdisMRegisterIoPortRange returned\n");
MadgePrint2("MappedIORange2 = %x\n", (UINT) ndisAdap->MappedIOLocation2);
if (status != NDIS_STATUS_SUCCESS)
{
MadgePrint2("NdisMRegisterIoPortRange failed rc = %x\n", status);
return status;
}
ndisAdap->IORange2Initialized = TRUE;
}
MadgePrint1("MadgeRegisterAdapter finished\n");
return NDIS_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------
|
| Function - FlagIsTrue
|
| Parameters - flag -> Pointer to a flag to find the value of.
|
| Purpose - Return the value of a flag. Can be called by a function
Ý that polls a flag to avoid the compiler optimising out
Ý the test of the flag.
|
| Returns - The value of the flag.
|
|--------------------------------------------------------------------------*/
STATIC BOOLEAN
FlagIsTrue(BOOLEAN * flag);
#pragma FTK_INIT_FUNCTION(FlagIsTrue)
STATIC BOOLEAN
FlagIsTrue(BOOLEAN * flag)
{
MadgePrint1("FlagIsTrue\n");
return *flag;
}
/*---------------------------------------------------------------------------
|
| Function - MadgeMapMmioMemory
|
| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
|
| Purpose - Attempt to map in our MMIO memory.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeMapMmioMemory(PMADGE_ADAPTER ndisAdap);
#pragma FTK_INIT_FUNCTION(MadgeMapMmioMemory)
STATIC NDIS_STATUS
MadgeMapMmioMemory(PMADGE_ADAPTER ndisAdap)
{
NDIS_PHYSICAL_ADDRESS mmioPhysAddr = NDIS_PHYSICAL_ADDRESS_CONST(0, 0);
UINT status;
NdisSetPhysicalAddressLow(
mmioPhysAddr,
ndisAdap->MmioRawAddress
);
status = NdisMMapIoSpace(
&ndisAdap->MmioVirtualAddress,
ndisAdap->UsedInISR.MiniportHandle,
mmioPhysAddr,
PCI_MMIO_SIZE
);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_MEMORY_CONFLICT,
2,
initAdapter,
MADGE_ERRMSG_MAPPING_PCI_MMIO
);
}
else
{
ndisAdap->MmioMapped = TRUE;
}
return status;
}
#ifndef LINK_FMPLUS
/*---------------------------------------------------------------------------
|
| Function - MadgeReadDownload
|
| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
Ý downloadFile -> Pointer to as handle for the download file.
| download -> Pointer to a holder for a pointer to the
Ý download image read into memory.
Ý
| Purpose - Read the download into memory. If the function returns
Ý success then must unmap and close *downloadFile.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeReadDownload(
PMADGE_ADAPTER ndisAdap,
NDIS_HANDLE * downloadFile,
void * * download
);
#pragma FTK_INIT_FUNCTION(MadgeReadDownload)
STATIC NDIS_STATUS
MadgeReadDownload(
PMADGE_ADAPTER ndisAdap,
NDIS_HANDLE * downloadFile,
void * * download
)
{
NDIS_STATUS status;
NDIS_HANDLE imageFile;
UINT imageLength;
PVOID imagePtr;
NDIS_PHYSICAL_ADDRESS highestAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
DOWNLOAD_FILE_HEADER * downHdrPtr;
UCHAR * chkPtr;
ULONG chkSum;
UINT i;
//
// Open the FastMAC Plus image file.
//
MadgePrint1("NdisOpenFile called\n");
NdisOpenFile(
&status,
&imageFile,
&imageLength,
&FmpImageFileName,
highestAddress
);
MadgePrint1("NdisOpenFile returned\n");
if (status != NDIS_STATUS_SUCCESS)
{
MadgePrint2("NdisOpenFile failed rc= %x\n", status);
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_INVALID_DOWNLOAD_FILE_ERROR,
2,
initAdapter,
MADGE_ERRMSG_OPEN_IMAGE_FILE
);
return NDIS_STATUS_RESOURCES;
}
//
// Map in the FastMAC Plus image file.
//
NdisMapFile(&status, &imagePtr, imageFile);
if (status != NDIS_STATUS_SUCCESS)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_OUT_OF_RESOURCES,
2,
initAdapter,
MADGE_ERRMSG_MAP_IMAGE_FILE
);
NdisCloseFile(imageFile);
return NDIS_STATUS_RESOURCES;
}
//
// Make sure that the image file is valid by checking its checksum,
// version number and signature.
//
downHdrPtr = (DOWNLOAD_FILE_HEADER *) imagePtr;
chkPtr = ((UCHAR *) imagePtr) + DOWNLOAD_CHECKSUM_SKIP;
chkSum = 0;
for (i = DOWNLOAD_CHECKSUM_SKIP; i < imageLength; i++)
{
DOWNLOAD_CHECKSUM_BYTE(chkSum, *chkPtr);
chkPtr++;
}
if (!IS_DOWNLOAD_OK(downHdrPtr, chkSum))
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_INVALID_DOWNLOAD_FILE_ERROR,
2,
initAdapter,
MADGE_ERRMSG_BAD_IMAGE_FILE
);
NdisUnmapFile(imageFile);
NdisCloseFile(imageFile);
return NDIS_STATUS_RESOURCES;
}
*downloadFile = imageFile;
*download = imagePtr;
return NDIS_STATUS_SUCCESS;
}
#else
#include "fmplus.c"
#endif
#ifdef _M_IX86
/*---------------------------------------------------------------------------
|
| Function - MadgeArbitrateBufferMemory
|
| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
|
| Purpose - Determine if we can allocate all the shared memory
Ý we need for DMA buffer space and if we can't then
Ý reduce our requirements until we can or we reach
Ý our minimum requirements. If the buffer space cannot
Ý be aribtrated then the requirements are left as is and
Ý it is assumed that the FTK initialisation will fail
Ý and generate an out of memory error.
|
| Returns - Nothing.
|
|--------------------------------------------------------------------------*/
STATIC VOID
MadgeArbitrateBufferMemory(PMADGE_ADAPTER ndisAdap);
#pragma FTK_INIT_FUNCTION(MadgeArbitrateBufferMemory)
STATIC VOID
MadgeArbitrateBufferMemory(PMADGE_ADAPTER ndisAdap)
{
VOID * testVirt;
VOID * rxVirt;
VOID * txVirt;
NDIS_PHYSICAL_ADDRESS testPhys;
NDIS_PHYSICAL_ADDRESS rxPhys;
NDIS_PHYSICAL_ADDRESS txPhys;
ULONG rxBufferSize;
ULONG txBufferSize;
UINT maxFrameSize;
UINT rxSlots;
UINT txSlots;
BOOLEAN succeeded;
BOOLEAN failed;
BOOLEAN arbitrated;
//
// There doesn't seem to be a problem allocating none
// shared memory so if we aren't in DMA mode then
// don't do anything.
//
if (ndisAdap->TransferMode != DMA_DATA_TRANSFER_MODE)
{
return;
}
//
// The first bit of shared memory we must have is for the DMA
// test buffers.
//
testVirt = NULL;
NdisMAllocateSharedMemory(
ndisAdap->UsedInISR.MiniportHandle,
SCB_TEST_PATTERN_LENGTH + SSB_TEST_PATTERN_LENGTH,
FALSE,
&testVirt,
&testPhys
);
//
// If we can't allocate the test buffer then just give up.
//
if (testVirt == NULL)
{
return;
}
//
// We've got the test buffer memory so now arbitrate the
// RX/TX buffers. Note: the buffer allocation MUST MATCH
// THAT IN FTK_USER.C.
//
maxFrameSize = ndisAdap->MaxFrameSize;
rxSlots = ndisAdap->FastmacRxSlots;
txSlots = ndisAdap->FastmacTxSlots;
failed = FALSE;
succeeded = FALSE;
arbitrated = FALSE;
while (!failed && !succeeded)
{
rxVirt = NULL;
txVirt = NULL;
//
// Try to allocate the receive buffer.
//
rxBufferSize = ((maxFrameSize + 4 + 32 + 3) & ~3) * rxSlots;
NdisMAllocateSharedMemory(
ndisAdap->UsedInISR.MiniportHandle,
rxBufferSize,
FALSE,
&rxVirt,
&rxPhys
);
//
// If we allocated the RX buffer space then try to allocate
// the TX buffer space.
//
if (rxVirt != NULL)
{
txBufferSize = ((maxFrameSize + 3) & ~3) * txSlots;
NdisMAllocateSharedMemory(
ndisAdap->UsedInISR.MiniportHandle,
txBufferSize,
FALSE,
&txVirt,
&txPhys
);
}
//
// Free any buffers we managed to allocate.
//
if (rxVirt != NULL)
{
NdisMFreeSharedMemory(
ndisAdap->UsedInISR.MiniportHandle,
rxBufferSize,
FALSE,
rxVirt,
rxPhys
);
}
if (txVirt != NULL)
{
NdisMFreeSharedMemory(
ndisAdap->UsedInISR.MiniportHandle,
txBufferSize,
FALSE,
txVirt,
txPhys
);
}
//
// If we managed to allocate both buffers then we have
// succeeded.
//
if (rxVirt != NULL && txVirt != NULL)
{
succeeded = TRUE;
}
//
// Otherwise we must reduce our memory requirements.
//
else
{
arbitrated = TRUE;
//
// First try reducing the number of transmit slots.
//
if (txSlots > FMPLUS_MIN_TX_SLOTS)
{
txSlots--;
}
//
// Next try reducing the number of receive slots.
//
else if (rxSlots > FMPLUS_MIN_RX_SLOTS)
{
rxSlots--;
}
//
// Finally try reducing the frame size. 1800 bytes has
// empirically shown to be the minimum value required
// for the DOMAIN server startup to work at NT installation.
//
else if (maxFrameSize > 1800)
{
maxFrameSize -= 512;
if (maxFrameSize < 1800)
{
maxFrameSize = 1800;
}
}
//
// If we can't reduce our buffer requirements any further
// then fail.
//
else
{
failed = TRUE;
}
}
}
//
// Free the memory for the DMA test buffer.
//
NdisMFreeSharedMemory(
ndisAdap->UsedInISR.MiniportHandle,
SCB_TEST_PATTERN_LENGTH + SSB_TEST_PATTERN_LENGTH,
FALSE,
testVirt,
testPhys
);
//
// If we have succeded then we must update the requirements in
// adapter structure and if we have changed any values we must
// write a message to the event log.
//
if (succeeded && arbitrated)
{
ndisAdap->MaxFrameSize = maxFrameSize;
ndisAdap->FastmacRxSlots = rxSlots;
ndisAdap->FastmacTxSlots = txSlots;
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
1,
initAdapter
);
}
}
#endif
/*---------------------------------------------------------------------------
|
| Function - MadgeInitAdapter
|
| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
|
| Purpose - Initialise an adapter.
|
| Returns - An NDIS3 status code.
|
|--------------------------------------------------------------------------*/
STATIC NDIS_STATUS
MadgeInitAdapter(PMADGE_ADAPTER ndisAdap);
#pragma FTK_INIT_FUNCTION(MadgeInitAdapter)
STATIC NDIS_STATUS
MadgeInitAdapter(PMADGE_ADAPTER ndisAdap)
{
WORD ftkStatus;
NDIS_STATUS status;
PREPARE_ARGS prepare;
START_ARGS start;
#ifndef LINK_FMPLUS
NDIS_HANDLE imageFile;
PVOID imagePtr;
#endif
MadgePrint1("MadgeInitAdapter started\n");
//
// If we are doing MMIO then we need to map in the MMIO memory.
// If we fail to map in the memory then default ti PIO.
//
if (ndisAdap->TransferMode == MMIO_DATA_TRANSFER_MODE)
{
if (MadgeMapMmioMemory(ndisAdap) != NDIS_STATUS_SUCCESS)
{
ndisAdap->TransferMode = PIO_DATA_TRANSFER_MODE;
}
}
#ifdef _M_IX86
//
// Arbitrate "DMA" buffer memory.
//
MadgeArbitrateBufferMemory(ndisAdap);
#endif
//
// Set up the arguments to pass to driver_prepare_adapter.
//
MADGE_ZERO_MEMORY(&prepare, sizeof(PREPARE_ARGS));
prepare.user_information = (void *) ndisAdap;
prepare.number_of_rx_slots = (WORD) ndisAdap->FastmacRxSlots;
prepare.number_of_tx_slots = (WORD) ndisAdap->FastmacTxSlots;
prepare.max_frame_size = (WORD) ndisAdap->MaxFrameSize;
//
// Try to prepare the adapter for use.
//
//
// Mark the fact that the FTK has been called, so that we know if we
// have to call driver_remove_adapter() when doing clean up.
//
ndisAdap->FtkInitialized = TRUE;
MadgePrint1("driver_prepare_adapter called\n");
if (!driver_prepare_adapter(&prepare, &(ndisAdap->FtkAdapterHandle)))
{
return NDIS_STATUS_FAILURE;
}
MadgePrint1("driver_prepare_adapter returned\n");
MadgePrint2("adapter_handle = %d\n", ndisAdap->FtkAdapterHandle);
#ifndef LINK_FMPLUS
//
// Read in the download file.
//
status = MadgeReadDownload(ndisAdap, &imageFile, &imagePtr);
if (status != NDIS_STATUS_SUCCESS)
{
return status;
}
#endif
//
// Set up the arguments to driver_start_adapter.
//
MADGE_ZERO_MEMORY(&start, sizeof(START_ARGS));
start.adapter_card_bus_type = (UINT) ndisAdap->FTKCardBusType;
start.io_location = (WORD) ndisAdap->IoLocation1;
start.transfer_mode = (UINT) ndisAdap->TransferMode;
start.dma_channel = (WORD) ndisAdap->DmaChannel;
start.interrupt_number = (WORD) ndisAdap->UsedInISR.InterruptNumber;
start.set_dma_channel = TRUE;
start.set_interrupt_number = TRUE;
start.mmio_base_address = (DWORD) ndisAdap->MmioVirtualAddress;
start.pci_handle = (DWORD) ndisAdap->SlotNumber;
if (ndisAdap->Force16)
{
start.set_ring_speed = 16;
}
else if (ndisAdap->Force4)
{
start.set_ring_speed = 4;
}
start.opening_node_address = ndisAdap->OpeningNodeAddress;
start.auto_open_option = TRUE;
if (ndisAdap->ForceOpen)
{
ndisAdap->OpenOptions |= OPEN_OPT_FORCE_OPEN;
}
start.open_options = (WORD) ndisAdap->OpenOptions;
start.rx_tx_buffer_size = (WORD) ndisAdap->CardBufferSize;
#ifndef LINK_FMPLUS
start.code = (DOWNLOAD_IMAGE *)
(((UCHAR *) imagePtr) + sizeof(DOWNLOAD_FILE_HEADER));
#else
start.code = (DOWNLOAD_IMAGE *) fmplus_image;
#endif
MadgePrint1("driver_start_adapter called\n");
ftkStatus = driver_start_adapter(
ndisAdap->FtkAdapterHandle,
&start,
&ndisAdap->PermanentNodeAddress
);
MadgePrint1("driver_start_adapter returned\n");
MadgePrint2("MAC buffer size = %d\n",
adapter_record[ndisAdap->FtkAdapterHandle
]->init_block->smart_parms.rx_tx_buffer_size
);
#ifndef LINK_FMPLUS
//
// No matter what we have finished with the FastMAC Plus image file.
//
NdisUnmapFile(imageFile);
NdisCloseFile(imageFile);
#endif
if (!ftkStatus)
{
MadgePrint1("driver_start_adapter failed\n");
//
// Were it not for the fact that we are going to clean up and fail
// as soon as we return, we ought to set the CurrentRingState to
// NdisRingStateOpenFailure here if AutoOpen was selected.
//
return NDIS_STATUS_FAILURE;
}
//
// Warn the user if FastMAC Plus had to reduce the frame size.
//
if (ndisAdap->MaxFrameSize > start.max_frame_size)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
3,
initAdapter,
MADGE_ERRMSG_REDUCE_MAX_FSIZE,
ndisAdap->MaxFrameSize
);
}
ndisAdap->MaxFrameSize = start.max_frame_size;
//
// If we did not specify a locally administered address then copy the
// permanent one across to the local one.
//
if (ndisAdap->OpeningNodeAddress.byte[0] == 0)
{
MADGE_MOVE_MEMORY(
&ndisAdap->OpeningNodeAddress,
&ndisAdap->PermanentNodeAddress,
sizeof(ndisAdap->PermanentNodeAddress)
);
}
//
// Note that the adapter is open.
//
ndisAdap->CurrentRingState = NdisRingStateOpened;
ndisAdap->LastOpenStatus = start.open_status;
//
// Nasty hack. If we have a PciT atapter with broken dma and we are
// running on a multiprocessor we need set the multiprocessor safe
// PIO flag to make sure that we don't do DIO whilst our interrupt
// hander is running. Unfortunately we don't know if we have
// broken DMA until after we've started the adapter.
//
if (ndisAdap->Multiprocessor &&
adapter_record[ndisAdap->FtkAdapterHandle]->mc32_config ==
TRN_PCIT_BROKEN_DMA)
{
MadgePrint1("Using MP sfae PIO because of PCIT DMA.\n");
ndisAdap->UseMPSafePIO = TRUE;
}
//
// Note that we MUST start the receive process, even if we are NOT using
// auto-open, because FastmacPlus ignores SRBs (including OPEN SRBs) if
// this has not been done.
//
driver_start_receive_process(ndisAdap->FtkAdapterHandle);
//
// We now need to set the product instance ID. The product instance
// ID will be set to the contents of ftk_product_inst_id[] if we
// issue an open SRB, but since Miniports always auto-open we
// need to generate a set product instance SRB to set it.
//
//
// Note that we are generating a private SRB (not to be treated
// as a normal NDIS request), generate the SRB and then wait
// for it to finish.
//
ndisAdap->PrivateSrbInProgress = TRUE;
MadgePrint1("Calling driver_set_product_instance_id\n");
driver_set_product_instance_id(
ndisAdap->FtkAdapterHandle,
NT_PRODUCT_INSTANCE_ID
);
MadgePrint1("Waiting for SRB to complete\n");
while (FlagIsTrue(&ndisAdap->PrivateSrbInProgress))
NdisMSleep(100);
MadgePrint1("MadgeInitAdapter finished\n");
return NDIS_STATUS_SUCCESS;
}
/*---------------------------------------------------------------------------
|
| Function - MadgeCleanupAdapter
|
| Parameters - ndisAdap -> Pointer to an NDIS3 level adapter structure.
|
| Purpose - Deallocate the resources associated with an adapter.
|
| Returns - Nothing.
|
|--------------------------------------------------------------------------*/
STATIC VOID
MadgeCleanupAdapter(PMADGE_ADAPTER ndisAdap)
{
BOOLEAN timerOutstanding;
MadgePrint1("MadgeCleanupAdapter 1\n");
if (ndisAdap->TimerInitialized)
{
NdisMCancelTimer(&ndisAdap->WakeUpTimer, &timerOutstanding);
NdisMCancelTimer(&ndisAdap->CompletionTimer, &timerOutstanding);
ndisAdap->TimerInitialized = FALSE;
}
MadgePrint1("MadgeCleanupAdapter 2\n");
if (ndisAdap->FtkInitialized)
{
rxtx_await_empty_tx_slots(ndisAdap->FtkAdapterHandle);
driver_remove_adapter(ndisAdap->FtkAdapterHandle);
ndisAdap->FtkInitialized = FALSE;
}
if (ndisAdap->MapRegistersAllocated > 0)
{
NdisMFreeMapRegisters(ndisAdap->UsedInISR.MiniportHandle);
ndisAdap->MapRegistersAllocated = 0;
}
MadgePrint1("MadgeCleanupAdapter 3\n");
if (ndisAdap->MmioMapped)
{
NdisMUnmapIoSpace(
ndisAdap->UsedInISR.MiniportHandle,
ndisAdap->MmioVirtualAddress,
PCI_MMIO_SIZE
);
ndisAdap->MmioMapped = FALSE;
}
MadgePrint1("MadgeCleanupAdapter 4\n");
if (ndisAdap->IORange1Initialized)
{
NdisMDeregisterIoPortRange(
ndisAdap->UsedInISR.MiniportHandle,
ndisAdap->IoLocation1 + ndisAdap->IoLocationBase,
ndisAdap->IORange1,
ndisAdap->MappedIOLocation1
);
ndisAdap->IORange1Initialized = FALSE;
}
MadgePrint1("MadgeCleanupAdapter 5\n");
if (ndisAdap->IORange2Initialized)
{
NdisMDeregisterIoPortRange(
ndisAdap->UsedInISR.MiniportHandle,
ndisAdap->IoLocation2 + ndisAdap->IoLocationBase,
ndisAdap->IORange2,
ndisAdap->MappedIOLocation2
);
ndisAdap->IORange2Initialized = FALSE;
}
MadgePrint1("MadgeCleanupAdapter 6\n");
if (ndisAdap->ShutdownHandlerRegistered)
{
NdisMDeregisterAdapterShutdownHandler(
ndisAdap->UsedInISR.MiniportHandle
);
ndisAdap->ShutdownHandlerRegistered = FALSE;
MadgePrint1("De-registered shutdown handler\n");
}
MADGE_FREE_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
}
/***************************************************************************
*
* Function - MadgeHalt
*
* Parameters - adapterContext -> Pointer to our NDIS level adapter
* structure.
*
* Purpose - Process a call from the NDIS3 wrapper to remove an
* adapter instance.
*
* Returns - Nothing.
*
****************************************************************************/
VOID
MadgeHalt(NDIS_HANDLE adapterContext)
{
PMADGE_ADAPTER ndisAdap;
MadgePrint1("MadgeHalt started\n");
ndisAdap = PMADGE_ADAPTER_FROM_CONTEXT(adapterContext);
//
// The NDIS interface guarantees that all bindings are closed, i.e. all
// MadgeCloseAdapter calls have completed successfully.
//
ndisAdap->HardwareStatus = NdisHardwareStatusClosing;
MadgeCleanupAdapter(ndisAdap);
MadgePrint1("MadgeHalt finished\n");
}
/****************************************************************************
*
* Function - MadgeTxCompletion
*
* Parameters - systemSpecific1 -> Unused.
* context -> Actually a pointer to our NDIS3 level
* adapter structure.
* systemSpecific2 -> Unused.
* systemSpecific3 -> Unused.
*
* Purpose - Call our TX competion routine as a result of a timer.
*
* Returns - Nothing.
*
****************************************************************************/
VOID
MadgeTxCompletion(
PVOID systemSpecific1,
PVOID context,
PVOID systemSpecific2,
PVOID systemSpecific3
)
{
PMADGE_ADAPTER ndisAdap = (PMADGE_ADAPTER) context;
//
// Call the TX completion function.
//
rxtx_irq_tx_completion_check(
ndisAdap->FtkAdapterHandle,
adapter_record[ndisAdap->FtkAdapterHandle]
);
}
/***************************************************************************
*
* Function - MadgeInitialise
*
* Parameters - openErrorStatus -> Pointer to a holder for an open
* error status.
* selectedMediumIndex -> Pointer to a holder for the index
* of the medium selected.
* mediumArray -> Array of media types.
* mediumArraySize -> Size of the media array.
* miniportHandle -> Miniport adapter handle.
* wrapperConfigContext -> Handle used when querying the
* registry.
*
* Purpose - Carry out adapter instance initialisation.
*
* Returns - An NDIS3 status code.
*
***************************************************************************/
NDIS_STATUS
MadgeInitialize(
PNDIS_STATUS openErrorStatus,
PUINT selectedMediumIndex,
PNDIS_MEDIUM mediumArray,
UINT mediumArraySize,
NDIS_HANDLE miniportHandle,
NDIS_HANDLE wrapperConfigContext
);
#pragma FTK_INIT_FUNCTION(MadgeInitialize)
NDIS_STATUS
MadgeInitialize(
PNDIS_STATUS openErrorStatus,
PUINT selectedMediumIndex,
PNDIS_MEDIUM mediumArray,
UINT mediumArraySize,
NDIS_HANDLE miniportHandle,
NDIS_HANDLE wrapperConfigContext
)
{
NDIS_STATUS status;
PMADGE_ADAPTER ndisAdap;
NDIS_HANDLE configHandle;
UINT i;
MadgePrint1("MadgeInitialize started\n");
//
// ---------------------------------------------------------------------
// Check that the upper protocol knows about token ring and if
// it does set the index.
//
for (i = 0; i < mediumArraySize; i++)
{
if (mediumArray[i] == NdisMedium802_5)
{
break;
}
}
if (i == mediumArraySize)
{
return NDIS_STATUS_UNSUPPORTED_MEDIA;
}
*selectedMediumIndex = i;
//
// ---------------------------------------------------------------------
// Doing basic sanity checks and allocating some memory for our
// per-adapter structure.
//
if (wrapperConfigContext == NULL)
{
//
// No registry config. information found by NDIS library for us.
// We cannot proceed without it.
//
return NDIS_STATUS_FAILURE;
}
//
// Allocate memory for the adapter structure.
//
MADGE_ALLOC_MEMORY(&status, &ndisAdap, sizeof(MADGE_ADAPTER));
if (status != NDIS_STATUS_SUCCESS)
{
//
// Failed to allocate adapter structure. Can't go on without it.
//
return status;
}
MADGE_ZERO_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
MadgePrint2("ndisAdap = %x\n", ndisAdap);
//
// We need the mini port handle early on.
//
ndisAdap->UsedInISR.MiniportHandle = miniportHandle;
//
// ---------------------------------------------------------------------
// Read the registry: open the registry, read the contents, and close it
// again. This will handle adapter parameters and LAAs, and also working
// out various values to do with interrupt modes.
//
MadgePrint1("NdisOpenConfiguration called\n");
NdisOpenConfiguration(
&status,
&configHandle,
wrapperConfigContext
);
MadgePrint1("NdisOpenConfiguration returned\n");
if (status != NDIS_STATUS_SUCCESS)
{
MadgePrint2("NdisOpenConfiguration failed rc=%x\n", status);
MADGE_FREE_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
return status;
}
status = MadgeReadRegistry(
wrapperConfigContext,
configHandle,
ndisAdap
);
NdisCloseConfiguration(configHandle);
//
// We have gleaned all we can from the registry - was it all OK?
//
if (status != NDIS_STATUS_SUCCESS)
{
//
// If Status is not success, it will be either NDIS_STATUS_FAILURE
// if a parameter was out of range, or it will be the error code
// returned by NdisReadConfiguration().
//
MadgePrint2("MadgeReadRegistry failed rc = %x\n", status);
MADGE_FREE_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
return status;
}
//
// ---------------------------------------------------------------------
// Having read the registry, we can initialize the rest of the fields in
// the adapter structure.
//
#define I_DATA ActualValue.ParameterData.IntegerData
//
// Copy the values from the Parameter table into the per-adapter struct.
// This is necessary because the Parameter table will be used again for
// the next card that is added.
//
// Note that we handle the rx/tx slots configuration in a special way.
// The value of rx/tx slots is set by indexing into a table with the
// single paramter RxTxSlots, unless RxSlots or TxSlots have been set in
// which case these values override the values derived from RxTxSlots.
//
switch (MadgeParmTable.RxTxSlots.I_DATA)
{
case 0:
ndisAdap->FastmacTxSlots = 2;
ndisAdap->FastmacRxSlots = 2;
break;
case 1:
ndisAdap->FastmacTxSlots = 3;
ndisAdap->FastmacRxSlots = 3;
break;
case 2:
ndisAdap->FastmacTxSlots = 4;
ndisAdap->FastmacRxSlots = 4;
break;
case 3:
ndisAdap->FastmacTxSlots = 6;
ndisAdap->FastmacRxSlots = 6;
break;
case 4:
ndisAdap->FastmacTxSlots = 8;
ndisAdap->FastmacRxSlots = 8;
break;
case 5:
ndisAdap->FastmacTxSlots = 10;
ndisAdap->FastmacRxSlots = 10;
break;
default:
ndisAdap->FastmacTxSlots = 4;
ndisAdap->FastmacRxSlots = 4;
break;
}
if (MadgeParmTable.TxSlots.I_DATA != 0)
{
ndisAdap->FastmacTxSlots = MadgeParmTable.TxSlots.I_DATA;
}
if (MadgeParmTable.RxSlots.I_DATA != 0)
{
ndisAdap->FastmacRxSlots = MadgeParmTable.RxSlots.I_DATA;
}
MadgePrint3("TX slots = %d RX slots = %d\n",
ndisAdap->FastmacTxSlots,
ndisAdap->FastmacRxSlots
);
ndisAdap->MaxFrameSize = MadgeParmTable.MaxFrameSize.I_DATA;
ndisAdap->CardBufferSize = MadgeParmTable.CardBufferSize.I_DATA;
ndisAdap->PromiscuousMode = (MadgeParmTable.PromiscuousMode.I_DATA == 1);
ndisAdap->AlternateIo = (MadgeParmTable.AlternateIo.I_DATA == 1);
ndisAdap->TestAndXIDEnabled = (MadgeParmTable.TestAndXIDEnabled.I_DATA == 1);
ndisAdap->ForceOpen = (MadgeParmTable.ForceOpen.I_DATA == 1);
ndisAdap->Force4 = (MadgeParmTable.Force4.I_DATA == 1);
ndisAdap->Force16 = (MadgeParmTable.Force16.I_DATA == 1);
ndisAdap->Multiprocessor = (NdisSystemProcessorCount() > 1);
if (ndisAdap->TransferMode != DMA_DATA_TRANSFER_MODE &&
ndisAdap->Multiprocessor)
{
ndisAdap->UseMPSafePIO = TRUE;
}
//
// If the RingSpeed parameter is present then this overrides the
// Force4 and Force16 parameters. RingSpeed == 0 means either not
// present or don't care. RingSpeed == 1 means 4MBits. RingSpeed == 2
// means 16MBits.
//
switch (MadgeParmTable.RingSpeed.I_DATA)
{
case 1:
ndisAdap->Force4 = TRUE;
ndisAdap->Force16 = FALSE;
break;
case 2:
ndisAdap->Force4 = FALSE;
ndisAdap->Force16 = TRUE;
default:
break;
}
//
// Initialize the rest of the Adapter structure.
//
ndisAdap->UsedInISR.MiniportHandle = miniportHandle;
ndisAdap->CurrentLookahead = ndisAdap->MaxFrameSize - FRAME_HEADER_SIZE;
ndisAdap->CurrentRingState = NdisRingStateClosed;
ndisAdap->HardwareStatus = NdisHardwareStatusNotReady;
//
// These next few lines are strictly unnecessary because their fields in
// the structure are already zero from our earlier ZERO_MEMORY() call.
//
ndisAdap->UsedInISR.SrbRequestCompleted = FALSE;
ndisAdap->UsedInISR.SrbRequestStatus = FALSE;
ndisAdap->DprInProgress = FALSE;
//
// One nasty piece of hackery for Smart16 cards, whereby we must add to
// the IoLocation 0x1000 if the Alternate switch is true.
//
if (ndisAdap->NTCardBusType == NdisInterfaceIsa &&
ndisAdap->IoLocation1 > 0x3a20 &&
ndisAdap->AlternateIo)
{
ndisAdap->IoLocation1 += 0x1000;
}
//
// We need to know where the end of the first range of IO locations
// we use is.
//
ndisAdap->IORange1End = ndisAdap->IoLocation1 + ndisAdap->IORange1 - 1;
//
// ---------------------------------------------------------------------
// We can now try to register the adapter. This involves filling in the
// AdapterInformation structure and calling NdisRegisterAdapter(). See
// the function MadgeRegisterAdapter for details.
//
if ((status = MadgeRegisterAdapter(
ndisAdap,
wrapperConfigContext
)) != NDIS_STATUS_SUCCESS)
{
//
// Either we failed to allocate memory for the adapter information
// structure, or the NdisRegisterAdapter() call failed.
//
MadgePrint2("MadgeRegisterAdapter failed rc = %x\n", status);
MADGE_FREE_MEMORY(ndisAdap, sizeof(MADGE_ADAPTER));
return status;
}
//
// ---------------------------------------------------------------------
// We are now into the last stages of initialization. This is going to
// cause to be allocated several more resources (in the form of kernel
// objects, filter databases, FTK structures, interrupt channels, ...)
// so from here on we have to be a lot more careful about cleaning up.
//
ndisAdap->HardwareStatus = NdisHardwareStatusInitializing;
//
// Call the FTK to download the MAC code to the card and initialize it.
//
status = MadgeInitAdapter(ndisAdap);
if (status != NDIS_STATUS_SUCCESS)
{
//
// If it was an FTK generated error then log an appropriate event.
//
if (status == NDIS_STATUS_FAILURE)
{
BYTE error_type;
BYTE error_value;
char * error_message;
driver_explain_error(
ndisAdap->FtkAdapterHandle,
&error_type,
&error_value,
&error_message
);
MadgePrint3("FTK error %02x, %02x\n", error_type, error_value);
//
// To keep Microsoft happy we will generate special error
// messages for some of the more common error conditions.
//
//
// An open error is probably because the cable isn't plugged in.
//
if (error_type == ERROR_TYPE_OPEN ||
error_type == ERROR_TYPE_AUTO_OPEN)
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER,
4,
madgeInitialize,
MADGE_ERRMSG_INITIAL_INIT,
(ULONG) error_type,
(ULONG) error_value
);
}
else
{
NdisWriteErrorLogEntry(
ndisAdap->UsedInISR.MiniportHandle,
NDIS_ERROR_CODE_HARDWARE_FAILURE,
4,
madgeInitialize,
MADGE_ERRMSG_INITIAL_INIT,
(ULONG) error_type,
(ULONG) error_value
);
}
}
//
// In any case, tidy up the adapter and abort.
//
MadgeCleanupAdapter(ndisAdap);
return status;
}
ndisAdap->HardwareStatus = NdisHardwareStatusReady;
//
// Set up the ring status monitor function.
//
NdisMInitializeTimer(
&ndisAdap->WakeUpTimer,
ndisAdap->UsedInISR.MiniportHandle,
(PVOID) MadgeGetAdapterStatus,
ndisAdap
);
NdisMSetTimer(&ndisAdap->WakeUpTimer, EVERY_2_SECONDS);
NdisMInitializeTimer(
&ndisAdap->CompletionTimer,
ndisAdap->UsedInISR.MiniportHandle,
(PVOID) MadgeTxCompletion,
ndisAdap
);
ndisAdap->TimerInitialized = TRUE;
MadgePrint1("MadgeInitialize finished\n");
return NDIS_STATUS_SUCCESS;
}
/***************************************************************************
*
* Function - DriverEntry
*
* Parameters - driverObject -> Pointer to a driver object.
* registryPath -> Path to our configuration information in
* the registry.
*
* Purpose - Carry out the driver (as opposed to adapter instance)
* initialisation. This is the main entry point.
*
* Returns - An NDIS3 status code.
*
***************************************************************************/
NDIS_STATUS
DriverEntry(PDRIVER_OBJECT driverObject, PUNICODE_STRING registryPath);
#pragma FTK_INIT_FUNCTION(DriverEntry)
NDIS_STATUS
DriverEntry(PDRIVER_OBJECT driverObject, PUNICODE_STRING registryPath)
{
NDIS_HANDLE ndisWrapperHandle;
NDIS_STATUS status;
NDIS_MINIPORT_CHARACTERISTICS madgeChar;
UINT i;
MadgePrint1("DriverEntry starting\n");
//
// We are obliged first of all to initialize the NDIS wrapper.
//
MadgePrint1("NdisMInitializeWrapper called\n");
NdisMInitializeWrapper(
&ndisWrapperHandle,
driverObject,
registryPath,
NULL
);
MadgePrint1("NdisMInitializeWrapper returned\n");
//
// Decode any hidden strings here, for use later in MacAddAdapter. This
// only applies to PromiscuousMode support at the moment.
//
for (i = 0;
i < MadgeParmTable.PromiscuousMode.Keyword.Length /
sizeof(*(MadgeParmTable.PromiscuousMode.Keyword.Buffer));
i++)
{
MadgeParmTable.PromiscuousMode.Keyword.Buffer[i] -= HIDDEN_OFFS;
}
//
// Fill in the characteristics table - this lists all the driver entry
// points that may be called by the NDIS wrapper.
//
madgeChar.MajorNdisVersion = MADGE_NDIS_MAJOR_VERSION;
madgeChar.MinorNdisVersion = MADGE_NDIS_MINOR_VERSION;
madgeChar.CheckForHangHandler = MadgeCheckForHang;
madgeChar.DisableInterruptHandler = MadgeDisableInterrupts;
madgeChar.EnableInterruptHandler = MadgeEnableInterrupts;
madgeChar.HaltHandler = MadgeHalt;
madgeChar.HandleInterruptHandler = MadgeHandleInterrupt;
madgeChar.InitializeHandler = MadgeInitialize;
madgeChar.ISRHandler = MadgeISR;
madgeChar.QueryInformationHandler = MadgeQueryInformation;
madgeChar.ReconfigureHandler = NULL;
madgeChar.ResetHandler = MadgeReset;
madgeChar.SendHandler = MadgeSend;
madgeChar.SetInformationHandler = MadgeSetInformation;
madgeChar.TransferDataHandler = MadgeTransferData;
//
// Register the miniport driver with NDIS library.
//
MadgePrint1("NdisMRegisterMiniport called\n");
status = NdisMRegisterMiniport(
ndisWrapperHandle,
&madgeChar,
sizeof(madgeChar)
);
MadgePrint1("NdisMRegisterMiniport returned\n");
if (status != NDIS_STATUS_SUCCESS)
{
MadgePrint2("NdisMRegisterMiniport failed rc=%x\n", status);
NdisTerminateWrapper(ndisWrapperHandle, NULL);
return NDIS_STATUS_FAILURE;
}
MadgePrint1("DriverEntry finished\n");
return NDIS_STATUS_SUCCESS;
}
/******** End of MADGE.C ***************************************************/