summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/elnk3
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/elnk3/card.c1321
-rw-r--r--private/ntos/ndis/elnk3/config.c514
-rw-r--r--private/ntos/ndis/elnk3/debug.h133
-rw-r--r--private/ntos/ndis/elnk3/elnk3.c174
-rw-r--r--private/ntos/ndis/elnk3/elnk3.h424
-rw-r--r--private/ntos/ndis/elnk3/elnk3.rc39
-rw-r--r--private/ntos/ndis/elnk3/elnk3hrd.h549
-rw-r--r--private/ntos/ndis/elnk3/elnk3sft.h361
-rw-r--r--private/ntos/ndis/elnk3/init.c897
-rw-r--r--private/ntos/ndis/elnk3/interrup.c418
-rw-r--r--private/ntos/ndis/elnk3/keywords.h56
-rw-r--r--private/ntos/ndis/elnk3/makefile6
-rw-r--r--private/ntos/ndis/elnk3/receive.c1722
-rw-r--r--private/ntos/ndis/elnk3/request.c839
-rw-r--r--private/ntos/ndis/elnk3/send.c292
-rw-r--r--private/ntos/ndis/elnk3/sources51
16 files changed, 7796 insertions, 0 deletions
diff --git a/private/ntos/ndis/elnk3/card.c b/private/ntos/ndis/elnk3/card.c
new file mode 100644
index 000000000..ba8e26d9f
--- /dev/null
+++ b/private/ntos/ndis/elnk3/card.c
@@ -0,0 +1,1321 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ card.c
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+Author:
+
+ Brian Lieuallen BrianLie 09/22/92
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+
+
+--*/
+
+
+
+#include <ndis.h>
+#include <efilter.h>
+
+#include "debug.h"
+
+
+#include "elnk3hrd.h"
+#include "elnk3sft.h"
+#include "elnk3.h"
+
+#include "keywords.h"
+
+
+#pragma NDIS_INIT_FUNCTION(Elnk3FindIsaBoards)
+#pragma NDIS_INIT_FUNCTION(Elnk3ActivateIsaBoard)
+#pragma NDIS_INIT_FUNCTION(ReadStationAddress)
+#pragma NDIS_INIT_FUNCTION(ELNK3WriteIDSequence)
+#pragma NDIS_INIT_FUNCTION(ELNK3ContentionTest)
+#pragma NDIS_INIT_FUNCTION(Elnk3GetEisaResources)
+#pragma NDIS_INIT_FUNCTION(CardEnable)
+#pragma NDIS_INIT_FUNCTION(CardTest)
+#pragma NDIS_INIT_FUNCTION(ELNK3ReadEEProm)
+#pragma NDIS_INIT_FUNCTION(Elnk3ProgramEEProm)
+#pragma NDIS_INIT_FUNCTION(Elnk3WriteEEProm)
+#pragma NDIS_INIT_FUNCTION(Elnk3WaitEEPromNotBusy)
+
+
+BOOLEAN
+CardTest (
+ OUT PELNK3_ADAPTER pAdapter
+ )
+/*++
+
+ Routine Description:
+
+
+ Arguments:
+
+
+ Return Value:
+
+
+--*/
+{
+
+ IF_INIT_LOUD (DbgPrint("Elnk3: CardTest(): Entered\n");)
+
+
+ if (!ReadStationAddress(pAdapter)) {
+ return FALSE;
+ }
+
+
+ if (!CardEnable(pAdapter)) {
+ return FALSE;
+ }
+
+
+ return TRUE;
+}
+
+
+BOOLEAN
+CardEnable(
+ IN PELNK3_ADAPTER pAdapter
+ )
+/*++
+
+Routine Description:
+
+ This routine enables the card hardware and sets the dma channel and
+ interrupts number by writing to the Cards option register
+
+Arguments:
+
+Return Value:
+
+Note:
+
+ This should not be called before the registry is read and the Dma
+ and interrupt info is in place.
+
+--*/
+
+{
+
+ USHORT Temp;
+ UINT i;
+ ULONG Limit;
+ USHORT AddressConfig;
+ USHORT RevisionLevel;
+
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: CardEnable\n");)
+
+
+ CardReset(pAdapter);
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_FIFO);
+
+ ELNK3ReadAdapterUshort(pAdapter,PORT_FREE_RX_BYTES,&pAdapter->RxFifoSize);
+
+
+ //
+ // Set the station address
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_STATIONADDRESS);
+
+ for (i=0;i<3;i++) {
+ Temp=pAdapter->StationAddress[i*2] | (((USHORT)pAdapter->StationAddress[i*2+1])<<8);
+ ELNK3WriteAdapterUshort(pAdapter,(i*2),Temp);
+ }
+
+ //
+ // Read address config register to find out transceiver type
+ //
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_SETUP);
+
+ ELNK3ReadAdapterUshort(pAdapter,PORT_CfgAddress,&AddressConfig);
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_DIAGNOSTICS);
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: Address config register is %04x\n",AddressConfig);)
+
+ if ((AddressConfig >> 14) == 0) {
+ //
+ // Enable link beat on TP
+ //
+ if (pAdapter->EEpromSoftwareInfo & LINK_BEAT_DISABLED) {
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: CardEnable: NOT Enabling link beat on 10 Base-T\n");)
+
+ ELNK3WriteAdapterUshort(pAdapter,PORT_MEDIA_TYPE, MEDIA_JABBER);
+
+ } else {
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: CardEnable: Enabling link beat on 10 Base-T\n");)
+
+ ELNK3WriteAdapterUshort(pAdapter,PORT_MEDIA_TYPE,MEDIA_LINK_BEAT | MEDIA_JABBER);
+
+ }
+
+ }
+
+ ELNK3ReadAdapterUshort(pAdapter,PORT_NET_DIAG,&RevisionLevel);
+
+ RevisionLevel= ((RevisionLevel & 0x1e) >> 1);
+
+ pAdapter->RevisionLevel=(UCHAR)RevisionLevel;
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_OPERATING);
+
+ //
+ // Test to see if the interrupt works or not
+ //
+ ELNK3_COMMAND(pAdapter,EC_ACKNOWLEDGE_INTERRUPT,0xff);
+ ELNK3_COMMAND(pAdapter,EC_SET_INTERRUPT_MASK,EC_INT_INTERRUPT_REQUESTED);
+ ELNK3_COMMAND(pAdapter,EC_SET_READ_ZERO_MASK,0xff);
+
+ pAdapter->InitInterrupt=FALSE;
+
+ pAdapter->AdapterInitializing=TRUE;
+
+ ELNK3_COMMAND(pAdapter,EC_REQUEST_INTERRUPT,0);
+
+ Limit=2000;
+
+ while ((--Limit>0) && (!pAdapter->InitInterrupt)) {
+ NdisStallExecution(10);
+ }
+
+ pAdapter->AdapterInitializing=FALSE;
+
+ //
+ // Did it time out or did we get an interrupt
+ //
+ if (Limit==0) {
+ IF_INIT_LOUD(DbgPrint("ELNK3: Did not receive interrupt\n");)
+ return FALSE;
+ }
+
+ ELNK3_COMMAND(pAdapter,EC_RX_RESET,0);
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+
+
+
+// ELNK3_COMMAND(pAdapter,EC_RX_ENABLE,0);
+// ELNK3_COMMAND(pAdapter,EC_TX_ENABLE,0);
+
+ if ((AddressConfig >> 14) == 3) {
+ //
+ // turn on 10base2 converter
+ //
+ IF_INIT_LOUD(DbgPrint("ELNK3: CardEnable: Turning on 10base2 converter\n");)
+
+ ELNK3_COMMAND(pAdapter,EC_START_COAX_XCVR,0);
+
+ NdisStallExecution(800);
+ }
+
+
+
+ pAdapter->CurrentInterruptMask=EC_INT_RX_EARLY |
+ EC_INT_TX_COMPLETE |
+ EC_INT_RX_COMPLETE |
+ EC_INT_TX_AVAILABLE |
+ EC_INT_ADAPTER_FAILURE |
+ EC_INT_INTERRUPT_REQUESTED;
+
+ ELNK3_COMMAND(pAdapter,EC_SET_INTERRUPT_MASK,pAdapter->CurrentInterruptMask);
+ ELNK3_COMMAND(pAdapter,EC_SET_READ_ZERO_MASK,pAdapter->CurrentInterruptMask);
+
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: Adapter initialized correctly\n");)
+ return TRUE;
+}
+
+
+
+BOOLEAN
+CardReInit(
+ IN PELNK3_ADAPTER pAdapter
+ )
+
+{
+ USHORT FifoStatus;
+ USHORT FreeFifoBytes;
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_DIAGNOSTICS);
+
+ ELNK3ReadAdapterUshort(pAdapter,PORT_FIFO_DIAG,&FifoStatus);
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_OPERATING);
+
+ if (FifoStatus & RX_UNDERRUN) {
+ IF_LOUD(DbgPrint("ELNK3: Receive Underrun\n");)
+
+ ELNK3_COMMAND(pAdapter,EC_RX_RESET,0);
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+
+ ELNK3_COMMAND(pAdapter,EC_RX_ENABLE,0);
+
+ ELNK3_COMMAND(pAdapter, EC_SET_RX_FILTER, pAdapter->RxFilter);
+ }
+
+ if (FifoStatus & TX_OVERRUN) {
+
+ ELNK3ReadAdapterUshort(pAdapter,PORT_TxFree,&FreeFifoBytes);
+
+ IF_LOUD(DbgPrint("ELNK3: Transmit Overrun - Bytesfree=%d\n",FreeFifoBytes);)
+
+
+ ELNK3_COMMAND(pAdapter,EC_TX_RESET,0);
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+
+ ELNK3_COMMAND(pAdapter,EC_TX_ENABLE,0);
+ }
+
+
+ return TRUE;
+
+}
+
+
+VOID
+CardReStart(
+ IN PELNK3_ADAPTER pAdapter
+ )
+
+{
+
+ IF_LOUD(DbgPrint("ELNK3: CardRestart\n");)
+
+ //
+ // put the filter back
+ //
+ ELNK3_COMMAND(pAdapter, EC_SET_RX_FILTER, 0);
+
+
+ ELNK3_COMMAND(pAdapter,EC_SET_READ_ZERO_MASK,0x00);
+
+ pAdapter->CurrentInterruptMask=EC_INT_RX_EARLY |
+ EC_INT_TX_COMPLETE |
+ EC_INT_RX_COMPLETE |
+ EC_INT_TX_AVAILABLE |
+ EC_INT_ADAPTER_FAILURE |
+ EC_INT_INTERRUPT_REQUESTED;
+
+ ELNK3_COMMAND(pAdapter,EC_SET_INTERRUPT_MASK,pAdapter->CurrentInterruptMask);
+
+
+
+ //
+ // Reset and re-enable the receiver
+ //
+ ELNK3_COMMAND(pAdapter,EC_RX_RESET,0);
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+
+ ELNK3_COMMAND(pAdapter,EC_RX_ENABLE,0);
+
+
+ //
+ // reset and restart the transmitter
+ //
+ ELNK3_COMMAND(pAdapter,EC_TX_RESET,0);
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+
+ ELNK3_COMMAND(pAdapter,EC_TX_ENABLE,0);
+
+ ELNK3_COMMAND(pAdapter,EC_SET_TX_START,pAdapter->TxStartThreshold & 0x7ff);
+
+ //
+ // clear all pending interrupts
+ //
+ ELNK3_COMMAND(pAdapter,EC_ACKNOWLEDGE_INTERRUPT,0xff);
+
+ //
+ // reset the receive buffer info
+ //
+ pAdapter->CurrentPacket=0;
+
+ pAdapter->TransContext[0].BytesAlreadyRead=0;
+ pAdapter->TransContext[0].PacketLength=0;
+
+ pAdapter->TransContext[1].BytesAlreadyRead=0;
+ pAdapter->TransContext[1].PacketLength=0;
+}
+
+
+VOID
+CardReStartDone(
+ IN PELNK3_ADAPTER pAdapter
+ )
+
+{
+
+ IF_LOUD(DbgPrint("ELNK3: CardRestartDone\n");)
+
+ ELNK3_COMMAND(pAdapter,EC_SET_READ_ZERO_MASK,0xff);
+ //
+ // put the filter back
+ //
+ ELNK3_COMMAND(pAdapter, EC_SET_RX_FILTER, pAdapter->RxFilter);
+
+ return;
+}
+
+
+VOID
+CardReset(
+ IN PELNK3_ADAPTER pAdapter
+ )
+/*++
+
+ Routine Description:
+
+
+ Arguments:
+
+
+ Return Value:
+
+
+--*/
+{
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: Reset Card\n");)
+
+ //
+ // Mask everything
+ //
+ ELNK3_COMMAND(pAdapter,EC_SET_INTERRUPT_MASK,0);
+
+ //
+ // Clear all interrupt reasons
+ //
+ ELNK3_COMMAND(pAdapter,EC_ACKNOWLEDGE_INTERRUPT,0xff);
+
+
+ ELNK3_COMMAND(pAdapter,EC_RX_RESET,0);
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+
+ ELNK3_COMMAND(pAdapter,EC_TX_RESET,0);
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+}
+
+
+
+
+BOOLEAN
+ReadStationAddress(
+ OUT PELNK3_ADAPTER pAdapter
+ )
+/*++
+
+ Routine Description:
+ Read the station address from the PROM
+
+ Arguments:
+
+
+ Return Value:
+
+
+--*/
+
+{
+
+ UINT i,Sum;
+ USHORT Temp;
+
+ Sum=0;
+
+ IF_INIT_LOUD( DbgPrint("Elnk3: The Station address is ");)
+
+ ELNK3_SELECT_WINDOW(pAdapter,0);
+
+
+ //
+ // Read the eeprom software info to see if we need
+ // to enable link beat of not
+ //
+ pAdapter->EEpromSoftwareInfo=ELNK3ReadEEProm(
+ pAdapter,
+ (UCHAR)EEPROM_SOFTWARE_INFO
+ );
+
+
+
+ for (i=0;i<3;i++) {
+ Temp=ELNK3ReadEEProm(
+ pAdapter,
+ (UCHAR)i
+ );
+
+
+ pAdapter->PermanentAddress[i*2] = Temp>>8;
+ pAdapter->PermanentAddress[i*2+1] = Temp & 0x00ff;
+ IF_INIT_LOUD( DbgPrint(" %04X",Temp);)
+ }
+
+ //
+ // Put the product id value back in the eeprom data register
+ //
+ ELNK3ReadEEProm(
+ pAdapter,
+ (UCHAR)EEPROM_PRODUCT_ID
+ );
+
+
+
+
+ //
+ // Copy in permanent address if necessary
+ //
+
+ if (!(pAdapter->StationAddress[0] |
+ pAdapter->StationAddress[1] |
+ pAdapter->StationAddress[2] |
+ pAdapter->StationAddress[3] |
+ pAdapter->StationAddress[4] |
+ pAdapter->StationAddress[5])) {
+
+ ETH_COPY_NETWORK_ADDRESS(pAdapter->StationAddress,
+ pAdapter->PermanentAddress
+ );
+ }
+
+
+ IF_INIT_LOUD( DbgPrint("\n");)
+
+
+ return TRUE;
+}
+
+
+
+
+
+UINT
+Elnk3FindIsaBoards(
+ IN PMAC_BLOCK pMacBlock
+ )
+
+{
+
+ PVOID IdPort=pMacBlock->TranslatedIdPort;
+ UINT i;
+ USHORT ProductId;
+
+
+ if (pMacBlock->IsaAdaptersFound != 0) {
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: FindIsaBorads: called again\n");)
+
+ return pMacBlock->IsaAdaptersFound;
+ }
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: FindIsaBorads: called, first time\n");)
+
+ //
+ // Untag all adapters
+ //
+
+ ELNK3WriteIDSequence( IdPort );
+
+ NdisRawWritePortUchar(IdPort, IDCMD_SET_TAG+0);
+
+ //
+ // We find all the ISA boards in the system and tag them
+ // We note each ones configured I/O base, so that
+ // we can reset all of the ones not configured as EISA
+ //
+
+ for (i=0; i<7 ; i++) {
+
+ //
+ // Get the cards' attention
+ //
+ ELNK3WriteIDSequence( IdPort );
+
+ //
+ // See if there any cards out there
+ //
+ if ( ELNK3ContentionTest( IdPort, EE_MANUFACTURER_CODE ) == EISA_MANUFACTURER_ID ) {
+ //
+ // we found at least one
+ //
+ ELNK3ContentionTest( IdPort, EE_TCOM_NODE_ADDR_WORD0 );
+ ELNK3ContentionTest( IdPort, EE_TCOM_NODE_ADDR_WORD1 );
+ ELNK3ContentionTest( IdPort, EE_TCOM_NODE_ADDR_WORD2 );
+
+ //
+ // This one won the contention battle
+ // Get it's i/o base and irq from the eeprom
+ //
+
+ ProductId=ELNK3ContentionTest( IdPort, EE_VULCAN_PROD_ID );
+
+ ProductId&=0xf0ff;
+
+ if (ProductId == 0x9050) {
+ //
+ // This one is a elnk3 adapter
+ //
+ pMacBlock->IsaCards[i].AddressConfigRegister=
+ ELNK3ContentionTest( IdPort, EE_ADDR_CONFIGURATION );
+
+ pMacBlock->IsaCards[i].IOPort= 0x200 + ((pMacBlock->IsaCards[i].AddressConfigRegister & 0x1f)<<4);
+
+ } else {
+ //
+ // We found a 3Com card that is not an elnk3.
+ // We will set the base address, to make it look like an EISA
+ // one so that code below will leave it alone
+ //
+ IF_INIT_LOUD(DbgPrint("Elnk3: Found non-elnk3 during contention ProductId=%04x\n",ProductId);)
+
+ pMacBlock->IsaCards[i].IOPort=0x3f0;
+ }
+
+ pMacBlock->IsaCards[i].Tagged=TRUE;
+ //
+ // Tag it so it don't bother us again
+ //
+ NdisRawWritePortUchar(IdPort, IDCMD_SET_TAG+(i+1));
+
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: Found Elnk3 card #%d, io=%04x\n",
+ i,
+ pMacBlock->IsaCards[i].IOPort
+ );)
+
+
+ } else {
+ //
+ // No more elnk3 cards
+ //
+ break;
+ }
+ }
+
+
+ //
+ // Now all of the ISA adapters have been found and tagged
+ // We now go through and reset all of the ones that are
+ // not configured as EISA.
+ //
+
+ for (i=0; i<7 ; i++) {
+
+ //
+ // Get the cards' attention
+ //
+ ELNK3WriteIDSequence( IdPort );
+
+ //
+ // If it is not configured as eisa reset it
+ //
+ if ((pMacBlock->IsaCards[i].IOPort != 0x03f0) && pMacBlock->IsaCards[i].Tagged) {
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: Reseting Elnk3 card #%d\n",i);)
+
+ //
+ // Put the others back to sleep
+ //
+ NdisRawWritePortUchar(IdPort, IDCMD_TEST_TAG+(i+1));
+
+ //
+ // Reset this one
+ //
+ NdisRawWritePortUchar(IdPort, IDCMD_RESET);
+
+ NdisStallExecution(500);
+
+ } else {
+#if DBG
+ if (pMacBlock->IsaCards[i].Tagged) {
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: NOT Reseting EISA configured Elnk3 card #%d\n",i);)
+ }
+#endif
+ }
+
+ }
+
+ //
+ // Now we go and find the adapters for real.
+ //
+
+ //
+ // Untag all adapters
+ //
+
+ ELNK3WriteIDSequence( IdPort );
+
+ NdisRawWritePortUchar(IdPort, IDCMD_SET_TAG+0);
+
+
+ for (i=0; i<7 ; i++) {
+
+ //
+ // Get the cards' attention
+ //
+ ELNK3WriteIDSequence( IdPort );
+
+ //
+ // See if there any cards out there
+ //
+ if ( ELNK3ContentionTest( IdPort, EE_MANUFACTURER_CODE ) == EISA_MANUFACTURER_ID ) {
+
+ //
+ // we found at least one
+ //
+ ELNK3ContentionTest( IdPort, EE_TCOM_NODE_ADDR_WORD0 );
+ ELNK3ContentionTest( IdPort, EE_TCOM_NODE_ADDR_WORD1 );
+ ELNK3ContentionTest( IdPort, EE_TCOM_NODE_ADDR_WORD2 );
+
+ //
+ // This one won the contention battle
+ // Get it's i/o base and irq from the eeprom
+ //
+
+ ProductId=ELNK3ContentionTest( IdPort, EE_VULCAN_PROD_ID );
+
+ ProductId&=0xf0ff;
+
+ if (ProductId == 0x9050) {
+ //
+ // This one is a elnk3 adapter
+ //
+
+ pMacBlock->IsaCards[i].AddressConfigRegister=
+ ELNK3ContentionTest( IdPort, EE_ADDR_CONFIGURATION );
+
+ pMacBlock->IsaCards[i].ResourceConfigRegister=
+ ELNK3ContentionTest( IdPort, EE_RESOURCE_CONFIGURATION );
+
+
+ pMacBlock->IsaCards[i].IOPort= 0x200 + ((pMacBlock->IsaCards[i].AddressConfigRegister & 0x1f)<<4);
+ pMacBlock->IsaCards[i].Irq=pMacBlock->IsaCards[i].ResourceConfigRegister >> 12;
+
+ if (pMacBlock->IsaCards[i].IOPort == 0x03f0) {
+ //
+ // This one is configured as EISA. Mark it as active
+ // so it will be ignored
+ //
+ IF_INIT_LOUD(DbgPrint("ELNK3: Found Elnk3 ISA configed as EISA\n");)
+
+ pMacBlock->IsaCards[i].Active=TRUE;
+ }
+
+ } else {
+ //
+ // We found a 3Com card that is not an elnk3.
+ // We will set the base address, to make it look like an EISA
+ // one so that code below will leave it alone
+ //
+ IF_INIT_LOUD(DbgPrint("Elnk3: Found non-elnk3 during contention ProductId=%04x\n",ProductId);)
+
+ pMacBlock->IsaCards[i].IOPort=0x3f0;
+
+ pMacBlock->IsaCards[i].Active=TRUE;
+ }
+
+
+ //
+ // Tag it so it don't bother us again
+ //
+ NdisRawWritePortUchar(IdPort, IDCMD_SET_TAG+(i+1));
+
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: Found Elnk3 card #%d, io=%04x, irq=%d\n",
+ i,
+ pMacBlock->IsaCards[i].IOPort,
+ pMacBlock->IsaCards[i].Irq
+ );)
+
+ //
+ // One more found
+ //
+ pMacBlock->IsaAdaptersFound++;
+
+ } else {
+ //
+ // No more elnk3 cards
+ //
+ break;
+ }
+ }
+
+ return pMacBlock->IsaAdaptersFound;
+
+}
+
+
+BOOLEAN
+Elnk3ActivateIsaBoard(
+ IN PMAC_BLOCK pMacBlock,
+ IN PELNK3_ADAPTER pAdapter,
+ IN NDIS_HANDLE AdapterHandle,
+ IN PUCHAR TranslatedIoBase,
+ IN ULONG ConfigIoBase,
+ IN OUT PULONG Irq,
+ IN ULONG Transceiver,
+ IN NDIS_HANDLE ConfigurationHandle
+ )
+
+{
+
+ PVOID IdPort=pMacBlock->TranslatedIdPort;
+ UINT i;
+ USHORT AddressConfig;
+ USHORT ResourceConfig;
+
+ for (i=0; i<pMacBlock->IsaAdaptersFound; i++) {
+ //
+ // Search our table for a card that matches the I/O base passed
+ // in from the registry
+ //
+
+ if ((pMacBlock->IsaCards[i].IOPort == ConfigIoBase)
+ &&
+ (pMacBlock->IsaCards[i].Irq==*Irq)
+ &&
+ ((pMacBlock->IsaCards[i].AddressConfigRegister>>14) == (USHORT)Transceiver)
+ &&
+ (!pMacBlock->IsaCards[i].Active)) {
+ //
+ // Everything matched and it is not currently active
+ //
+
+ IF_LOUD(DbgPrint("ELNK3: Found Match-Activating ISA card # %d at %04x\n",i,ConfigIoBase);)
+ //
+ // Found one, Now get the cards' attention
+ //
+
+ ELNK3WriteIDSequence( IdPort );
+
+ //
+ // Put the others back to sleep
+ //
+ NdisRawWritePortUchar(IdPort, IDCMD_TEST_TAG+(i+1));
+
+ //
+ // Activate it at the its configured base.
+ //
+ NdisRawWritePortUchar(IdPort,IDCMD_ACTIVATE + ((ConfigIoBase-0x200) >> 4));
+
+ //
+ // this one is in use now
+ //
+ pMacBlock->IsaCards[i].Active=TRUE;
+
+ //
+ // enable the IRQ drivers
+ //
+ NdisRawWritePortUchar(
+ TranslatedIoBase+PORT_CfgControl,
+ CCR_ENABLE
+ );
+
+ return TRUE;
+ }
+ }
+
+ IF_LOUD(DbgPrint("ELNK3: Did not find an adapter that matched i/O base %04x\n",ConfigIoBase);)
+
+ //
+ // Did not find a match, So now we activate the first unused
+ // card at the address supplied in the registry.
+ //
+ if ((*Irq != 0) && (Transceiver != 2)) {
+ //
+ // The irq and transceiver parameters are present,
+ // so we will reprogram the card to make them match
+ //
+
+ for (i=0; i<pMacBlock->IsaAdaptersFound; i++) {
+ //
+ // Search our table for a card that has not been activated
+ //
+
+ if ((!pMacBlock->IsaCards[i].Active)) {
+
+ IF_LOUD(DbgPrint("ELNK3: Reconfiguring ISA card # %d to %04x, %d, %d\n",i,ConfigIoBase,*Irq,Transceiver);)
+
+ //
+ // Found one, Now get the cards' attention
+ //
+
+ ELNK3WriteIDSequence( IdPort );
+
+ //
+ // Put the others back to sleep
+ //
+ NdisRawWritePortUchar(IdPort, IDCMD_TEST_TAG+(i+1));
+
+ //
+ // Activate where we want it
+ //
+ NdisRawWritePortUchar((PUCHAR)IdPort,IDCMD_ACTIVATE + ((ConfigIoBase-0x200) >> 4));
+
+ //
+ // in use now
+ //
+ pMacBlock->IsaCards[i].Active=TRUE;
+
+ //
+ // set the transceiver bits in the address config register
+ //
+ NdisRawReadPortUshort(
+ TranslatedIoBase+PORT_CfgAddress,
+ &AddressConfig
+ );
+
+ //
+ // only want the change the transceiver bits and io base
+ //
+ AddressConfig &= 0x3fc0;
+
+ AddressConfig |= (Transceiver << 14) | ((ConfigIoBase - 0x200) >> 4);
+
+ NdisRawWritePortUshort(
+ TranslatedIoBase+PORT_CfgAddress,
+ AddressConfig
+ );
+
+ //
+ // set the irq number in resources config register
+ //
+ ResourceConfig=((USHORT)*Irq << 12) | 0x0f00;
+
+
+ NdisRawWritePortUshort(
+ TranslatedIoBase+PORT_CfgResource,
+ ResourceConfig
+ );
+
+ //
+ // enable the IRQ drivers
+ //
+ NdisRawWritePortUchar(
+ TranslatedIoBase+PORT_CfgControl,
+ CCR_ENABLE
+ );
+
+
+ //
+ // Program the eeprom to match the registry
+ //
+ Elnk3ProgramEEProm(
+ pAdapter,
+ AddressConfig,
+ ResourceConfig
+ );
+
+ return TRUE;
+ }
+ }
+
+ //
+ // Did not find any un activated cards
+ //
+ IF_LOUD(DbgPrint("ELNK3: Did not find an un activated adapter\n");)
+
+ return FALSE;
+
+ } else {
+ //
+ // the irq and/or transceiver values were missing from the registry.
+ // Activate the card where the eeprom says it should be.
+ //
+ IF_LOUD(DbgPrint("Elnk3: irq and transceiver values missing\n");)
+
+ for (i=0; i<pMacBlock->IsaAdaptersFound; i++) {
+ //
+ // Search our table for a card that has not been activated
+ //
+ if ((pMacBlock->IsaCards[i].IOPort == ConfigIoBase)
+ &&
+ (!pMacBlock->IsaCards[i].Active)) {
+
+ IF_LOUD(DbgPrint("ELNK3: Activating ISA card # %d at %04x\n",i,ConfigIoBase);)
+
+ //
+ // Found one, Now get the cards' attention
+ //
+
+ ELNK3WriteIDSequence( IdPort );
+
+ //
+ // Put the others back to sleep
+ //
+ NdisRawWritePortUchar(IdPort, IDCMD_TEST_TAG+(i+1));
+
+ //
+ // Activate where we want it
+ //
+ NdisRawWritePortUchar((PUCHAR)IdPort,IDCMD_ACTIVATE + ((ConfigIoBase-0x200) >> 4));
+
+ //
+ // enable the IRQ drivers
+ //
+ NdisRawWritePortUchar(
+ TranslatedIoBase+PORT_CfgControl,
+ CCR_ENABLE
+ );
+
+ //
+ // in use now
+ //
+ pMacBlock->IsaCards[i].Active=TRUE;
+
+ *Irq=pMacBlock->IsaCards[i].Irq;
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: Missing IRQ is now %d\n",*Irq);)
+
+ {
+ NDIS_CONFIGURATION_PARAMETER Value;
+ NDIS_STATUS Status;
+ NDIS_STRING IrqKeyword = INTERRUPT;
+ NDIS_STRING TransceiverKeyword = TRANSCEIVER;
+ NDIS_HANDLE ConfigHandle = NULL;
+
+ //
+ // Open the configuration database.
+ //
+ NdisOpenConfiguration(
+ &Status,
+ &ConfigHandle,
+ ConfigurationHandle);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ return(FALSE);
+ }
+
+ Value.ParameterType = NdisParameterInteger;
+ Value.ParameterData.IntegerData = *Irq;
+ NdisWriteConfiguration(
+ &Status,
+ ConfigHandle,
+ &IrqKeyword,
+ &Value);
+
+ Value.ParameterType = NdisParameterInteger;
+ Value.ParameterData.IntegerData =
+ pMacBlock->IsaCards[i].AddressConfigRegister>>14;
+ NdisWriteConfiguration(
+ &Status,
+ ConfigHandle,
+ &TransceiverKeyword,
+ &Value);
+
+ NdisCloseConfiguration(ConfigHandle);
+ }
+
+ return TRUE;
+ }
+ }
+
+ //
+ // Did not find any un activated cards
+ //
+ IF_LOUD(DbgPrint("ELNK3: Did not find an un activated adapter\n");)
+
+ return FALSE;
+ }
+}
+
+
+VOID
+Elnk3ProgramEEProm(
+ PELNK3_ADAPTER pAdapter,
+ USHORT AddressConfig,
+ USHORT ResourceConfig
+ )
+
+{
+ USHORT Temp;
+ USHORT CheckSum;
+
+ Elnk3WriteEEProm(
+ pAdapter,
+ EE_ADDR_CONFIGURATION,
+ AddressConfig
+ );
+
+ Elnk3WriteEEProm(
+ pAdapter,
+ EE_RESOURCE_CONFIGURATION,
+ ResourceConfig
+ );
+
+ Temp=ELNK3ReadEEProm(
+ pAdapter,
+ EE_SOFTWARE_CONFIG_INFO
+ );
+
+ CheckSum=((AddressConfig>>8) ^ (AddressConfig & 0x00ff));
+
+ CheckSum= CheckSum ^ (ResourceConfig >> 8);
+ CheckSum= CheckSum ^ (ResourceConfig & 0x00ff);
+
+ CheckSum= CheckSum ^ (Temp >> 8);
+ CheckSum= CheckSum ^ (Temp & 0x00ff);
+
+ Temp=ELNK3ReadEEProm(
+ pAdapter,
+ EE_CHECK_SUM
+ );
+
+ Elnk3WriteEEProm(
+ pAdapter,
+ EE_CHECK_SUM,
+ (USHORT)((Temp & 0xff00) | (CheckSum & 0x00ff))
+ );
+
+}
+
+
+
+
+VOID
+ELNK3WriteIDSequence(
+ IN PVOID IdPort
+ )
+/*++
+
+Routine Description:
+
+ Writes the magic EtherLink III wake up sequence to a port.
+
+ This puts all uninitialized EtherLink III cards on the bus in the ID_CMD
+ state.
+
+ Must be called with exclusive access to all 1x0h ports, where x is any
+ hex digit.
+
+
+Arguments:
+
+
+Return Value:
+
+
+
+--*/
+
+
+{
+ USHORT outval;
+ UINT i;
+
+ NdisRawWritePortUchar(IdPort,0);
+ NdisRawWritePortUchar(IdPort,0);
+
+
+ for ( outval = 0xff, i = 255 ; i-- ; ) {
+ NdisRawWritePortUchar(IdPort,outval);
+ outval <<= 1;
+ if ( ( outval & 0x0100 ) != 0 ){
+ outval ^= 0xCF;
+ }
+ }
+}
+
+
+
+
+USHORT
+ELNK3ContentionTest(
+ IN PVOID IdPort,
+ IN UCHAR EEPromWord
+ )
+{
+
+ UCHAR data;
+ USHORT result;
+ UINT i;
+
+ NdisRawWritePortUchar((PUCHAR)IdPort,IDCMD_READ_PROM + EEPromWord);
+
+
+ /*
+ 3COM's detection code has a 400 microsecond delay here.
+ */
+ NdisStallExecution(400);
+
+ for ( i = 16, result = 0 ; i-- ; ) {
+ result <<= 1;
+ NdisRawReadPortUchar(IdPort,&data);
+ result += (data & 1);
+ }
+ return (result);
+}
+
+
+
+
+
+
+
+
+
+
+
+USHORT
+ELNK3ReadEEProm(
+ IN PELNK3_ADAPTER Adapter,
+ IN UCHAR EEPromWord
+)
+{
+ USHORT result;
+ ULONG Limit=10;
+
+ // Issue an EEPROM read command.
+
+ NdisRawWritePortUchar(Adapter->PortOffsets[PORT_EECmd],(UCHAR)(IDCMD_READ_PROM+EEPromWord));
+
+ //
+ // Spin until the EEPROM busy bit goes off.
+ //
+ Elnk3WaitEEPromNotBusy(Adapter);
+
+ //
+ // Fetch the data from the EEPROM data register.
+ //
+ ELNK3ReadAdapterUshort(Adapter,PORT_EEData,&result);
+
+ return ( result );
+}
+
+VOID
+Elnk3WriteEEProm(
+ IN PELNK3_ADAPTER pAdapter,
+ IN UCHAR EEPromWord,
+ IN USHORT Value
+ )
+
+{
+ Elnk3WaitEEPromNotBusy(pAdapter);
+
+ //
+ // put the data in the data register
+ //
+ ELNK3WriteAdapterUshort(pAdapter,PORT_EEData,Value);
+
+ //
+ // enable erase and write
+ //
+ ELNK3WriteAdapterUchar(pAdapter,PORT_EECmd,(UCHAR)EE_COMMAND_EW_ENABLE);
+
+ Elnk3WaitEEPromNotBusy(pAdapter);
+
+ //
+ // erase the register
+ //
+ ELNK3WriteAdapterUchar(pAdapter,PORT_EECmd,(UCHAR)EE_COMMAND_ERASE+EEPromWord);
+
+ Elnk3WaitEEPromNotBusy(pAdapter);
+
+ //
+ // enable erase and write again
+ //
+ ELNK3WriteAdapterUchar(pAdapter,PORT_EECmd,(UCHAR)EE_COMMAND_EW_ENABLE);
+
+ Elnk3WaitEEPromNotBusy(pAdapter);
+
+ //
+ // Now write the data
+ //
+ ELNK3WriteAdapterUchar(pAdapter,PORT_EECmd,(UCHAR)EE_COMMAND_WRITE+EEPromWord);
+
+ Elnk3WaitEEPromNotBusy(pAdapter);
+
+}
+
+VOID
+Elnk3WaitEEPromNotBusy(
+ PELNK3_ADAPTER Adapter
+ )
+
+{
+
+ USHORT result;
+ ULONG Limit;
+ //
+ // Spin until the EEPROM busy bit goes off.
+ //
+ Limit=100;
+
+ ELNK3ReadAdapterUshort(Adapter,PORT_EECmd,&result);
+
+ while ((--Limit>0) && ( (result & EE_BUSY) != 0)) {
+
+ NdisStallExecution(1000);
+ ELNK3ReadAdapterUshort(Adapter,PORT_EECmd,&result);
+
+ }
+
+#if DBG
+ if (Limit == 0) {
+
+ IF_LOUD(DbgPrint("Elnk3: time out waiting for eeprom to not be busy\n");)
+
+ }
+#endif
+
+}
+
+
+VOID
+Elnk3GetEisaResources(
+ IN PELNK3_ADAPTER pAdapter,
+ IN OUT PULONG Irq
+ )
+
+{
+ USHORT Config;
+
+ ELNK3_SELECT_WINDOW(pAdapter, WNO_SETUP);
+
+ ELNK3ReadAdapterUshort(pAdapter,PORT_CfgResource,&Config);
+
+ IF_LOUD(DbgPrint("Elnk3: Eisa Irq is %d\n",Config>>12);)
+
+ *Irq=Config>>12;
+
+}
+
+
+#ifdef IO_DBG
+USHORT ELNK3_READ_PORT_USHORT( PVOID Adapter, ULONG Offset )
+{
+ USHORT data;
+ data = READ_PORT_USHORT((PUSHORT)((PELNK3_ADAPTER)Adapter)->PortOffsets[Offset]);
+ IF_IO_LOUD(DbgPrint("read ushort %x from port %x\n", data, Offset );)
+ return data;
+}
+USHORT ELNK3_READ_PORT_USHORT_DIRECT( PVOID Offset )
+{
+ USHORT data;
+ data = READ_PORT_USHORT((PUSHORT)Offset);
+ IF_IO_LOUD(DbgPrint("read ushort %x from port %x\n", data, Offset );)
+ return data;
+}
+#endif
+
diff --git a/private/ntos/ndis/elnk3/config.c b/private/ntos/ndis/elnk3/config.c
new file mode 100644
index 000000000..3b8744842
--- /dev/null
+++ b/private/ntos/ndis/elnk3/config.c
@@ -0,0 +1,514 @@
+ /*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ config.c
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+
+Author:
+ Brian Lieuallen (BrianLie) 07/02/92
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+
+--*/
+
+
+
+#include <ndis.h>
+//#include <efilter.h>
+
+#include "debug.h"
+
+
+#include "elnk3hrd.h"
+#include "elnk3sft.h"
+#include "elnk3.h"
+
+#include "keywords.h"
+
+
+#pragma NDIS_INIT_FUNCTION(Elnk3ReadRegistry)
+
+
+
+NDIS_STATUS
+Elnk3ReadRegistry(
+ IN PELNK3_ADAPTER pAdapter,
+ IN NDIS_HANDLE ConfigurationHandle
+ )
+
+{
+ NDIS_HANDLE ConfigHandle = NULL;
+ PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
+ NDIS_STRING MaxMulticastListStr = MAX_MULTICAST_LIST;
+ NDIS_STRING IOAddressStr = IOADDRESS;
+ NDIS_STRING BusTypeStr = BUS_TYPE;
+ NDIS_STRING InterruptStr = INTERRUPT;
+ NDIS_STRING TransceiverStr = TRANSCEIVER;
+ NDIS_STRING ReceiveMethodStr = NDIS_STRING_CONST("ReceiveMethod");
+ NDIS_STRING ThresholdStr = NDIS_STRING_CONST("ThresholdTarget");
+ NDIS_STRING IdPortAddressStr = NDIS_STRING_CONST("IdPortBaseAddress");
+ NDIS_STRING TxThresholdStr = NDIS_STRING_CONST("EarlyTransmitThreshold");
+ NDIS_STRING TxThresholdIncStr = NDIS_STRING_CONST("EarlyTransmitThresholdIncrement");
+ NDIS_STRING CardTypeStr = NDIS_STRING_CONST("CardType");
+
+ BOOLEAN ConfigError = FALSE;
+ ULONG ConfigErrorValue = 0;
+
+ NDIS_MCA_POS_DATA McaData;
+
+ NDIS_STATUS Status;
+
+ UINT i;
+ //
+ // These are used when calling Elnk3RegisterAdapter.
+ //
+
+ ULONG TxThreshold = 384;
+ ULONG TxThresholdInc = 256;
+
+ ULONG ThresholdTarget = 400;
+ ELNK3_ADAPTER_TYPE AdapterType = 0;
+ UINT IoBaseAddr = 0x300;
+ UINT BusNumber = 0;
+ NDIS_INTERFACE_TYPE BusType = Eisa;
+ UINT ChannelNumber = 0;
+ ULONG InterruptNumber = 0;
+ PUCHAR NetworkAddress;
+ UINT Length;
+ UINT IdPortBaseAddr = 0x110;
+
+ NDIS_EISA_FUNCTION_INFORMATION EisaData;
+
+ NDIS_INTERRUPT_MODE InterruptMode=NdisInterruptLatched;
+
+ ULONG Transceiver = 2;
+
+ TxThreshold = 128;
+ TxThresholdInc = 64;
+
+ pAdapter->ReceiveMethod=0;
+
+ pAdapter->EarlyReceiveHandler=Elnk3IndicatePackets2;
+ pAdapter->ReceiveCompleteHandler=Elnk3IndicatePackets2;
+
+ NdisOpenConfiguration(
+ &Status,
+ &ConfigHandle,
+ ConfigurationHandle);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ return(Status);
+ }
+
+ //
+ // Read Adapter Type (determine if this is a 3c589 PCMCIA card)
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &CardTypeStr,
+ NdisParameterInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ AdapterType = (UINT)(ReturnedValue->ParameterData.IntegerData);
+ pAdapter->CardType = AdapterType;
+ }
+
+ //
+ // Read network address
+ //
+ NdisReadNetworkAddress(
+ &Status,
+ &NetworkAddress,
+ &Length,
+ ConfigHandle);
+ if (Status==NDIS_STATUS_SUCCESS)
+ {
+ for (i = 0; i < 6; i++)
+ {
+ pAdapter->StationAddress[i]=NetworkAddress[i];
+ }
+ }
+
+ //
+ // Read receive method
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &ReceiveMethodStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ pAdapter->ReceiveMethod=ReturnedValue->ParameterData.IntegerData;
+
+ if ((ReturnedValue->ParameterData.IntegerData) == 1)
+ {
+ //
+ // Change to alternate
+ //
+ IF_LOUD(DbgPrint("ELNK3: Using alternate receive method\n");)
+
+ pAdapter->EarlyReceiveHandler=Elnk3EarlyReceive;
+ pAdapter->ReceiveCompleteHandler=Elnk3IndicatePackets;
+ }
+ else
+ {
+ pAdapter->ReceiveMethod=0;
+
+ pAdapter->EarlyReceiveHandler=Elnk3IndicatePackets2;
+ pAdapter->ReceiveCompleteHandler=Elnk3IndicatePackets2;
+ }
+ }
+
+ //
+ // Read Threshold point
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &ThresholdStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ ThresholdTarget=ReturnedValue->ParameterData.IntegerData;
+ }
+
+
+ //
+ // Read TX Threshold start point
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &TxThresholdStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ TxThreshold=ReturnedValue->ParameterData.IntegerData;
+ }
+
+ //
+ // Read TX Threshold start point increment
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &TxThresholdIncStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ TxThresholdInc=ReturnedValue->ParameterData.IntegerData;
+ }
+
+ //
+ // Read Id port Address
+ //
+ if (AdapterType != ELNK3_3C589)
+ {
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &IdPortAddressStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ IdPortBaseAddr = (ReturnedValue->ParameterData.IntegerData);
+
+ //
+ // Confirm value
+ //
+ if (IdPortBaseAddr < 0x100 ||
+ IdPortBaseAddr > 0x1f0 ||
+ ((IdPortBaseAddr & 0x0f) != 0))
+ {
+ //
+ // Error
+ //
+ goto Fail00;
+ }
+ }
+ }
+
+ //
+ // Read interrupt number
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &InterruptStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ InterruptNumber = (CCHAR)(ReturnedValue->ParameterData.IntegerData);
+ }
+
+ //
+ // Read tranceiver type
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &TransceiverStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ Transceiver = (ReturnedValue->ParameterData.IntegerData);
+ }
+
+ //
+ // Read BusType type
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &BusTypeStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ BusType = (ReturnedValue->ParameterData.IntegerData);
+ }
+
+ if (BusType == Isa)
+ {
+ //
+ // Bus type ISA must be a 3c509.
+ //
+ if (AdapterType != ELNK3_3C589)
+ AdapterType=ELNK3_3C509;
+
+ //
+ // Read I/O Address
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &IOAddressStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ IoBaseAddr = (ReturnedValue->ParameterData.IntegerData);
+
+ //
+ // Confirm value
+ //
+ if (IoBaseAddr < 0x200 ||
+ IoBaseAddr > 0x3e0 ||
+ ((IoBaseAddr & 0x0f) != 0))
+ {
+ //
+ // If the user is going to bother to give us a base address it
+ // had better be valid
+ //
+ goto Fail00;
+ }
+ }
+ else if (pAdapter->CardType == ELNK3_3C589)
+ {
+ // PCMCIA Adapter MUST get something for IRQ keyword
+ // otherwise there is I/O allocated to this adapter
+ //
+ goto Fail00;
+ }
+ }
+ else
+ {
+ if (BusType == MicroChannel)
+ {
+ //
+ // Bus type MCA must be a 3c529
+ //
+ AdapterType=ELNK3_3C529;
+
+ NdisReadMcaPosInformation(
+ &Status,
+ ConfigurationHandle,
+ &ChannelNumber,
+ &McaData);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // Info read failed
+ //
+ IF_LOUD(DbgPrint("Elnk3: Failed to read POS information for card, slot# %d\n",ChannelNumber);)
+ goto Fail00;
+ }
+
+ if ((McaData.AdapterId != ELNK3_3C529_TP_MCA_ID) &&
+ (McaData.AdapterId != ELNK3_3C529_COMBO_MCA_ID) &&
+ (McaData.AdapterId != ELNK3_3C529_BNC_MCA_ID) &&
+ (McaData.AdapterId != ELNK3_3C529_TPCOAX_MCA_ID) &&
+ (McaData.AdapterId != ELNK3_3C529_TPONLY_MCA_ID))
+ {
+ //
+ // Not an Elnk3 adapter in this position
+ //
+ IF_LOUD(DbgPrint("Elnk3: The card found is not an ELNK3\n");)
+ goto Fail00;
+ }
+
+ if (!(McaData.PosData1 & 0x01))
+ {
+ //
+ // Bit 0 is set if the adapter is enabled
+ //
+ IF_LOUD(DbgPrint("Elnk3: The elnk3 is not enabled\n");)
+ goto Fail00;
+ }
+
+ //
+ // We have found an 3c529 in the specified slot
+ //
+ InterruptNumber=McaData.PosData4 & 0x0f;
+ IoBaseAddr=((McaData.PosData3 & 0xfc) << 8) + 0x200;
+
+ //
+ // The NIUps has a level triggered interrupt, as compared to
+ // the other two which do not
+ //
+ InterruptMode=NdisInterruptLevelSensitive;
+ }
+ else
+ {
+ if (BusType == Eisa)
+ {
+ //
+ // It's an eisa bus, Two possiblities, 3c579 or 3c509.
+ //
+ // Initialize the EisaData with garbage, in case the EISA
+ // config doesn't return any function information.
+ //
+ EisaData.CompressedId = 0xf00df00d;
+ EisaData.MinorRevision = 0xca;
+ EisaData.MajorRevision = 0xfe;
+
+ NdisReadEisaSlotInformation(
+ &Status,
+ ConfigurationHandle,
+ &ChannelNumber,
+ &EisaData);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // If the call worked, but the EisaData didn't change,
+ // we'll just assume that the card is a 3c579. If the
+ // EisaData did change, then we check to make sure it's
+ // an Elnk3.
+ //
+ if (((EisaData.CompressedId == 0xf00df00d) &&
+ (EisaData.MinorRevision = 0xca) &&
+ (EisaData.MajorRevision = 0xfe)) ||
+ ((EisaData.CompressedId & 0xf0ffffff) == ELNK3_EISA_ID))
+ {
+ AdapterType=ELNK3_3C579;
+
+ IoBaseAddr=(ChannelNumber<<12);
+
+ goto CloseConfig;
+ }
+ else
+ {
+ IF_LOUD(DbgPrint("ELNK3: The card found is not an ELNK3 id=%0lx\n",EisaData.CompressedId);)
+ }
+ }
+ else
+ {
+ //
+ // Info read failed
+ //
+ IF_LOUD(DbgPrint("ELNK3: Failed to get Eisa config information for card, bus# %d slot# %d\n",BusNumber,ChannelNumber);)
+ }
+
+ //
+ // Does not seem to be an EISA card, try for an ISA
+ //
+ AdapterType=ELNK3_3C509;
+
+ //
+ // Read I/O Address
+ //
+ NdisReadConfiguration(
+ &Status,
+ &ReturnedValue,
+ ConfigHandle,
+ &IOAddressStr,
+ NdisParameterHexInteger);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ IoBaseAddr = (ReturnedValue->ParameterData.IntegerData);
+
+ //
+ // Confirm value
+ //
+ if (IoBaseAddr < 0x200 ||
+ IoBaseAddr > 0x3e0 ||
+ ((IoBaseAddr & 0x0f) != 0))
+ {
+ //
+ // Error
+ //
+ goto Fail00;
+ }
+ }
+ }
+ }
+ }
+
+CloseConfig:
+
+
+ NdisCloseConfiguration(ConfigHandle);
+
+ pAdapter->TxStartThreshold = (USHORT)TxThreshold;
+ pAdapter->TxStartThresholdInc = (USHORT)TxThresholdInc;
+
+ pAdapter->IdPortBaseAddr = IdPortBaseAddr;
+ pAdapter->IoPortBaseAddr = IoBaseAddr;
+
+ pAdapter->ThresholdTarget = ThresholdTarget;
+ pAdapter->IrqLevel = InterruptNumber;
+ pAdapter->InterruptMode = InterruptMode;
+ pAdapter->CardType = AdapterType;
+
+ pAdapter->Transceiver = Transceiver;
+
+ IF_LOUD( DbgPrint( "\n\nElnk3: Registering adapter \n"
+ "Elnk3: I/O base addr 0x%lx\n"
+ "Elnk3: Interrupt number %d\n\n",
+ IoBaseAddr,
+ InterruptNumber);)
+
+
+ return(NDIS_STATUS_SUCCESS);
+
+Fail00:
+
+ NdisCloseConfiguration(ConfigHandle);
+ return(NDIS_STATUS_FAILURE);
+}
diff --git a/private/ntos/ndis/elnk3/debug.h b/private/ntos/ndis/elnk3/debug.h
new file mode 100644
index 000000000..da849a12c
--- /dev/null
+++ b/private/ntos/ndis/elnk3/debug.h
@@ -0,0 +1,133 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ debug.h
+
+Abstract:
+
+ It contains the various debug definitions and macros used in displaying
+ debugging information on the kernel debugger.
+
+Author:
+
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+
+--*/
+
+
+#if DBG
+
+typedef struct _DEBUG_STATS {
+
+ ULONG TotalInterrupts;
+ ULONG TxCompIntCount;
+ ULONG TxAvailIntCount;
+ ULONG TxCompleted;
+
+ ULONG RxCompIntCount;
+ ULONG RxEarlyIntCount;
+ ULONG PacketIndicated;
+ ULONG IndicationCompleted;
+ ULONG TransferDataCount;
+ ULONG IndicateWithDataReady;
+ ULONG BadReceives;
+ ULONG SecondEarlyReceive;
+ ULONG BroadcastsRejected;
+
+ } DEBUG_STATS, *PDEBUG_STATUS;
+
+typedef struct _LOG_ENTRY {
+ UCHAR Letter1;
+ UCHAR Letter2;
+ USHORT Data;
+ } LOG_ENTRY, *PLOG_ENTRY;
+
+
+#define ELNK3_MAX_LOG_SIZE 128
+
+extern ULONG Elnk3LogArray[];
+extern ULONG ElnkLogPointer;
+
+
+#define IF_ELNK3DEBUG(f) if (Elnk3DebugFlag & (f))
+extern ULONG Elnk3DebugFlag;
+
+#define ELNK3_DEBUG_LOUD 0x00000001 // debugging info
+#define ELNK3_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info
+#define ELNK3_DEBUG_IO 0x00000004 // debug I/O port access
+
+#define ELNK3_DEBUG_INIT 0x00000100 // init debugging info
+#define ELNK3_DEBUG_SEND 0x00000200 // init debugging info
+#define ELNK3_DEBUG_RCV 0x00000400
+#define ELNK3_DEBUG_REQ 0x00000800
+
+#define ELNK3_DEBUG_LOG 0x00001000
+
+#define ELNK3_DEBUG_INIT_BREAK 0x80000000 // break at DriverEntry
+#define ELNK3_DEBUG_INIT_FAIL 0x40000000 // fail driver load
+
+//
+// Macro for deciding whether to dump lots of debugging information.
+//
+
+#define IF_LOUD(A) IF_ELNK3DEBUG( ELNK3_DEBUG_LOUD ) { A }
+#define IF_VERY_LOUD(A) IF_ELNK3DEBUG( ELNK3_DEBUG_VERY_LOUD ) { A }
+#define IF_IO_LOUD(A) IF_ELNK3DEBUG( ELNK3_DEBUG_IO ) { A }
+#define IF_INIT_LOUD(A) IF_ELNK3DEBUG( ELNK3_DEBUG_INIT ) { A }
+#define IF_SEND_LOUD(A) IF_ELNK3DEBUG( ELNK3_DEBUG_SEND ) { A }
+#define IF_RCV_LOUD(A) IF_ELNK3DEBUG( ELNK3_DEBUG_RCV ) { A }
+#define IF_REQ_LOUD(A) IF_ELNK3DEBUG( ELNK3_DEBUG_REQ ) { A }
+
+
+#define IF_LOG(c1,c2,data) { \
+ if (Elnk3DebugFlag & ELNK3_DEBUG_LOG) { \
+ Elnk3LogArray[ElnkLogPointer]=((ULONG)(data)<<16) | ((c1)<<8) | (c2); \
+ ElnkLogPointer=(ElnkLogPointer+1)% ELNK3_MAX_LOG_SIZE; \
+ Elnk3LogArray[ElnkLogPointer]=0; \
+ } \
+ }
+#if 0
+
+#define IF_LOG(c1,c2,data) { \
+ \
+ if (Elnk3DebugFlag & ELNK3_DEBUG_LOG) { \
+ Elnk3LogArray[ElnkLogPointer].Letter1=(c2); \
+ Elnk3LogArray[ElnkLogPointer].Letter2=(c1); \
+ Elnk3LogArray[ElnkLogPointer].Data =(USHORT)(data); \
+ ElnkLogPointer=(ElnkLogPointer+1)% ELNK3_MAX_LOG_SIZE; \
+ \
+ Elnk3LogArray[ElnkLogPointer].Letter1=0; \
+ Elnk3LogArray[ElnkLogPointer].Letter2=0; \
+ Elnk3LogArray[ElnkLogPointer].Data =0; \
+ } \
+ }
+#endif
+
+#define DEBUG_STAT(x) ((x)++)
+
+
+#else
+
+#define IF_LOUD(A)
+#define IF_VERY_LOUD(A)
+#define IF_IO_LOUD(A)
+#define IF_INIT_LOUD(A)
+#define IF_SEND_LOUD(A)
+#define IF_RCV_LOUD(A)
+#define IF_REQ_LOUD(A)
+
+#define DEBUG_STAT(x)
+
+#define IF_LOG(c1,c2,data)
+
+#endif
diff --git a/private/ntos/ndis/elnk3/elnk3.c b/private/ntos/ndis/elnk3/elnk3.c
new file mode 100644
index 000000000..3bb2caaf1
--- /dev/null
+++ b/private/ntos/ndis/elnk3/elnk3.c
@@ -0,0 +1,174 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Elnk3.c
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+Author:
+
+ Brian Lieuallen BrianLie 07/21/92
+
+Environment:
+
+ Kernel Mode Operating Systems : NT, Chicago
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+--*/
+
+
+
+#include <ndis.h>
+//#include <efilter.h>
+
+#include "debug.h"
+
+
+#include "elnk3hrd.h"
+#include "elnk3sft.h"
+#include "elnk3.h"
+
+VOID
+Elnk3ResetCompleteOpens(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+
+//
+// This constant is used for places where NdisAllocateMemory
+// needs to be called and the HighestAcceptableAddress does
+// not matter.
+//
+
+NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
+ NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
+
+
+
+
+
+
+
+
+
+
+
+
+BOOLEAN
+Elnk3CheckForHang(
+ IN NDIS_HANDLE Context
+ )
+/*++
+
+Routine Description:
+
+ This routine is called to WakeUp the driver. It has to functions.
+
+Arguments:
+
+ DeferredContext - will be a pointer to the adapter block
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PELNK3_ADAPTER pAdapter = ((PELNK3_ADAPTER)Context);
+ BOOLEAN Hung;
+
+
+ IF_VERY_LOUD(DbgPrint("WakeUpTimer: entered\n");)
+
+ Hung=FALSE;
+
+
+
+ return Hung;
+
+}
+
+
+
+
+
+
+NDIS_STATUS
+Elnk3Reset(
+ OUT PBOOLEAN AddressResetting,
+ IN NDIS_HANDLE MacBindingHandle
+ )
+
+/*++
+
+Routine Description:
+
+ NDIS function.
+
+Arguments:
+
+ See NDIS 3.0 spec.
+
+--*/
+
+{
+ PELNK3_ADAPTER pAdapter = MacBindingHandle;
+
+ IF_LOUD(DbgPrint("ELNK3: Reset() Called\n");)
+
+ CardReStart(pAdapter);
+ CardReStartDone(pAdapter);
+
+#if 0
+
+ IF_LOUD(
+ DbgPrint("\nELNK3: Stats\n"
+ " Total Interrupts = %7d\n"
+ " EarlyReceiveInterrupts = %7d\n"
+ " RecieveCompInterrutps = %7d\n"
+ " TransmitCompInterrupts = %7d\n"
+ " TransmitAvailInterrupts = %7d\n"
+ " TransmitCompleted = %7d\n"
+ " Recevice Indications = %7d\n"
+ " Indication with data = %7d\n"
+ " Indications Complete = %7d\n"
+ " TransferData calls = %7d\n"
+ " SecondEarlyReceive = %7d\n"
+ " Broadcasts rejected = %7d\n"
+ " Bad receives = %7d\n\n",
+ pAdapter->Stats.TotalInterrupts,
+ pAdapter->Stats.RxEarlyIntCount,
+ pAdapter->Stats.RxCompIntCount,
+ pAdapter->Stats.TxCompIntCount,
+ pAdapter->Stats.TxAvailIntCount,
+ pAdapter->Stats.TxCompleted,
+ pAdapter->Stats.PacketIndicated,
+ pAdapter->Stats.IndicateWithDataReady,
+ pAdapter->Stats.IndicationCompleted,
+ pAdapter->Stats.TransferDataCount,
+ pAdapter->Stats.SecondEarlyReceive,
+ pAdapter->Stats.BroadcastsRejected,
+ pAdapter->Stats.BadReceives);
+
+ NdisZeroMemory(&pAdapter->Stats,sizeof(DEBUG_STATS));
+ )
+
+#endif
+
+ *AddressResetting=TRUE;
+
+ return NDIS_STATUS_SUCCESS;
+
+
+}
diff --git a/private/ntos/ndis/elnk3/elnk3.h b/private/ntos/ndis/elnk3/elnk3.h
new file mode 100644
index 000000000..5a2770edf
--- /dev/null
+++ b/private/ntos/ndis/elnk3/elnk3.h
@@ -0,0 +1,424 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ Elnk3.h
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+Author:
+
+ Brian Lieuallen BrianLie 07/21/92
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+--*/
+
+
+
+
+
+#define STATIC static
+
+
+//
+// This constant is used for places where NdisAllocateMemory
+// needs to be called and the HighestAcceptableAddress does
+// not matter.
+//
+
+extern NDIS_PHYSICAL_ADDRESS HighestAcceptableMax;
+
+//
+// NDIS 3.0 entry functions
+//
+
+BOOLEAN
+Elnk3CheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+
+
+NDIS_STATUS
+Elnk3QueryInformation(
+ IN NDIS_HANDLE MiniportContext,
+ IN NDIS_OID Oid,
+ IN PVOID InfoBuffer,
+ IN ULONG BytesLeft,
+ OUT PULONG BytesNeeded,
+ OUT PULONG BytesWritten
+ );
+
+
+
+NDIS_STATUS
+Elnk3SetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesRead,
+ OUT PULONG BytesNeeded
+ );
+
+NDIS_STATUS
+Elnk3Initialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_HANDLE WrapperConfigurationContext
+ );
+
+VOID
+Elnk3Halt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+
+VOID
+Elnk3Shutdown(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+
+NDIS_STATUS
+Elnk3Reset(
+ OUT PBOOLEAN AddressResetting,
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+
+
+
+NDIS_STATUS
+Elnk3MacSend(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_PACKET pPacket,
+ IN UINT Flags
+ );
+
+NDIS_STATUS
+Elnk3TransferData(
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer
+ );
+
+
+
+NDIS_STATUS
+Elnk3Reconfigure(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE ConfigurationHanel
+ );
+
+
+
+
+
+
+VOID
+Elnk3AdjustMaxLookAhead(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+
+
+
+
+//
+// Contained in Interrup.c
+//
+
+VOID
+Elnk3Isr(
+ OUT PBOOLEAN InterruptRecognized,
+ OUT PBOOLEAN QueueDpc,
+ IN NDIS_HANDLE Context
+ );
+
+
+
+VOID
+Elnk3IsrDpc(
+ IN NDIS_HANDLE DeferredContext // will be a pointer to the adapter block
+ );
+
+
+
+VOID
+Elnk3EnableInterrupts(
+ IN NDIS_HANDLE Context
+ );
+
+
+VOID
+Elnk3DisableInterrupts(
+ IN NDIS_HANDLE Context
+ );
+
+
+
+
+//
+// Contained in CARD.C
+//
+
+BOOLEAN
+CardTest (
+ OUT PELNK3_ADAPTER pAdapter
+ );
+
+
+
+//
+// Contained in send.c
+//
+
+
+PNDIS_PACKET
+RemovePacketFromQueue(
+ IN PPACKET_QUEUE pQueue
+ );
+
+
+BOOLEAN
+MovePacketToCard(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+
+//
+// Contained in receive.c
+//
+
+BOOLEAN
+CheckForReceives(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+
+
+//
+// Contained in config.c
+//
+
+NDIS_STATUS
+Elnk3ReadRegistry(
+ IN PELNK3_ADAPTER pAdapter,
+ IN NDIS_HANDLE ConfigurationHandle
+ );
+
+
+BOOLEAN
+CardEnable(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+
+BOOLEAN
+CardReInit(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+VOID
+CardReset(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+
+//
+// Elnk3 starts here
+//
+
+
+
+
+
+
+BOOLEAN
+HandleXmtInterrupts(
+ PELNK3_ADAPTER pAdapter
+ );
+
+BOOLEAN
+Elnk3EarlyReceive(
+ PELNK3_ADAPTER pAdapter
+ );
+
+
+BOOLEAN
+Elnk3IndicatePackets(
+ PELNK3_ADAPTER pAdapter
+ );
+
+BOOLEAN
+Elnk3IndicatePackets2(
+ PELNK3_ADAPTER pAdapter
+ );
+
+
+
+
+BOOLEAN
+CardInit(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+
+
+
+UINT
+Elnk3FindIsaBoards(
+ IN PMAC_BLOCK pMacBlock
+ );
+
+BOOLEAN
+Elnk3ActivateIsaBoard(
+ IN PMAC_BLOCK pMacBlock,
+ IN PELNK3_ADAPTER pAdapter,
+ IN NDIS_HANDLE AdapterHandle,
+ IN PUCHAR TranslatedIoBase,
+ IN ULONG ConfigIoBase,
+ IN OUT PULONG Irq,
+ IN ULONG Transceiver,
+ IN NDIS_HANDLE ConfigurationHandle
+ );
+
+
+VOID
+Elnk3EnableIsaBoard(
+ PVOID TranslatedIoBase
+ );
+
+
+
+VOID
+Elnk3GetEisaResources(
+ IN PELNK3_ADAPTER pAdapter,
+ IN OUT PULONG Irq
+ );
+
+
+VOID
+CardReStart(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+VOID
+CardReStartDone(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+
+VOID
+Elnk3AdjustMaxLookAhead(
+ IN PELNK3_ADAPTER Adapter
+ );
+
+BOOLEAN
+ReadStationAddress(
+ OUT PELNK3_ADAPTER pNewAdapt
+ );
+
+
+USHORT
+CardSetMulticast(
+ PELNK3_ADAPTER pAdapter
+ );
+
+
+BOOLEAN
+CardInit(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+VOID
+ELNK3WriteIDSequence(
+ IN PVOID IdPort
+ );
+
+USHORT
+ELNK3ContentionTest(
+ IN PVOID IdPort,
+ IN UCHAR EEPromWord
+ );
+
+USHORT
+ELNK3ReadEEProm(
+ IN PELNK3_ADAPTER Adapter,
+ IN UCHAR EEPromWord
+ );
+
+VOID
+Elnk3ProgramEEProm(
+ PELNK3_ADAPTER Adapter,
+ USHORT AddressConfig,
+ USHORT ResourceConfig
+ );
+
+VOID
+Elnk3WriteEEProm(
+ IN PELNK3_ADAPTER Adatper,
+ IN UCHAR EEPromWord,
+ IN USHORT Value
+ );
+
+VOID
+Elnk3WaitEEPromNotBusy(
+ PELNK3_ADAPTER pAdapter
+ );
+
+NDIS_STATUS
+Elnk3Init3C589(
+ IN OUT PELNK3_ADAPTER Adapter
+ );
+
+NDIS_STATUS
+Elnk3InitializeAdapter(
+ IN PMAC_BLOCK pMac,
+ IN PELNK3_ADAPTER pAdapter,
+ IN NDIS_HANDLE ConfigurationHandle
+ );
+
+
+NDIS_STATUS
+Elnk3AllocateBuffers(
+ IN PELNK3_ADAPTER pAdapter,
+ IN NDIS_HANDLE NdisAdapterHandle,
+ BOOLEAN Allocate
+ );
+
+
+VOID
+Elnk3InitAdapterBlock(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+
diff --git a/private/ntos/ndis/elnk3/elnk3.rc b/private/ntos/ndis/elnk3/elnk3.rc
new file mode 100644
index 000000000..6c380821e
--- /dev/null
+++ b/private/ntos/ndis/elnk3/elnk3.rc
@@ -0,0 +1,39 @@
+#include <windows.h>
+#include <ntverp.h>
+
+/*-----------------------------------------------*/
+/* the following lines are specific to this file */
+/*-----------------------------------------------*/
+
+/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR
+ * and VER_INTERNALNAME_STR must be defined before including COMMON.VER
+ * The strings don't need a '\0', since common.ver has them.
+ */
+#define VER_FILETYPE VFT_DRV
+/* possible values: VFT_UNKNOWN
+ VFT_APP
+ VFT_DLL
+ VFT_DRV
+ VFT_FONT
+ VFT_VXD
+ VFT_STATIC_LIB
+*/
+#define VER_FILESUBTYPE VFT2_DRV_NETWORK
+/* possible values VFT2_UNKNOWN
+ VFT2_DRV_PRINTER
+ VFT2_DRV_KEYBOARD
+ VFT2_DRV_LANGUAGE
+ VFT2_DRV_DISPLAY
+ VFT2_DRV_MOUSE
+ VFT2_DRV_NETWORK
+ VFT2_DRV_SYSTEM
+ VFT2_DRV_INSTALLABLE
+ VFT2_DRV_SOUND
+ VFT2_DRV_COMM
+*/
+#define VER_FILEDESCRIPTION_STR "3Com Etherlink III network driver"
+#define VER_INTERNALNAME_STR "ELNK3.SYS"
+#define VER_ORIGINALFILENAME_STR "ELNK3.SYS"
+
+#include "common.ver"
+
diff --git a/private/ntos/ndis/elnk3/elnk3hrd.h b/private/ntos/ndis/elnk3/elnk3hrd.h
new file mode 100644
index 000000000..d84c39841
--- /dev/null
+++ b/private/ntos/ndis/elnk3/elnk3hrd.h
@@ -0,0 +1,549 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ elnk3hrd.h
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+
+Author:
+
+ Brian Lieuallen BrianLie 08/21/92
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+--*/
+
+
+#define ELNK3_ETHERNET_HEADER_SIZE 14
+#define ELNK3_MAX_FRAME_SIZE 1514
+
+
+#define ELNK3_MAX_LOOKAHEAD_SIZE 1500
+
+
+
+typedef struct _ETHERNET_HEADER {
+ UCHAR Destination[6];
+ UCHAR Source[6];
+ UCHAR EthLength[2];
+ } ETHERNET_HEADER, *PETHERNET_HEADER;
+
+
+
+typedef struct _NIC_RCV_HEADER {
+ ETHERNET_HEADER EthHeader;
+ UCHAR LookAheadData[1500];
+ } NIC_RCV_HEADER, *PNIC_RCV_HEADER;
+
+//
+// EhterTypes
+//
+
+#define XNS_FRAME_TYPE 0x0600
+#define IP_FRAME_TYPE 0x0800
+#define IPX_FRAME_TYPE 0x8137
+
+
+typedef struct _XNSHDR {
+ UCHAR Ether[ELNK3_ETHERNET_HEADER_SIZE];
+ USHORT Checksum;
+ UCHAR Size[2];
+ } XNSHDR, PXNSHDR;
+
+typedef struct _IPHRD {
+ UCHAR Ether[ELNK3_ETHERNET_HEADER_SIZE];
+ USHORT Type;
+ UCHAR Size[2];
+ } IPHDR, PIPHDR;
+
+typedef struct _IPXHDR {
+ UCHAR Ether[ELNK3_ETHERNET_HEADER_SIZE];
+ USHORT Checksum;
+ UCHAR Size[2];
+ } IPXHDR, PIPXHDR;
+
+
+
+
+typedef struct _BUFFDESC {
+ ULONG CardOffset;
+ PNDIS_PACKET pPacket;
+ } BUFFDESC, *PBUFFDESC;
+
+
+
+
+typedef enum _ELNK3_ADAPTER_TYPE {
+ ELNK3_3C509,
+ ELNK3_3C579,
+ ELNK3_3C529,
+ ELNK3_3C589
+ } ELNK3_ADAPTER_TYPE, PELNK3_ADAPTER_TYPE;
+
+
+#define ELNK3_3C529_TP_MCA_ID 0x627c
+#define ELNK3_3C529_BNC_MCA_ID 0x627d
+#define ELNK3_3C529_COMBO_MCA_ID 0x61db
+#define ELNK3_3C529_TPCOAX_MCA_ID 0x62f6
+#define ELNK3_3C529_TPONLY_MCA_ID 0x62f7
+
+#define ELNK3_EISA_ID 0x90506d50
+
+#define ELNK3_3C579_EISA_ID 0x92506d50
+#define ELNK3_3C509_EISA_ID 0x90506d50
+
+
+/* :ts=4 this file uses 4 space tab stops */
+
+/*
+ Hardware equates for the EtherLink III network adapter.
+
+ Adapted from
+
+ "3C509 and 3C509-TP Adapters Technical Reference Guide"
+ Manual Part No. 8369-00
+ 3COM Corporation
+
+ */
+
+/*
+ When the adapter is in the ID_CMD state, the following writes to
+ the ID port are interpreted as commands.
+ */
+
+
+
+
+
+
+#define IDCMD_WAIT 0x00 /* Go to ID_WAIT state, actually 0 to 0x7f */
+#define IDCMD_READ_PROM 0x80 /* Read EEPROM word n, n is last six bits */
+ /* of command */
+#define IDCMD_RESET 0xC0 /* Global reset, same as power on reset */
+#define IDCMD_SET_TAG 0xD0 /* Set Adapter tag to value in last 3 bits */
+#define IDCMD_TEST_TAG 0xD8 /* Test Adapter tag by value in last 3 bits */
+#define MAXTAG 7
+#define IDCMD_ACTIVATE 0xE0 /* Activate adapter, writing last 5 bits */
+ /* into Address Configuration register */
+#define IDCMD_ACTIVATE_FF 0xFF /* Activate adapter using preconfigured */
+ /* I/O base address */
+/*
+ Default configuration values for the EtherLink III adapter.
+ */
+
+#define DEFAULT_ID_PORT 0x00000110 /* A port (maybe) not being used by */
+ /* anything else in an ISA machine */
+/*
+ Card EEPROM configuration, as shipped.
+ */
+#define DEFAULT_IO_PORT (PVOID)0x300
+#define DEFAULT_IRQ 10
+#define DEFAULT_TRANSCEIVER TRANSCEIVER_BNC /* For the 3C509-TP, this will */
+ /* be TRANSCEIVER_TP */
+
+// AdaptP->MulticastListMax
+//
+// the maximum number of different multicast addresses that
+// may be specified to this adapter (the list is global for
+// all protocols).
+
+#define DEFAULT_MULTICASTLISTMAX 16
+
+
+/*
+ EEPROM data structure.
+ */
+
+#define EEPROM_NODE_ADDRESS_0 0
+#define EEPROM_NODE_ADDRESS_1 1
+#define EEPROM_NODE_ADDRESS_2 2
+
+#define EEPROM_PRODUCT_ID 3
+
+#define EEPROM_MANUFACTURING_DATE 4
+#define EEPROM_MANUFACTURING_DATA1 5
+#define EEPROM_MANUFACTURING_DATA2 6
+#define EEPROM_MANUFACTURER_CODE 7
+
+#define EEPROM_ADDRESS_CONFIGURATION 8
+#define EEPROM_RESOURCE_CONFIGURATION 9
+
+#define EEPROM_OEM_NODE_0 10
+#define EEPROM_OEM_NODE_1 11
+#define EEPROM_OEM_NODE_2 12
+
+#define EEPROM_SOFTWARE_INFO 13
+
+#define EEPROM_RESERVED 14
+
+#define EEPROM_CHECKSUM 15
+
+#define EEPROM_NETWORK_MANAGEMENT_DATA_0 16
+
+//
+// eeprom software info bits
+//
+#define LINK_BEAT_DISABLED (1<<14)
+
+
+
+/*
+ Address configuration register.
+ */
+
+typedef union ELNK3_Address_Configuration_Register{
+ struct{
+ USHORT eacf_iobase : 5;
+ USHORT eacf_reserved : 3;
+ USHORT eacf_ROMbase : 4;
+ USHORT eacf_ROMsize : 2;
+ USHORT eacf_XCVR : 2;
+ };
+ USHORT eacf_contents;
+}ELNK3_Address_Configuration_Register, *PELNK3_Address_Configuration_Register;
+
+
+/*
+ EtherLink III configuration control register.
+ */
+
+#define CCR_ENABLE_BIT 0
+#define CCR_RESET_BIT 2
+
+#define CCR_ENABLE ( 1 << CCR_ENABLE_BIT )
+#define CCR_RESET ( 1 << CCR_RESET_BIT )
+/*
+ Transceiver configuration as stored in Address Configuration Register.
+ */
+
+#define TRANSCEIVER_TP 0 /* Twisted pair transceiver enabled. */
+#define TRANSCEIVER_EXTERNAL 1 /* AUI port enabled, using ext. trans. */
+#define TRANSCEIVER_RESERVED 2 /* reserved - undefined */
+#define TRANSCEIVER_BNC 3 /* BNC transceiver enabled */
+#define TRANSCEIVER_UNDEFINED TRANSCEIVER_RESERVED
+ /* Handy dandy undefined transceiver value */
+
+/*
+ Conversion from eacf_iobase to I/O port used.
+ */
+#define IOBASE_EISA 0x31 /* EISA mode slot-specific I/O address */
+
+typedef union EISA_IO_Address {
+ struct{
+ USHORT eia_port : 12;
+ USHORT eia_slot : 4;
+ };
+ USHORT eia_contents;
+}EISA_IO_Address, *PEISA_IO_Address;
+
+#define EISA_Window_0_Address 0xC80 /* Window zero is always mapped here */
+ /* on an EISA machine configured */
+ /* adapter */
+
+/*
+ IOBaseAddress for an EtherLink III configured for EISA operation and installed
+ in an EISA slot is the slotnumber times 1000h.
+ */
+#define EISA_SlotNumber_To_IOBase(x) ((x) * 0x1000)
+
+#define EACF_IOBASE_TO_ISA_IOBASE(x) ( ( (x) << 4 ) + 0x200 )
+#define ISA_IOBASE_TO_EACF_IOBASE(x) ( ( (x) - 0x200 ) >> 4 )
+
+/*
+ Elnk III resource configuration register.
+ */
+
+typedef union ELNK3_Resource_Configuration_Register{
+ struct{
+ USHORT ercf_reserved : 8;
+ USHORT ercf_reserved_F : 4;
+ USHORT ercf_IRQ : 4;
+ };
+ USHORT ercf_contents;
+}ELNK3_Resource_Configuration_Register, *PELNK3_Resource_Configuration_Register;
+
+/*
+ Format of command word written to ELNK III command register.
+ */
+
+typedef union ELNK3_Command{
+ struct{
+ USHORT ec_arg : 11;
+ USHORT ec_command : 5;
+ };
+ USHORT ec_contents;
+}ELNK3_Command,*PELNK3_Command;
+
+#define EC_GLOBAL_RESET 0
+#define EC_SELECT_WINDOW 1
+#define EC_START_COAX_XCVR 2
+#define EC_RX_DISABLE 3
+#define EC_RX_ENABLE 4
+#define EC_RX_RESET 5
+
+#define EC_RX_DISCARD_TOP_PACKET 8
+#define EC_TX_ENABLE 9
+#define EC_TX_DISABLE 10
+#define EC_TX_RESET 11
+
+#define EC_REQUEST_INTERRUPT 12
+
+#define EC_INT_LATCH 0x01
+#define EC_INT_ADAPTER_FAILURE 0x02
+#define EC_INT_TX_COMPLETE 0x04
+#define EC_INT_TX_AVAILABLE 0x08
+#define EC_INT_RX_COMPLETE 0x10
+#define EC_INT_RX_EARLY 0x20
+#define EC_INT_INTERRUPT_REQUESTED 0x40
+#define EC_INT_UPDATE_STATISTICS 0x80
+
+#define EC_ACKNOWLEDGE_INTERRUPT 13
+#define EC_SET_INTERRUPT_MASK 14
+#define EC_SET_READ_ZERO_MASK 15
+
+#define EC_SET_RX_EARLY 17
+#define EC_SET_TX_AVAILIBLE 18
+#define EC_SET_TX_START 19
+
+#define EC_SET_RX_FILTER 16
+
+#define EC_FILTER_ADDRESS 1
+#define EC_FILTER_GROUP 2
+#define EC_FILTER_BROADCAST 4
+#define EC_FILTER_PROMISCUOUS 8
+
+//
+// Window Numbers
+//
+#define WNO_SETUP 0 // setup/configuration
+#define WNO_OPERATING 1 // operating set
+#define WNO_STATIONADDRESS 2 // station address setup/read
+#define WNO_FIFO 3 // FIFO management
+#define WNO_DIAGNOSTICS 4 // diagnostics
+#define WNO_READABLE 5 // registers set by commands
+#define WNO_STATISTICS 6 // statistics
+//
+// Port offsets, Window 1
+//
+#define PORT_CmdStatus 0x0E // command/status
+#define PORT_TxFree 0x0C // free transmit bytes
+#define PORT_TxStatus 0x0B // transmit status (byte)
+#define PORT_Timer 0x0A // latency timer (byte)
+#define PORT_RxStatus 0x08 // receive status
+#define PORT_RxFIFO 0x00 // RxFIFO read
+#define PORT_TxFIFO 0x00 // TxFIFO write
+//
+// Port offsets, Window 0
+//
+#define PORT_EEData 0x0C // EEProm data register
+#define PORT_EECmd 0x0A // EEProm command register
+#define PORT_CfgResource 0x08 // resource configuration
+#define PORT_CfgAddress 0x06 // address configuration
+#define PORT_CfgControl 0x04 // configuration control
+#define PORT_ProductID 0x02 // product id (EISA)
+#define PORT_Manufacturer 0x00 // Manufacturer code (EISA)
+//
+// Port offsets, Window 2
+//
+#define PORT_SA0_1 0x00 // station address bytes 0,1
+#define PORT_SA2_3 0x02 // station address bytes 2,3
+#define PORT_SA4_5 0x04 // station address bytes 4,5
+
+//
+// port offsets, window 3
+//
+#define PORT_FREE_RX_BYTES 0x0a
+
+//
+//
+// Port Offsets window 4
+//
+#define PORT_FIFO_DIAG 0x04
+
+#define RX_UNDERRUN 0x2000
+#define TX_OVERRUN 0x0400
+
+
+#define PORT_MEDIA_TYPE 0x0a
+
+#define MEDIA_LINK_BEAT 0x0080
+#define MEDIA_JABBER 0x0040
+#define MEDIA_SQE 0x0008
+
+
+#define PORT_NET_DIAG 0x06
+
+
+
+//
+// board identification codes
+//
+#define EISA_MANUFACTURER_ID 0x6D50 // EISA manufacturer code
+
+#define ISAID_BNC 0x9050 // Product ID for ISA TP board
+#define ISAID_TP 0x9051 // Product ID for ISA coax board
+#define EISAID 0x9052 // Product ID for EISA board
+#define PCMCIAID 0x9058 // Product ID for PCMCIA board (3C589)
+
+//...so far the list is 5090=ISA 3C509-TP (TP/AUI), 5091h=ISA 3C509 (BNC/AUI),
+// 5092h=EISA 3C579-TP (TP/AUI) and 5092h=EISA 3C579 (BNC/AUI). other
+// bottom nibbles will likely be assigned to TP-only/combo/whatever
+// else marketting thinks up...
+
+#define PRODUCT_ID_MASK 0xF0FF // Mask off revision nibble
+
+#define MCAID_BNC 0x627C // MCA Adapter ID: BNC/AUI
+#define MCAID_TP 0x627D // MCA Adapter ID: TP/AUI
+#define MCAID_COMBO 0x61DB // MCA Adapter ID: Combo (future)
+#define MCAID_TPCOAX 0x62F6 // MCA Adapter ID: TP/COAX (future)
+#define MCAID_TPONLY 0x62F7 // MCA Adapter ID: TP only (future)
+
+/*
+ Note: This is referred to as POS2 in 3COM's MCA Technical Reference Addendum
+ for the EtherLink III.
+ */
+#define POS1_CDEN 1 // Card enable bit in POS2 register
+
+/*
+ Note: This is referred to as POS4 in 3COM's MCA Technical Reference Addendum
+ for the EtherLink III.
+ */
+#define POS3_TO_IOBASE(x) ((((x) << 8) & 0xFC00) | 0x0200)
+//
+// EEProm access
+//
+#define EE_COMMAND_EW_ENABLE 0x30
+#define EE_COMMAND_ERASE 0xc0
+#define EE_COMMAND_WRITE 0x40
+#define EE_COMMAND_READ 0x80
+
+#define EE_BUSY 0x8000 // EEProm busy bit in EECmd
+#define EE_TCOM_NODE_ADDR_WORD0 0x00
+#define EE_TCOM_NODE_ADDR_WORD1 0x1
+#define EE_TCOM_NODE_ADDR_WORD2 0x2
+#define EE_VULCAN_PROD_ID 0x3
+#define EE_MANUFACTURING_DATA 0x4
+#define EE_SERIAL_NUMBER_WORD0 0x5
+#define EE_SERIAL_NUMBER_WORD1 0x6
+#define EE_MANUFACTURER_CODE 0x7
+#define EE_ADDR_CONFIGURATION 0x8
+#define EE_RESOURCE_CONFIGURATION 0x9
+#define EE_OEM_NODE_ADDR_WORD0 0xA
+#define EE_OEM_NODE_ADDR_WORD1 0xB
+#define EE_OEM_NODE_ADDR_WORD2 0xC
+#define EE_SOFTWARE_CONFIG_INFO 0xD
+#define EE_CHECK_SUM 0xF
+
+#define MIN_IO_BASE_ADDR 0x200
+#define MAX_IO_BASE_ADDR 0x3F0
+#define REGISTER_SET_SIZE 0x10
+
+
+#define RX_STATUS_INCOMPLETE 0x8000
+#define RX_STATUS_ERROR 0x4000
+
+#define RX_STATUS_OVERRUN 0x08
+#define RX_STATUS_RUNT 0x0b
+
+#define TX_STATUS_COMPLETE 0x80
+#define TX_STATUS_INTERRUPT 0x40
+#define TX_STATUS_JABBER 0x20
+#define TX_STATUS_UNDERRUN 0x10
+#define TX_STATUS_MAX_COLLISION 0x08
+#define TX_STATUS_TX_OVERFLOW 0x04
+
+
+#define ELNK3_PACKET_COMPLETE(_RcvStatus) (!(((_RcvStatus) & RX_STATUS_INCOMPLETE)))
+
+#define DWORDS_FROM_BYTES(_status) ((_status) >> 2)
+
+#define BYTES_IN_FIFO(_status) ((ULONG)((_status) & 0x7ff))
+
+#define BYTES_IN_FIFO_DW(_status) ((ULONG)((_status) & 0x7fc))
+
+#define ELNK3_ROUND_TO_DWORD(x) (((x)+3) & 0xfffffffc)
+
+#ifdef NDIS_NT
+
+#ifndef IO_DBG
+#define ELNK3_READ_PORT_USHORT(_pAdapt,offset) \
+ READ_PORT_USHORT((PUSHORT)(_pAdapt)->PortOffsets[(offset)]);
+
+#define ELNK3_READ_PORT_USHORT_DIRECT(offset) \
+ READ_PORT_USHORT((PUSHORT)(offset));
+#else
+USHORT ELNK3_READ_PORT_USHORT( PVOID Adapter, ULONG Offset );
+USHORT ELNK3_READ_PORT_USHORT_DIRECT( PVOID Offset );
+#endif
+
+#else
+
+#define ELNK3_READ_PORT_USHORT(_pAdapt,offset) \
+ inpw((_pAdapt)->PortOffsets[(offset)]);
+
+#define ELNK3_READ_PORT_USHORT_DIRECT(offset) \
+ inpw((offset));
+
+#endif
+
+#define ELNK3_COMMAND(_p,_c,_d) \
+ IF_IO_LOUD(DbgPrint("Writing command %d.%d\n", (USHORT)(_c), (USHORT)(_d));) \
+ NdisRawWritePortUshort((_p)->PortOffsets[PORT_CmdStatus], ((USHORT)(_c)<<11) | (_d))
+
+
+#define ELNK3_SELECT_WINDOW(_p,_w) \
+ ELNK3_COMMAND(_p,(EC_SELECT_WINDOW),_w)
+
+#define ELNK3_READ_STATUS(_pAdapt,_pData) \
+ NdisRawReadPortUshort((_pAdapt)->PortOffsets[PORT_CmdStatus],(_pData)); \
+ IF_IO_LOUD(DbgPrint("Read status %x\n", *(PUSHORT)(_pData));)
+
+#define ELNK3_WAIT_NOT_BUSY(_pAdapt) { \
+ \
+ USHORT Status; \
+ ULONG Limit=1000; \
+ \
+ Status=ELNK3_READ_PORT_USHORT((_pAdapt),PORT_CmdStatus); \
+ \
+ while ((Status & 0x1000) && (--Limit>0)) { \
+ \
+ Status=ELNK3_READ_PORT_USHORT((_pAdapt),PORT_CmdStatus); \
+ } \
+ \
+ }
+
+
+#define ELNK3WriteAdapterUchar(Adapter,PortOffset,UcharToWrite)\
+ IF_IO_LOUD(DbgPrint("Writing uchar %x to port %x\n", (UCHAR)(UcharToWrite), (PortOffset));) \
+ NdisRawWritePortUchar((Adapter)->PortOffsets[PortOffset],(UcharToWrite))
+
+
+#define ELNK3WriteAdapterUshort(Adapter,PortOffset,UshortToWrite)\
+ IF_IO_LOUD(DbgPrint("Writing ushort %x to port %x\n", (USHORT)(UshortToWrite), (PortOffset));) \
+ NdisRawWritePortUshort((Adapter)->PortOffsets[PortOffset],(UshortToWrite))
+
+
+#define ELNK3ReadAdapterUchar(Adapter,PortOffset,PUcharToRead)\
+ NdisRawReadPortUchar((Adapter)->PortOffsets[PortOffset],(PUcharToRead)); \
+ IF_IO_LOUD(DbgPrint("Read uchar %x from port %x\n", *(PUCHAR)(PUcharToRead), (PortOffset));) \
+
+
+#define ELNK3ReadAdapterUshort(Adapter,PortOffset,PUshortToRead)\
+ NdisRawReadPortUshort((Adapter)->PortOffsets[PortOffset],(PUshortToRead)); \
+ IF_IO_LOUD(DbgPrint("Read ushort %x from port %x\n", *(PUSHORT)(PUshortToRead), (PortOffset));) \
+
+
diff --git a/private/ntos/ndis/elnk3/elnk3sft.h b/private/ntos/ndis/elnk3/elnk3sft.h
new file mode 100644
index 000000000..7f557a12a
--- /dev/null
+++ b/private/ntos/ndis/elnk3/elnk3sft.h
@@ -0,0 +1,361 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ elnk3sft.h
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+Author:
+
+ Brian Lieuallen BrianLie 07/21/92
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+--*/
+
+
+
+
+
+
+
+
+#define DEFAULT_MULTICAST_SIZE 16
+#define DEFAULT_RECEIVE_BUFFER_SIZE 238
+
+
+#define ELNK3_NDIS_MAJOR_VERSION 3
+#define ELNK3_NDIS_MINOR_VERSION 0
+
+#define TIMER_ARRAY_SIZE 4
+
+#define ELNK3_LENGTH_OF_ADDRESS 6
+
+
+//
+// Macros
+//
+#define MACRO_ASSERTALL() { \
+ ASSERT ( sizeof(CHAR) = 1 ); \
+ ASSERT ( sizeof(UCHAR) = 1 ); \
+ ASSERT ( sizeof(USHORT) = 2 ); \
+ ASSERT ( sizeof(UINT) = 4 ); \
+ ASSERT ( sizeof(ULONG) = 4 ); \
+ }
+
+//
+// The main MAC block structure allocated and initialized once
+//
+
+typedef struct _ELNK3_ISA_DESCRIPTION {
+ USHORT AddressConfigRegister;
+ USHORT ResourceConfigRegister;
+ USHORT IOPort;
+ USHORT Irq;
+ BOOLEAN Tagged;
+ BOOLEAN Active;
+ } ELNK3_ISA_DESCRIPTION, *PELNK3_ISA_DESCRIPTION;
+
+
+
+typedef struct _MAC_BLOCK {
+
+ //
+ // Translated ID port Address
+ //
+
+ PUCHAR TranslatedIdPort;
+
+ ELNK3_ISA_DESCRIPTION IsaCards[7];
+
+ UCHAR IsaAdaptersFound;
+
+} MAC_BLOCK, * PMAC_BLOCK;
+
+
+typedef struct _PACKET_QUEUE {
+ PNDIS_PACKET QIn;
+ PNDIS_PACKET QOut;
+ } PACKET_QUEUE, *PPACKET_QUEUE;
+
+
+
+typedef struct _TRANSFERDATA_CONTEXT {
+ struct _ELNK3_ADAPTER *pAdapter;
+ ULONG PacketLength;
+ ULONG BytesAlreadyRead;
+
+ PNIC_RCV_HEADER LookAhead;
+
+ PNDIS_PACKET LoopBackPacket;
+
+ PNDIS_PACKET Stack;
+
+ ULONG pad[2];
+
+ } TRANSFERDATA_CONTEXT, *PTRANSFERDATA_CONTEXT;
+
+
+
+
+
+typedef
+BOOLEAN
+(*ELNK3_RECEIVE_HANDLER)(
+ struct _ELNK3_ADAPTER *pAdapter
+ );
+
+
+
+
+//
+// One of these structures per adapter registered.
+//
+
+typedef struct _ELNK3_ADAPTER {
+
+ PVOID PortOffsets[16];
+
+ //
+ // Xmit queues stuff
+ //
+
+ ELNK3_RECEIVE_HANDLER EarlyReceiveHandler;
+ ELNK3_RECEIVE_HANDLER ReceiveCompleteHandler;
+
+ ULONG XmtCompleted;
+
+
+ //
+ // Recieve stuff
+ //
+ UINT CurrentPacket;
+
+ UCHAR CurrentInterruptMask;
+
+ TRANSFERDATA_CONTEXT TransContext[2];
+
+
+ //
+ // Elnk3 stuff
+ //
+
+ UCHAR AdapterStatus;
+
+ UINT WakeUpErrorCount;
+
+ BOOLEAN RejectBroadcast;
+
+ BOOLEAN InitInterrupt;
+
+ //
+ // NDIS Interrupt information
+ //
+
+ NDIS_MINIPORT_INTERRUPT NdisInterrupt;
+ NDIS_INTERRUPT_MODE InterruptMode;
+ BOOLEAN AdapterInitializing;
+
+ //
+ // NDIS wrapper information.
+ //
+
+ NDIS_HANDLE NdisAdapterHandle; // returned from NdisRegisterAdapter
+
+ //
+ // Registry information
+ //
+ ULONG Transceiver;
+
+ UINT IoPortBaseAddr;
+ PVOID TranslatedIoBase;
+
+
+ ELNK3_ADAPTER_TYPE CardType;
+ ULONG IrqLevel;
+ ULONG ReceiveMethod;
+
+ UCHAR StationAddress[ELNK3_LENGTH_OF_ADDRESS]; // filled in at init time
+
+ UCHAR PermanentAddress[ELNK3_LENGTH_OF_ADDRESS]; // filled in at init time
+
+ USHORT EEpromSoftwareInfo;
+
+ ULONG FramesXmitGood; // Good Frames Transmitted
+ ULONG FramesRcvGood; // Good Frames Received
+ ULONG FramesXmitBad; // Bad Frames Transmitted
+ ULONG FramesXmitOneCollision; // Frames Transmitted with one collision
+ ULONG FramesXmitManyCollisions; // Frames Transmitted with > 1 collision
+ ULONG FrameAlignmentErrors; // FAE errors counted
+ ULONG CrcErrors; // CRC errors counted
+ ULONG MissedPackets; // missed packet counted
+
+
+ //
+ // Look Ahead information.
+ //
+
+ ULONG MaxLookAhead;
+ ULONG EarlyReceiveThreshold;
+ ULONG LatencyAdjustment;
+ ULONG LookAheadLatencyAdjustment;
+ LONG FirstEarlyThreshold;
+ ULONG LowWaterMark;
+ ULONG ThresholdTarget;
+
+ ULONG AverageLatency;
+ ULONG IdPortBaseAddr;
+
+ USHORT TxStartThreshold;
+ USHORT TxStartThresholdInc;
+
+ ULONG RxMinimumThreshold;
+ ULONG RxFifoSize;
+ UINT NdisRxFilter;
+ UCHAR RxFilter;
+ UCHAR RevisionLevel;
+ ULONG RxHiddenBytes;
+
+ BOOLEAN IdPortOwner;
+
+ //
+ // Adapter specific Infomation
+ //
+
+
+ UCHAR WakeUpState;
+ BOOLEAN AdapterFailed;
+
+
+
+ ULONG TimerValues[TIMER_ARRAY_SIZE];
+ ULONG CurrentTimerValue;
+
+
+#if DBG
+
+ DEBUG_STATS Stats;
+
+#endif
+
+
+
+} ELNK3_ADAPTER, * PELNK3_ADAPTER;
+
+#define STATUS_REINIT_REQUESTED 0x0001
+#define STATUS_RESET_INITIATED 0x0002
+#define STATUS_RESET_IN_PROGRESS 0x0004
+#define STATUS_MOVING_TO_CARD 0x0008
+#define STATUS_SEND_BLOCK_USED 0x0010
+#define STATUS_INITIALIZING 0x0020
+#define STATUS_SHUTDOWN 0x0040
+
+//
+// What we map into the reserved section of a packet.
+// Cannot be more than 16 bytes (see ASSERT in send.c).
+//
+
+
+#define NdisRequestClose 1
+#define NdisRequestRequest 2
+#define NdisRequestReset1 3
+#define NdisRequestReset2 4
+
+
+#define SEND_STATUS_LOOPBACK 0x01
+#define SEND_STATUS_FAILED 0x02
+#define SEND_STATUS_BUFFER_USED 0x04
+#define SEND_STATUS_ABORTED 0x08
+#define SEND_STATUS_ONE_COLLISION 0x10
+#define SEND_STATUS_MANY_COLLISIONS 0x20
+
+#define SEND_STATUS_SMALL_PACKET 0x40
+
+
+typedef struct _PACKET_RESERVED {
+ PNDIS_PACKET Next; // used to link in the queues (4 bytes)
+ union {
+ struct {
+
+ USHORT PacketLength;
+ UCHAR Status;
+
+ } Send;
+
+ struct {
+
+ USHORT ByteOffset;
+ USHORT BytesToTransfer;
+
+ } TransData;
+ } u;
+
+ } PACKET_RESERVED, * PPACKET_RESERVED;
+
+
+
+//
+// These appear in the status field of MAC_RESERVED; they are
+// used because there is not enough room for a full NDIS_HANDLE.
+//
+
+#define RESERVED_SUCCESS ((USHORT)0)
+#define RESERVED_FAILURE ((USHORT)1)
+
+//
+// Retrieve the MAC_RESERVED structure from a packet.
+//
+
+#define PACKET_RESERVED(Packet) ((PPACKET_RESERVED)((Packet)->MacReserved))
+
+#define ADD_PACKET_TO_QUEUE(pQueue,pPacket) { \
+ \
+ PACKET_RESERVED(pPacket)->Next = NULL; \
+ if ((pQueue)->QOut==NULL) { \
+ \
+ (pQueue)->QOut=pPacket; \
+ \
+ } else { \
+ \
+ PACKET_RESERVED((pQueue)->QIn)->Next=pPacket; \
+ } \
+ \
+ (pQueue)->QIn=pPacket; \
+ \
+ }
+
+#define INIT_PACKET_QUEUE(pQueue) { \
+ (pQueue)->QIn=NULL; \
+ (pQueue)->QOut=NULL; \
+ }
+
+#define QUEUE_EMPTY(pQueue) ((pQueue)->QOut==NULL)
+
+#define PEEK_QUEUE(pQueue) (pQueue)->QOut
+
+#define NEXT_PACKET(pQueue) (pQueue)->QOut=PACKET_RESERVED((pQueue)->QOut)->Next;
+
+
+
+#define DEFAULT_MULTICASTLISTMAX 16
+
+
+
+
+typedef struct _SYNC_CONTEXT {
+ ULONG Value;
+ PELNK3_ADAPTER pAdapter;
+ } SYNC_CONTEXT, *PSYNC_CONTEXT;
diff --git a/private/ntos/ndis/elnk3/init.c b/private/ntos/ndis/elnk3/init.c
new file mode 100644
index 000000000..a20c96a8d
--- /dev/null
+++ b/private/ntos/ndis/elnk3/init.c
@@ -0,0 +1,897 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ init.c
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+
+Author:
+
+ Brian Lieuallen (BrianLie) 12/14/92
+
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+--*/
+
+
+
+#include <ndis.h>
+
+//#include <efilter.h>
+
+#include "debug.h"
+
+#include "elnk3hrd.h"
+#include "elnk3sft.h"
+#include "elnk3.h"
+
+#if defined(ALLOC_PRAGMA)
+#pragma NDIS_INIT_FUNCTION(DriverEntry)
+#pragma NDIS_INIT_FUNCTION(Elnk3Initialize)
+#pragma NDIS_INIT_FUNCTION(Elnk3InitializeAdapter)
+#pragma NDIS_INIT_FUNCTION(Elnk3Init3C589)
+#endif
+
+
+#if DBG
+
+ULONG Elnk3DebugFlag;
+ULONG Elnk3LogArray[ELNK3_MAX_LOG_SIZE+16];
+ULONG ElnkLogPointer;
+
+#endif
+
+MAC_BLOCK MacBlock = {0};
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+
+/*++
+
+Routine Description:
+
+ This is the transfer address of the driver. It initializes all the
+ appropriate variables used and calls NdisInitializeWrapper() and
+ NdisRegisterMac().
+
+
+Arguments:
+
+Return Value:
+
+ Indicates the success or failure of the initialization.
+
+--*/
+
+{
+ NDIS_STATUS InitStatus;
+ NDIS_MINIPORT_CHARACTERISTICS Characteristics;
+ NDIS_HANDLE WrapperHandle;
+
+
+
+#if DBG
+
+ Elnk3DebugFlag = 0;
+ Elnk3DebugFlag|= ELNK3_DEBUG_LOG;
+// Elnk3DebugFlag|= ELNK3_DEBUG_LOUD;
+// Elnk3DebugFlag|= ELNK3_DEBUG_VERY_LOUD;
+// Elnk3DebugFlag|= ELNK3_DEBUG_INIT;
+// Elnk3DebugFlag|= ELNK3_DEBUG_IO;
+// Elnk3DebugFlag|= ELNK3_DEBUG_REQ;
+// Elnk3DebugFlag|= ELNK3_DEBUG_RCV;
+// Elnk3DebugFlag|= ELNK3_DEBUG_SEND;
+// Elnk3DebugFlag|= ELNK3_DEBUG_INIT_BREAK;
+
+
+#endif
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: DriverEntry\n");)
+#if DBG
+ if (Elnk3DebugFlag & ELNK3_DEBUG_INIT_BREAK) DbgBreakPoint();
+ if (Elnk3DebugFlag & ELNK3_DEBUG_INIT_FAIL) return STATUS_UNSUCCESSFUL;
+#endif
+
+ NdisMInitializeWrapper(
+ &WrapperHandle,
+ DriverObject,
+ RegistryPath,
+ NULL
+ );
+
+
+
+ //
+ // Prepare to call NdisRegisterMac.
+ //
+
+ Characteristics.MajorNdisVersion = ELNK3_NDIS_MAJOR_VERSION;
+ Characteristics.MinorNdisVersion = ELNK3_NDIS_MINOR_VERSION;
+ Characteristics.Reserved = 0;
+ Characteristics.CheckForHangHandler = Elnk3CheckForHang;
+
+// Characteristics.DisableInterruptHandler = Elnk3DisableInterrupts;
+// Characteristics.EnableInterruptHandler = Elnk3EnableInterrupts;
+ Characteristics.DisableInterruptHandler = NULL;
+ Characteristics.EnableInterruptHandler = NULL;
+
+ Characteristics.SendHandler = Elnk3MacSend;
+ Characteristics.TransferDataHandler = Elnk3TransferData;
+ Characteristics.ResetHandler = Elnk3Reset;
+ Characteristics.SetInformationHandler = Elnk3SetInformation;
+ Characteristics.QueryInformationHandler = Elnk3QueryInformation;
+ Characteristics.InitializeHandler = Elnk3Initialize;
+ Characteristics.HaltHandler = Elnk3Halt;
+ Characteristics.ISRHandler = Elnk3Isr;
+ Characteristics.HandleInterruptHandler = Elnk3IsrDpc;
+ Characteristics.ReconfigureHandler = Elnk3Reconfigure;
+
+ InitStatus=NdisMRegisterMiniport(
+ WrapperHandle,
+ &Characteristics,
+ sizeof(Characteristics)
+ );
+
+
+#if DBG
+
+ if (InitStatus != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD(DbgPrint("Elnk3: NdisMRegisterMiniport failed with code 0x%x\n", InitStatus );)
+
+ } else {
+
+ IF_INIT_LOUD (DbgPrint("Elnk3: NdisMRegisterMiniport succeeded\n" );)
+
+
+ }
+
+#endif
+
+ return InitStatus;
+
+}
+
+
+
+
+
+
+NDIS_STATUS
+Elnk3Initialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE AdapterHandle,
+ IN NDIS_HANDLE ConfigurationHandle
+ )
+/*++
+Routine Description:
+
+ This is the Elnk3 MacAddAdapter routine. The system calls this routine
+ to add support for particular UB adapter. This routine extracts
+ configuration information from the configuration data base and registers
+ the adapter with NDIS.
+
+
+Arguments:
+
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS - Adapter was successfully added.
+ NDIS_STATUS_FAILURE - Adapter was not added
+
+--*/
+{
+
+ PELNK3_ADAPTER pAdapter;
+ NDIS_STATUS status;
+
+
+
+
+ *OpenErrorStatus=NDIS_STATUS_SUCCESS;
+
+ IF_LOUD (DbgPrint("ELNK3: Initialize\n");)
+
+ //
+ // Scan the media list for our media type (802.3)
+ //
+
+ *SelectedMediumIndex =(UINT) -1;
+
+ while (MediumArraySize > 0) {
+
+ if (MediumArray[--MediumArraySize] == NdisMedium802_3 ) {
+
+ *SelectedMediumIndex = MediumArraySize;
+
+ break;
+ }
+ }
+
+
+ if (*SelectedMediumIndex == -1) {
+
+ return NDIS_STATUS_UNSUPPORTED_MEDIA;
+
+ }
+
+
+
+ status = NdisAllocateMemory(
+ (PVOID *)&pAdapter,
+ sizeof(ELNK3_ADAPTER),
+ 0,
+ HighestAcceptableMax
+ );
+
+ if (status != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD (DbgPrint("Elnk3AddAdapter():NdisAllocateMemory() failed\n");)
+
+ return NDIS_STATUS_RESOURCES;
+
+ }
+
+ NdisZeroMemory(pAdapter,sizeof(ELNK3_ADAPTER));
+
+ pAdapter->NdisAdapterHandle=AdapterHandle;
+
+ //
+ // Read Registery information into Adapter structure
+ //
+
+ if (Elnk3ReadRegistry(pAdapter,ConfigurationHandle)==NDIS_STATUS_SUCCESS) {
+ //
+ // We got the registry info try to register the adpater
+ //
+
+ if (Elnk3InitializeAdapter(
+ &MacBlock,
+ pAdapter,
+ ConfigurationHandle)== NDIS_STATUS_SUCCESS) {
+
+
+ return NDIS_STATUS_SUCCESS;
+
+ }
+
+ } else {
+
+ IF_LOUD(DbgPrint("Failed to get config info, probably bad Slot number\n");)
+
+ }
+
+ //
+ // We failed to register the adapter for some reason, so free the
+ // memory for the adapter block and return failure
+
+ NdisFreeMemory(pAdapter,
+ sizeof(ELNK3_ADAPTER),
+ 0);
+
+ return NDIS_STATUS_FAILURE;
+
+}
+
+
+
+
+NDIS_STATUS
+Elnk3InitializeAdapter(
+ IN PMAC_BLOCK pMac,
+ IN PELNK3_ADAPTER pAdapter,
+ IN NDIS_HANDLE ConfigurationHandle
+ )
+
+/*++
+
+Routine Description:
+
+ Called when a new adapter should be registered.
+ Initializes the adapter block, and calls NdisRegisterAdapter().
+
+Arguments:
+
+ AdapterName - The name that the system will refer to the adapter by.
+ Others - Adapter-specific parameters as defined in defaults.h.
+
+Return Value:
+
+ Indicates the success or failure of the registration.
+
+--*/
+
+{
+ NDIS_STATUS Status;
+ NDIS_INTERFACE_TYPE InterfaceType;
+ UINT i;
+ PVOID TranslatedIdPort=NULL;
+
+
+ Elnk3InitAdapterBlock(pAdapter);
+
+ //
+ // Initialize various elments in the Adapter Structure;
+ //
+
+ if ((pAdapter->CardType==ELNK3_3C509) ||
+ ((pAdapter->CardType==ELNK3_3C589))) {
+
+ InterfaceType = NdisInterfaceIsa;
+
+ } else {
+
+ if (pAdapter->CardType==ELNK3_3C579) {
+
+ InterfaceType = NdisInterfaceEisa;
+
+ } else {
+
+ InterfaceType = NdisInterfaceMca;
+ }
+
+ }
+
+ NdisMSetAttributes(
+ pAdapter->NdisAdapterHandle,
+ pAdapter,
+ FALSE,
+ InterfaceType
+ );
+
+ if ((pMac->TranslatedIdPort==0) && (pAdapter->CardType==ELNK3_3C509)) {
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: First ISA card claiming Id port\n");)
+
+ Status=NdisMRegisterIoPortRange(
+ &TranslatedIdPort,
+ pAdapter->NdisAdapterHandle,
+ pAdapter->IdPortBaseAddr,
+ 1
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: First ISA card claiming Id port---FAILED\n");)
+
+ goto fail0;
+
+ }
+
+
+ pAdapter->IdPortOwner=TRUE;
+
+ pMac->TranslatedIdPort=TranslatedIdPort;
+
+ //
+ // See if there are any boards around
+ //
+ Elnk3FindIsaBoards(pMac);
+ }
+
+ Status=NdisMRegisterIoPortRange(
+ &pAdapter->TranslatedIoBase,
+ pAdapter->NdisAdapterHandle,
+ pAdapter->IoPortBaseAddr,
+ 16
+ );
+
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: Failed to register i/o ports\n");)
+
+ goto fail1;
+
+ }
+
+ //
+ // Compute the portaddresses now so we don't have to
+ // do it on each port access
+ //
+ for (i=0;i<16;i++) {
+
+ pAdapter->PortOffsets[i]=(PUCHAR)pAdapter->TranslatedIoBase+i;
+
+ }
+
+
+
+
+
+ if (pAdapter->CardType==ELNK3_3C509) {
+ //
+ // Lets try to find a card at the address specified
+ //
+ // Note: this service may change the I/O base aquired
+ // from the registry. This will happen if we can't
+ // find a match.
+ //
+
+ if (!Elnk3ActivateIsaBoard(
+ pMac,
+ pAdapter,
+ pAdapter->NdisAdapterHandle,
+ pAdapter->TranslatedIoBase,
+ pAdapter->IoPortBaseAddr,
+ &pAdapter->IrqLevel,
+ pAdapter->Transceiver,
+ ConfigurationHandle
+ )) {
+
+ NdisWriteErrorLogEntry(
+ pAdapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS,
+ 8,
+ pAdapter->IoPortBaseAddr,
+ pMac->IsaCards[0].IOPort,
+ pMac->IsaCards[1].IOPort,
+ pMac->IsaCards[2].IOPort,
+ pMac->IsaCards[3].IOPort,
+ pMac->IsaCards[4].IOPort,
+ pMac->IsaCards[5].IOPort,
+ pMac->IsaCards[6].IOPort
+ );
+
+ Status=NDIS_STATUS_ADAPTER_NOT_FOUND;
+
+ goto fail2;
+ }
+
+ }
+
+
+
+ else if (pAdapter->CardType==ELNK3_3C579) {
+ //
+ // Get the Irq from the eisa adapter since the 3com
+ // CFG put the interrupt information in the second
+ // function of the EISA info instead of making it
+ // a sub function.
+ //
+
+ Elnk3GetEisaResources(
+ pAdapter,
+ &pAdapter->IrqLevel
+ );
+ }
+
+ else if (pAdapter->CardType==ELNK3_3C589)
+ {
+ Status = Elnk3Init3C589( pAdapter);
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: Failed to initialize 3C589\n");)
+
+ goto fail1;
+ }
+ }
+
+
+ //
+ // Allocate the Send, LookAhead and LoopBack buffers
+ //
+ Status=Elnk3AllocateBuffers(
+ pAdapter,
+ pAdapter->NdisAdapterHandle,
+ TRUE
+ );
+
+
+ if (Status!=NDIS_STATUS_SUCCESS) {
+
+ goto fail2;
+ }
+
+
+ //
+ // Make sure the card is inactive
+ //
+ CardReset(pAdapter);
+
+ pAdapter->AdapterInitializing=TRUE;
+
+
+
+ //
+ // Set up the interrupt handlers.
+ //
+
+ NdisZeroMemory (&pAdapter->NdisInterrupt, sizeof(NDIS_MINIPORT_INTERRUPT) );
+
+ Status=NdisMRegisterInterrupt(
+ &pAdapter->NdisInterrupt, // interrupt info str
+ pAdapter->NdisAdapterHandle, // NDIS adapter handle
+ (UINT)pAdapter->IrqLevel, // vector or int number
+ (UINT)pAdapter->IrqLevel, // level or priority
+ TRUE,
+ FALSE, // NOT shared
+ pAdapter->InterruptMode
+ );
+
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD (DbgPrint("ELNK3: NdisInitializeInterruptFailed\n");)
+ NdisWriteErrorLogEntry(
+ pAdapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_INTERRUPT_CONNECT,
+ 1,
+ (ULONG)pAdapter->IrqLevel
+ );
+
+
+ goto fail3;
+ }
+
+
+ //
+ // Perform card tests.
+ //
+ if (!CardTest(pAdapter) ) {
+
+ IF_LOUD ( DbgPrint("ELNK3: CardTest() failed, game over\n");)
+
+ NdisWriteErrorLogEntry(
+ pAdapter->NdisAdapterHandle,
+ NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
+ 2,
+ (ULONG)pAdapter->IrqLevel,
+ (ULONG)pAdapter->IoPortBaseAddr
+ );
+
+
+ Status = NDIS_STATUS_FAILURE;
+ goto fail4;
+ }
+
+ // register a shutdown handler for this card
+ NdisMRegisterAdapterShutdownHandler(
+ pAdapter->NdisAdapterHandle, // miniport handle.
+ pAdapter, // shutdown context.
+ Elnk3Shutdown // shutdown handler.
+ );
+
+ CardReStart(pAdapter);
+ CardReStartDone(pAdapter);
+
+ IF_LOUD (DbgPrint("Elnk3: Elnk3InitializeAdapter() Succeeded\n");)
+
+ return NDIS_STATUS_SUCCESS;
+
+
+ //
+ // IF WE ARE HERE SOME INITIALIZATION FAILURE OCCURRED
+ //
+
+
+ //
+ // Code to unwind what has already been set up when a part of
+ // initialization fails, which is jumped into at various
+ // points based on where the failure occured. Jumping to
+ // a higher-numbered failure point will execute the code
+ // for that block and all lower-numbered ones.
+ //
+
+
+fail4:
+
+ NdisMDeregisterInterrupt(&pAdapter->NdisInterrupt);
+
+
+fail3:
+
+ Elnk3AllocateBuffers(
+ pAdapter,
+ pAdapter->NdisAdapterHandle,
+ FALSE
+ );
+
+fail2:
+
+ NdisMDeregisterIoPortRange(
+ pAdapter->NdisAdapterHandle,
+ pAdapter->IoPortBaseAddr,
+ 16,
+ pAdapter->TranslatedIoBase
+ );
+
+
+
+fail1:
+
+ if (pAdapter->IdPortOwner) {
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: Id port owner going away\n");)
+
+ NdisMDeregisterIoPortRange(
+ pAdapter->NdisAdapterHandle,
+ pAdapter->IdPortBaseAddr,
+ 1,
+ pMac->TranslatedIdPort
+ );
+
+
+
+ pMac->TranslatedIdPort=0;
+ }
+
+fail0:
+
+ IF_LOUD (DbgPrint("Elnk3RegisterAdapter() Failed\n");)
+ return Status;
+}
+
+
+
+
+
+NDIS_STATUS
+Elnk3AllocateBuffers(
+ IN PELNK3_ADAPTER pAdapter,
+ IN NDIS_HANDLE NdisAdapterHandle,
+ BOOLEAN Allocate
+ )
+
+{
+ NDIS_STATUS Status;
+
+
+ if (Allocate) {
+
+ //
+ // Allocate the memory to hold the loopback indication
+ //
+
+ Status=NdisAllocateMemory(
+ (PVOID *)(&pAdapter->TransContext[0].LookAhead),
+ 4096,
+ 0,
+ HighestAcceptableMax
+ );
+
+ if (Status!=NDIS_STATUS_SUCCESS) {
+ goto Fail0000;
+ }
+
+ pAdapter->TransContext[1].LookAhead=
+ (PNIC_RCV_HEADER)((PUCHAR)pAdapter->TransContext[0].LookAhead+2048);
+
+ IF_INIT_LOUD(DbgPrint("ELNK3: Lookahead->%08lx\n",pAdapter->TransContext[0].LookAhead);)
+
+
+
+ return NDIS_STATUS_SUCCESS;
+
+ }
+
+
+ NdisFreeMemory(
+ pAdapter->TransContext[0].LookAhead,
+ 4096,
+ 0
+ );
+
+
+
+Fail0000:
+
+ return NDIS_STATUS_RESOURCES;
+
+}
+
+
+
+VOID
+Elnk3InitAdapterBlock(
+ IN PELNK3_ADAPTER pAdapter
+ )
+
+{
+ UINT i;
+
+
+ //
+ // BUGBUG: This could probably be smaller, but NBF doesn't currently set a
+ // lookahead size
+ //
+
+ pAdapter->MaxLookAhead=60 ; //ELNK3_MAX_LOOKAHEAD_SIZE;
+
+ Elnk3AdjustMaxLookAhead(pAdapter);
+
+ for (i=0; i<TIMER_ARRAY_SIZE; i++) {
+ pAdapter->TimerValues[i]=25;
+ }
+
+ pAdapter->TransContext[0].pAdapter = pAdapter;
+ pAdapter->TransContext[1].pAdapter = pAdapter;
+
+
+ if (pAdapter->CardType==ELNK3_3C529) {
+ //
+ // MCA card does not hide bytes
+ //
+ pAdapter->RxHiddenBytes=0;
+
+ } else {
+ //
+ // ISA hides 16
+ //
+ pAdapter->RxHiddenBytes=16;
+ }
+
+ pAdapter->RxMinimumThreshold=8;
+
+ //
+ // Set the minimum amount that needs to be in the fifo
+ // before we draw out some of an incomplete packet
+ //
+ pAdapter->LowWaterMark=64;
+
+
+ return;
+}
+
+
+VOID
+Elnk3Shutdown(
+ IN NDIS_HANDLE MiniportHandle
+ )
+{
+ PELNK3_ADAPTER pAdapter=MiniportHandle;
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: Shutdown\n");)
+
+ //
+ // It's time to rock and roll
+ //
+ CardReStart(pAdapter);
+}
+
+VOID
+Elnk3Halt(
+ IN NDIS_HANDLE MiniportHandle
+ )
+{
+
+ PELNK3_ADAPTER pAdapter=MiniportHandle;
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: Halt\n");)
+ //
+ // It's time to rock and roll
+ //
+ CardReStart(pAdapter);
+
+ NdisMDeregisterInterrupt(&pAdapter->NdisInterrupt);
+
+ if (pAdapter->IdPortOwner) {
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: Id port owner going away\n");)
+
+ NdisMDeregisterIoPortRange(
+ pAdapter->NdisAdapterHandle,
+ pAdapter->IdPortBaseAddr,
+ 1,
+ MacBlock.TranslatedIdPort
+ );
+
+ MacBlock.TranslatedIdPort=0;
+ }
+
+
+ NdisMDeregisterIoPortRange(
+ pAdapter->NdisAdapterHandle,
+ pAdapter->IoPortBaseAddr,
+ 16,
+ pAdapter->TranslatedIoBase
+ );
+
+ Elnk3AllocateBuffers(
+ pAdapter,
+ pAdapter->NdisAdapterHandle,
+ FALSE
+ );
+
+
+ NdisFreeMemory(
+ pAdapter,
+ sizeof(ELNK3_ADAPTER),
+ 0
+ );
+}
+
+
+NDIS_STATUS
+Elnk3Reconfigure(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE ConfigurationHandle
+ )
+
+{
+
+ IF_INIT_LOUD(DbgPrint("Elnk3: Reconfigure\n");)
+
+ return NDIS_STATUS_NOT_SUPPORTED;
+
+
+}
+
+
+NDIS_STATUS
+Elnk3Init3C589(
+ IN OUT PELNK3_ADAPTER pAdapter
+ )
+
+{
+ ELNK3_Address_Configuration_Register acr;
+ ELNK3_Resource_Configuration_Register rcr;
+ USHORT i, window;
+ NDIS_STATUS Status;
+
+ Status = NDIS_STATUS_SUCCESS;
+
+ ELNK3ReadAdapterUshort ( pAdapter , PORT_CmdStatus , &window );
+ window &= 0xE000; // Current window - high 3 bits
+
+ ELNK3_SELECT_WINDOW( pAdapter, WNO_SETUP );
+
+ //
+ // init address configuration
+ //
+ acr.eacf_contents = 0;
+
+ if ( pAdapter->Transceiver == TRANSCEIVER_BNC ) {
+ acr.eacf_XCVR = TRANSCEIVER_BNC;
+ }
+
+ ELNK3WriteAdapterUshort(pAdapter,PORT_CfgAddress,acr.eacf_contents);
+
+ // Believe it or not, to make the 3C589 (not 3C589B) the IRQ have to be set
+ // to 3 (it can be anything - the card must be told 3).
+ rcr.ercf_contents = 0;
+ // rcr.ercf_IRQ = (USHORT)pAdapter->IrqLevel;
+ rcr.ercf_IRQ = 3;
+ rcr.ercf_reserved_F = 0xF;
+ ELNK3WriteAdapterUshort(pAdapter,PORT_CfgResource,rcr.ercf_contents);
+
+ // read in product ID
+ i = ELNK3ReadEEProm( pAdapter, EEPROM_PRODUCT_ID );
+ ELNK3WriteAdapterUshort( pAdapter, PORT_ProductID, i );
+
+ // Enable the adapter by setting the bit in the configuration control register
+ ELNK3WriteAdapterUchar(pAdapter,PORT_CfgControl,CCR_ENABLE);
+
+ // restore to whatever it used to be
+ ELNK3_SELECT_WINDOW( pAdapter, window);
+
+ return (Status);
+
+}
+
+
diff --git a/private/ntos/ndis/elnk3/interrup.c b/private/ntos/ndis/elnk3/interrup.c
new file mode 100644
index 000000000..d357eb7a1
--- /dev/null
+++ b/private/ntos/ndis/elnk3/interrup.c
@@ -0,0 +1,418 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ interrup.c
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+Author:
+
+ Brian Lieuallen (BrianLie) 07/02/92
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+
+--*/
+
+
+
+
+#include <ndis.h>
+#include <efilter.h>
+
+#include "debug.h"
+
+
+#include "elnk3hrd.h"
+#include "elnk3sft.h"
+#include "elnk3.h"
+
+
+VOID
+CompleteRequests(
+ IN PELNK3_ADAPTER pAdapter
+ );
+
+VOID
+ELNK3MaskClearInterrupt(
+ IN PELNK3_ADAPTER pAdapter,
+ IN UCHAR Mask
+ );
+
+VOID
+ELNK3UnmaskInterrupt(
+ IN PELNK3_ADAPTER pAdapter,
+ IN UCHAR Mask
+ );
+
+
+
+VOID
+Elnk3Isr(
+ OUT PBOOLEAN InterruptRecognized,
+ OUT PBOOLEAN QueueDpc,
+ IN NDIS_HANDLE Context
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ ServiceContext - pointer to the adapter object
+
+Return Value:
+
+ TRUE, if the DPC is to be executed, otherwise FALSE.
+
+--*/
+
+{
+ PELNK3_ADAPTER pAdapter = ((PELNK3_ADAPTER)Context);
+ USHORT InterruptReason;
+
+ *InterruptRecognized=TRUE;
+ *QueueDpc=TRUE;
+
+
+ InterruptReason=ELNK3_READ_PORT_USHORT(pAdapter,PORT_CmdStatus);
+
+ if ((InterruptReason & 0x01)==0) {
+ //
+ // The ISR has run with out an interrupt present on the card, Hmm
+ //
+ // This was added because the AST manhatton seems to run the ISR on
+ // muliple processors for a given interrupt
+ //
+
+ IF_LOUD(DbgPrint("Elnk3: Isr bit 0 clear %04x adapter=%08lx\n",InterruptReason,pAdapter);)
+
+ *InterruptRecognized=FALSE;
+ *QueueDpc=FALSE;
+ return;
+ }
+
+ if (pAdapter->AdapterInitializing) {
+ IF_INIT_LOUD (DbgPrint("Elnk3: ISR called during init\n");)
+ pAdapter->InitInterrupt=TRUE;
+
+ ELNK3_COMMAND(pAdapter,EC_ACKNOWLEDGE_INTERRUPT,EC_INT_INTERRUPT_REQUESTED | 1);
+
+ *QueueDpc=FALSE;
+
+ return;
+ }
+
+
+
+ //
+ // needed for level triggered MCA cards
+ //
+ ELNK3_COMMAND(pAdapter,EC_SET_INTERRUPT_MASK, 0x00 );
+
+ ELNK3_COMMAND(pAdapter,EC_ACKNOWLEDGE_INTERRUPT, 1);
+
+ return;
+}
+
+
+
+VOID
+Elnk3IsrDpc(
+ IN NDIS_HANDLE Context
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PELNK3_ADAPTER pAdapter = ((PELNK3_ADAPTER)Context);
+ UCHAR InterruptReason;
+ USHORT TimerValue;
+ ULONG Latency;
+ UINT LoopLimit=10;
+
+
+
+ DEBUG_STAT(pAdapter->Stats.TotalInterrupts);
+
+ //
+ // Read the timer port to keep track of latencies
+ //
+ TimerValue=ELNK3_READ_PORT_USHORT(pAdapter,PORT_Timer);
+
+ if ((UCHAR)TimerValue==0xff) {
+ //
+ // The timer has maxed out. We will just use the last
+ // average to hopefully keep things in line.
+ //
+
+ TimerValue=(UCHAR)pAdapter->AverageLatency;
+ }
+
+ pAdapter->TimerValues[pAdapter->CurrentTimerValue]=(UCHAR)TimerValue;
+
+ pAdapter->CurrentTimerValue= (pAdapter->CurrentTimerValue+1) % TIMER_ARRAY_SIZE;
+
+ IF_LOG(0x11,0x11,(TimerValue & 0xff)<<2);
+
+
+ InterruptReason=(UCHAR)ELNK3_READ_PORT_USHORT(pAdapter,PORT_CmdStatus);
+
+ while (((InterruptReason & pAdapter->CurrentInterruptMask) != 0)
+ &&
+ ((--LoopLimit) != 0)) {
+
+
+ IF_LOG(0x11,0x22,InterruptReason);
+
+ if (InterruptReason & EC_INT_ADAPTER_FAILURE) {
+
+ IF_LOUD(
+ DbgPrint("ELNK3: Adapter Failed\n");
+ DbgBreakPoint();
+ )
+
+ //
+ // No more interrupts
+ //
+ ELNK3_COMMAND(pAdapter,EC_SET_READ_ZERO_MASK,0x00);
+
+ //
+ // Clear what ever is there now
+ //
+ ELNK3_COMMAND(pAdapter,EC_ACKNOWLEDGE_INTERRUPT, 0xff);
+
+ //
+ // Something is messed up so no point in handling any thing
+ //
+ InterruptReason=0;
+
+ //
+ // Get the reinit code to run
+ //
+ pAdapter->AdapterStatus |= STATUS_REINIT_REQUESTED;
+ }
+
+ //
+ // Interrupts are basically grouped into two catagories
+ // Recieve and xmit
+ //
+
+ if ((InterruptReason & (EC_INT_TX_COMPLETE)) ) {
+
+ IF_VERY_LOUD (DbgPrint("Handle xmit int\n");)
+
+ DEBUG_STAT(pAdapter->Stats.TxCompIntCount);
+
+
+ HandleXmtInterrupts(pAdapter);
+
+ NdisMSendResourcesAvailable(pAdapter->NdisAdapterHandle);
+
+ } else {
+
+ if ((InterruptReason & (EC_INT_RX_EARLY | EC_INT_RX_COMPLETE)) ) {
+
+ if (InterruptReason & (EC_INT_RX_COMPLETE) ) {
+
+ //
+ // Rx complete will be clear when we handle the interrupt
+ //
+ DEBUG_STAT(pAdapter->Stats.RxCompIntCount);
+
+ (*pAdapter->ReceiveCompleteHandler)(pAdapter);
+
+ } else {
+
+ DEBUG_STAT(pAdapter->Stats.RxEarlyIntCount);
+
+ //
+ // dismiss the rx early int
+ //
+ ELNK3_COMMAND(pAdapter,EC_ACKNOWLEDGE_INTERRUPT,EC_INT_RX_EARLY );
+
+ (*pAdapter->EarlyReceiveHandler)(pAdapter);
+ }
+
+
+ } else {
+
+ if ((InterruptReason & (EC_INT_TX_AVAILABLE)) ) {
+
+ ELNK3_COMMAND(pAdapter,EC_ACKNOWLEDGE_INTERRUPT,EC_INT_TX_AVAILABLE );
+
+ DEBUG_STAT(pAdapter->Stats.TxAvailIntCount);
+
+ NdisMSendResourcesAvailable(pAdapter->NdisAdapterHandle);
+
+ } else {
+
+ if ((InterruptReason & (EC_INT_INTERRUPT_REQUESTED)) ) {
+ //
+ // Dismiss the user requested interrupt
+ //
+ IF_SEND_LOUD(DbgPrint("Elnk3: Requested interrupt\n");)
+
+ ELNK3_COMMAND(pAdapter, EC_ACKNOWLEDGE_INTERRUPT, EC_INT_INTERRUPT_REQUESTED);
+
+ }
+ }
+ }
+ }
+
+
+ InterruptReason=(UCHAR)ELNK3_READ_PORT_USHORT(pAdapter,PORT_CmdStatus);
+
+ } // while (interrupt reasons)
+
+ //
+ // Unmask interrupts
+ //
+
+ ELNK3_COMMAND(pAdapter,EC_SET_INTERRUPT_MASK,pAdapter->CurrentInterruptMask);
+
+
+ //
+ // We calculate the latency average from the last four
+ // DPC latencies every four DPC runs
+ //
+
+ if (pAdapter->CurrentTimerValue == 0) {
+
+ Latency=((ULONG)pAdapter->TimerValues[0] +
+ pAdapter->TimerValues[1] +
+ pAdapter->TimerValues[2] +
+ pAdapter->TimerValues[3])/4;
+
+ //
+ // The latency is dword times and we want byte times
+ //
+
+ pAdapter->AverageLatency=Latency;
+
+ Latency<<=2;
+
+ if ((pAdapter->EarlyReceiveThreshold-pAdapter->RxMinimumThreshold) < Latency) {
+
+ pAdapter->LookAheadLatencyAdjustment=pAdapter->RxMinimumThreshold & 0x7fc;
+ pAdapter->LatencyAdjustment=Latency+pAdapter->RxHiddenBytes;
+ } else {
+
+ pAdapter->LookAheadLatencyAdjustment=pAdapter->EarlyReceiveThreshold-Latency & 0x7fc;
+ pAdapter->LatencyAdjustment=Latency+pAdapter->RxHiddenBytes;
+ }
+
+ IF_LOG(0xcc,0xcc,Latency);
+
+ }
+
+
+
+ //
+ // See if the card needs to restarted
+ //
+ if (pAdapter->AdapterStatus & STATUS_REINIT_REQUESTED ) {
+ IF_LOUD(DbgPrint("Elnk3: Handling pending request\n");)
+
+ //
+ // It's time to rock and roll
+ //
+ CardReStart(pAdapter);
+
+
+ CardReStartDone(pAdapter);
+
+ //
+ // Done re-initializing
+ //
+ pAdapter->AdapterStatus &= ~STATUS_REINIT_REQUESTED;
+
+
+ }
+
+
+
+#if DBG
+ InterruptReason=(UCHAR)ELNK3_READ_PORT_USHORT(pAdapter,PORT_CmdStatus);
+
+ IF_LOG(0x11,0x33,InterruptReason);
+#endif
+}
+
+#if 0
+
+VOID
+Elnk3EnableInterrupts(
+ IN NDIS_HANDLE Context
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PELNK3_ADAPTER pAdapter=Context;
+
+// IF_INIT_LOUD(DbgPrint("Elnk3: EnableInterrupts\n");)
+
+ ELNK3_COMMAND(pAdapter,EC_SET_INTERRUPT_MASK,pAdapter->CurrentInterruptMask);
+
+}
+
+
+VOID
+Elnk3DisableInterrupts(
+ IN NDIS_HANDLE Context
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ PELNK3_ADAPTER pAdapter=Context;
+
+// IF_INIT_LOUD(DbgPrint("Elnk3: DisableInterrupts\n");)
+
+ ELNK3_COMMAND(pAdapter,EC_SET_INTERRUPT_MASK, 0x00);
+
+}
+
+#endif
diff --git a/private/ntos/ndis/elnk3/keywords.h b/private/ntos/ndis/elnk3/keywords.h
new file mode 100644
index 000000000..f820aa5c6
--- /dev/null
+++ b/private/ntos/ndis/elnk3/keywords.h
@@ -0,0 +1,56 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ keywords.h
+
+Abstract:
+
+ Contains all Ndis2 and Ndis3 mac-specific keywords.
+
+Author:
+
+ Bob Noradki
+
+Environment:
+
+ This driver is expected to work in DOS, OS2 and NT at the equivalent
+ of kernal mode.
+
+ Architecturally, there is an assumption in this driver that we are
+ on a little endian machine.
+
+Notes:
+
+ optional-notes
+
+Revision History:
+
+
+
+--*/
+#ifndef NDIS2
+#define NDIS2 0
+#endif
+
+#if NDIS2
+
+#define IOADDRESS NDIS_STRING_CONST("IOBASE")
+#define INTERRUPT NDIS_STRING_CONST("INTERRUPT")
+#define MAX_MULTICAST_LIST NDIS_STRING_CONST("MAXMULTICAST")
+#define NETWORK_ADDRESS NDIS_STRING_CONST("NETADDRESS")
+#define BUS_TYPE NDIS_STRING_CONST("BusType")
+#define TRANSCEIVER NDIS_STRING_CONST("Transceiver")
+
+#else // NDIS3
+
+#define IOADDRESS NDIS_STRING_CONST("IoBaseAddress")
+#define INTERRUPT NDIS_STRING_CONST("InterruptNumber")
+#define MAX_MULTICAST_LIST NDIS_STRING_CONST("MaximumMulticastList")
+#define NETWORK_ADDRESS NDIS_STRING_CONST("NetworkAddress")
+#define BUS_TYPE NDIS_STRING_CONST("BusType")
+#define TRANSCEIVER NDIS_STRING_CONST("Transceiver")
+
+#endif
diff --git a/private/ntos/ndis/elnk3/makefile b/private/ntos/ndis/elnk3/makefile
new file mode 100644
index 000000000..677d610db
--- /dev/null
+++ b/private/ntos/ndis/elnk3/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/ndis/elnk3/receive.c b/private/ntos/ndis/elnk3/receive.c
new file mode 100644
index 000000000..2acd4d6a9
--- /dev/null
+++ b/private/ntos/ndis/elnk3/receive.c
@@ -0,0 +1,1722 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ receive.c
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+
+ FYI: The ELNK III behaves maginally if it is overflowing.
+
+ A note to the curious:
+
+ This module supports two different methods of handling received frames.
+
+ Method 0: the default method, basically tries to keep the stinking 2k
+ receive fifo as empty as possible. In order to do this, it needs to
+ port i/o the data into system memory and then copy from this system
+ memory to packets during transferdata. Obviously it would be best to
+ not have this memory copy.
+
+ Method 1: tries to avoid the memory copy by port i/o'ing straigth
+ into the packet buffers during transfer data. The problem with method
+ is that by the time you indicate the frame up, their is going to be
+ about 1300 bytes sitting in fifo from this packet. This obviously
+ means that if the total latency to transfer data port i/o'ing is
+ more than ~700 byte times, you are going to under run the next packet.
+ The more protocol's bound, the more delay.
+
+ Method zero is the best at avoiding underruns, but you pay a price in
+ the extra memory copy. An offsetting factor in addition to the fewer
+ overruns is that it appears that pending transferdata and later completing
+ it adds a fair amount of overhead to the code path.
+
+ Another interesting thing is that on MP machines the speed that you
+ can port i/o is signifigantly reduced do to contention for the bus
+ from the other processor(s). This increases the danger of overflowing.
+ Also, depending on how RISC platforms, deal with ISA boards and ports,
+ I think there is also a risk here of slower port i/o'ing.
+
+ As long as DPC latencies are fairly low and constant, either method will
+ work OK. The problem occures when the DPC latency increases. Like up around
+ a millisecond. In looking at this occurance it looks like the DPC is getting
+ stuck behind the HD DPC. If you get an 1ms latency you are almost assured of
+ overflowing if you are receiving full size frames back to back.
+
+
+ Bascially I believe that method 0 is the most solid and likely to
+ work on varied platforms.
+
+ If only 3Com had not been so cheap and had put another 2k in the fifo.
+
+ You should also take note that the asic on the isa and EISA cards have
+ a problem with loosing there place in the fifo. This is delt with in the
+ packet discard code. It also seems the these boards will also falsly detect
+ an adapter failure on the receive side.
+
+ Also, according to the 3com specs it is not possible for the card to
+ have both the packet incomplete bit set and receive error bit set
+ at the same time, but I have seen this happen. I suspect that this
+ is related to the above asic problem
+
+ Another neat feature of the card is that when it is overflowing it
+ has a tendancy to concatenate frames together to form really large
+ frames. When the frame completes it is marked with an error in the
+ receive status.
+
+
+
+
+
+Author:
+
+ Brian Lieuallen (BrianLie) 12/14/92
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+--*/
+
+
+
+#include <ndis.h>
+//#include <efilter.h>
+
+#include "debug.h"
+
+
+#include "elnk3hrd.h"
+#include "elnk3sft.h"
+#include "elnk3.h"
+
+
+VOID
+Elnk3DiscardIfBroadcast(
+ IN PELNK3_ADAPTER pAdapter,
+ IN PTRANSFERDATA_CONTEXT TransDataContext
+ );
+
+
+
+
+BOOLEAN
+Elnk3QuickPacketTest(
+ IN PNIC_RCV_HEADER Frame,
+ IN UINT NdisFilter
+ );
+
+
+
+ULONG
+Elnk3GuessFrameSize(
+ IN PNIC_RCV_HEADER Frame,
+ IN ULONG BytesNow
+ );
+
+
+BOOLEAN
+Elnk3IndicateLoopbackPacket(
+ IN PELNK3_ADAPTER pAdapter,
+ IN PNDIS_PACKET Packet
+ );
+
+
+
+VOID
+Elnk3TransferDataCompletion(
+ PTRANSFERDATA_CONTEXT TransDataContext
+ );
+
+
+VOID
+Elnk3DiscardPacketSync(
+ IN PTRANSFERDATA_CONTEXT TransDataContext
+ );
+
+BOOLEAN
+Elnk3CheckFifoSync(
+ IN PTRANSFERDATA_CONTEXT TransDataContext
+ );
+
+
+
+
+BOOLEAN
+Elnk3IndicatePackets2(
+ PELNK3_ADAPTER pAdapter
+ )
+/*++
+
+ Routine Description:
+ This routine Indicates all of the packets in the ring one at a time
+
+ Arguments:
+
+
+ Return Value:
+
+--*/
+
+{
+
+ USHORT RcvStatus;
+ ULONG AdditionalData;
+ ULONG GoodReceives=0;
+ ULONG BadReceives=0;
+
+ BOOLEAN Indicated=FALSE;
+
+ UINT CurrentPacket;
+ UINT NextPacket;
+ USHORT InterruptReason;
+ ULONG PossibleLength;
+
+
+ PTRANSFERDATA_CONTEXT TransDataContext;
+ PTRANSFERDATA_CONTEXT AltTransDataContext;
+
+
+ CurrentPacket=pAdapter->CurrentPacket;
+
+ TransDataContext= &pAdapter->TransContext[CurrentPacket];
+
+ if ((TransDataContext->BytesAlreadyRead == 0) && pAdapter->RejectBroadcast) {
+ //
+ // First interrupt for this packet
+ //
+ Elnk3DiscardIfBroadcast(
+ pAdapter,
+ TransDataContext
+ );
+ }
+
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ IF_LOG(0xdc,0xdc,TransDataContext->BytesAlreadyRead);
+
+ IF_RCV_LOUD(DbgPrint("ELNK3: IndicatePackets RX status=%04x\n",RcvStatus);)
+
+ while ((BYTES_IN_FIFO(RcvStatus) > pAdapter->LowWaterMark ) ||
+ !(RcvStatus & RX_STATUS_INCOMPLETE)) {
+
+ //
+ // There is a completed packet or some data from a yet to be completed
+ // packet
+ //
+ if (ELNK3_PACKET_COMPLETE(RcvStatus) || (RcvStatus & RX_STATUS_ERROR)) {
+ //
+ // The packet has completed
+ //
+ if (!(RcvStatus & RX_STATUS_ERROR)) {
+
+ //
+ // The packet completed with out error
+ //
+
+ //
+ // Get the total packet length by adding the number of bytes still
+ // in the fifo to the number already taken out
+ //
+ TransDataContext->PacketLength=BYTES_IN_FIFO(RcvStatus);
+
+ TransDataContext->PacketLength+=TransDataContext->BytesAlreadyRead;
+
+ IF_LOG(0xdc,0x01,TransDataContext->PacketLength);
+
+ //
+ // Have we read all of the packet in already?
+ //
+ if (TransDataContext->PacketLength <= 1514) {
+ //
+ // It is a valid length
+ //
+ if (TransDataContext->PacketLength > TransDataContext->BytesAlreadyRead) {
+ //
+ // No, Need this much more
+ // The data in the fifo is padded to a dword boundary
+ //
+ AdditionalData=ELNK3_ROUND_TO_DWORD(TransDataContext->PacketLength)-TransDataContext->BytesAlreadyRead;
+
+ IF_LOG(0xad,0x01,AdditionalData);
+
+ //
+ // Go and get the rest
+ //
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)(((PUCHAR)TransDataContext->LookAhead)+TransDataContext->BytesAlreadyRead),
+ (AdditionalData>>2)
+ );
+
+ IF_RCV_LOUD(DbgPrint("IP: Da=%d Ad=%d\n",TransDataContext->BytesAlreadyRead, AdditionalData);)
+
+ //
+ // Now we have this much
+ //
+ TransDataContext->BytesAlreadyRead+=AdditionalData;
+
+ }
+ }
+
+ //
+ // Now discard the packet before indicating
+ //
+
+ Elnk3DiscardPacketSync(TransDataContext);
+
+ pAdapter->FramesRcvGood+=1;
+
+
+ //
+ // See if any data from the next packet is in the fifo
+ //
+ // If there is any data then it will go in the other unused buffer
+ //
+ NextPacket=(CurrentPacket+1) % 2;
+
+ AltTransDataContext= &pAdapter->TransContext[NextPacket];
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ AdditionalData=BYTES_IN_FIFO_DW(RcvStatus);
+
+
+ //
+ // Go and get the data
+ //
+ while ((AdditionalData >= (pAdapter->LowWaterMark*2))
+ &&
+ (AdditionalData+AltTransDataContext->BytesAlreadyRead<=1514)
+ &&
+ !(RcvStatus & RX_STATUS_ERROR)) {
+
+
+ IF_LOG(0xaf,0x00,RcvStatus & 0xc7fc);
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)((PUCHAR)AltTransDataContext->LookAhead+AltTransDataContext->BytesAlreadyRead),
+ (AdditionalData >> 2)
+ );
+
+ AltTransDataContext->BytesAlreadyRead += AdditionalData;
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ AdditionalData=BYTES_IN_FIFO_DW(RcvStatus);
+
+ }
+
+
+ //
+ // It seems that some asic's will generate an adapter failure
+ // when there really isn't one. Just to be safe we will check
+ // now. Since we have port i/o the whole packet now we will
+ // check. Better to not indicate a bad packet than to loose a
+ // good one
+ //
+ InterruptReason=ELNK3_READ_PORT_USHORT(pAdapter,PORT_CmdStatus);
+
+ if ((TransDataContext->PacketLength <=1514)
+ &&
+ (TransDataContext->PacketLength >= 14)
+ &&
+ !(InterruptReason & EC_INT_ADAPTER_FAILURE)) {
+
+ //
+ // The packet seems to be OK
+ // Subtract the header length(14) from the packet length
+ //
+ TransDataContext->PacketLength-=ELNK3_ETHERNET_HEADER_SIZE;
+
+ GoodReceives++;
+
+ NdisMEthIndicateReceive(
+ pAdapter->NdisAdapterHandle,
+ TransDataContext,
+ (PUCHAR)&TransDataContext->LookAhead->EthHeader,
+ ELNK3_ETHERNET_HEADER_SIZE,
+ TransDataContext->LookAhead->LookAheadData,
+ TransDataContext->PacketLength,
+ TransDataContext->PacketLength
+ );
+
+ DEBUG_STAT(pAdapter->Stats.PacketIndicated);
+
+ Indicated=TRUE;
+
+ } else {
+
+ IF_RCV_LOUD(DbgPrint("ELNK3: IndicatePacket: bad size or adapter failed -> not idicated\n");)
+
+ }
+
+ } else {
+ //
+ // The packet completed with some sort of error, just
+ // discard it
+ //
+
+ IF_RCV_LOUD(DbgPrint("ELNK3: IndicatePackets: error %04x\n", RcvStatus & 0xf800);)
+ IF_LOG(0xff,0xff,RcvStatus & 0xf800);
+
+ Elnk3DiscardPacketSync(TransDataContext);
+
+ pAdapter->MissedPackets++;
+
+
+ //
+ // This will be the next packet that we are using
+ //
+ NextPacket=(CurrentPacket+1) % 2;
+
+ AltTransDataContext= &pAdapter->TransContext[NextPacket];
+
+ DEBUG_STAT(pAdapter->Stats.BadReceives);
+
+ } // if (!(RcvStatus & RX_STATUS_ERROR))
+
+ //
+ // Re-initialize the info for this buffer
+ //
+ TransDataContext->BytesAlreadyRead=0;
+// TransDataContext->PacketLength=0;
+
+
+ //
+ // Switch buffers now. The one we are switching to may already
+ // have data in it from above.
+ //
+// pAdapter->CurrentPacket=NextPacket;
+ CurrentPacket=NextPacket;
+
+ //
+ // Update the pointer
+ //
+
+ TransDataContext=AltTransDataContext;
+
+
+ } // if (packet complete)
+
+ //
+ // The packet in the fifo is not complete yet.
+ // If there is enough data in the fifo copy it out now
+ // to reduce the chance of overflow
+ //
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ if ((BYTES_IN_FIFO_DW(RcvStatus) >= pAdapter->LowWaterMark)
+ &&
+ (BYTES_IN_FIFO_DW(RcvStatus)+TransDataContext->BytesAlreadyRead<=1514)
+ &&
+ ((RcvStatus & RX_STATUS_INCOMPLETE))
+ &&
+ !(RcvStatus & RX_STATUS_ERROR)) {
+
+ IF_LOG(0xdc,0xea,(RcvStatus & 0xc7fc));
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)((PUCHAR)TransDataContext->LookAhead+TransDataContext->BytesAlreadyRead),
+ ((RcvStatus & 0x7fc) >> 2)
+ );
+
+ TransDataContext->BytesAlreadyRead += BYTES_IN_FIFO_DW(RcvStatus);
+
+ }
+
+
+
+
+ //
+ // if the receiver should happen to fail we might
+ // not ever exit this loop. The receiver should
+ // only fail if we read past our packet in the
+ // fifo
+ //
+
+ InterruptReason=ELNK3_READ_PORT_USHORT(pAdapter,PORT_CmdStatus);
+
+ if (InterruptReason & EC_INT_ADAPTER_FAILURE) {
+
+ IF_LOUD(
+ DbgPrint("Elnk3: Adapter failed\n");
+ DbgBreakPoint();
+ )
+
+ break;
+ }
+
+ //
+ // get a new receive for the logic up top
+ //
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+
+ } // While (!complete and > 64 bytes in fifo
+
+
+
+
+
+ //
+ // Figure out where to set the early receive threshold depending
+ // how much of the packet we have so far
+ //
+
+ if (TransDataContext->BytesAlreadyRead > 16) {
+
+ PossibleLength=Elnk3GuessFrameSize(TransDataContext->LookAhead,
+ TransDataContext->BytesAlreadyRead);
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: Possible length is %d\n",PossibleLength);)
+
+ if (PossibleLength > pAdapter->LatencyAdjustment) {
+ //
+ // There is enough time to set the threshold before
+ // the packet passes the new threshold
+ //
+
+ IF_LOG(0xef,0x02,((PossibleLength)-pAdapter->LatencyAdjustment) & 0x7ff);
+ ELNK3_COMMAND(pAdapter,EC_SET_RX_EARLY, ((PossibleLength)-pAdapter->LatencyAdjustment) & 0x7fc);
+
+ }
+
+
+ } else {
+ //
+ // Set rx early to catch the front of the packet
+ //
+ IF_LOG(0xef,0x03,(pAdapter->LookAheadLatencyAdjustment));
+ ELNK3_COMMAND(pAdapter,EC_SET_RX_EARLY, (pAdapter->LookAheadLatencyAdjustment) );
+ }
+
+ //
+ // save this so we know where we are
+ //
+ pAdapter->CurrentPacket=CurrentPacket;
+
+ if (Indicated) {
+
+ DEBUG_STAT(pAdapter->Stats.IndicationCompleted);
+
+
+ NdisMEthIndicateReceiveComplete(pAdapter->NdisAdapterHandle);
+ }
+
+#if DBG
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ IF_LOG(0xdc,0xdd,RcvStatus & 0xc7ff);
+#endif
+
+ return TRUE;
+}
+
+
+
+
+
+
+
+
+
+
+VOID
+Elnk3DiscardPacketSync(
+ IN PTRANSFERDATA_CONTEXT TransDataContext
+ )
+/*++
+
+Routine Description:
+
+ Discard tap packet in receive fifo
+
+Arguments:
+
+
+Notes:
+
+ We do this as a sync with interrupt routine because the discard
+ command does not complete with in the time it takes the I/O command
+ to complete. Since another command cannot be issued during the time
+ that one is in progress we must do this to protect our selves against
+ the mask command issued in the ISR.
+
+--*/
+
+{
+
+ PELNK3_ADAPTER pAdapter=TransDataContext->pAdapter;
+ ULONG RcvStatus;
+ ULONG Sum;
+ ULONG FreeBytes;
+
+
+ ELNK3_COMMAND(pAdapter, EC_RX_DISCARD_TOP_PACKET, 0);
+
+ //
+ // An interesting thing to do at raised IRQL.
+ // Unfortuanly I don't really see an alternative
+ // The wait appears to be very short any way
+ //
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ if (RcvStatus & RX_STATUS_INCOMPLETE) {
+ //
+ // If the status is incomplete then we need to check
+ // to make sure that the fifo is not fucked up with a
+ // packet lost in it. To find out we read the
+ // the number of free bytes out of page 3 and add
+ // the number of bytes received from the RX status.
+ // If this value isn't with in 100 of the total
+ // fifo size then we conclude that is screwed up
+ // and we reset the receiver
+ //
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_FIFO);
+
+ FreeBytes=ELNK3_READ_PORT_USHORT(pAdapter,PORT_FREE_RX_BYTES);
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_OPERATING);
+
+
+ Sum=(BYTES_IN_FIFO(RcvStatus) + FreeBytes);
+
+ if ((Sum + 90 < pAdapter->RxFifoSize)
+ ||
+ ((pAdapter->RxFifoSize==FreeBytes) && (BYTES_IN_FIFO(RcvStatus)!=0))) {
+
+ BOOLEAN FifoBad;
+
+ IF_LOG(0xde,0xad,0xffff);
+
+ IF_RCV_LOUD(DbgPrint("ELNK3: RX fifo problem used=%d free=%d size=%d\n",RcvStatus & 0x7ff,FreeBytes, pAdapter->RxFifoSize);)
+
+ //
+ // Looks like the fifo is messed up, try it again
+ // syncronized with interrupts
+ //
+ FifoBad=NdisMSynchronizeWithInterrupt(
+ &pAdapter->NdisInterrupt,
+ Elnk3CheckFifoSync,
+ TransDataContext
+ );
+
+ if (FifoBad) {
+ //
+ // It's fucked up. Reset the receiver
+ //
+ ELNK3_COMMAND(pAdapter,EC_RX_RESET,0);
+
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+
+ ELNK3_COMMAND(pAdapter,EC_RX_ENABLE,0);
+
+ ELNK3_COMMAND(pAdapter, EC_SET_RX_FILTER, pAdapter->RxFilter);
+ }
+ }
+ }
+}
+
+
+BOOLEAN
+Elnk3CheckFifoSync(
+ IN PTRANSFERDATA_CONTEXT TransDataContext
+ )
+/*++
+
+Routine Description:
+
+ Check the fifo's state to try to determine if a packet
+ is lost in it. We do this syncronized with interrupts
+ to reduce the chance of interrupt occuring between the
+ port reads.
+
+Arguments:
+
+
+Notes:
+
+
+--*/
+
+{
+
+ PELNK3_ADAPTER pAdapter=TransDataContext->pAdapter;
+ ULONG RcvStatus;
+ ULONG Sum;
+ ULONG FreeBytes;
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ if (!(RcvStatus & RX_STATUS_INCOMPLETE)) {
+ //
+ // It's completed now
+ //
+ return FALSE;
+ }
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_FIFO);
+
+ FreeBytes=ELNK3_READ_PORT_USHORT(pAdapter,PORT_FREE_RX_BYTES);
+
+ ELNK3_SELECT_WINDOW(pAdapter,WNO_OPERATING);
+
+ Sum=(BYTES_IN_FIFO(RcvStatus) + FreeBytes);
+
+#if DBG
+ if ((Sum + 90 < pAdapter->RxFifoSize)
+ ||
+ ((pAdapter->RxFifoSize==FreeBytes) && (BYTES_IN_FIFO(RcvStatus)!=0))) {
+
+ IF_LOUD(DbgPrint("ELNK3: RX fifo problem used=%d free=%d size=%d\n",RcvStatus & 0x7ff,FreeBytes, pAdapter->RxFifoSize);)
+ }
+#endif
+
+ return ((Sum + 90 < pAdapter->RxFifoSize)
+ ||
+ ((pAdapter->RxFifoSize==FreeBytes) && (BYTES_IN_FIFO(RcvStatus)!=0)));
+
+
+
+
+}
+
+
+NDIS_STATUS
+Elnk3TransferData(
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred,
+ IN NDIS_HANDLE MacBindingHandle,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer
+ )
+
+/*++
+
+Routine Description:
+
+ NDIS function.
+
+Arguments:
+
+ see NDIS 3.0 spec.
+
+Notes:
+
+ The receive context is a pointer to a structure that describes the packet
+
+--*/
+
+{
+ UINT BytesLeft, BytesNow, BytesWanted;
+ PNDIS_BUFFER CurBuffer;
+ PUCHAR BufStart;
+ UINT BufLen;
+ ULONG DataAvailible;
+
+ PUCHAR pBuffer;
+
+
+ PTRANSFERDATA_CONTEXT TransDataContext= ((PTRANSFERDATA_CONTEXT)MacReceiveContext);
+ PELNK3_ADAPTER pAdapter = MacBindingHandle;
+
+
+
+ IF_LOG(0xDD,0xdd,TransDataContext->PacketLength);
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: Transferdata: bo=%d bt=%d\n",ByteOffset, BytesToTransfer);)
+
+ DEBUG_STAT(pAdapter->Stats.TransferDataCount);
+
+
+
+ if (ByteOffset+BytesToTransfer > TransDataContext->PacketLength) {
+ //
+ // Adjust the amount of data the protocol wants
+ //
+
+ IF_LOUD(DbgPrint("Elnk3: TD() Protocol asked for too much data bo=%d btt=%d pl=%d Da=%d\n",
+ ByteOffset,
+ BytesToTransfer,
+ TransDataContext->PacketLength
+ );)
+
+ if (TransDataContext->PacketLength > ByteOffset) {
+
+ BytesToTransfer = TransDataContext->PacketLength - ByteOffset;
+
+ } else {
+ //
+ // the offset is past the packet length, bad protocol bad
+ //
+ *BytesTransferred = 0;
+
+ return NDIS_STATUS_SUCCESS;
+
+ }
+ }
+
+ DataAvailible=TransDataContext->BytesAlreadyRead;
+
+ if (DataAvailible < (TransDataContext->PacketLength+ELNK3_ETHERNET_HEADER_SIZE)) {
+ //
+ // We haven't read all of the data out of the fifo yet, so
+ // let our transfer data completetion handler do it
+ //
+ // See how much data there is to transfer.
+ //
+
+ PACKET_RESERVED(Packet)->u.TransData.ByteOffset = ByteOffset;
+ PACKET_RESERVED(Packet)->u.TransData.BytesToTransfer = BytesToTransfer;
+
+ PACKET_RESERVED(Packet)->Next=TransDataContext->Stack;
+
+ TransDataContext->Stack=Packet;
+
+ return NDIS_STATUS_PENDING;
+
+ }
+
+ //
+ // The whole packet fit in the lookahead data, so copy it out
+ // right now
+ //
+
+
+
+
+ BytesWanted = BytesToTransfer;
+
+ IF_RCV_LOUD(DbgPrint("TD: bo=%d bt=%d ps=%d\n",ByteOffset, BytesToTransfer, TransDataContext->PacketLength);)
+
+
+
+ BytesLeft = BytesWanted;
+
+ //
+ // Get a pointer to the begining of the data to be copied.
+ // The 14 byte header is handled by lookahead element
+ //
+ pBuffer=TransDataContext->LookAhead->LookAheadData+ByteOffset;
+
+ NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
+
+ if (BytesLeft > 0) {
+
+ while (1) {
+
+ NdisQueryBuffer(CurBuffer, (PVOID *)&BufStart, &BufLen);
+
+ //
+ // See how much data to read into this buffer.
+ //
+
+ BytesNow= BufLen < BytesLeft ? BufLen : BytesLeft;
+
+ NdisMoveMemory(
+ BufStart,
+ pBuffer,
+ BytesNow
+ );
+
+
+ pBuffer += BytesNow;
+
+ BytesLeft -= BytesNow;
+
+
+ //
+ // Is the transfer done now?
+ //
+
+ if (BytesLeft == 0) {
+
+ break;
+ }
+
+ NdisGetNextBuffer(CurBuffer, &CurBuffer);
+
+ if (CurBuffer == (PNDIS_BUFFER)NULL) {
+
+ break;
+ }
+ }
+ }
+
+ *BytesTransferred = BytesWanted - BytesLeft;
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+
+
+
+
+
+BOOLEAN
+Elnk3EarlyReceive(
+ PELNK3_ADAPTER pAdapter
+ )
+/*++
+
+ Routine Description:
+ This routine Indicates all of the packets in the ring one at a time
+
+ Arguments:
+
+
+ Return Value:
+
+--*/
+
+{
+
+ ULONG PacketLength;
+ USHORT RcvStatus;
+ ULONG DataAvailible;
+ UINT PossibleLength;
+
+
+ PTRANSFERDATA_CONTEXT TransDataContext= &pAdapter->TransContext[0];
+
+
+ DataAvailible=TransDataContext->BytesAlreadyRead;
+
+
+ if (DataAvailible == 0) {
+
+ //
+ // First early receive get the lookahead and set the second early receive
+ //
+ // With any luck the packet will complete and the packet complete
+ // interrupt will mask the this early receive thus reducing the effective
+ // delay in processing the interrupt
+ //
+ // If not then this routine will run again and kill some time reading
+ // in data from the card. This should happen to often and when it
+ // does we should not have missed by much. The data that we do copy
+ // will most likely be used any way so not much will be lost.
+ //
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ PacketLength=BYTES_IN_FIFO_DW(RcvStatus);
+
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)((PUCHAR)TransDataContext->LookAhead+DataAvailible),
+ (PacketLength >> 2)
+ );
+
+ TransDataContext->BytesAlreadyRead += PacketLength;
+
+
+
+ IF_LOG(0xee,0x01,PacketLength);
+
+
+ PossibleLength=Elnk3GuessFrameSize(TransDataContext->LookAhead,
+ TransDataContext->BytesAlreadyRead);
+
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: Possible length is %d\n",PossibleLength);)
+
+
+
+ if (PossibleLength-pAdapter->RxMinimumThreshold > (UINT)pAdapter->LatencyAdjustment) {
+
+ ELNK3_COMMAND(pAdapter,EC_SET_RX_EARLY, ((PossibleLength)-pAdapter->LatencyAdjustment) & 0x7ff);
+ IF_LOG(0xef,0x01,((PossibleLength)-pAdapter->LatencyAdjustment) & 0x7ff);
+ }
+
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ if (!(RcvStatus & RX_STATUS_INCOMPLETE)) {
+ //
+ // The packet completed while we were reading it in
+ //
+ Elnk3IndicatePackets(pAdapter);
+ }
+
+ } else {
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ IF_LOG(0xee,0x02,BYTES_IN_FIFO(RcvStatus));
+
+ //
+ // Second early receive, Copy data until it completes
+ // and then call indicatepackets
+ //
+ while ((RcvStatus & RX_STATUS_INCOMPLETE) && !(RcvStatus & RX_STATUS_ERROR)) {
+
+ IF_LOG(0xee,0x03,RcvStatus & 0xc7fc);
+
+ if (BYTES_IN_FIFO_DW(RcvStatus) >= 32) {
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)((PUCHAR)TransDataContext->LookAhead+TransDataContext->BytesAlreadyRead),
+ 32 >> 2
+ );
+
+ TransDataContext->BytesAlreadyRead += 32;
+ }
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+ }
+
+ Elnk3IndicatePackets(pAdapter);
+
+
+ DEBUG_STAT(pAdapter->Stats.SecondEarlyReceive);
+ }
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+Elnk3IndicatePackets(
+ PELNK3_ADAPTER pAdapter
+ )
+/*++
+
+ Routine Description:
+ This routine Indicates all of the packets in the ring one at a time
+
+ Arguments:
+
+
+ Return Value:
+
+--*/
+
+{
+
+ ULONG LookAheadSize;
+ USHORT RcvStatus;
+ ULONG DataAvailible;
+ ULONG AdditionalData;
+ ULONG GoodReceives=0;
+ ULONG BadReceives=0;
+ ULONG PossibleLength;
+
+
+
+ PTRANSFERDATA_CONTEXT TransDataContext= &pAdapter->TransContext[0];
+
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ IF_LOG(0xdc,0xdc,RcvStatus & 0xc7ff);
+
+ IF_RCV_LOUD(DbgPrint("ELNK3: IndicatePackets RX status=%04x\n",RcvStatus);)
+
+
+ do {
+
+ while (!(RcvStatus & RX_STATUS_INCOMPLETE)) {
+
+ if (!(RcvStatus & RX_STATUS_ERROR)) {
+
+ TransDataContext->PacketLength=BYTES_IN_FIFO(RcvStatus);
+
+ DataAvailible=TransDataContext->BytesAlreadyRead;
+
+ TransDataContext->PacketLength+=DataAvailible;
+
+ IF_LOG(0xdc,0x01,TransDataContext->PacketLength);
+
+ if ((TransDataContext->PacketLength<=1514) &&
+ (TransDataContext->PacketLength >= 14)) {
+
+ //
+ // The packet seems to be OK
+ // Subtract the header length(14) from the packet length
+ //
+
+ TransDataContext->PacketLength-=ELNK3_ETHERNET_HEADER_SIZE;
+
+ //
+ // Lookahead is the smaller of Packetsize and the current lookahead size
+ //
+ LookAheadSize=TransDataContext->PacketLength < pAdapter->MaxLookAhead ?
+ TransDataContext->PacketLength : pAdapter->MaxLookAhead;
+
+
+ if (LookAheadSize+ELNK3_ETHERNET_HEADER_SIZE > DataAvailible) {
+ //
+ // We did not get an early receive for this packet.
+ // Most likly it is a small packet that is less than our threshold.
+ // Or the latency is too great
+ //
+ AdditionalData=ELNK3_ROUND_TO_DWORD(LookAheadSize+ELNK3_ETHERNET_HEADER_SIZE)-DataAvailible;
+
+ IF_LOG(0xad,0x01,AdditionalData);
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)(((PUCHAR)TransDataContext->LookAhead)+DataAvailible),
+ (AdditionalData>>2)
+ );
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: Indicate: Da=%d Ad=%d\n",DataAvailible, AdditionalData);)
+
+ TransDataContext->BytesAlreadyRead+=AdditionalData;
+
+ } else {
+ //
+ // The lookahead data is waiting for us, so just go ahead and indicate.
+ //
+ DEBUG_STAT(pAdapter->Stats.IndicateWithDataReady);
+
+ }
+
+
+ GoodReceives++;
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: Indicate: ls=%d pl=%d\n", LookAheadSize, TransDataContext->PacketLength);)
+
+ TransDataContext->Stack=NULL;
+
+ NdisMEthIndicateReceive(
+ pAdapter->NdisAdapterHandle,
+ TransDataContext,
+ (PUCHAR)&TransDataContext->LookAhead->EthHeader,
+ ELNK3_ETHERNET_HEADER_SIZE,
+ TransDataContext->LookAhead->LookAheadData,
+ LookAheadSize,
+ TransDataContext->PacketLength
+ );
+
+ DEBUG_STAT(pAdapter->Stats.PacketIndicated);
+
+ if (TransDataContext->Stack!=NULL) {
+ //
+ // at least one protocol called transferdata
+ //
+ Elnk3TransferDataCompletion(
+ TransDataContext
+ );
+
+ }
+
+
+
+ } else {
+
+ IF_RCV_LOUD(DbgPrint("ELNK3: (Packet>1514) || (error in packet) -> not idicated\n");)
+
+ }
+
+ } else {
+
+ IF_RCV_LOUD(DbgPrint("ELNK3: IndicatePackets: error %04x\n", RcvStatus & 0xf800);)
+ IF_LOG(0xff,0xff,0xffff);
+
+ DEBUG_STAT(pAdapter->Stats.BadReceives);
+
+ }
+
+ Elnk3DiscardPacketSync(TransDataContext);
+
+ pAdapter->FramesRcvGood+=GoodReceives;
+
+
+ TransDataContext->BytesAlreadyRead=0;
+
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ } // while complete
+
+
+ DEBUG_STAT(pAdapter->Stats.IndicationCompleted);
+
+ NdisMEthIndicateReceiveComplete(pAdapter->NdisAdapterHandle);
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ //
+ // See if there is a lookahead's worth of data from the next yet
+ //
+ if ( BYTES_IN_FIFO_DW(RcvStatus) > pAdapter->EarlyReceiveThreshold) {
+
+ if ( BYTES_IN_FIFO_DW(RcvStatus) > 1200 && (RcvStatus & RX_STATUS_INCOMPLETE)) {
+ //
+ // There is alot of data in the fifo, but the packet has not completed yet.
+ // In order to try to prevent an over flow, lets empty now
+ //
+ IF_LOG(0xdc,0xeb,RcvStatus & 0xc7fc);
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)((PUCHAR)TransDataContext->LookAhead+TransDataContext->BytesAlreadyRead),
+ BYTES_IN_FIFO_DW(RcvStatus) >> 2
+ );
+
+ TransDataContext->BytesAlreadyRead += BYTES_IN_FIFO_DW(RcvStatus);
+
+ } else {
+
+ IF_LOG(0xdc,0xea,RcvStatus & 0xc7fc);
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)((PUCHAR)TransDataContext->LookAhead+TransDataContext->BytesAlreadyRead),
+ pAdapter->EarlyReceiveThreshold >> 2
+ );
+
+ TransDataContext->BytesAlreadyRead += pAdapter->EarlyReceiveThreshold;
+ }
+
+ }
+
+ //
+ // In the time it took to port i/o in the lookahead data the packet may
+ // have completed
+ //
+
+ } while (!(RcvStatus & RX_STATUS_INCOMPLETE));
+
+
+
+ //
+ // At this point there is either 0 or EarlyReceiveThreshold bytes in the buffer
+ //
+
+ if (TransDataContext->BytesAlreadyRead > 16) {
+
+ PossibleLength=Elnk3GuessFrameSize(TransDataContext->LookAhead,
+ TransDataContext->BytesAlreadyRead);
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: Possible length is %d\n",PossibleLength);)
+
+ if (PossibleLength > pAdapter->LatencyAdjustment) {
+ //
+ // There is enough time to set the threshold before
+ // the packet passes the new threshold
+ //
+
+ IF_LOG(0xef,0x02,((PossibleLength)-pAdapter->LatencyAdjustment) & 0x7ff);
+ ELNK3_COMMAND(pAdapter,EC_SET_RX_EARLY, ((PossibleLength)-pAdapter->LatencyAdjustment) & 0x7fc);
+
+ }
+
+
+ } else {
+ //
+ // Set rx early to catch the front of the packet
+ //
+ IF_LOG(0xef,0x02,(pAdapter->LookAheadLatencyAdjustment));
+ ELNK3_COMMAND(pAdapter,EC_SET_RX_EARLY, (pAdapter->LookAheadLatencyAdjustment) );
+ }
+
+
+
+
+#if DBG
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ IF_LOG(0xdc,0xdd,RcvStatus & 0xc7ff);
+#endif
+
+
+ return TRUE;
+}
+
+
+
+
+
+
+ULONG
+Elnk3GuessFrameSize(
+ IN PNIC_RCV_HEADER Frame,
+ IN ULONG BytesNow
+ )
+/*++
+
+ Routine Description:
+
+ This rountine endevers to determine the size of the packet
+ from the packet header.
+
+ This scheme was borrowed from 3com's ndis 2 driver
+
+ Arguments:
+
+
+ Return Value:
+
+--*/
+
+{
+
+ ULONG PossibleLength;
+
+
+ PossibleLength=(Frame->EthHeader.EthLength[0]<<8)+
+ Frame->EthHeader.EthLength[1];
+
+
+ //
+ // Is it 802.3
+ //
+ if (PossibleLength < 0x600 ) {
+ //
+ // Looks to an 802.3 frame
+ //
+ return (PossibleLength+14);
+ }
+
+ //
+ // Xns, IP, IPX ?
+ //
+
+ if (PossibleLength==XNS_FRAME_TYPE ||
+ PossibleLength==IP_FRAME_TYPE ||
+ PossibleLength==IPX_FRAME_TYPE ) {
+
+ PossibleLength=(Frame->LookAheadData[2]<<8)+
+ Frame->LookAheadData[3]+14;
+
+ } else {
+ //
+ // Not one we recognise
+ //
+ return 1514;
+ }
+
+
+ if (PossibleLength<=1514 && PossibleLength>=BytesNow) {
+ //
+ // Looks reasonable
+ //
+ return PossibleLength;
+
+ } else {
+ //
+ // Don't look like we got the length, just go with max
+ //
+ return 1514;
+ }
+
+
+}
+
+
+
+VOID
+Elnk3DiscardIfBroadcast(
+ IN PELNK3_ADAPTER pAdapter,
+ IN PTRANSFERDATA_CONTEXT TransDataContext
+ )
+
+{
+ USHORT RcvStatus;
+
+
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ while (BYTES_IN_FIFO_DW(RcvStatus) > 8) {
+
+ IF_LOG(0xaf,0xff,BYTES_IN_FIFO_DW(RcvStatus));
+
+#if DBG
+ if (TransDataContext->BytesAlreadyRead != 0) {
+ DbgPrint("Elnk3: FindNextPacket called with BytesAlreadyRead != 0\n");
+ DbgBreakPoint();
+ }
+#endif
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)((PUCHAR)TransDataContext->LookAhead),
+ (8 >> 2)
+ );
+
+ TransDataContext->BytesAlreadyRead = 8;
+
+ if (ETH_IS_BROADCAST(&TransDataContext->LookAhead->EthHeader.Destination[0])) {
+
+ //
+ // We don't want this one so, we discard it now
+ //
+
+ Elnk3DiscardPacketSync(TransDataContext);
+
+
+ DEBUG_STAT(pAdapter->Stats.BroadcastsRejected);
+
+
+ //
+ // No bytes anymore
+ //
+ TransDataContext->BytesAlreadyRead = 0;
+
+ //
+ // we chucked it, see what the next one holds in store for us
+ //
+ RcvStatus=ELNK3_READ_PORT_USHORT(pAdapter,PORT_RxStatus);
+
+ continue;
+
+ }
+
+
+ //
+ // We need to indicate it
+ //
+
+ break;
+
+ }
+}
+
+
+
+
+
+VOID
+Elnk3TransferDataCompletion(
+ PTRANSFERDATA_CONTEXT TransDataContext
+ )
+
+{
+
+ PELNK3_ADAPTER pAdapter;
+ PNDIS_PACKET Packet;
+ PNDIS_BUFFER CurBuffer;
+ PUCHAR BufferAddress;
+ ULONG BufferLength;
+ ULONG DataAvailible;
+ ULONG OffsetInLookAhead;
+ ULONG BytesLeft;
+ ULONG BytesNow;
+ ULONG ByteOffset;
+ ULONG BytesToTransfer;
+ ULONG AdditionalData;
+
+
+
+ pAdapter=TransDataContext->pAdapter;
+ //
+ // See if more than one binding called transferdata
+ //
+ if (PACKET_RESERVED(TransDataContext->Stack)->Next==NULL) {
+ //
+ // just one, just port io into the ndis buffer
+ //
+ IF_RCV_LOUD(DbgPrint("Elnk3: TransComp: One transferdata call\n");)
+
+ Packet=TransDataContext->Stack;
+
+
+ //
+ // See just what this protocol wants
+ //
+ BytesToTransfer = PACKET_RESERVED(Packet)->u.TransData.BytesToTransfer;
+
+ ByteOffset = PACKET_RESERVED(Packet)->u.TransData.ByteOffset;
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: TransComp: bo=%d bt=%d\n",ByteOffset,BytesToTransfer);)
+
+
+
+
+ BytesLeft=BytesToTransfer;
+
+ OffsetInLookAhead=ByteOffset+ELNK3_ETHERNET_HEADER_SIZE;
+
+ NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
+
+ NdisQueryBuffer(CurBuffer, (PVOID *)&BufferAddress, &BufferLength);
+
+ DataAvailible=TransDataContext->BytesAlreadyRead;
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: TransComp: DataAvailible=%d offset=%d\n",DataAvailible,OffsetInLookAhead);)
+
+ //
+ // copy the data out of the lookahead buffer
+ //
+ // Note, that this loop assumes that whole packet does not fit
+ // in the lookahead data. If it does TransferData does not pend
+ // and this routine is not called. This is a problem because
+ // we read data out of the fifo in multiples of dwords and we
+ // get padding bytes in our data availible count
+ //
+
+ if (OffsetInLookAhead > DataAvailible) {
+ //
+ // The byte offset is past the lookahead data.
+ // We need to port some more stuff out of the fifo
+ // to get to where the data is that we want
+ //
+
+ NdisRawReadPortBufferUchar(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PUCHAR)((PUCHAR)TransDataContext->LookAhead+TransDataContext->BytesAlreadyRead),
+ OffsetInLookAhead - DataAvailible
+ );
+
+ TransDataContext->BytesAlreadyRead+=(OffsetInLookAhead - DataAvailible);
+
+ } else {
+ //
+ // the byteoffset is with in the lookahead data
+ // copy it to the ndis buffer
+ //
+
+
+ while (OffsetInLookAhead < DataAvailible) {
+ //
+ // Need to copy some of lookeahead into protocol packet
+ //
+
+ BytesNow= BufferLength < (DataAvailible-OffsetInLookAhead) ?
+ BufferLength : (DataAvailible-OffsetInLookAhead);
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: TransComp: lookahead bn=%d offset=%d\n",BytesNow,OffsetInLookAhead);)
+
+
+ NdisMoveMemory(
+ BufferAddress,
+ (PUCHAR)TransDataContext->LookAhead+OffsetInLookAhead,
+ BytesNow
+ );
+
+ BytesLeft-=BytesNow;
+
+ OffsetInLookAhead+=BytesNow;
+
+ BufferAddress+=BytesNow;
+
+ BufferLength-=BytesNow;
+
+ if (BufferLength==0) {
+
+ NdisGetNextBuffer(CurBuffer, &CurBuffer);
+
+ if (CurBuffer==NULL) {
+
+ break;
+ }
+
+ NdisQueryBuffer(CurBuffer, (PVOID *)&BufferAddress, &BufferLength);
+ }
+
+ }
+ }
+
+ //
+ // port i/o in the rest of the packet into the protocols packet
+ //
+
+ while (BytesLeft > 0) {
+
+ BytesNow= BufferLength < BytesLeft ?
+ BufferLength : BytesLeft;
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: TransComp: bl=%d bn=%d\n",BytesLeft,BytesNow);)
+ IF_LOG(0xad,0xd1,BytesNow);
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)BufferAddress,
+ BytesNow>>2
+ );
+
+ if (BytesNow & 3) {
+
+ NdisRawReadPortBufferUchar(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PUCHAR)((PUCHAR)BufferAddress+(BytesNow & 0xfffffffc)),
+ BytesNow & 3
+ );
+ }
+
+ BytesLeft-=BytesNow;
+
+ NdisGetNextBuffer(CurBuffer, &CurBuffer);
+
+ if (CurBuffer == NULL) {
+
+ break;
+ }
+
+ NdisQueryBuffer(CurBuffer, (PVOID *)&BufferAddress, &BufferLength);
+
+ }
+
+
+ NdisMTransferDataComplete(
+ pAdapter->NdisAdapterHandle,
+ Packet,
+ NDIS_STATUS_SUCCESS,
+ BytesToTransfer
+ );
+
+
+
+
+ return ;
+ }
+
+
+ //
+ // More than one protocol wants the packet.
+ // We will port i/o the whole thing to one of our buffers
+ // and then copy the data into the protocols packets
+ //
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: TransComp: Multiple transferdata calls\n");)
+
+ while ((Packet=TransDataContext->Stack) != NULL) {
+
+ TransDataContext->Stack=PACKET_RESERVED(Packet)->Next;
+
+ //
+ // See just what this protocol wants
+ //
+ BytesToTransfer = PACKET_RESERVED(Packet)->u.TransData.BytesToTransfer;
+
+ ByteOffset = PACKET_RESERVED(Packet)->u.TransData.ByteOffset;
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: TransComp: bo=%d bt=%d\n",ByteOffset,BytesToTransfer);)
+
+
+ IF_RCV_LOUD(DbgPrint("TD: bo=%d bt=%d ps=%d\n",ByteOffset, BytesToTransfer, TransDataContext->PacketLength);)
+
+
+ //
+ // We got this much so far
+ //
+ DataAvailible=TransDataContext->BytesAlreadyRead;
+
+
+ //
+ // See if the whole thing has been removed from the fifo
+ //
+ if (DataAvailible < (TransDataContext->PacketLength+ELNK3_ETHERNET_HEADER_SIZE)) {
+ //
+ // Get the rest of the data from the fifo
+ //
+
+ AdditionalData=ELNK3_ROUND_TO_DWORD((TransDataContext->PacketLength+ELNK3_ETHERNET_HEADER_SIZE)-DataAvailible);
+
+ NdisRawReadPortBufferUlong(
+ pAdapter->PortOffsets[PORT_RxFIFO],
+ (PULONG)((PUCHAR)TransDataContext->LookAhead+DataAvailible),
+ AdditionalData>>2
+ );
+
+ IF_LOG(0xad,0x02,AdditionalData);
+
+ IF_RCV_LOUD(DbgPrint("Elnk3: TransComp: Da=%d Ad=%d\n",DataAvailible, AdditionalData);)
+
+ TransDataContext->BytesAlreadyRead+=AdditionalData;
+
+ }
+
+
+
+ BytesLeft = BytesToTransfer;
+
+
+ OffsetInLookAhead=ByteOffset;
+
+
+ NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
+
+ while (BytesLeft > 0) {
+
+ NdisQueryBuffer(CurBuffer, (PVOID *)&BufferAddress, &BufferLength);
+
+ //
+ // See how much data to read into this buffer.
+ //
+
+ BytesNow= BufferLength < BytesLeft ? BufferLength : BytesLeft;
+
+ //
+ // Note: the LookAheadData element of the structure handles the
+ // 14 byte header discrepency
+ //
+ NdisMoveMemory(
+ BufferAddress,
+ TransDataContext->LookAhead->LookAheadData+OffsetInLookAhead,
+ BytesNow
+ );
+
+
+ OffsetInLookAhead += BytesNow;
+
+ BytesLeft -= BytesNow;
+
+
+ //
+ // Is the transfer done now?
+ //
+
+ if (BytesLeft == 0) {
+
+ break;
+ }
+
+ NdisGetNextBuffer(CurBuffer, &CurBuffer);
+
+ if (CurBuffer == (PNDIS_BUFFER)NULL) {
+
+ break;
+ }
+
+ }
+
+
+
+ NdisMTransferDataComplete(
+ pAdapter->NdisAdapterHandle,
+ Packet,
+ NDIS_STATUS_SUCCESS,
+ BytesToTransfer
+ );
+
+
+
+
+
+ } // while packets
+
+
+
+
+ return;
+
+}
diff --git a/private/ntos/ndis/elnk3/request.c b/private/ntos/ndis/elnk3/request.c
new file mode 100644
index 000000000..a267b3da9
--- /dev/null
+++ b/private/ntos/ndis/elnk3/request.c
@@ -0,0 +1,839 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ request.c
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+ This file handles NdisRequest. The module was for the most part extracted
+ from the elnkii driver
+
+Author:
+
+ Brian Lieuallen (BrianLie) 07/02/92
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+--*/
+
+
+
+
+
+#include <ndis.h>
+//#include <efilter.h>
+
+#include "debug.h"
+
+
+#include "elnk3hrd.h"
+#include "elnk3sft.h"
+#include "elnk3.h"
+
+
+
+
+
+
+NDIS_STATUS
+Elnk3FilterChangeAction(
+ IN UINT NewFilterClasses,
+ IN NDIS_HANDLE MacBindingHandle
+ );
+
+
+
+
+
+//
+// If you add to this, make sure to add the
+// a case in Elnk3FillInGlobalData() and in
+// Elnk3QueryGlobalStatistics() if global
+// information only or
+// Elnk3QueryProtocolStatistics() if it is
+// protocol queriable information.
+//
+STATIC UINT Elnk3GlobalSupportedOids[] = {
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_LOOKAHEAD,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_MAC_OPTIONS,
+ OID_GEN_PROTOCOL_OPTIONS,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BUFFER_SPACE,
+ OID_GEN_RECEIVE_BUFFER_SPACE,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+ OID_802_3_RCV_ERROR_ALIGNMENT,
+ OID_802_3_XMIT_ONE_COLLISION,
+ OID_802_3_XMIT_MORE_COLLISIONS
+ };
+
+
+
+
+
+
+NDIS_STATUS
+Elnk3QueryInformation(
+ IN NDIS_HANDLE MiniportContext,
+ IN NDIS_OID Oid,
+ IN PVOID InfoBuffer,
+ IN ULONG BytesLeft,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+ )
+
+/*++
+
+Routine Description:
+
+ The Elnk3QueryProtocolInformation process a Query request for
+ NDIS_OIDs that are specific to a binding about the MAC. Note that
+ some of the OIDs that are specific to bindings are also queryable
+ on a global basis. Rather than recreate this code to handle the
+ global queries, I use a flag to indicate if this is a query for the
+ global data or the binding specific data.
+
+Arguments:
+
+ Adapter - a pointer to the adapter.
+
+ Oid - the NDIS_OID to process.
+
+ PlaceInInfoBuffer - a pointer into the NdisRequest->InformationBuffer
+ into which store the result of the query.
+
+ BytesLeft - the number of bytes left in the InformationBuffer.
+
+ BytesNeeded - If there is not enough room in the information buffer
+ then this will contain the number of bytes needed to complete the
+ request.
+
+ BytesWritten - a pointer to the number of bytes written into the
+ InformationBuffer.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+ NDIS_MEDIUM Medium = NdisMedium802_3;
+ ULONG GenericULong = 0;
+ USHORT GenericUShort = 0;
+ UCHAR GenericArray[6];
+
+ PELNK3_ADAPTER pAdapter=MiniportContext;
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ //
+ // Common variables for pointing to result of query
+ //
+
+ PVOID MoveSource;
+ ULONG MoveBytes;
+
+ NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
+
+ //
+ // General Algorithm:
+ //
+ // Switch(Request)
+ // Get requested information
+ // Store results in a common variable.
+ // Copy result in common variable to result buffer.
+ //
+
+ //
+ // Make sure that ulong is 4 bytes. Else GenericULong must change
+ // to something of size 4.
+ //
+ ASSERT(sizeof(ULONG) == 4);
+
+ MoveSource = (PVOID)(&GenericULong);
+ MoveBytes = sizeof(GenericULong);
+
+
+
+ IF_REQ_LOUD(DbgPrint("ELNK3: QueryProtocol %08lx\n",Oid);)
+
+
+ //
+ // Switch on request type
+ //
+
+ switch (Oid) {
+
+ case OID_GEN_MAC_OPTIONS:
+
+ if (pAdapter->ReceiveMethod==1) {
+
+ GenericULong = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
+ NDIS_MAC_OPTION_NO_LOOPBACK ;
+
+ } else {
+
+ GenericULong = ( NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
+ NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
+ NDIS_MAC_OPTION_NO_LOOPBACK);
+ }
+
+
+ break;
+
+ case OID_GEN_SUPPORTED_LIST:
+
+
+ MoveSource = (PVOID)(Elnk3GlobalSupportedOids);
+ MoveBytes = sizeof(Elnk3GlobalSupportedOids);
+
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+
+ HardwareStatus = NdisHardwareStatusReady;
+
+
+ MoveSource = (PVOID)(&HardwareStatus);
+ MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
+
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+
+ MoveSource = (PVOID) (&Medium);
+ MoveBytes = sizeof(NDIS_MEDIUM);
+ break;
+
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+
+ GenericULong = ELNK3_MAX_LOOKAHEAD_SIZE;
+
+ break;
+
+
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+
+ GenericULong = (ULONG)(1514 - 14);
+
+ break;
+
+
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+
+ GenericULong = (ULONG)(1514);
+ break;
+
+
+ case OID_GEN_LINK_SPEED:
+
+ GenericULong = (ULONG)(100000);
+ break;
+
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+
+ GenericULong = 2048;
+ break;
+
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+
+ GenericULong = 2048;
+ break;
+
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+
+ GenericULong = 1514;
+
+ break;
+
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+
+ GenericULong = 1514;
+ break;
+
+ case OID_GEN_VENDOR_ID:
+
+ NdisMoveMemory(
+ (PVOID)&GenericULong,
+ pAdapter->PermanentAddress,
+ 3
+ );
+ GenericULong &= 0xFFFFFF00;
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+
+ MoveSource = (PVOID)"ELNK3 Ethernet Adapter.";
+ MoveBytes = 24;
+
+ break;
+
+ case OID_GEN_DRIVER_VERSION:
+
+ GenericUShort = ((USHORT)ELNK3_NDIS_MAJOR_VERSION << 8) |
+ ELNK3_NDIS_MINOR_VERSION;
+
+ MoveSource = (PVOID)(&GenericUShort);
+ MoveBytes = sizeof(GenericUShort);
+ break;
+
+
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+
+ GenericULong = (ULONG)(pAdapter->MaxLookAhead);
+
+
+
+ IF_REQ_LOUD(DbgPrint("Querying LookAhead: %d\n,GenericULong");)
+
+ break;
+
+ case OID_802_3_PERMANENT_ADDRESS:
+
+ IF_REQ_LOUD(DbgPrint("Querying Permanent address\n");)
+
+ NdisMoveMemory((PCHAR)GenericArray,
+ pAdapter->PermanentAddress,
+ ELNK3_LENGTH_OF_ADDRESS);
+
+ MoveSource = (PVOID)(GenericArray);
+ MoveBytes = sizeof(pAdapter->PermanentAddress);
+ break;
+
+
+ case OID_802_3_CURRENT_ADDRESS:
+
+ IF_REQ_LOUD(DbgPrint("Querying Current address\n");)
+
+ NdisMoveMemory(
+ (PCHAR)GenericArray,
+ pAdapter->StationAddress,
+ ELNK3_LENGTH_OF_ADDRESS
+ );
+
+ MoveSource = (PVOID)(GenericArray);
+ MoveBytes = sizeof(pAdapter->StationAddress);
+ break;
+
+
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+
+ GenericULong = (ULONG) DEFAULT_MULTICAST_SIZE;
+
+ break;
+
+ case OID_GEN_XMIT_OK:
+
+ GenericULong = pAdapter->FramesXmitGood;
+
+ break;
+
+ case OID_GEN_RCV_OK:
+
+ GenericULong = pAdapter->FramesRcvGood;
+
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+
+ GenericULong = pAdapter->FramesXmitBad;
+
+ break;
+
+ case OID_GEN_RCV_ERROR:
+
+ GenericULong = pAdapter->CrcErrors;
+
+ break;
+
+ case OID_GEN_RCV_NO_BUFFER:
+
+ GenericULong = (UINT)(pAdapter->MissedPackets);
+
+ break;
+
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+
+ GenericULong = (UINT)pAdapter->FrameAlignmentErrors;
+
+ break;
+
+ case OID_802_3_XMIT_ONE_COLLISION:
+
+ GenericULong = (UINT)pAdapter->FramesXmitOneCollision;
+
+ break;
+
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+
+ GenericULong = (UINT)pAdapter->FramesXmitManyCollisions;
+
+ break;
+
+
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ if ((StatusToReturn == NDIS_STATUS_SUCCESS) &&
+ (Oid != OID_802_3_MULTICAST_LIST)) {
+
+ if (MoveBytes > BytesLeft) {
+
+ //
+ // Not enough room in InformationBuffer. Punt
+ //
+
+ *BytesNeeded = MoveBytes;
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ } else {
+
+ //
+ // Store result.
+ //
+
+ NdisMoveMemory(InfoBuffer, MoveSource, MoveBytes);
+
+ (*BytesWritten) = MoveBytes;
+
+ }
+ }
+
+
+#if DBG
+
+ if (StatusToReturn != NDIS_STATUS_SUCCESS) {
+
+ IF_REQ_LOUD(DbgPrint("Out QueryInfo oid=%08lx failed\n",Oid);)
+ }
+#endif
+
+
+ IF_VERY_LOUD( DbgPrint("Out QueryProtocol\n");)
+
+ return StatusToReturn;
+
+}
+
+
+NDIS_STATUS
+Elnk3SetInformation(
+ IN NDIS_HANDLE MiniportContext,
+ IN NDIS_OID Oid,
+ IN PVOID InfoBuffer,
+ IN ULONG BytesLeft,
+ OUT PULONG BytesRead,
+ OUT PULONG BytesNeeded
+ )
+
+/*++
+
+Routine Description:
+
+ The Elnk3SetInformation is used by Elnk3Request to set information
+ about the MAC.
+
+Arguments:
+
+ Adapter - A pointer to the adapter.
+
+ Open - A pointer to an open instance.
+
+ NdisRequest - A structure which contains the request type (Set),
+ an array of operations to perform, and an array for holding
+ the results of the operations.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+
+{
+
+ //
+ // General Algorithm:
+ //
+ // Verify length
+ // Switch(Request)
+ // Process Request
+ //
+
+ //
+ // Variables for a particular request
+ //
+
+ PELNK3_ADAPTER pAdapter=MiniportContext;
+
+ UINT OidLength;
+
+ //
+ // Variables for holding the new values to be used.
+ //
+
+ ULONG LookAhead;
+ ULONG Filter;
+
+ NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
+
+
+ IF_REQ_LOUD( DbgPrint("ELNK3: SetInfo %08lx %0d\n",(UINT)Oid,BytesLeft);)
+
+ //
+ // Get Oid and Length of request
+ //
+
+
+ OidLength = BytesLeft;
+
+ switch (Oid) {
+
+
+ case OID_802_3_MULTICAST_LIST:
+
+ //
+ // Verify length
+ //
+
+ if ((OidLength % ELNK3_LENGTH_OF_ADDRESS) != 0){
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ break;
+
+ }
+
+#if DBG
+ {
+ UINT j;
+ PUCHAR Address;
+
+ Address=InfoBuffer;
+
+ for (j=0; j<(OidLength / ELNK3_LENGTH_OF_ADDRESS); j++) {
+
+ IF_REQ_LOUD(DbgPrint(" %02x-%02x-%02x-%02x-%02x-%02x\n",
+ Address[j*6],
+ Address[j*6+1],
+ Address[j*6+2],
+ Address[j*6+3],
+ Address[j*6+4],
+ Address[j*6+5]);)
+ }
+ }
+#endif
+
+ break;
+
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+
+ //
+ // Verify length
+ //
+
+ if (OidLength != 4 ) {
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ break;
+
+ }
+
+
+
+ NdisMoveMemory(&Filter, InfoBuffer, 4);
+
+
+ StatusToReturn=Elnk3FilterChangeAction(
+ Filter,
+ pAdapter
+ );
+
+
+
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+
+ //
+ // Verify length
+ //
+ if (OidLength != 4) {
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ break;
+
+ }
+
+ NdisMoveMemory(
+ &LookAhead,
+ InfoBuffer,
+ 4
+ );
+
+ IF_REQ_LOUD(DbgPrint("Setting LookAhead: %d\n",LookAhead);)
+
+
+ if (LookAhead <= ELNK3_MAX_LOOKAHEAD_SIZE) {
+
+ pAdapter->MaxLookAhead=LookAhead;
+ Elnk3AdjustMaxLookAhead(pAdapter);
+
+
+ } else {
+
+ StatusToReturn = NDIS_STATUS_INVALID_LENGTH;
+
+ }
+
+ break;
+
+
+ case OID_GEN_PROTOCOL_OPTIONS:
+
+ StatusToReturn = NDIS_STATUS_SUCCESS;
+
+ break;
+
+
+ default:
+
+ StatusToReturn = NDIS_STATUS_INVALID_OID;
+
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+
+ break;
+
+ }
+
+
+ if (StatusToReturn == NDIS_STATUS_SUCCESS) {
+
+ *BytesRead = BytesLeft;
+ *BytesNeeded = 0;
+
+ }
+
+
+#if DBG
+
+ if (StatusToReturn != NDIS_STATUS_SUCCESS) {
+
+ IF_REQ_LOUD(DbgPrint("Out SetInfo oid=%08lx failed\n",Oid);)
+ }
+#endif
+
+ return StatusToReturn;
+
+}
+
+
+
+
+VOID
+Elnk3AdjustMaxLookAhead(
+ IN PELNK3_ADAPTER Adapter
+ )
+/*++
+
+Routine Description:
+
+ This routine finds the open with the maximum lookahead value and
+ stores that in the adapter block.
+
+Arguments:
+
+ Adapter - A pointer to the adapter block.
+
+Returns:
+
+ None.
+
+--*/
+{
+ ULONG CurrentMax;
+
+ if (Adapter->MaxLookAhead < 60 ) {
+
+ Adapter->MaxLookAhead =60;
+
+ }
+
+
+ CurrentMax=Adapter->MaxLookAhead;
+
+ if (Adapter->ReceiveMethod==1) {
+
+ Adapter->EarlyReceiveThreshold=ELNK3_ROUND_TO_DWORD((CurrentMax+
+ ELNK3_ETHERNET_HEADER_SIZE)
+ & 0x7ff);
+ } else {
+
+ Adapter->EarlyReceiveThreshold=Adapter->ThresholdTarget & 0x7fc;
+ }
+
+
+ IF_REQ_LOUD(DbgPrint("ELNK3: Setting LookAhead: %d Threshold: %d\n", CurrentMax, Adapter->EarlyReceiveThreshold);)
+
+
+}
+
+
+NDIS_STATUS
+Elnk3FilterChangeAction(
+ IN UINT NewFilterClasses,
+ IN NDIS_HANDLE MacBindingHandle
+ )
+
+/*++
+
+Routine Description:
+
+ Action routine that will get called when an address is added to
+ the filter that wasn't referenced by any other open binding.
+
+Arguments:
+
+ NewFilterClasses - A bit mask that should be put on the card telling
+ which packet types to accept.
+
+ MacBindingHandle - The context value returned by the MAC when the
+ adapter was opened.
+
+Return Value:
+
+ Status of the change (successful or pending).
+
+
+--*/
+
+{
+ PELNK3_ADAPTER pAdapter = MacBindingHandle;
+
+ UCHAR NewFilter=0;
+
+ IF_REQ_LOUD(DbgPrint("ELNK3: FilterChangeAction called %08lx\n",NewFilterClasses);)
+
+ if (NewFilterClasses & ~(NDIS_PACKET_TYPE_DIRECTED |
+ NDIS_PACKET_TYPE_MULTICAST |
+ NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_BROADCAST |
+ NDIS_PACKET_TYPE_PROMISCUOUS )) {
+
+ IF_REQ_LOUD(DbgPrint("ELNK3: protocol set bogus filter\n");)
+ return NDIS_STATUS_NOT_SUPPORTED;
+ }
+
+
+ if (NewFilterClasses & NDIS_PACKET_TYPE_DIRECTED) {
+ IF_REQ_LOUD(DbgPrint("ELNK3: FilterChangeAction: directed\n");)
+ NewFilter|=EC_FILTER_ADDRESS;
+ }
+
+ if (NewFilterClasses & NDIS_PACKET_TYPE_MULTICAST ) {
+ IF_REQ_LOUD(DbgPrint("ELNK3: FilterChangeAction: multicast\n");)
+ NewFilter|=EC_FILTER_GROUP;
+ }
+
+ if (NewFilterClasses & NDIS_PACKET_TYPE_ALL_MULTICAST) {
+ IF_REQ_LOUD(DbgPrint("ELNK3: FilterChangeAction: all multicast\n");)
+ NewFilter|=EC_FILTER_GROUP;
+ }
+
+ if (NewFilterClasses & NDIS_PACKET_TYPE_BROADCAST) {
+ IF_REQ_LOUD(DbgPrint("ELNK3: FilterChangeAction: broadcast\n");)
+ NewFilter|=EC_FILTER_BROADCAST;
+ }
+
+ if (NewFilterClasses & NDIS_PACKET_TYPE_PROMISCUOUS) {
+ IF_REQ_LOUD(DbgPrint("ELNK3: FilterChangeAction: promiscuous\n");)
+ NewFilter|=EC_FILTER_PROMISCUOUS;
+ }
+
+
+ pAdapter->RejectBroadcast=FALSE;
+
+ if (NewFilterClasses & NDIS_PACKET_TYPE_MULTICAST) {
+ //
+ // The multicast bit is set so the card receives every thing
+ // that is not directed
+ //
+ if ((NewFilterClasses & (NDIS_PACKET_TYPE_BROADCAST |
+ NDIS_PACKET_TYPE_PROMISCUOUS))==0) {
+ //
+ // We want multicast but not broadcast and we aren't
+ // in promiscuous mode
+ //
+ pAdapter->RejectBroadcast=TRUE;
+ }
+ }
+
+
+
+
+ pAdapter->NdisRxFilter=NewFilterClasses;
+
+ pAdapter->RxFilter=NewFilter;
+
+ ELNK3_COMMAND(pAdapter, EC_SET_RX_FILTER, NewFilter);
+
+ return NDIS_STATUS_SUCCESS;
+
+
+}
diff --git a/private/ntos/ndis/elnk3/send.c b/private/ntos/ndis/elnk3/send.c
new file mode 100644
index 000000000..b76cf8beb
--- /dev/null
+++ b/private/ntos/ndis/elnk3/send.c
@@ -0,0 +1,292 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ send.c
+
+Abstract:
+
+ Ndis 3.0 MAC driver for the 3Com Etherlink III
+
+
+Author:
+
+ Brian Lieuallen (BrianLie) 12/14/92
+
+
+Environment:
+
+ Kernel Mode Operating Systems : NT
+
+Revision History:
+
+ Portions borrowed from ELNK3 driver by
+ Earle R. Horton (EarleH)
+
+
+
+--*/
+
+
+
+#include <ndis.h>
+#include <efilter.h>
+
+
+#include "debug.h"
+
+
+#include "elnk3hrd.h"
+#include "elnk3sft.h"
+#include "elnk3.h"
+
+
+
+
+
+
+
+
+
+
+NDIS_STATUS
+Elnk3MacSend(
+ IN NDIS_HANDLE MacBindingHandle,
+ IN PNDIS_PACKET Packet,
+ IN UINT Flags
+ )
+/*++
+
+Routine Description:
+ MacSend
+
+
+Arguments:
+ See NDIS 3.0 spec
+
+Return Value:
+
+
+--*/
+
+
+ {
+ PELNK3_ADAPTER pAdapter = MacBindingHandle;
+ UINT PacketLength;
+ BOOLEAN Retry=FALSE;
+ ULONG FreeFifoBytes;
+ ULONG PadBuffer=0;
+
+ IF_SEND_LOUD(DbgPrint("MacSend called Packets\n");)
+
+ NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
+
+ //
+ // Here we check to make sure the packet meets some size constraints
+ //
+
+ if (PacketLength < 14 || PacketLength > 1514) {
+
+ IF_LOUD(DbgPrint("MovePacketToCard: Packet too long or too short\n");)
+
+ return NDIS_STATUS_FAILURE;
+
+ }
+
+ //
+ // See if there is enough room in the fifo to send it now.
+ //
+ FreeFifoBytes=ELNK3_READ_PORT_USHORT(pAdapter,PORT_TxFree);
+
+ if ((FreeFifoBytes) < ELNK3_ROUND_TO_DWORD(PacketLength)+4) {
+ //
+ // Nope, Ask for a transmit availible interrupt when there is
+ //
+ ELNK3_COMMAND(pAdapter, EC_SET_TX_AVAILIBLE, ELNK3_ROUND_TO_DWORD(PacketLength)+4);
+
+ return NDIS_STATUS_RESOURCES;
+
+ }
+
+ do {
+
+
+ UCHAR XmitStatus;
+ PNDIS_BUFFER CurBuffer;
+ PUCHAR BufferAddress;
+ UINT Len;
+ ULONG Pad;
+ PVOID Port=pAdapter->PortOffsets[PORT_TxFIFO];
+
+
+
+ NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL);
+
+ NdisQueryBuffer(CurBuffer, (PVOID *)&BufferAddress, &Len);
+
+
+ //
+ // Write out the length and a pad word
+ //
+
+ NdisRawWritePortUlong(Port,(PacketLength & 0x7ff));
+
+ while (1) {
+
+ NdisRawWritePortBufferUlong(
+ (ULONG)Port,
+ (PULONG)BufferAddress,
+ Len >> 2
+ );
+
+
+ if ((Len & 3) != 0) {
+
+ NdisRawWritePortBufferUchar(
+ Port,
+ BufferAddress+(Len & 0xfffffffc),
+ (Len & 3)
+ );
+
+ }
+
+
+ NdisGetNextBuffer(CurBuffer, &CurBuffer);
+
+ if (CurBuffer==NULL) {
+ //
+ // done
+ //
+ break;
+ }
+
+ NdisQueryBuffer(CurBuffer, (PVOID *)&BufferAddress, &Len);
+
+ }
+
+ Pad=(ELNK3_ROUND_TO_DWORD(PacketLength) - PacketLength);
+
+ if (Pad != 0) {
+
+ NdisRawWritePortBufferUchar(
+ (ULONG)Port,
+ (PUCHAR)&PadBuffer,
+ Pad
+ );
+
+
+ }
+
+
+ Retry=FALSE;
+
+ //
+ // Check the status, if it underan then it would be set now
+ //
+ ELNK3ReadAdapterUchar(pAdapter,PORT_TxStatus,&XmitStatus);
+
+ if ((XmitStatus & TX_STATUS_COMPLETE) && (XmitStatus & TX_STATUS_UNDERRUN)) {
+ //
+ // The transmitter under-ran. Restart it and try again
+ //
+
+ IF_LOG(0xaa,0xcc, PacketLength);
+
+ HandleXmtInterrupts(pAdapter);
+
+ Retry=TRUE;
+
+ }
+
+
+ } while (Retry);
+
+ //
+ // we sent something
+ //
+ NdisMSendResourcesAvailable(pAdapter->NdisAdapterHandle);
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+
+
+BOOLEAN
+HandleXmtInterrupts(
+ PELNK3_ADAPTER pAdapter
+ )
+{
+ UCHAR XmitStatus;
+
+
+
+ ELNK3ReadAdapterUchar(pAdapter,PORT_TxStatus,&XmitStatus);
+
+ IF_LOUD (DbgPrint("ELNK3: HandleXmitInts: Status=%02x\n",XmitStatus);)
+
+ if (XmitStatus != 0) {
+ //
+ // pop the tx status
+ //
+ ELNK3WriteAdapterUchar(pAdapter,PORT_TxStatus,0);
+
+ if ((XmitStatus & TX_STATUS_JABBER)
+ ||
+ (XmitStatus & TX_STATUS_UNDERRUN)) {
+ //
+ // If it is one of these then it the xmiter needs to be reset
+ //
+ ELNK3_COMMAND(pAdapter,EC_TX_RESET,0);
+ ELNK3_WAIT_NOT_BUSY(pAdapter);
+
+ ELNK3_COMMAND(pAdapter,EC_TX_ENABLE,0);
+
+ //
+ // Could use a better message, But...
+ //
+//
+// Commented out so as not to alarm people with random events
+// in the registry.
+//
+// NdisWriteErrorLogEntry(
+// pAdapter->NdisAdapterHandle,
+// NDIS_ERROR_CODE_TIMEOUT,
+// 3,
+// pAdapter->FramesXmitGood,
+// pAdapter->TxStartThreshold,
+// pAdapter->TxStartThresholdInc
+// );
+
+ if ((XmitStatus & TX_STATUS_UNDERRUN)) {
+ //
+ // Underrun bump up the threshold
+ //
+ pAdapter->TxStartThreshold+=pAdapter->TxStartThresholdInc;
+
+ if (pAdapter->TxStartThreshold > 2040) {
+
+ pAdapter->TxStartThreshold=2040;
+ }
+ }
+
+ ELNK3_COMMAND(pAdapter,EC_SET_TX_START,(USHORT)pAdapter->TxStartThreshold & 0x7ff);
+
+ } else {
+ //
+ // Otherwise the xmitter just needs to be restarted
+ //
+
+ ELNK3_COMMAND(pAdapter,EC_TX_ENABLE,0);
+ }
+
+ pAdapter->FramesXmitBad++;
+ }
+
+
+ IF_SEND_LOUD (DbgPrint("HandleXmitInts: Exit\n");)
+
+ return TRUE;
+}
diff --git a/private/ntos/ndis/elnk3/sources b/private/ntos/ndis/elnk3/sources
new file mode 100644
index 000000000..eec91287c
--- /dev/null
+++ b/private/ntos/ndis/elnk3/sources
@@ -0,0 +1,51 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=ndis
+
+TARGETNAME=elnk3
+TARGETPATH=\nt\public\sdk\lib
+TARGETTYPE=DRIVER
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib
+C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER
+
+INCLUDES=..\..\inc
+
+SOURCES= send.c\
+ receive.c\
+ interrup.c\
+ config.c\
+ init.c\
+ elnk3.c\
+ card.c\
+ request.c \
+ elnk3.rc
+
+
+
+RELATIVE_DEPTH=..\..
+
+MSC_WARNING_LEVEL=/W3 /WX