summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/madge/driver/madge.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/madge/driver/madge.c')
-rw-r--r--private/ntos/ndis/madge/driver/madge.c3393
1 files changed, 3393 insertions, 0 deletions
diff --git a/private/ntos/ndis/madge/driver/madge.c b/private/ntos/ndis/madge/driver/madge.c
new file mode 100644
index 000000000..9e3e22dda
--- /dev/null
+++ b/private/ntos/ndis/madge/driver/madge.c
@@ -0,0 +1,3393 @@
+/***************************************************************************
+*
+* 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 ***************************************************/
+