summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/ieepro
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/ieepro
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/ndis/ieepro')
-rw-r--r--private/ntos/ndis/ieepro/82595.h218
-rw-r--r--private/ntos/ndis/ieepro/eeprom.c392
-rw-r--r--private/ntos/ndis/ieepro/epro.c512
-rw-r--r--private/ntos/ndis/ieepro/epro.h221
-rw-r--r--private/ntos/ndis/ieepro/epro.rc39
-rw-r--r--private/ntos/ndis/ieepro/eprodbg.c57
-rw-r--r--private/ntos/ndis/ieepro/eprodbg.h129
-rw-r--r--private/ntos/ndis/ieepro/eprohw.h202
-rw-r--r--private/ntos/ndis/ieepro/eprosw.h254
-rw-r--r--private/ntos/ndis/ieepro/init.c1418
-rw-r--r--private/ntos/ndis/ieepro/makefile6
-rw-r--r--private/ntos/ndis/ieepro/request.c989
-rw-r--r--private/ntos/ndis/ieepro/sndrcv.c1178
-rw-r--r--private/ntos/ndis/ieepro/sources48
14 files changed, 5663 insertions, 0 deletions
diff --git a/private/ntos/ndis/ieepro/82595.h b/private/ntos/ndis/ieepro/82595.h
new file mode 100644
index 000000000..58b100ee6
--- /dev/null
+++ b/private/ntos/ndis/ieepro/82595.h
@@ -0,0 +1,218 @@
+#ifndef _I82595TX_
+#define _I82595TX_
+
+//////////////////////////////////////////////////////////////
+// General Parameters
+//////////////////////////////////////////////////////////////
+// There are 3 switchable banks of 16 IO ports
+// Bank switching is done via register 0
+#define I82595_PORTS_WIDTH 0x10
+#define I82595_NUM_BANKS 0x3
+
+// Number of usec to spin in various places before we give up...
+#define I82595_SPIN_TIMEOUT 10000
+
+//////////////////////////////////////////////////////////////
+// Exec States
+//////////////////////////////////////////////////////////////
+#define I82595_EXEC_STATE_ACTIVE (2 << 4)
+#define I82595_EXEC_STATE_IDLE 0
+#define I82595_EXEC_STATE_ABORTING (3 << 4)
+
+//////////////////////////////////////////////////////////////
+// Receive States
+//////////////////////////////////////////////////////////////
+#define I82595_RCV_STATE_DISABLED 0
+#define I82595_RCV_STATE_READY (1<<6)
+#define I82595_RCV_STATE_ACTIVE (2<<6)
+#define I82595_RCV_STATE_STOPPING (3<<6)
+
+//////////////////////////////////////////////////////////////
+// Command Constants
+//////////////////////////////////////////////////////////////
+// Bank switches...
+#define I82595_CMD_BANK0 0x0
+#define I82595_CMD_BANK1 0x40
+#define I82595_CMD_BANK2 0x80
+
+// Other command constants...
+#define I82595_CMD_MC_SETUP 0x03
+#define I82595_XMT 0x04
+#define I82595_XMT_SHORT 0x0004
+#define I82595_CMD_DIAGNOSE 0x07
+#define I82595_FULL_RESET 0x0e
+#define I82595_SEL_RESET 0x1e
+#define I82595_PWR_DOWN 0x18
+#define I82595_STOP_RCV 0x0b
+#define I82595_RCV_ENABLE 0x08
+#define I82595_XMT_RESUME 0x1c
+
+//////////////////////////////////////////////////////////////
+// Return Values (valid after 0,1,3 goes high)
+//////////////////////////////////////////////////////////////
+#define I82595_DIAGNOSE_PASS 0x07
+#define I82595_DIAGNOSE_FAIL 0x0f
+#define I82595_INIT_DONE 0x0e
+#define I82595_POWERUP_DONE 0x19
+
+
+//////////////////////////////////////////////////////////////
+// Register Defines
+//////////////////////////////////////////////////////////////
+#define I82595_CMD_REG 0x0
+
+// These are in bank 0
+#define I82595_STATUS_REG 0x1
+#define I82595_ID_REG 0x2
+#define I82595_INTMASK_REG 0x3
+#define I82595_32IOSEL_REG 0x3
+#define I82595_RX_BAR_REG 0x4
+#define I82595_RX_STOP_REG 0x6
+#define I82595_TX_BAR_REG 0xa
+#define I82595_HOST_ADDR_REG 0xc // LOW
+#define I82595_32MEM_IO_REG 0xc
+#define I82595_HOST_ADDR_HIGH_REG 0xd // HIGH
+#define I82595_MEM_IO_REG 0xe // LOW
+#define I82595_MEM_IO_HIGH_REG 0xf // HIGH
+
+// Bank 1
+#define I82595_ALT_RDY_REG 0x1
+#define I82595_INTENABLE_REG 0x1
+#define I82595_INT_SELECT_REG 0x2
+#define I82595_IOMAP_REG 0x3
+
+#define I82595_RX_LOWER_LIMIT_REG 0x8
+#define I82595_RX_UPPER_LIMIT_REG 0x9
+#define I82595_TX_LOWER_LIMIT_REG 0xa
+#define I82595_TX_UPPER_LIMIT_REG 0xb
+#define I82595_IOCHRDY_TEST_REG 0xd
+
+// Bank 2
+#define I82595_CONFIG1_REG 0x1
+#define I82595_CONFIG2_REG 0x2
+#define I82595_CONFIG3_REG 0x3
+#define I82595_IA_REG_0 0x4
+#define I82595_IA_REG_1 0x5
+#define I82595_IA_REG_2 0x6
+#define I82595_IA_REG_3 0x7
+#define I82595_IA_REG_4 0x8
+#define I82595_IA_REG_5 0x9
+#define I82595_EEPROM_REG 0xa // eeprom access reg
+#define I82595_STEPPING_REG 0xa
+
+//////////////////////////////////////////////////////////////
+// Register Masks...
+//////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////
+// Command Register (ALL,0)
+//////////////////////////////////////////////////////////////
+#define I82595_CUR_BANK_MASK 0xC0
+
+//////////////////////////////////////////////////////////////
+// Status Register (0,1) bitmasks
+//////////////////////////////////////////////////////////////
+#define I82595_RX_STP_INT_RCVD 0x1 // bit 0
+
+// Did we get a RX Interrupt
+#define I82595_RX_INT_RCVD 0x2 // bit 1
+
+// Mask the TX interupt?
+#define I82595_TX_INT_RCVD 0x4 // bit 2
+
+// This goes high when a command execution is complete.
+#define I82595_EXEC_INT_RCVD 0x8 // bit 3
+
+// status codes
+#define I82595_EXEC_STATE 0x30 // bit 4,5
+#define I82595_RCV_STATE 0xC0 // bit 6,7
+
+#define I82595_STATES_OFFSET 0x4
+
+//////////////////////////////////////////////////////////////
+// Reg 0,3
+//////////////////////////////////////////////////////////////
+#define I82595_RX_STP_INT_MASK 0x1 // bit 0
+
+// Mask the RX interrupt?
+#define I82595_RX_INT_MASK 0x2 // bit 1
+
+// Mask the TX interupt?
+#define I82595_TX_INT_MASK 0x4 // bit 2
+
+// This goes high when a command execution is complete.
+#define I82595_EXEC_INT_MASK 0x8 // bit 3
+
+#define I82595_32IOSEL 0x10 // bit 4
+
+//////////////////////////////////////////////////////////////
+// Reg 0,4
+//////////////////////////////////////////////////////////////
+#define I82595_IOBASE_SELECT 0x3f // bits 0-5
+#define I82595_IOBASE_TO_SELECTION(a) (a>>4)
+
+//////////////////////////////////////////////////////////////
+// Register 1,1
+//////////////////////////////////////////////////////////////
+#define I82595_USE_8_BIT_FLAG 0x2
+#define I82595_ALT_IOCHRDY 0x40
+#define I82595_ENABLE_INTS_FLAG 0x80
+
+//////////////////////////////////////////////////////////////
+// Register 1,2
+//////////////////////////////////////////////////////////////
+#define I82595_INTERRUPT_SELECT_MASK 0x3 // bits 0,1
+#define I82595_ALT_RDY_FLAG 0x40 // bit 6
+
+//////////////////////////////////////////////////////////////
+// Register 1,13
+//////////////////////////////////////////////////////////////
+#define I82595_IOCHRDY_PASS_FLAG 0x1
+#define I82595_IOCHRDY_TEST_FLAG 0x2
+
+
+//////////////////////////////////////////////////////////////
+// Register 2.2 - configuration
+//////////////////////////////////////////////////////////////
+#define I82595_PROMISCUOUS_FLAG 0x01
+#define I82595_NO_BROADCAST_FLAG 0x02
+
+//////////////////////////////////////////////////////////////
+// Register 2.10 -- eeprom access
+//////////////////////////////////////////////////////////////
+#define I82595_EESK_MASK 0x1
+#define I82595_EECS_MASK 0x2
+#define I82595_EEDI_MASK 0x4
+#define I82595_EEDO_MASK 0x8
+#define I82595_TURNOFF_ENABLE 0x10
+
+#define I82595_EEDI_OFFSET 0x2
+#define I82595_EEDO_OFFSET 0x3
+
+#define I82595_EEPROM_READ 0x6 // 110:b
+#define I82595_EEPROM_WRITE 0x5
+#define I82595_EEPROM_ERASE 0x7
+#define I82595_EEPROM_EWEN 19
+#define I82595_EEPROM_EWDS 16
+
+#define I82595_EEPROM_IOADDR_REG 0
+#define I82595_EEPROM_IOMASK ((0x3f) << 10)
+
+#define I82595_STEPPING_OFFSET 0x5 // bits 5-7 are 82595 stepping
+
+//////////////////////////////////////////////////////////////////////
+// TX constants
+//////////////////////////////////////////////////////////////////////
+#define I82595_TX_FRM_HDR_SIZE 0x8
+#define I82595_TX_DN_BYTE_MASK 0x80
+#define I82595_CH_SHORT_MASK 0x8000
+#define I82595_TX_OK_SHORT_MASK 0x2000
+#define I82595_NO_COLLISIONS_MASK 0x0f
+
+//////////////////////////////////////////////////////////////////////
+// RX Constants
+//////////////////////////////////////////////////////////////////////
+#define I82595_RX_EOF 0x08
+#define I82595_RX_OK 0x20
+
+#endif // ifndef _i82595TX_
diff --git a/private/ntos/ndis/ieepro/eeprom.c b/private/ntos/ndis/ieepro/eeprom.c
new file mode 100644
index 000000000..10b8fe9f0
--- /dev/null
+++ b/private/ntos/ndis/ieepro/eeprom.c
@@ -0,0 +1,392 @@
+#include <ndis.h>
+#include "82595.h"
+#include "eprohw.h"
+#include "eprosw.h"
+#include "epro.h"
+#include "eprodbg.h"
+
+VOID EProEERead(
+ PEPRO_ADAPTER adapter,
+ USHORT address,
+ PUSHORT data)
+/*++
+
+ Routine Description:
+
+ This function reads the 16-bit register at address (address % 64)
+ from the EPro's eeprom (there are only 64 words of registers
+ on the eeprom)
+
+ IMPORTANT NOTE - for PnP accesses to the EPro's eeprom (registers
+ 0x10 and higher), you must use the EProEEReverseRead since for some
+ reason the EPro stores PnP data in the reverse bit-order (except for
+ the low byte of word 10, which is in the normal bit order) -- see
+ the 82595 docs and PnP docs for an explanation.
+
+ Arguments:
+
+ data - the where the result is written to
+
+ Return Value:
+
+ none
+
+--*/
+{
+ UCHAR result;
+ UCHAR opcode;
+
+// siwtch to bank2
+ EPRO_SWITCH_BANK_2(adapter);
+
+// Get the value from the register, so we can flip the eecs bit
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
+
+// turn the eecs bit on.. (1)
+ result |= I82595_EECS_MASK;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+
+// Write the read opcode to the eeprom (2)
+ opcode = I82595_EEPROM_READ;
+ EProEEShiftOutBits(adapter, opcode, 3);
+
+// Write the address to read to the eeprom
+ EProEEShiftOutBits(adapter, address, 6);
+
+// Read the result
+ EProEEShiftInBits(adapter, data, 16);
+
+ EProEECleanup(adapter);
+
+ EPRO_SWITCH_BANK_0(adapter);
+}
+
+
+VOID EProEEWrite(
+ PEPRO_ADAPTER adapter,
+ USHORT address,
+ USHORT data)
+{
+ UCHAR result;
+
+// siwtch to bank2
+ EPRO_SWITCH_BANK_2(adapter);
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
+ result &= ~(I82595_EEDI_MASK | I82595_EEDO_MASK | I82595_EESK_MASK);
+ result |= I82595_EECS_MASK;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+
+ // write the read opcode and register number
+ EProEEShiftOutBits(adapter, I82595_EEPROM_EWEN, 5);
+ EProEEShiftOutBits(adapter, address, 4);
+
+ EProEEStandBy(adapter);
+
+ EProEEShiftOutBits(adapter, I82595_EEPROM_ERASE, 3);
+ EProEEShiftOutBits(adapter, address, 6);
+
+ if (EProEEWaitCmdDone(adapter) == FALSE) {
+ EPRO_DPRINTF_INIT(("Failed EEPROM erase!\n"));
+ return;
+ }
+
+ EProEEStandBy(adapter);
+
+ EProEEShiftOutBits(adapter, I82595_EEPROM_WRITE, 3);
+ EProEEShiftOutBits(adapter, address, 6);
+ EProEEShiftOutBits(adapter, data, 16);
+
+ if (EProEEWaitCmdDone(adapter) == FALSE) {
+ EPRO_DPRINTF_INIT(("Failed EEPROM write!\n"));
+ return;
+ }
+
+ EProEEStandBy(adapter);
+
+ EProEEShiftOutBits(adapter, I82595_EEPROM_EWDS, 5);
+ EProEEShiftOutBits(adapter, address, 4);
+
+ EProEECleanup(adapter);
+
+// siwtch to bank0
+ EPRO_SWITCH_BANK_0(adapter);
+
+}
+
+
+VOID EProEECleanup(PEPRO_ADAPTER adapter)
+{
+ UCHAR result;
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
+ result &= ~(I82595_EECS_MASK | I82595_EEDI_MASK);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+ EProEERaiseClock(adapter, &result);
+ EProEELowerClock(adapter, &result);
+}
+
+
+VOID EProEEUpdateChecksum(PEPRO_ADAPTER adapter)
+{
+ USHORT chkSum = 0, result, i;
+
+ for (i=0;i<0x3f;i++) {
+ EProEERead(adapter, i, &result);
+ chkSum+=result;
+ }
+
+ chkSum = (USHORT)0xBABA - chkSum;
+ EProEEWrite(adapter, 0x3f, chkSum);
+}
+
+
+VOID EProEEStandBy(
+ PEPRO_ADAPTER adapter)
+{
+ UCHAR result;
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
+ result &= ~(I82595_EECS_MASK | I82595_EESK_MASK);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+ NdisStallExecution(100);
+ result |= I82595_EECS_MASK;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+}
+
+
+
+BOOLEAN EProEEWaitCmdDone(
+ PEPRO_ADAPTER adapter)
+{
+ USHORT i;
+ UCHAR result;
+
+ EProEEStandBy(adapter);
+
+ for (i=0; i<200;i++) {
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
+ if (result & I82595_EEDO_MASK) {
+ return(TRUE);
+ }
+ NdisStallExecution(100);
+ }
+
+ return(FALSE);
+
+}
+
+VOID EProEEReverseRead(
+ PEPRO_ADAPTER adapter,
+ USHORT address,
+ PUSHORT data)
+{
+ UCHAR result, opcode;
+ UINT i;
+
+// siwtch to bank2
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_CMD_BANK2);
+
+// Get the value from the register, so we can flip the eecs bit
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
+
+// turn the eecs bit on.. (1)
+ result |= I82595_EECS_MASK;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+
+// Write the read opcode to the eeprom (2)
+ opcode = I82595_EEPROM_READ;
+ EProEEShiftOutBits(adapter, opcode, 3);
+
+// Write the address to read to the eeprom
+ EProEEShiftOutBits(adapter, address, 6);
+
+// Read the result
+ EProEEReverseShiftInBits(adapter, data, 16);
+
+// Turn off EEPROM
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
+ result &= (~I82595_EECS_MASK);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+
+ EPRO_SWITCH_BANK_0(adapter);
+}
+
+VOID EProEEShiftOutBits(
+ PEPRO_ADAPTER adapter,
+ USHORT data,
+ SHORT count)
+/*++
+
+ Routine Description:
+
+ This function shifts count bits OUT TO THE EEPROM through it's serial
+ interface
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ data - the word to shift out from (MSB first)
+
+ count - the number of bits to shift out...
+
+ Return Value:
+
+ none
+
+--*/
+{
+ UCHAR result;
+ USHORT mask;
+
+ mask = 0x1 << (count - 1);
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
+ result &= ~(I82595_EEDO_MASK | I82595_EEDI_MASK);
+
+ do
+ {
+ result &= ~I82595_EEDI_MASK;
+ if (data & mask)
+ {
+ result |= I82595_EEDI_MASK;
+ }
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+ NdisStallExecution(100);
+ EProEERaiseClock(adapter, &result);
+ EProEELowerClock(adapter, &result);
+ mask = mask >> 1;
+ } while(mask);
+
+ result &= ~I82595_EEDI_MASK;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+}
+
+VOID EProEEShiftInBits(
+ PEPRO_ADAPTER adapter,
+ PUSHORT data,
+ SHORT count)
+/*++
+
+ Routine Description:
+
+ This routine is analagous to shift-out-bits, except reads bits from
+ the eeprom... Note that for PNP accesses to the EPro
+ (pnp for the EPro lives in registers 0x10 and higher) you must use
+ a different function since PnP data is written in reverse bit order
+ for some reason
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ data - the word to read into
+
+ count - how many bits to read
+
+ Return Value:
+
+ none
+
+--*/
+{
+ UCHAR result;
+ USHORT i;
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result);
+ result &= ~(I82595_EEDO_MASK | I82595_EEDI_MASK);
+ *data = 0;
+
+ for (i=0;i<16;i++)
+ {
+ *data = *data << 1;
+ EProEERaiseClock(adapter, &result); // 4.1
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result); // 4.2
+ result &= ~I82595_EEDI_MASK;
+ if (result & I82595_EEDO_MASK) {
+ *data |= 1;
+ }
+ EProEELowerClock(adapter, &result);
+ }
+}
+
+void EProEEReverseShiftInBits(PEPRO_ADAPTER adapter, PUSHORT data, SHORT count)
+{
+ UCHAR result;
+ SHORT count1;
+
+ *data = 0;
+
+ for (count1=0;count1<=count;count1++) {
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, &result); // 4.2
+
+ result &= I82595_EEDO_MASK; // turn off everything but the EEDO bit
+
+ // according to docs we get MSB out first...
+ // this is a REVERSE read - get LSB first
+ *data |= ((result >> I82595_EEDO_OFFSET) << count1);
+ }
+}
+
+VOID EProEERaiseClock(
+ PEPRO_ADAPTER adapter,
+ PUCHAR result)
+/*++
+
+ Routine Description:
+
+ This routine raises the "clock" bit in the eeprom access register --
+ basically since the eeprom is a serial device you raise then lower the
+ clock between bits...
+
+ Arguments:
+
+ adapter - pointer to the adapter structure
+
+ Return Value:
+
+ none
+
+--*/
+{
+// UCHAR result;
+
+// turn EESK bit high
+ *result = *result | I82595_EESK_MASK;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, *result);
+ NdisStallExecution(EPRO_SK_STALL_TIME);
+}
+
+VOID EProEELowerClock(
+ PEPRO_ADAPTER adapter,
+ PUCHAR result)
+/*++
+
+ Routine Description:
+
+ Analagous to EProEERaiseClock...
+
+ Arguments:
+
+ adapter - pointer to our adapter structure.
+
+ Return Value:
+
+ none
+
+--*/
+{
+// UCHAR result;
+
+// EPRO_RD_PORT_UCHAR(adapter, I82595_EEPROM_REG, result);
+
+ // turn EESK bit low...
+ *result = *result & ~I82595_EESK_MASK;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_EEPROM_REG, *result);
+
+ NdisStallExecution(EPRO_SK_STALL_TIME);
+}
+
+
diff --git a/private/ntos/ndis/ieepro/epro.c b/private/ntos/ndis/ieepro/epro.c
new file mode 100644
index 000000000..ca80d467f
--- /dev/null
+++ b/private/ntos/ndis/ieepro/epro.c
@@ -0,0 +1,512 @@
+#include <ndis.h>
+#include "82595.h"
+#include "eprohw.h"
+#include "eprosw.h"
+#include "epro.h"
+#include "eprodbg.h"
+
+// Global data
+
+NDIS_MINIPORT_CHARACTERISTICS EPro_Miniport_Char;
+
+EPRO_DRIVER EProMiniportDriver={0};
+
+NDIS_STATUS EProSelReset(PEPRO_ADAPTER adapter)
+/*++
+
+ Routine Description:
+
+ This does a SEL-RESET of the i82595 chip. Read the 82595 docs
+ for more info on what this does.
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ Return Values:
+
+ always returns NDIS_STATUS_SUCCESS
+
+--*/
+{
+ EPRO_ASSERT_BANK_0(adapter);
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_SEL_RESET);
+
+// according to 82595 prelim doc: wait 2 us after sel reset before
+// accessing the 82595
+ NdisStallExecution(2);
+
+ EProEnableInterrupts((NDIS_HANDLE)adapter);
+
+ adapter->fHung = FALSE;
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+VOID
+EProInitializeAdapterData(
+ IN PEPRO_ADAPTER adapter
+ )
+/*++
+
+ Routine Description:
+
+ This routine initializes our adapter structure - setting default
+ values, zeroing fields, etc. This is called on adapter initialization
+ and adapter reset.
+
+ Arguments:
+
+ A pointer to the adapter structure to clear.
+
+ Return Values:
+
+ none
+
+--*/
+{
+ UINT i;
+
+ adapter->CurrentHardwareStatus = NdisHardwareStatusReady;
+
+ adapter->vendorID[0] = EPRO_VENDOR_ID_L;
+ adapter->vendorID[1] = EPRO_VENDOR_ID_M;
+ adapter->vendorID[2] = EPRO_VENDOR_ID_H;
+
+ adapter->CurrentPacketFilter = 0;
+
+ // hack to get around wrapper bug:
+ // adapter->RXLookAheadSize = 0;
+ //
+ adapter->RXLookAheadSize = 256;
+ adapter->FramesXmitOK = 0;
+ adapter->FramesRcvOK = 0;
+ adapter->FramesXmitErr = 0;
+ adapter->FramesRcvErr = 0;
+ adapter->FramesMissed = 0;
+
+ adapter->FrameAlignmentErrors = 0;
+ adapter->FramesXmitOneCollision = 0;
+ adapter->FramesXmitManyCollisions = 0;
+
+ adapter->CurrentTXBuf = &adapter->TXBuf[0];
+ adapter->TXChainStart = NULL;
+
+ // Packet filter settings...
+ //
+ adapter->fPromiscuousEnable = FALSE;
+ adapter->fBroadcastEnable = FALSE;
+ adapter->fMulticastEnable = FALSE;
+ adapter->fReceiveEnabled = FALSE;
+ adapter->NumMCAddresses = 0;
+
+ // Don't force 8-bit operation
+ //
+ adapter->Use8Bit = FALSE;
+
+ adapter->IntPending = EPRO_INT_NONE_PENDING;
+ adapter->fHung = FALSE;
+ // adapter->fTransmitInProgress = FALSE;
+
+ // Set up the TX buffers...
+ //
+ for (i = 0;i < EPRO_NUM_TX_BUFFERS; i++)
+ {
+ if (0 == i)
+ {
+ adapter->TXBuf[0].LastBuf = &adapter->TXBuf[EPRO_NUM_TX_BUFFERS - 1];
+ }
+ else
+ {
+ adapter->TXBuf[i].LastBuf = &adapter->TXBuf[i-1];
+ }
+
+ if ((EPRO_NUM_TX_BUFFERS - 1) == i)
+ {
+ adapter->TXBuf[i].NextBuf = &adapter->TXBuf[0];
+ }
+ else
+ {
+ adapter->TXBuf[i].NextBuf = &adapter->TXBuf[i + 1];
+ }
+
+ adapter->TXBuf[i].fEmpty = TRUE;
+ adapter->TXBuf[i].TXBaseAddr = 0;
+ adapter->TXBuf[i].TXSendAddr = 0xffff;
+ }
+}
+
+VOID EProEnableInterrupts(IN NDIS_HANDLE miniportAdapterContext)
+/*++
+
+ Routine Description:
+
+ The MiniportEnableInterrupt Handler for the card.
+
+ Arguments:
+
+ miniportAdapterContext - really a PEPRO_ADAPTER to our adapter structure
+
+ Return Value: none
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
+
+// If this isn't true, then NdisMSyncronizeWithInterrupt is broken
+// or we've called a function which switches banks without syncronizing
+// it...
+ EPRO_ASSERT_BANK_0(adapter);
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_INTMASK_REG,
+ adapter->CurrentInterruptMask);
+
+}
+
+VOID EProDisableInterrupts(IN NDIS_HANDLE miniportAdapterContext)
+/*++
+
+ Routine Description:
+
+ The MiniportDisableInterrupts handler for the driver
+
+ Arguments:
+
+ miniportAdapterContext - really a pointer to our adapter structure
+
+ Return Values: none
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
+
+// If this isn't true, then NdisMSyncronizeWithInterrupt is broken
+// or we've called a function which switches banks without syncronizing
+// it...
+ EPRO_ASSERT_BANK_0(adapter);
+
+// mask all int's
+ EPRO_WR_PORT_UCHAR(adapter, I82595_INTMASK_REG,
+ (adapter->CurrentInterruptMask | 0x0f));
+}
+
+
+VOID EProHalt(IN NDIS_HANDLE miniportAdapterContext)
+/*++
+
+ Routine Description:
+
+ This is the function which halts the 82595 chip and disables the
+ adapter - frees hardware resources, etc.
+
+ Arguments:
+
+ miniportAdapterContext - pointer to our adapter structure
+
+ Returns: nothing
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
+
+// Shut down the card - disable receives.
+ EProReceiveDisable(adapter);
+
+// There won't be any more interrupts
+ NdisMDeregisterInterrupt(&adapter->Interrupt);
+
+// Pause, wait for pending DPC stuff to clear... Random number stolen
+// from the NE2000 driver...
+ NdisStallExecution(250000);
+
+// Unmap our IO ports
+ NdisMDeregisterIoPortRange(adapter->MiniportAdapterHandle,
+ (ULONG)adapter->IoBaseAddr,
+ 0x10,
+ (PVOID)adapter->IoPAddr);
+
+// Free up our adapter structure...
+ NdisFreeMemory(adapter, sizeof(EPRO_ADAPTER), 0);
+}
+
+NDIS_STATUS EProReset(OUT PBOOLEAN fAddressingReset,
+ IN NDIS_HANDLE miniportAdapterContext)
+/*++
+
+ Routine Description:
+
+ This is the MiniportReset handler for the EPro driver
+
+ Arguments:
+
+ fAddressingReset - Do we need to be re-told our MC address list?
+ currently we say yes, although probably we don't
+ have to be told this (the driver saves it)
+
+ Return Values:
+
+ the return from EProSelReset (always NDIS_STATUS_SUCCESS)
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
+
+// Okay, we don't want to get any interrupts anymore.
+ EProDisableInterrupts(adapter);
+ EProReceiveDisable(adapter);
+
+// clear out TX structures...
+ EProInitializeAdapterData(adapter);
+
+// We probably can set this to false -- TODO
+ *fAddressingReset = TRUE;
+
+ return(EProSelReset(adapter));
+}
+
+BOOLEAN EProCheckForHang(IN NDIS_HANDLE miniportAdapterContext)
+/*++
+
+ Routine Description:
+
+ This is the MiniportCheckForHang handler for the driver.
+ It does absolutely nothing right now.
+
+ Arguments:
+
+ miniportAdapterContext - right now a pointer to our adapter structure
+
+ Return Value:
+
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
+
+ if (adapter->fHung)
+ {
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+VOID EProHandleInterrupt(
+ IN NDIS_HANDLE miniportAdapterContext)
+/*++
+
+ Routine Description:
+
+ This is the function that gets called at DPC level in response
+ to a hardware interrupt. It is queued by the wrapper's ISR routines.
+ Interrupts have been disabled when this routine is called.
+
+ Arguments:
+
+ miniportAdapterContext - really a pointer to our adapter structure
+
+ Return Value:
+
+ none
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
+ UCHAR whichInt;
+ BOOLEAN fFoundInts, fFoundRX = FALSE;
+
+ // verify bank 0
+ EPRO_ASSERT_BANK_0(adapter);
+
+ do
+ {
+ fFoundInts = FALSE;
+
+ // Read in the int mask
+ //
+ EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &whichInt);
+
+ // quick out if there are no ints pending...
+ if (!(whichInt & 0x0f))
+ {
+ break;
+ }
+
+ // acknowlege interrupts - writing a 1 over the int flag clears it
+ EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG, whichInt);
+
+ if (whichInt & I82595_TX_INT_RCVD)
+ {
+ fFoundInts = TRUE;
+ if (adapter->TXChainStart != NULL)
+ {
+ EProCheckTransmitCompletion(adapter, adapter->TXChainStart);
+ }
+ }
+
+// if (whichInt & I82595_TX_INT_RCVD)
+// {
+// fFoundInts = TRUE;
+// if (adapter->TXChainStart != NULL)
+// {
+// while (EProCheckTransmitCompletion(adapter, adapter->TXChainStart))
+// ;
+// }
+// }
+
+ if (whichInt & I82595_RX_INT_RCVD)
+ {
+ fFoundInts = TRUE;
+ if (EProHandleReceive(adapter) > 0)
+ {
+ fFoundRX = TRUE;
+ }
+ }
+
+ if (whichInt & I82595_EXEC_INT_RCVD)
+ {
+ fFoundInts = TRUE;
+
+ EProSetInterruptMask(adapter, EPRO_DEFAULT_INTERRUPTS);
+
+ switch(adapter->IntPending)
+ {
+ case EPRO_INT_MC_SET_PENDING:
+
+ ((PEPRO_TRANSMIT_BUFFER)adapter->IntContext)->fEmpty = TRUE;
+ EPRO_DPRINTF_INTERRUPT(("Set COMPLETED!"));
+
+ NdisMSetInformationComplete(
+ adapter->MiniportAdapterHandle,
+ NDIS_STATUS_SUCCESS);
+
+ break;
+// default:
+// EPRO_ASSERT(FALSE); // we shouldn't hit this...
+ }
+
+ // clear the pending interrupt...
+ //
+ adapter->IntPending = 0;
+ adapter->IntContext = NULL;
+ }
+ } while ((fFoundInts == TRUE) && !adapter->fHung);
+
+ if (fFoundRX)
+ {
+ NdisMEthIndicateReceiveComplete(adapter->MiniportAdapterHandle);
+ }
+}
+
+void
+EProISR(
+ OUT PBOOLEAN interruptRecognized,
+ OUT PBOOLEAN queueMiniportHandleInterrupt,
+ IN NDIS_HANDLE miniportAdapterContext)
+{
+ EPRO_DPRINTF_INTERRUPT(("ISR"));
+
+ *interruptRecognized = TRUE;
+ *queueMiniportHandleInterrupt = FALSE;
+}
+
+
+BOOLEAN EProSyncSetInterruptMask(PVOID context)
+{
+ PEPRO_ADAPTER adapter = ((PEPRO_SETINTERRUPT_CONTEXT)context)->Adapter;
+ UCHAR newMask = ((PEPRO_SETINTERRUPT_CONTEXT)context)->NewMask;
+
+// unmask everyone...
+ adapter->CurrentInterruptMask &= 0xf0;
+// now mask the ones we don't want
+ adapter->CurrentInterruptMask |= newMask;
+
+ EPRO_ASSERT_BANK_0(adapter);
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_INTMASK_REG,
+ adapter->CurrentInterruptMask);
+
+ return(TRUE);
+}
+
+// Poll the exec-states reg (0,1), waiting for any execution to finish...
+BOOLEAN EProWaitForExeDma(PEPRO_ADAPTER adapter)
+{
+ UINT i;
+ UCHAR result;
+
+// status reg is in bank 0
+ EPRO_ASSERT_BANK_0(adapter);
+
+ for (i=0;i<I82595_SPIN_TIMEOUT;i++) {
+ // make sure the dma is idle
+ EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &result);
+ if (!(result&I82595_EXEC_STATE)) {
+ if (result & I82595_EXEC_INT_RCVD) {
+ // clear the exec int if it's high...
+ EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG,
+ I82595_EXEC_INT_RCVD);
+ }
+ return(TRUE);
+ }
+ NdisStallExecution(1);
+ }
+
+ return(FALSE);
+}
+
+BOOLEAN EProReceiveEnable(PEPRO_ADAPTER adapter)
+{
+ UINT i = 0;
+ UCHAR result;
+
+ adapter->RXCurrentAddress = 0 | (((USHORT)EPRO_RX_LOWER_LIMIT) << 8);
+
+ // EPRO_ASSERT(!adapter->fReceiveEnabled);
+
+ // don't enable if we're already enabled.
+ if (adapter->fReceiveEnabled)
+ {
+ return(TRUE);
+ }
+
+ // bank0
+ // EPRO_SWITCH_BANK_0(adapter);
+ //
+ EPRO_ASSERT_BANK_0(adapter);
+ EPRO_WR_PORT_USHORT(adapter, I82595_RX_STOP_REG, 0 | (((USHORT)EPRO_RX_UPPER_LIMIT) << 8));
+ EPRO_WR_PORT_USHORT(adapter, I82595_RX_BAR_REG, 0 | (((USHORT)EPRO_RX_LOWER_LIMIT) << 8));
+
+ //
+ // validate registers...
+ //
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_RCV_ENABLE);
+
+ adapter->fReceiveEnabled = TRUE;
+
+ return(TRUE);
+}
+
+BOOLEAN EProReceiveDisable(PEPRO_ADAPTER adapter)
+{
+ UINT i = 0;
+ UCHAR result;
+
+// bank0
+// EPRO_SWITCH_BANK_0(adapter);
+ EPRO_ASSERT_BANK_0(adapter);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_STOP_RCV);
+
+ adapter->fReceiveEnabled = FALSE;
+
+ return(TRUE);
+}
+
+//VOID EProTimerFunc(IN PVOID foo1, IN PVOID context, IN PVOID foo2, IN PVOID foo3)
+//{
+// EProHandleInterrupt((NDIS_HANDLE)context);
+//
+// queue another timer...
+// NdisMSetTimer(&(((PEPRO_ADAPTER)context)->MiniportTimer), 10);
+//}
diff --git a/private/ntos/ndis/ieepro/epro.h b/private/ntos/ndis/ieepro/epro.h
new file mode 100644
index 000000000..f5f6ed7aa
--- /dev/null
+++ b/private/ntos/ndis/ieepro/epro.h
@@ -0,0 +1,221 @@
+#ifndef _IEPRO_
+#define _IEPRO_
+
+#define EPRO_DRIVER_VER_MAJOR 1
+#define EPRO_DRIVER_VER_MINOR 0
+
+#include "eprosw.h"
+
+///////////////////////////////////////////////////////////////////
+//epro.c:
+///////////////////////////////////////////////////////////////////
+
+NDIS_STATUS EProSelReset(PEPRO_ADAPTER adapter);
+
+VOID EProInitializeAdapterData(PEPRO_ADAPTER adapter);
+
+VOID EProEnableInterrupts(IN NDIS_HANDLE miniportAdapterContext);
+
+VOID EProDisableInterrupts(IN NDIS_HANDLE miniportAdapterContext);
+
+BOOLEAN EProVerifyRoundRobin(UCHAR *buf);
+
+BOOLEAN EProPowerupBoard(PEPRO_ADAPTER adapter);
+
+extern VOID EProHalt(IN NDIS_HANDLE miniportAdapterContext);
+
+NDIS_STATUS EProReset(OUT PBOOLEAN fAddressingReset,
+ IN NDIS_HANDLE miniportAdapterContext);
+
+BOOLEAN EProCheckForHang(IN NDIS_HANDLE miniportAdapterContext);
+
+VOID EProHandleInterrupt(IN NDIS_HANDLE miniportAdapterContext);
+
+VOID EProISR(OUT PBOOLEAN interruptRecognized,
+ OUT PBOOLEAN queueMiniportHandleInterrupt,
+ IN NDIS_HANDLE miniportAdapterContext);
+
+BOOLEAN EProCardReadEthernetAddress(PEPRO_ADAPTER adapter);
+
+BOOLEAN EProAltIOCHRDYTest(PEPRO_ADAPTER adapter);
+
+BOOLEAN EProSyncSetInterruptMask(PVOID context);
+
+// This is implemented via a macro
+//VOID EProSetInterruptMask(PEPRO_ADAPTER adapter, UCHAR newMask);
+
+#define EProSetInterruptMask(_adapter, _newMask) { \
+ EPRO_SETINTERRUPT_CONTEXT _context; \
+ _context.Adapter = _adapter; \
+ _context.NewMask = _newMask; \
+ NdisMSynchronizeWithInterrupt(&_adapter->Interrupt, \
+ &EProSyncSetInterruptMask, \
+ &_context); \
+}
+
+BOOLEAN EProWaitForExeDma(PEPRO_ADAPTER adapter);
+
+BOOLEAN EProReceiveEnable(PEPRO_ADAPTER adapter);
+
+BOOLEAN EProReceiveDisable(PEPRO_ADAPTER adapter);
+
+VOID EProMyLog(char *s);
+
+//VOID EProTimerFunc(IN PVOID foo1, IN PVOID context, IN PVOID foo2, IN PVOID foo3);
+
+#if DBG
+
+VOID EProLogStr(char *s);
+VOID EProLogLong(ULONG l);
+VOID EProLogBuffer(UCHAR *s, ULONG len);
+
+#else
+
+#define EProLogStr(a)
+#define EProLogLong(a)
+#define EProLogBuffer(a, b)
+
+#endif
+
+///////////////////////////////////////////////////////////////////
+// init.c
+///////////////////////////////////////////////////////////////////
+
+NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject_,
+ IN PUNICODE_STRING RegistryPath_);
+
+NDIS_STATUS EProInitialize(OUT PNDIS_STATUS openErrorStatus,
+ OUT PUINT selectedMedumIndex,
+ IN PNDIS_MEDIUM medumArray,
+ IN UINT mediumArraySize,
+ IN NDIS_HANDLE miniportAdapterHandle,
+ IN NDIS_HANDLE configurationHandle);
+
+NDIS_STATUS EProReadConfiguration(IN PEPRO_ADAPTER adapterxo,
+ IN NDIS_HANDLE configurationHandle);
+
+NDIS_STATUS EProRegisterAdapterHW(IN PEPRO_ADAPTER adapter);
+
+NDIS_STATUS EProInitialReset(IN PEPRO_ADAPTER adapter);
+
+NDIS_STATUS EProHWInitialize(IN PEPRO_ADAPTER adapter);
+
+VOID EProUpdateEEProm(IN PEPRO_ADAPTER adapter);
+
+NDIS_STATUS EProHWConfigure(IN PEPRO_ADAPTER adapter);
+
+//////////////////////////////////////////////////////////////////////
+// request.c:
+//////////////////////////////////////////////////////////////////////
+
+NDIS_STATUS EProSetInformation(IN NDIS_HANDLE miniportAdapterContext,
+ IN NDIS_OID oid,
+ IN PVOID informationBuffer,
+ IN ULONG informationLength,
+ OUT PULONG bytesRead,
+ OUT PULONG bytesNeeded);
+
+NDIS_STATUS EProQueryInformation(IN NDIS_HANDLE miniportAdapterContext,
+ IN NDIS_OID oid,
+ IN PVOID informationBuffer,
+ IN ULONG informationBuffrLength,
+ OUT PULONG bytesWritten,
+ OUT PULONG bytesNeeded);
+
+BOOLEAN EProSetEthernetAddress(PEPRO_ADAPTER adapter);
+
+NDIS_STATUS EProSetPacketFilter(PEPRO_ADAPTER adapter, ULONG newFilter);
+
+BOOLEAN EProSyncBroadcastPromiscuousChange(PVOID context);
+
+// Implemented via a macro
+//VOID EProBroadcastPromiscuousChange(PEPRO_ADAPTER adapter, UCHAR reg2flags);
+#define EProBroadcastPromiscuousChange(_adapter, _reg2Flags) { \
+ EPRO_BRDPROM_CONTEXT _context; \
+ _context.Adapter =_adapter; \
+ _context.Reg2Flags = _reg2Flags; \
+ NdisMSynchronizeWithInterrupt(&adapter->Interrupt, \
+ &EProSyncBroadcastPromiscuousChange, \
+ (PVOID)&_context); \
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// eeprom.c:
+//////////////////////////////////////////////////////////////////////
+
+// EEProm Routines
+VOID EProEECleanup(PEPRO_ADAPTER adapter);
+VOID EProEEUpdateChecksum(PEPRO_ADAPTER adapter);
+VOID EProEEStandBy(PEPRO_ADAPTER adapter);
+VOID EProEERead(PEPRO_ADAPTER adapter, USHORT address, PUSHORT data);
+VOID EProEEWrite(PEPRO_ADAPTER adapter, USHORT address, USHORT data);
+VOID EProEEReverseRead(PEPRO_ADAPTER adapter, USHORT address, PUSHORT data);
+VOID EProEEShiftOutBits(PEPRO_ADAPTER adapter, USHORT data, SHORT count);
+VOID EProEEShiftInBits(PEPRO_ADAPTER adapter, PUSHORT data, SHORT count);
+VOID EProEEReverseShiftInBits(PEPRO_ADAPTER adapter, PUSHORT data, SHORT count);
+VOID EProEERaiseClock(PEPRO_ADAPTER adapter, PUCHAR result);
+VOID EProEELowerClock(PEPRO_ADAPTER adapter, PUCHAR result);
+BOOLEAN EProEEWaitCmdDone(PEPRO_ADAPTER adapter);
+
+
+//////////////////////////////////////////////////////////////////////
+// sndrcv.c
+//////////////////////////////////////////////////////////////////////
+
+BOOLEAN EProSyncReadBufferFromNicUlong(PVOID context);
+BOOLEAN EProSyncWriteBufferToNicUlong(PVOID context);
+
+NDIS_STATUS EProSend(IN NDIS_HANDLE miniportAdapterContext,
+ IN PNDIS_PACKET packet,
+ IN UINT flags);
+
+VOID EProCopyPacketToCard(PEPRO_ADAPTER adapter, PNDIS_PACKET packet);
+
+
+BOOLEAN EProCheckTransmitCompletion(PEPRO_ADAPTER adapter,
+ PEPRO_TRANSMIT_BUFFER txBuf);
+
+UINT EProHandleReceive(PEPRO_ADAPTER adapter);
+
+NDIS_STATUS EProTransferData(OUT PNDIS_PACKET packet,
+ OUT PUINT bytesTransferred,
+ IN NDIS_HANDLE miniportAdapterContext,
+ IN NDIS_HANDLE miniportReceivedContext,
+ IN UINT byteOffset,
+ IN UINT bytesToTransfer);
+
+BOOLEAN EProChangeMulticastList(PEPRO_ADAPTER adapter,
+ UINT addressCount,
+ UCHAR addresses[][EPRO_LENGTH_OF_ADDRESS]);
+
+#define EPRO_SET_CARD_MC 0
+#define EPRO_CLEAR_CARD_MC 1
+BOOLEAN EProSetCardMulticastList(PEPRO_ADAPTER adapter, int operation);
+
+BOOLEAN EProSyncCopyBufferToNicUlong(PVOID context);
+
+#define EPRO_READ_BUFFER_FROM_NIC_ULONG(adapter, buffer, len) \
+ { \
+ EPRO_COPYBUF_CONTEXT _context; \
+ _context.Adapter = adapter; \
+ _context.Buffer = buffer; \
+ _context.Len = len; \
+ NdisMSynchronizeWithInterrupt(&adapter->Interrupt, \
+ &EProSyncReadBufferFromNicUlong, \
+ (PVOID)&_context); \
+ }
+
+#define EPRO_COPY_BUFFER_TO_NIC_ULONG(adapter, buffer, len) \
+ { \
+ EPRO_COPYBUF_CONTEXT _context; \
+ _context.Adapter = adapter; \
+ _context.Buffer = buffer; \
+ _context.Len = len; \
+ NdisMSynchronizeWithInterrupt(&adapter->Interrupt, \
+ &EProSyncCopyBufferToNicUlong, \
+ (PVOID)&_context); \
+ }
+
+
+#endif _IEPRO_
diff --git a/private/ntos/ndis/ieepro/epro.rc b/private/ntos/ndis/ieepro/epro.rc
new file mode 100644
index 000000000..254086031
--- /dev/null
+++ b/private/ntos/ndis/ieepro/epro.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 "Intel EtherExpress Pro network driver"
+#define VER_INTERNALNAME_STR "IEEPRO.SYS"
+#define VER_ORIGINALFILENAME_STR "IEEPRO.SYS"
+
+#include "common.ver"
+
diff --git a/private/ntos/ndis/ieepro/eprodbg.c b/private/ntos/ndis/ieepro/eprodbg.c
new file mode 100644
index 000000000..391349a73
--- /dev/null
+++ b/private/ntos/ndis/ieepro/eprodbg.c
@@ -0,0 +1,57 @@
+#include <ndis.h>
+#include "82595.h"
+#include "eprohw.h"
+#include "eprosw.h"
+#include "epro.h"
+#include "eprodbg.h"
+
+#if DBG
+
+// Flags to turn spew on or off from debugger...
+BOOLEAN EPRO_TX_DBG_ON = FALSE;
+BOOLEAN EPRO_RX_DBG_ON = FALSE;
+// default INIT spew to ON in debug version for now...
+BOOLEAN EPRO_INIT_DBG_ON = FALSE;
+BOOLEAN EPRO_REQ_DBG_ON = FALSE;
+BOOLEAN EPRO_INTERRUPT_DBG_ON = FALSE;
+
+#define EPRO_LOG_SIZE 10000
+
+UCHAR EPro_Log[EPRO_LOG_SIZE];
+UINT EPro_Log_Offset = 0;
+
+VOID EProLogStr(char *s)
+{
+ UINT len = strlen(s);
+
+ if ((EPro_Log_Offset + len) >= EPRO_LOG_SIZE) {
+ EPro_Log_Offset = 0;
+ }
+
+ NdisMoveMemory((&EPro_Log[EPro_Log_Offset]), s, len);
+ EPro_Log_Offset+=len;
+}
+
+VOID EProLogLong(ULONG l)
+{
+ if (EPro_Log_Offset + sizeof(ULONG) >= EPRO_LOG_SIZE) {
+ EPro_Log_Offset = 0;
+ }
+
+ NdisMoveMemory((&EPro_Log[EPro_Log_Offset]), &l, sizeof(ULONG));
+ EPro_Log_Offset+=sizeof(ULONG);
+}
+
+VOID EProLogBuffer(UCHAR *s, ULONG len)
+{
+ if ((EPro_Log_Offset + len) >= EPRO_LOG_SIZE) {
+ EPro_Log_Offset = 0;
+ }
+
+ NdisMoveMemory(&EPro_Log[EPro_Log_Offset], s, len);
+ EPro_Log_Offset+=len;
+}
+
+#endif // IF DBG
+
+
diff --git a/private/ntos/ndis/ieepro/eprodbg.h b/private/ntos/ndis/ieepro/eprodbg.h
new file mode 100644
index 000000000..42d7fb721
--- /dev/null
+++ b/private/ntos/ndis/ieepro/eprodbg.h
@@ -0,0 +1,129 @@
+#ifndef _IEPRODBG_
+#define _IEPRODBG_
+
+////////////////////////////////////////////////////////////
+// Debug
+////////////////////////////////////////////////////////////
+#if DBG
+
+extern BOOLEAN EPRO_TX_DBG_ON;
+extern BOOLEAN EPRO_RX_DBG_ON;
+extern BOOLEAN EPRO_INIT_DBG_ON;
+extern BOOLEAN EPRO_REQ_DBG_ON;
+extern BOOLEAN EPRO_INTERRUPT_DBG_ON;
+
+// comment these out if you want don't want DbgPrint's compiling in at all
+// or set the global variables in epro.c if you just want
+// to turn them on or off...
+#define EPRO_DEBUG_TX
+#define EPRO_DEBUG_RX
+#define EPRO_DEBUG_INIT
+#define EPRO_DEBUG_REQ
+#define EPRO_DEBUG_INTERRUPT
+
+// If you want a dump of the EPro's EEPROM for some reason
+// uncomment the following line. The EEPROM will be dumped
+// to the kernel debugger during driver initialization...
+//#define EPRO_DUMP_EEPROM
+
+#define EPRO_ASSERT(expression) { \
+ if ((!(expression))) { \
+ DbgPrint("Assertion failed: %s, at line %d in file %s\n", \
+ #expression, __LINE__, __FILE__); \
+ DbgBreakPoint(); \
+ } \
+}
+
+// TRANSMIT debugging
+#ifdef EPRO_DEBUG_TX
+# define EPRO_DPRINTF_TX(a) { \
+ if (EPRO_TX_DBG_ON) \
+ DbgPrint a; \
+ }
+#else
+# define EPRO_DPRINTF_TX(a)
+#endif
+
+// RECEIVE debugging
+#ifdef EPRO_DEBUG_RX
+# define EPRO_DPRINTF_RX(a) { \
+ if (EPRO_RX_DBG_ON) \
+ DbgPrint a; \
+ }
+#else
+# define EPRO_DPRINTF_RX(a)
+#endif
+
+// INIT debugging
+#ifdef EPRO_DEBUG_INIT
+# define EPRO_DPRINTF_INIT(a) { \
+ if (EPRO_INIT_DBG_ON) \
+ DbgPrint a; \
+ }
+#else
+# define EPRO_DPRINTF_INIT(a)
+#endif
+
+// REQUEST debugging
+#ifdef EPRO_DEBUG_REQ
+# define EPRO_DPRINTF_REQ(a) { \
+ if (EPRO_REQ_DBG_ON) \
+ DbgPrint a; \
+ }
+
+#else
+# define EPRO_DPRINTF_REQ(a)
+#endif
+
+// INTERRUPT debugging
+#ifdef EPRO_DEBUG_INTERRUPT
+# define EPRO_DPRINTF_INTERRUPT(a) { \
+ if (EPRO_INTERRUPT_DBG_ON) \
+ DbgPrint a; \
+ }
+#else
+# define EPRO_DPRINTF_INTERRUPT(a)
+#endif
+
+
+#define EPRO_ASSERT_BANK_0(_adapter) { \
+ UCHAR _result; \
+ EPRO_RD_PORT_UCHAR(adapter, I82595_CMD_REG, &_result); \
+ EPRO_ASSERT((_result & I82595_CUR_BANK_MASK) == I82595_CMD_BANK0); \
+}
+
+#define EPRO_ASSERT_BANK_1(_adapter) { \
+ UCHAR _result; \
+ EPRO_RD_PORT_UCHAR(adapter, I82595_CMD_REG, &_result); \
+ EPRO_ASSERT((_result & I82595_CUR_BANK_MASK) == I82595_CMD_BANK1); \
+}
+
+#define EPRO_ASSERT_BANK_2(_adapter) { \
+ UCHAR _result; \
+ EPRO_RD_PORT_UCHAR(adapter, I82595_CMD_REG, &_result); \
+ EPRO_ASSERT((_result & I82595_CUR_BANK_MASK) == I82595_CMD_BANK2); \
+}
+
+#else // ifdef DEBUG
+
+#define EPRO_ASSERT(expression)
+
+#define EPRO_ASSERT_BANK_0(_adapter)
+#define EPRO_ASSERT_BANK_1(_adapter)
+#define EPRO_ASSERT_BANK_2(_adapter)
+
+#define EPRO_DPRINTF_TX(a)
+#define EPRO_DPRINTF_RX(a)
+#define EPRO_DPRINTF_INIT(a)
+#define EPRO_DPRINTF_REQ(a)
+#define EPRO_DPRINTF_INTERRUPT(a)
+#define EPRO_LOG_INIT(a)
+#define EPRO_LOG_TX(a)
+#define EPRO_LOG_RX(a)
+#define EPRO_LOG_REQ(a)
+#define EPRO_LOG_INTERRUPT(a)
+
+#endif // ifdef DEBUG
+
+
+#endif
diff --git a/private/ntos/ndis/ieepro/eprohw.h b/private/ntos/ndis/ieepro/eprohw.h
new file mode 100644
index 000000000..fb1678e66
--- /dev/null
+++ b/private/ntos/ndis/ieepro/eprohw.h
@@ -0,0 +1,202 @@
+#ifndef _IEPROHW_
+#define _IEPROHW_
+
+#define EPRO_LENGTH_OF_ADDRESS 6
+
+////////////////////////////////////////////////////////////
+// Bank Switches
+////////////////////////////////////////////////////////////
+#define EPRO_GOTO_B0 EPRO_WRITE_UCHAR(epro_cmd_reg, EPRO_CMD_BANK0)
+#define EPRO_GOTO_B1 EPRO_WRITE_UCHAR(epro_cmd_reg, EPRO_CMD_BANK1)
+#define EPRO_GOTO_B2 EPRO_WRITE_UCHAR(epro_cmd_reg, EPRO_CMD_BANK2)
+
+////////////////////////////////////////////////////////////
+// Port I/O
+////////////////////////////////////////////////////////////
+#define EPRO_READ_UCHAR(_Port, _pValue) \
+ NdisRawReadPortUchar( \
+ (ULONG)(_Port), \
+ (PUCHAR)(_pValue) \
+ )
+
+#define EPRO_READ_USHORT(_Port, _pValue) \
+ NdisRawReadPortUshort( \
+ (ULONG)(_Port), \
+ (PUSHORT)(_pValue) \
+ )
+
+#define EPRO_WRITE_UCHAR(_Port, _Value) \
+ NdisRawWritePortUchar( \
+ (ULONG)(_Port), \
+ (UCHAR) (_Value) \
+ )
+
+////////////////////////////////////////////////////////////
+// Command Macros
+// Care must be taken to ensure you are in the right bank
+////////////////////////////////////////////////////////////
+
+// Memory I/O
+#define EPRO_MEM_READADDR(_pValue) \
+ EPRO_READ_USHORT(EPro_IOBaseAddress + EPRO_HOST_ADDR_REG, _pValue)
+
+#define EPRO_MEM_WRITEADDR(_Value) \
+ EPRO_WRITE_USHORT(EPro_IOBaseAddress + EPRO_HOST_ADDR_REG, Value)
+
+#define EPRO_MEM_READSHORT(_pValue) \
+ EPRO_READ_USHORT(EPro_IOBaseAddress + EPRO_MEM_IO_REG)
+
+#define EPRO_MEM_WRITESHORT(_Value) \
+ EPRO_WRITE_USHORT(EPro_IOBaseAddress + EPRO_MEM_IO_REG)
+
+//BOOLEAN EProMemcpyW(void *pMainMemSrc_, void *OnBoardDest_, UINT count);
+//BOOLEAN EProMemcpyR(void *OnBoardSrc_, void *pMainMemDest_, UINT count);
+
+////////////////////////////////////////////////////////////
+// TX Defines
+////////////////////////////////////////////////////////////
+#define EPRO_NUM_TX_BUFFERS 30
+#define EPRO_TX_FIRST_BUF_START 0
+
+// 1514 bytes ethernet frame
+// 16 bytes epro header
+// 2 bytes pad for word alignment
+//#define EPRO_BUFFER_LEN 1532
+
+#define EPRO_TRANSMIT_HEADER_SHORT1 (USHORT)I82595_XMT
+#define EPRO_TRANSMIT_HEADER_SHORT2 (USHORT)0x0
+
+////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////
+
+#define EPRO_REGISTRY_INTERRUPT_STRING NDIS_STRING_CONST("INTERRUPT")
+#define EPRO_REGISTRY_IOADDRESS_STRING NDIS_STRING_CONST("IOADDRESS")
+#define EPRO_REGISTRY_OLDIOADDRESS_STRING NDIS_STRING_CONST("OLDIOADDRESS")
+#define EPRO_REGISTRY_BUSTYPE_STRING NDIS_STRING_CONST("BusType")
+#define EPRO_REGISTRY_TRANSCEIVER_STRING NDIS_STRING_CONST("Transceiver")
+#define EPRO_REGISTRY_IOCHRDY_STRING NDIS_STRING_CONST("IoChannelReady")
+
+#define EPRO_IOCHRDY_EARLY 0x01
+#define EPRO_IOCHRDY_LATE 0x02
+#define EPRO_IOCHRDY_NEVER 0x03
+#define EPRO_IOCHRDY_AUTO 0x04
+
+////////////////////////////////////////////////////////////
+// Capabilities/Statistics about the EPRO card
+////////////////////////////////////////////////////////////
+
+#define EPRO_VENDOR_ID_L 0x00
+#define EPRO_VENDOR_ID_M 0xaa
+#define EPRO_VENDOR_ID_H 0x00
+
+#define EPRO_GEN_MEDIA_SUPPORTED NdisMedium802_3
+#define EPRO_GEN_MEDIA_IN_USE NdisMedium802_3
+#define EPRO_GEN_MAXIMUM_LOKAHEAD 256
+#define EPRO_GEN_MAXIMUM_FRAME_SIZE 1500
+#define EPRO_GEN_MAXIMUM_TOTAL_SIZE 1514
+#define EPRO_MAX_MULTICAST 64
+#define EPRO_GEN_MAC_OPTIONS (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \
+ NDIS_MAC_OPTION_RECEIVE_SERIALIZED | \
+ NDIS_MAC_OPTION_NO_LOOPBACK)
+#define EPRO_GEN_LINK_SPEED 100000
+#define EPRO_GEN_RECEIVE_BUFFER_SPACE (0x8000 - 0x3000)
+#define EPRO_TX_BUF_SIZE 1514
+#define EPRO_RX_BUF_SIZE 0
+#define EPRO_GEN_TRANSMIT_BUFFER_SPACE EPRO_TX_BUF_SIZE * EPRO_NUM_TX_BUFFERS
+#define EPRO_VENDOR_DESC "Intel EtherExpress PRO"
+
+
+////////////////////////////////////////////////////////////
+// EPro EEPROM defines
+////////////////////////////////////////////////////////////
+#define EPRO_SK_STALL_TIME 1000 // use 1000 microsecs
+
+#define EPRO_ETHERNET_ADDR_H 0x2
+#define EPRO_ETHERNET_ADDR_M 0x3
+#define EPRO_ETHERNET_ADDR_L 0x4
+
+#define EPRO_EEPROM_CONFIG_OFFSET 0
+#define EPRO_EEPROM_CONFIG1_OFFSET 1
+
+// word 0 on the eeprom
+#define EPRO_EEPROM_IOADDR_BITPOS 0x0a // bits 10-15
+#define EPRO_EEPROM_IOADDR_MASK 0xfc00
+#define EPRO_EEPROM_AUTO_IO_ENABLE_MASK 0x0040
+#define EPRO_EEPROM_HOST_BUS_WD_MASK 0x0004
+#define EPRO_EEPROM_PNP_ENABLE_MASK 0x0001
+
+// word 1 on the eeprom. RM: Due to chenges for eeprom stepping 4, we
+// have additional masks. For simplicity's sake, stepping 4 masks
+// are prefixed with the '4' (even if there is no other stepping
+// equivalent INT for that IRQ).
+#define EPRO_EEPROM_IRQ_MASK 0x000f
+#define EPRO_EEPROM_IRQ_2_MASK 0x0
+#define EPRO_EEPROM_IRQ_3_MASK 0x1
+#define EPRO_EEPROM4_IRQ_3_MASK 0x0
+#define EPRO_EEPROM4_IRQ_4_MASK 0x1
+#define EPRO_EEPROM_IRQ_5_MASK 0x2
+#define EPRO_EEPROM4_IRQ_7_MASK 0x3
+#define EPRO_EEPROM4_IRQ_9_MASK 0x4
+#define EPRO_EEPROM_IRQ_10_MASK 0x3
+#define EPRO_EEPROM4_IRQ_10_MASK 0x5
+#define EPRO_EEPROM_IRQ_11_MASK 0x4
+#define EPRO_EEPROM4_IRQ_11_MASK 0x6
+#define EPRO_EEPROM4_IRQ_12_MASK 0x7
+
+
+////////////////////////////////////////////////////////////
+// TX/RX buffers
+////////////////////////////////////////////////////////////
+#define EPRO_TX_LOWER_LIMIT 0x00
+#define EPRO_TX_UPPER_LIMIT 0x27
+
+#define EPRO_TX_LOWER_LIMIT_SHORT 0x0000
+#define EPRO_TX_UPPER_LIMIT_SHORT 0x2800
+
+#define EPRO_RX_LOWER_LIMIT 0x28
+#define EPRO_RX_UPPER_LIMIT 0x7f
+
+#define EPRO_RX_LOWER_LIMIT_SHORT 0x2800
+#define EPRO_RX_UPPER_LIMIT_SHORT 0x8000
+
+////////////////////////////////////////////////////////////
+// Configuration Defaults
+////////////////////////////////////////////////////////////
+//#define EPRO_CONFIG_1 0xa0 // a0
+#define EPRO_CONFIG_1 0xe0 // a0
+#define EPRO_CONFIG_2 0x16 // no broadcast
+
+// 4 different ones depending on the transceiver setting...
+#define EPRO_CONFIG_3_AUI 0x10
+#define EPRO_CONFIG_3_BNC 0x34
+#define EPRO_CONFIG_3_TPE 0x14
+#define EPRO_CONFIG_3_AUTO 0x00
+
+#define EPRO_NO_RX_STP_INTERRUPTS 0x01
+#define EPRO_NO_RX_INTERRUPTS 0x02
+#define EPRO_NO_TX_INTERRUPTS 0x04
+#define EPRO_NO_EXEC_INTERRUPTS 0x08
+
+#define EPRO_DEFAULT_INTERRUPTS 0x09 // RX and TX
+#define EPRO_ALL_INTERRUPTS 0x0f
+#define EPRO_RX_TX_EXE_INTERRUPTS 0x01
+
+////////////////////////////////////////////////////////////
+// Various states for our ISR
+////////////////////////////////////////////////////////////
+#define EPRO_INT_NONE_PENDING 0
+//#define EPRO_INT_IN_SETUP 1
+//#define EPRO_INT_RESET_PENDING 2
+//#define EPRO_INT_SET_PENDING 3
+#define EPRO_INT_MC_SET_PENDING 4
+
+////////////////////////////////////////////////////////////
+//
+////////////////////////////////////////////////////////////
+// How long do we wait for a TX to free up before we
+// consider ourselves hung?
+#define EPRO_TX_TIMEOUT 10000 // 10000 usec right now
+
+#endif // _IEPROHW_
+
diff --git a/private/ntos/ndis/ieepro/eprosw.h b/private/ntos/ndis/ieepro/eprosw.h
new file mode 100644
index 000000000..421824dee
--- /dev/null
+++ b/private/ntos/ndis/ieepro/eprosw.h
@@ -0,0 +1,254 @@
+#ifndef _IEPROSW_
+#define _IEPROSW_
+
+#define EPRO_NDIS_MAJOR_VERSION 3
+#define EPRO_NDIS_MINOR_VERSION 0
+#define EPRO_USE_32_BIT_IO
+
+////////////////////////////////////////////////////////////
+// Internal data structures used by the driver...
+////////////////////////////////////////////////////////////
+// do i really need this?
+typedef struct EPRO_DRIVER {
+ NDIS_HANDLE EProWrapperHandle;
+} EPRO_DRIVER, *PEPRO_DRIVER;
+
+
+////////////////////////////////////////////////////////////
+typedef struct _EPRO_TRANSMIT_BUFFER {
+// This is basically to make computing the next and last buffer
+// faster... Maybe saves us a few instructions, but makes a
+// lot of code a lot easier to read...
+ struct _EPRO_TRANSMIT_BUFFER *LastBuf;
+ struct _EPRO_TRANSMIT_BUFFER *NextBuf;
+
+ BOOLEAN fEmpty; // TRUE if this is an empty buffer,
+
+// This is valid iff !fEmpty
+ PNDIS_PACKET TXPacket;
+
+// These are addresses ON THE NIC
+ USHORT TXBaseAddr;
+ USHORT TXSendAddr;
+// USHORT TXBottomAddr;
+ USHORT TXSize;
+} EPRO_TRANSMIT_BUFFER, *PEPRO_TRANSMIT_BUFFER;
+
+////////////////////////////////////////////////////////////
+// The header is supposed to be "compatible with the 8595tx'
+// transmit buffer structure. Whatever.
+typedef struct _EPRO_MC_HEADER {
+ UCHAR CommandField;
+ UCHAR NullBytes[5];
+
+// do it this way for endian-safety
+ UCHAR ByteCountLo;
+ UCHAR ByteCountHi;
+} EPRO_MC_HEADER, *PEPRO_MC_HEADER;
+
+////////////////////////////////////////////////////////////
+typedef struct _EPRO_MC_ADDRESS {
+ UCHAR AddrByte[EPRO_LENGTH_OF_ADDRESS];
+} EPRO_MC_ADDRESS, *PEPRO_MC_ADDRESS;
+
+////////////////////////////////////////////////////////////
+// These are the structures to be copied onto the NIC -- they
+// are documented in the 82595 documentation
+typedef struct _EPRO_TX_FRAME_HEADER {
+// High dword
+ UCHAR XmitOp;
+ UCHAR NULLByte;
+ UCHAR Status0;
+ UCHAR Status1;
+// Low dword
+ UCHAR XMTChainLo;
+ UCHAR XMTChainHi;
+} EPRO_TX_FRAME_HEADER, *PEPRO_TX_FRAME_HEADER;
+
+////////////////////////////////////////////////////////////
+// Same as above...
+typedef struct _EPRO_RCV_HEADER {
+ UCHAR Event;
+ UCHAR NullByte;
+ UCHAR Status0;
+ UCHAR Status1;
+ UCHAR NextFrmLo;
+ UCHAR NextFrmHi;
+ UCHAR ByteCountLo;
+ UCHAR ByteCountHi;
+} EPRO_RCV_HEADER, *PEPRO_RCV_HEADER;
+
+////////////////////////////////////////////////////////////
+// This is an ETHERNET 802.3 frame header.
+typedef struct _EPRO_ETH_HEADER {
+ UCHAR DestAddress[EPRO_LENGTH_OF_ADDRESS];
+ UCHAR SourceAddress[EPRO_LENGTH_OF_ADDRESS];
+ USHORT Length;
+} EPRO_ETH_HEADER, *PEPRO_ETH_HEADER;
+
+////////////////////////////////////////////////////////////
+// This is the context that gets passed to EProTransferData
+// through NdisMIndicateReceive
+typedef struct _EPRO_RCV_CONTEXT {
+ USHORT RXCurrentAddress;
+ USHORT RXFrameSize;
+ USHORT LookAheadSize;
+} EPRO_RCV_CONTEXT, *PEPRO_RCV_CONTEXT;
+
+////////////////////////////////////////////////////////////
+// The EPro adapter structure...
+typedef struct EPRO_ADAPTER {
+ NDIS_HANDLE MiniportAdapterHandle;
+ NDIS_MINIPORT_INTERRUPT Interrupt;
+// NDIS_MINIPORT_TIMER MiniportTimer;
+ PVOID IoBaseAddr;
+ ULONG TransceiverType;
+ ULONG IoPAddr; // Returned by NdisMRegisterIoPortRange - handle to mapped ports
+ ULONG IoChannelReady;
+ // What version of 82595 is this?
+ ULONG EProStepping;
+ // Can we use 32-bit IO? (ie is this a new enough version of the 82595
+ // chip?)
+ BOOLEAN EProUse32BitIO;
+
+ ULONG CurrentHardwareStatus;
+ // what is our current packet filter?
+ ULONG CurrentPacketFilter;
+ // are promiscuous receptions currently enabled?
+ BOOLEAN fPromiscuousEnable;
+ // are broadcast receptions currently enabled?
+ BOOLEAN fBroadcastEnable;
+ // are multicast receptions currently enabled?
+ BOOLEAN fMulticastEnable;
+ // are we hung? NOTUSED
+ BOOLEAN fHung;
+ // are receives currently enabled?
+ BOOLEAN fReceiveEnabled;
+ // do we really need this?
+// BOOLEAN fTransmitInProgress;
+
+// statistics
+ ULONG FramesXmitOK;
+ ULONG FramesRcvOK;
+ ULONG FramesXmitErr;
+ ULONG FramesRcvErr;
+ ULONG FramesMissed;
+ ULONG FrameAlignmentErrors;
+ ULONG FramesXmitOneCollision;
+ ULONG FramesXmitManyCollisions;
+
+// transmit info
+ // these are our transmit buffers - structures which basically
+ // keep track of what frames are where in the NIC's memory.
+ EPRO_TRANSMIT_BUFFER TXBuf[EPRO_NUM_TX_BUFFERS];
+ // this is the first free transmit buffer pointer.
+ PEPRO_TRANSMIT_BUFFER CurrentTXBuf;
+ // This is the frame that is currently in the process of
+ // being transmitted onto the wire.
+ PEPRO_TRANSMIT_BUFFER TXChainStart;
+
+// Multicast info
+ UCHAR MCAddress[EPRO_MAX_MULTICAST][EPRO_LENGTH_OF_ADDRESS];
+ // how many mc addresses are currently set?
+ USHORT NumMCAddresses;
+
+// receive info
+ // how big is our lookahead buffer currently?
+ USHORT RXLookAheadSize;
+ // our lookahead buffer data
+ UCHAR RXLookAhead[EPRO_GEN_MAXIMUM_LOKAHEAD];
+ // what address ON THE NIC are we currently receiveing at?
+ // ie where do we check when we get a receive interrupt.
+ USHORT RXCurrentAddress;
+
+ // Is there an exec int pending? If so, why?
+ // right now only used to resolve pended set-mc calls...
+ ULONG IntPending;
+ // This is our context for a pended set-mc call
+ PVOID IntContext;
+ // set based on result of IOCHRDY test
+ BOOLEAN Use8Bit;
+ // set in ReadConfigInfo
+ BOOLEAN UseDefaultAddress;
+ // the MAC address burned into the eeprom
+ UCHAR PermanentIndividualAddress[EPRO_LENGTH_OF_ADDRESS];
+ // the address we are currently receiving at
+ UCHAR CurrentIndividualAddress[EPRO_LENGTH_OF_ADDRESS];
+ // always 00 aa 00 for intel
+ UCHAR vendorID[3];
+
+ UCHAR InterruptNumber;
+ UCHAR BusType;
+
+ // This is only used at initialization time
+ BOOLEAN fUpdateIOAddress;
+ PVOID OldIOAddress;
+
+ UCHAR CurrentInterruptMask;
+} EPRO_ADAPTER, *PEPRO_ADAPTER;
+
+
+////////////////////////////////////////////////////////////
+// Sync contexts
+////////////////////////////////////////////////////////////
+typedef struct _EPRO_COPYBUF_CONTEXT {
+ PEPRO_ADAPTER Adapter;
+ PVOID Buffer;
+ UINT Len;
+} EPRO_COPYBUF_CONTEXT, *PEPRO_COPYBUF_CONTEXT;
+
+typedef struct _EPRO_SETINTERRUPT_CONTEXT {
+ PEPRO_ADAPTER Adapter;
+ UCHAR NewMask;
+} EPRO_SETINTERRUPT_CONTEXT, *PEPRO_SETINTERRUPT_CONTEXT;
+
+typedef struct _EPRO_BRDPROM_CONTEXT {
+ PEPRO_ADAPTER Adapter;
+ UCHAR Reg2Flags;
+} EPRO_BRDPROM_CONTEXT, *PEPRO_BRDPROM_CONTEXT;
+
+
+////////////////////////////////////////////////////////////
+// Some macros for commonly used stuff....
+
+#define EPRO_WR_PORT_UCHAR(adapter, port, ch) \
+ NdisRawWritePortUchar(adapter->IoPAddr + port, ch)
+
+#define EPRO_RD_PORT_UCHAR(adapter, port, ch) \
+ NdisRawReadPortUchar(adapter->IoPAddr + port, ch)
+
+#define EPRO_WR_PORT_USHORT(adapter, port, us) \
+ NdisRawWritePortUshort(adapter->IoPAddr + port, us)
+
+#define EPRO_RD_PORT_USHORT(adapter, port, us) \
+ NdisRawReadPortUshort(adapter->IoPAddr + port, us)
+
+
+////////////////////////////////////////////////////////////
+// The EPro is a bank-switching card. These macros switch between the banks...
+#define EPRO_SWITCH_BANK_0(adapter) \
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_CMD_BANK0)
+
+#define EPRO_SWITCH_BANK_1(adapter) \
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_CMD_BANK1)
+
+#define EPRO_SWITCH_BANK_2(adapter) \
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_CMD_BANK2)
+
+// Set the Host Address Register (0,c) -- use this to set up the NIC address
+// for PIO through the register via COPY_BUFFER macros.
+#define EPRO_SET_HOST_ADDR(adapter, addr) \
+ EPRO_WR_PORT_USHORT(adapter, I82595_HOST_ADDR_REG, addr);
+
+#define EPRO_COPY_BUFFER_TO_NIC_USHORT(adapter, buffer, len) \
+ NdisRawWritePortBufferUshort((adapter->IoPAddr + I82595_MEM_IO_REG), \
+ (buffer), \
+ (len))
+
+#define EPRO_READ_BUFFER_FROM_NIC_USHORT(adapter, buffer, len) \
+ NdisRawReadPortBufferUshort((adapter->IoPAddr + I82595_MEM_IO_REG), \
+ (buffer), \
+ len)
+
+
+#endif _IEPROSW_
diff --git a/private/ntos/ndis/ieepro/init.c b/private/ntos/ndis/ieepro/init.c
new file mode 100644
index 000000000..b94ae0e02
--- /dev/null
+++ b/private/ntos/ndis/ieepro/init.c
@@ -0,0 +1,1418 @@
+#include <stdio.h>
+#include <ndis.h>
+#include "82595.h"
+#include "eprohw.h"
+#include "eprosw.h"
+#include "epro.h"
+#include "eprodbg.h"
+
+NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
+ NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT pDriverObject_,
+ IN PUNICODE_STRING RegistryPath_)
+/*++
+ Routine Description:
+
+ This is the primary initialization routine for the EPRO driver.
+ It is simply responsible for the intializing the wrapper and registering
+ the Miniport driver. It then calls a system and architecture specific
+ routine that will initialize and register each adapter.
+
+ Arguments:
+
+ DriverObject - Pointer to driver object created by the system.
+
+ RegistryPath - Path to the parameters for this driver in the registry.
+
+ Return Value:
+
+ The status of the operation.
+--*/
+{
+ //
+ // Receives the status of the NdisMRegisterMiniport operation.
+ //
+ NDIS_STATUS status;
+
+ //
+ // Characteristics table for this driver.
+ //
+ NDIS_MINIPORT_CHARACTERISTICS EPro_Miniport_Char;
+
+ //
+ // Handle for referring to the wrapper about this driver.
+ //
+ NDIS_HANDLE ndisWrapperHandle;
+
+ //
+ // Initialize the wrapper.
+ //
+ NdisMInitializeWrapper(
+ &ndisWrapperHandle,
+ pDriverObject_,
+ RegistryPath_,
+ NULL);
+
+ //
+ // Initialize the Miniport characteristics for the call to
+ // NdisMRegisterMiniport.
+ //
+
+ // The major and minor version of the driver
+ EPro_Miniport_Char.MajorNdisVersion = EPRO_NDIS_MAJOR_VERSION;
+ EPro_Miniport_Char.MinorNdisVersion = EPRO_NDIS_MINOR_VERSION;
+
+ // our various Miniport handlers
+ EPro_Miniport_Char.CheckForHangHandler = EProCheckForHang;
+ EPro_Miniport_Char.DisableInterruptHandler = EProDisableInterrupts;
+ EPro_Miniport_Char.EnableInterruptHandler = EProEnableInterrupts;
+ EPro_Miniport_Char.HaltHandler = EProHalt;
+ EPro_Miniport_Char.HandleInterruptHandler = EProHandleInterrupt;
+ EPro_Miniport_Char.InitializeHandler = EProInitialize;
+ EPro_Miniport_Char.ISRHandler = EProISR;
+ EPro_Miniport_Char.QueryInformationHandler = EProQueryInformation;
+ EPro_Miniport_Char.ReconfigureHandler = NULL;
+ EPro_Miniport_Char.ResetHandler = EProReset;
+ EPro_Miniport_Char.SendHandler = EProSend;
+ EPro_Miniport_Char.SetInformationHandler = EProSetInformation;
+ EPro_Miniport_Char.TransferDataHandler = EProTransferData;
+
+ // register us as a miniport...
+ status = NdisMRegisterMiniport(
+ ndisWrapperHandle,
+ &EPro_Miniport_Char,
+ sizeof(EPro_Miniport_Char));
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ NdisTerminateWrapper(ndisWrapperHandle, NULL);
+ EPRO_DPRINTF_INIT(("DriverEntry UNSUCCESSFUL!\n"));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ EPRO_DPRINTF_INIT(("EPro DriverEntry Successful!\n"));
+
+ return(STATUS_SUCCESS);
+}
+
+NDIS_STATUS EProInitialize(
+ OUT PNDIS_STATUS openErrorStatus,
+ OUT PUINT selectedMediumIndex,
+ IN PNDIS_MEDIUM mediumArray,
+ IN UINT mediumArraySize,
+ IN NDIS_HANDLE miniportAdapterHandle,
+ IN NDIS_HANDLE configurationHandle)
+/*++
+
+ Routine Description:
+
+ EProInitialize starts an adapter and registers resources with the
+ wrapper.
+
+ Arguments:
+
+ OpenErrorStatus - Extra status bytes for opening token ring adapters.
+
+ SelectedMediumIndex - Index of the media type chosen by the driver.
+
+ MediumArray - Array of media types for the driver to chose from.
+
+ MediumArraySize - Number of entries in the array.
+
+ MiniportAdapterHandle - Handle for passing to the wrapper when
+ referring to this adapter.
+
+ ConfigurationHandle - A handle to pass to NdisOpenConfiguration.
+
+ Return Values:
+ NDIS_STATUS_UNSUPPORTED_MEDIA - the wrapper tried to set a media
+ type we couldn't do
+
+ NDIS_STATUS_SUCCESS - operation succeeded ok
+
+ perhaps other error status returned from the NdisM calls..
+
+--*/
+{
+ PEPRO_ADAPTER adapter = NULL;
+ UINT i;
+ NDIS_STATUS status;
+ BOOLEAN fAllocatedAdapterMemory;
+ BOOLEAN fRegisteredIoPortRange;
+
+ //
+ // Find the 802.3 medium type and return it to the wrapper...
+ //
+ for (i = 0; i < mediumArraySize; i++)
+ {
+ if (mediumArray[i] == NdisMedium802_3)
+ {
+ break;
+ }
+ }
+
+ if (i == mediumArraySize)
+ {
+ return(NDIS_STATUS_UNSUPPORTED_MEDIA);
+ }
+
+ // Return the correct medium to the wrapper
+ //
+ *selectedMediumIndex = i;
+
+ fAllocatedAdapterMemory = FALSE;
+ fRegisteredIoPortRange = FALSE;
+
+ do
+ {
+ //
+ // Allocate Memory for the Adapter Structure
+ //
+ status = NdisAllocateMemory(
+ (PVOID *)&adapter,
+ sizeof(EPRO_ADAPTER),
+ 0,
+ HighestAcceptableMax);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_INIT(("Failed to allocate memory for the EPRO adapter stucture\n"));
+ break;
+ }
+
+ fAllocatedAdapterMemory = TRUE;
+
+ //
+ // Zero the adapter structure.
+ //
+ NdisZeroMemory(adapter, sizeof(EPRO_ADAPTER));
+
+ //
+ // Set some initial values in the adapter structure...
+ //
+ EProInitializeAdapterData(adapter);
+
+ //
+ // Save the miniport adapter handle for later
+ //
+ adapter->MiniportAdapterHandle = miniportAdapterHandle;
+
+ //
+ // Read configuration information for this adapter
+ //
+ status = EProReadConfiguration(adapter, configurationHandle);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_INIT(("EProReadConfiguration FAILED!\n"));
+
+ break;
+ }
+
+ //
+ // Register our adapter handler with the wrapper.
+ //
+ NdisMSetAttributes(
+ adapter->MiniportAdapterHandle,
+ (NDIS_HANDLE)adapter,
+ FALSE,
+ adapter->BusType);
+
+ //
+ // Register the IO port range needed.
+ //
+ status = NdisMRegisterIoPortRange(
+ (PVOID *)(&adapter->IoPAddr),
+ adapter->MiniportAdapterHandle,
+ (ULONG)adapter->IoBaseAddr,
+ 0x10);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_INIT(("Could not register IO ports.\n"));
+
+ break;
+ }
+
+ fRegisteredIoPortRange = TRUE;
+
+ //
+ // Initialize the hardware and enable the card...
+ //
+ status = EProInitialReset(adapter);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_INIT(("Failed Initial Reset\n"));
+
+ break;
+ }
+
+ //
+ // Now, the resetting is done - configure the hardware...
+ //
+ status = EProHWConfigure(adapter);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_INIT(("Failed to configure EPRO hardware\n"));
+
+ break;
+ }
+
+ //
+ // If we are a step 2 or 3 adapter then update the eeprom if
+ // necessary. RM: add stepping 4.
+ //
+ if ((adapter->EProStepping == 2) || (adapter->EProStepping == 3) || (adapter->EProStepping == 4))
+ {
+ EProUpdateEEProm(adapter);
+ }
+
+ //
+ // Make sure that we do not free resources.
+ //
+ fAllocatedAdapterMemory = FALSE;
+ fRegisteredIoPortRange = FALSE;
+
+ } while (FALSE);
+
+ if (fRegisteredIoPortRange)
+ {
+ NdisMDeregisterIoPortRange(
+ adapter->MiniportAdapterHandle,
+ (ULONG)adapter->IoBaseAddr,
+ 0x10,
+ (PVOID)adapter->IoPAddr);
+ }
+
+ if (fAllocatedAdapterMemory)
+ {
+ NdisFreeMemory(adapter, sizeof(EPRO_ADAPTER), 0);
+ }
+
+ return(status);
+}
+
+VOID EProUpdateEEProm(IN PEPRO_ADAPTER adapter)
+/*++
+
+ Routine Description:
+
+ This routine is called after the card's configuration has been
+ read from the registry and after the card's IO ports have been
+ registered. Now we check the card's EEPROM and verify that the
+ configuration information in the registry matches that saved
+ in the EEPROM. If they DON'T match, we update the card's EEPROM
+ with the new info. Note that the registry always overrides the
+ info that is saved -- in fact the info saved on the card is never
+ used at all right now, except the IO address - it is always overriden
+ by defaults or the registry values. We just save it in case the user
+ boots to another OS or moves and re-installs the card (the detection
+ code DOES read the EEPROM-configured defaults, so a new install will
+ be interested in what we have set.)
+
+ Arguments:
+
+ adapter - pointer to our EPRO_ADAPTER structure
+
+ Return Values:
+
+ none
+
+--*/
+{
+ USHORT reg0, reg1;
+ BOOLEAN fCardUse8Bit;
+ BOOLEAN fUpdateEEPROM = FALSE;
+ USHORT cardIrq;
+
+ EProEERead(adapter, EPRO_EEPROM_CONFIG_OFFSET, &reg0);
+ EProEERead(adapter, EPRO_EEPROM_CONFIG1_OFFSET, &reg1);
+
+ //
+ // check the force 8-bit setting...
+ //
+ fCardUse8Bit = !(reg0 & EPRO_EEPROM_HOST_BUS_WD_MASK);
+ if (fCardUse8Bit != adapter->Use8Bit)
+ {
+ fUpdateEEPROM = TRUE;
+ if (adapter->Use8Bit)
+ {
+ reg0 &= ~EPRO_EEPROM_HOST_BUS_WD_MASK;
+ }
+ else
+ {
+ reg0 |= EPRO_EEPROM_HOST_BUS_WD_MASK;
+ }
+ }
+ //
+ // check the IRQ
+ //
+ switch(reg1 & EPRO_EEPROM_IRQ_MASK)
+ {
+ case 0:
+ cardIrq = (adapter->EProStepping == 4)? 3 : 9;
+ break;
+
+ case 1:
+ cardIrq = (adapter->EProStepping == 4)? 4 : 3;
+ break;
+
+ case 2:
+ cardIrq = 5;
+ break;
+
+ case 3:
+ cardIrq = (adapter->EProStepping == 4)? 7 : 10;
+ break;
+
+ case 4:
+ cardIrq = (adapter->EProStepping == 4)? 9 : 11;
+ break;
+
+ case 5:
+ cardIrq = (adapter->EProStepping == 4)? 10 : 5;
+ break;
+
+
+ case 6:
+ cardIrq = (adapter->EProStepping == 4)? 11 : 5;
+ break;
+
+ case 7:
+ cardIrq = (adapter->EProStepping == 4)? 12 : 5;
+ break;
+
+
+ default:
+ cardIrq = 0xff;
+ break;
+ }
+
+ EPRO_DPRINTF_INIT(("EEPROM Interrupt Number: 0x%x\n", cardIrq));
+
+ if (cardIrq != adapter->InterruptNumber)
+ {
+ EPRO_DPRINTF_INIT(("Changing EEPROM to interrupt number 0x%x\n", adapter->InterruptNumber));
+ fUpdateEEPROM = TRUE;
+ reg1 &= ~EPRO_EEPROM_IRQ_MASK;
+ //
+ // RM: in the following, some INTs are different for stepping 4.
+ // Unsupported ints default to IRQ 5. IRQ 2 and 9 are INT 0 for stepping 2/3.
+ //
+ switch(adapter->InterruptNumber)
+ {
+ case 2:
+ case 9:
+ reg1 |= (adapter->EProStepping == 4)? EPRO_EEPROM4_IRQ_9_MASK : EPRO_EEPROM_IRQ_2_MASK;
+ break;
+
+ case 3:
+ reg1 |= (adapter->EProStepping == 4)? EPRO_EEPROM4_IRQ_3_MASK : EPRO_EEPROM_IRQ_3_MASK;
+ break;
+
+ case 4:
+ reg1 |= (adapter->EProStepping == 4)? EPRO_EEPROM4_IRQ_4_MASK : EPRO_EEPROM_IRQ_5_MASK;
+ break;
+
+ case 5:
+ reg1 |= EPRO_EEPROM_IRQ_5_MASK;
+ break;
+
+ case 7:
+ reg1 |= (adapter->EProStepping == 4)? EPRO_EEPROM4_IRQ_7_MASK : EPRO_EEPROM_IRQ_5_MASK;
+ break;
+
+ case 10:
+ reg1 |= (adapter->EProStepping == 4)? EPRO_EEPROM4_IRQ_10_MASK : EPRO_EEPROM_IRQ_10_MASK;
+ break;
+
+ case 11:
+ reg1 |= (adapter->EProStepping == 4)? EPRO_EEPROM4_IRQ_11_MASK : EPRO_EEPROM_IRQ_11_MASK;
+ break;
+
+ case 12:
+ reg1 |= (adapter->EProStepping == 4)? EPRO_EEPROM4_IRQ_12_MASK : EPRO_EEPROM_IRQ_5_MASK;
+ break;
+
+ default:
+ reg1 |= EPRO_EEPROM_IRQ_5_MASK;
+ break;
+ }
+
+ EPRO_DPRINTF_INIT(("EEPROM interrupt mask 0x%x\n", reg1 & EPRO_EEPROM_IRQ_MASK));
+ }
+
+ if (fUpdateEEPROM)
+ {
+ EProEEWrite(adapter, EPRO_EEPROM_CONFIG_OFFSET, reg0);
+ EProEEWrite(adapter, EPRO_EEPROM_CONFIG1_OFFSET, reg1);
+ EProEEUpdateChecksum(adapter);
+ }
+}
+
+NDIS_STATUS
+EProReadConfiguration(
+ IN PEPRO_ADAPTER adapter,
+ IN NDIS_HANDLE configurationHandle
+ )
+/*++
+
+ Routine Description:
+
+ Read card config info from the registry and set the values
+ in the adapter structure
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ configurationHandle - a handle to a place in the registry we can
+ read our settings from
+
+ Return Values:
+
+--*/
+{
+ NDIS_STATUS status;
+ NDIS_HANDLE configHandle;
+ PNDIS_CONFIGURATION_PARAMETER returnedValue;
+
+ // These are the keys we read from the registry..
+ //
+ NDIS_STRING interruptNumberString = EPRO_REGISTRY_INTERRUPT_STRING;
+
+ // I/O Port Base Address
+ //
+ NDIS_STRING ioAddressString = EPRO_REGISTRY_IOADDRESS_STRING;
+
+ // OLD I/O Base Address
+ //
+ NDIS_STRING oldIOAddressString = EPRO_REGISTRY_OLDIOADDRESS_STRING;
+
+ // bus type
+ //
+ NDIS_STRING busTypeString = EPRO_REGISTRY_BUSTYPE_STRING;
+
+ // Transceiver Type
+ //
+ NDIS_STRING transceiverString = EPRO_REGISTRY_TRANSCEIVER_STRING;
+
+ // Io Channel Ready
+ //
+ NDIS_STRING IoChannelReadyString = EPRO_REGISTRY_IOCHRDY_STRING;
+
+ // Open the configuration file...
+ //
+ NdisOpenConfiguration(
+ &status,
+ &configHandle,
+ configurationHandle);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_INIT(("EProReadConfiguration - failed in NdisOpenConfiguration\n"));
+ NdisFreeMemory(adapter, sizeof(adapter),0);
+ return(status);
+ }
+
+ // right now we'll just assume it's an isa card...
+ //
+ adapter->BusType = NdisInterfaceIsa;
+
+ // Do we need to update the IO base address?
+ //
+ adapter->fUpdateIOAddress = FALSE;
+
+ // Read "Real" IO Base Address (the one we want to use)
+ //
+ NdisReadConfiguration(&status,
+ &returnedValue,
+ configHandle,
+ &ioAddressString,
+ NdisParameterHexInteger);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_INIT(("Error, can't find io address in registry...using default 0x300\n"));
+ adapter->IoBaseAddr = (PVOID)0x300;
+ }
+ else
+ {
+ adapter->IoBaseAddr = (PVOID)(returnedValue->ParameterData.IntegerData);
+ }
+
+ if ((adapter->IoBaseAddr > (PVOID)0x3f0) || (adapter->IoBaseAddr < (PVOID)0x200))
+ {
+ EPRO_DPRINTF_INIT(("Bad io address set in registry. Using 0x300.\n"));
+ adapter->IoBaseAddr = (PVOID)0x300;
+ }
+
+ //
+ // Read the InterruptNumber
+ //
+ NdisReadConfiguration(
+ &status,
+ &returnedValue,
+ configHandle,
+ &interruptNumberString,
+ NdisParameterHexInteger);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_REQ(("Error, can't read interrupt number from registry...using default\n"));
+ adapter->InterruptNumber = (CCHAR)5;
+ }
+ else
+ {
+ adapter->InterruptNumber = (CCHAR)(returnedValue->ParameterData.IntegerData);
+ }
+
+ // oh, yah, what was I on when I wrote this?
+ switch (adapter->InterruptNumber)
+ {
+ case 3:
+ case 5:
+ case 9:
+ case 10:
+ case 11:
+ // 4, 7 & 12 valid for v4 chips +RM
+ case 4:
+ case 7:
+ case 12:
+ break;
+
+ default:
+ adapter->InterruptNumber = (CCHAR)5;
+ }
+
+ //
+ // Read the TransceiverType
+ //
+ NdisReadConfiguration(
+ &status,
+ &returnedValue,
+ configHandle,
+ &transceiverString,
+ NdisParameterHexInteger);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_REQ(("Error, can't read transceiver type from registry...using AUTO\n"));
+ adapter->TransceiverType = (CCHAR)4;
+ }
+ else
+ {
+ adapter->TransceiverType = (CCHAR)(returnedValue->ParameterData.IntegerData);
+ }
+
+ //
+ // Read the IoChannelReady Setting
+ //
+ NdisReadConfiguration(
+ &status,
+ &returnedValue,
+ configHandle,
+ &IoChannelReadyString,
+ NdisParameterHexInteger);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_REQ(("Error, can't read transceiver type from registry...using AUTO\n"));
+ adapter->IoChannelReady = (CCHAR)4; // auto-detect is default
+ }
+ else
+ {
+ adapter->IoChannelReady = (CCHAR)(returnedValue->ParameterData.IntegerData);
+ }
+
+ //
+ // See if a MAC address has been specified in the registry to
+ // override our hardware-set one.
+ //
+ {
+ UINT addrLen;
+ PUCHAR netAddr;
+ NDIS_STATUS status;
+
+ //
+ // attempt to read the network address
+ //
+ NdisReadNetworkAddress(
+ &status,
+ &netAddr,
+ &addrLen,
+ configHandle);
+
+ // did the operation succeed?
+ //
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ adapter->UseDefaultAddress = FALSE;
+
+ // yes: use this address.
+ //
+ NdisMoveMemory(
+ &adapter->CurrentIndividualAddress,
+ netAddr,
+ EPRO_LENGTH_OF_ADDRESS);
+ }
+ else
+ {
+ // just use the one out of the eeprom
+ adapter->UseDefaultAddress = TRUE;
+ }
+ }
+
+
+ // Close the configuration file...
+ //
+ NdisCloseConfiguration(configHandle);
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+NDIS_STATUS EProInitialReset(PEPRO_ADAPTER adapter)
+/*++
+
+ Routine Description:
+
+ This call really does two things: first, it calls
+ EProHWInitialize to set up the hardware, and then it
+ registers the card's interrupt and starts the card going.
+
+ Arguments:
+
+ adapter - pointer to our adapter structure...
+
+ Return Values:
+
+--*/
+{
+ NDIS_STATUS status;
+
+ status = EProHWInitialize(adapter);
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_INIT(("FAILED in EProHWInitialize.\n"));
+ return(status);
+ }
+
+ switch (adapter->IoChannelReady)
+ {
+ case EPRO_IOCHRDY_EARLY:
+ EPRO_DPRINTF_INIT(("EPro configured for EARLY IoChannelReady\n"));
+ break;
+
+ case EPRO_IOCHRDY_LATE:
+ EPRO_DPRINTF_INIT(("EPro configured for LATE IoChannelReady\n"));
+ break;
+
+ case EPRO_IOCHRDY_NEVER:
+ // They've set this in the cpanel - force 8 bits
+ //
+ EPRO_DPRINTF_INIT(("EPro configured for NEVER IoChannelReady\n"));
+ adapter->Use8Bit = TRUE;
+ break;
+
+ case EPRO_IOCHRDY_AUTO:
+ default:
+
+ EPRO_DPRINTF_INIT(("EPro configured for AUTO IoChannelReady\n"));
+
+ if (adapter->EProStepping < 4) //RM: don't do rev 4
+ {
+ if (!EProAltIOCHRDYTest(adapter))
+ {
+ EPRO_DPRINTF_INIT(("EPro failed the IOCHRDY test. Forcing 8-bit operation\n"));
+
+ // configure for 8-bit operation
+ //
+ EPRO_DPRINTF_INIT(("EPro configured for NEVER IoChannelReady\n"));
+ adapter->Use8Bit = TRUE;
+ }
+ }
+ break;
+ }
+
+ return(status);
+}
+
+NDIS_STATUS
+EProHWInitialize(
+ IN PEPRO_ADAPTER adapter
+ )
+/*++
+
+ Routine Description:
+
+ Now we start dealing with the card. Probe and verify its
+ existence, try to power it up if necessary, init it, etc.
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ Return Values:
+
+--*/
+{
+ UCHAR buf[4], fExecDone, result, intReg;
+ UINT i;
+
+ // Make sure we're in bank 0
+ //
+ EPRO_SWITCH_BANK_0(adapter);
+
+ for (i = 0; i < 4; i++)
+ {
+ EPRO_RD_PORT_UCHAR(adapter, I82595_ID_REG, &buf[i]);
+ }
+
+ if (!EProVerifyRoundRobin(buf))
+ {
+ //
+ // hmm, didn't find the board. Try powering it up, then try again.
+ // It's concievable that the board was in its "powered down" state
+ // and so we try the powerup procedure as a last-ditch effort.
+ //
+ EPRO_DPRINTF_INIT(("Initial probe failing. Attempting to power board up.\n"));
+ if (!EProPowerupBoard(adapter))
+ {
+ EPRO_DPRINTF_INIT(("Couldn't power board up. Can't find board.\n"));
+ return(NDIS_STATUS_HARD_ERRORS);
+ }
+ }
+
+ // Do a full reset.
+ //
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_FULL_RESET);
+
+ // poll for the card to be done it's init sequence.
+ //
+ for (i = 0; i < 10000; i++)
+ {
+ EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &intReg);
+
+ if (intReg & I82595_EXEC_INT_RCVD)
+ break;
+
+ NdisStallExecution(10);
+ }
+
+ if (i >= 10000)
+ {
+ EPRO_DPRINTF_INIT(("EPRO: Did NOT get return from init....\n"));
+ return(NDIS_STATUS_SOFT_ERRORS);
+ }
+
+
+ // According to the docs, writing a _1_ to the execution int bit
+ // clears it -- so we can just overwrite it to clear it.
+ //
+ EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG, intReg);
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+NDIS_STATUS
+EProHWConfigure(
+ IN PEPRO_ADAPTER adapter
+ )
+/*++
+
+ Routine Description:
+
+ The second half of the init -- now the hardware has just been
+ told to reset. Wait for the reset to finish, then configure
+ the board...
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ Return Values:
+
+--*/
+{
+ UCHAR result, intReg;
+ NDIS_STATUS status;
+ UINT i;
+ UCHAR intMask;
+
+ EPRO_DPRINTF_INIT(("EPRO: In EProHWConfigure\n"));
+
+ //
+ // Configure the adapter
+ //
+ EPRO_SWITCH_BANK_0(adapter);
+
+ //
+ // These two lines are a blatant hack to get around some timing
+ // problems I was having in the init sequence.
+ //
+ EPRO_RD_PORT_UCHAR(adapter, I82595_CMD_REG, &result);
+ NdisStallExecution(1000);
+
+ if (!EProWaitForExeDma(adapter))
+ {
+ return(NDIS_STATUS_HARD_ERRORS);
+ }
+
+ // Set the 82595's config registers up for the driver.
+ // RM: Moved this up here so we have the chip version upfront.
+
+ //
+ // Switch to bank2 for configuration
+ //
+ EPRO_SWITCH_BANK_2(adapter);
+
+ //
+ // Get 82595 chip version.
+ //
+ EPRO_RD_PORT_UCHAR(adapter, I82595_STEPPING_REG, &result);
+ adapter->EProStepping = (result >> I82595_STEPPING_OFFSET);
+
+ EPRO_DPRINTF_INIT(("This is a level %x 82595\n", adapter->EProStepping));
+
+ if (adapter->EProStepping < 2)
+ {
+ adapter->EProUse32BitIO = FALSE;
+ EPRO_DPRINTF_INIT(("NOT using 32-bit I/O port.\n"));
+ }
+ else if (adapter->EProStepping > 4) //RM: included rev 4
+ {
+ //
+ // We don't support this step of the adapter!
+ //
+ EPRO_DPRINTF_INIT(("Do not support step %u epro's\n", adapter->EProStepping));
+ return(NDIS_STATUS_HARD_ERRORS);
+ }
+ else
+ {
+ //
+ // Step is 2, 3 or 4.
+ //
+ adapter->EProUse32BitIO = TRUE;
+ EPRO_DPRINTF_INIT(("using 32-bit I/O port.\n"));
+ }
+
+ //
+ // Set configuration register 1 in bank 2
+ //
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CONFIG1_REG, EPRO_CONFIG_1);
+
+ //
+ // Set the transceiver type...
+ //
+ EPRO_DPRINTF_INIT(("EPRO: Transceiver type is 0x%x\n",
+ adapter->TransceiverType));
+
+ switch (adapter->TransceiverType)
+ {
+ case 1:
+ result = EPRO_CONFIG_3_AUI;
+ break;
+
+ case 2:
+ result = EPRO_CONFIG_3_BNC;
+ break;
+
+ case 3:
+ result = EPRO_CONFIG_3_TPE;
+ break;
+
+ case 4:
+ default:
+ result = EPRO_CONFIG_3_AUTO;
+ break;
+ }
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CONFIG2_REG, EPRO_CONFIG_2);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CONFIG3_REG, result);
+
+ //
+ // Switch to Bank1
+ //
+ EPRO_SWITCH_BANK_1(adapter);
+
+ if (adapter->EProStepping < 4) //Alt Ready timing reg n/a in rev 4 --
+ // included in EEPROM for back-compat only
+ {
+
+ //
+ // Configure the card's IOCHRDY setting if we're forcing it
+ //
+ if (adapter->IoChannelReady == EPRO_IOCHRDY_EARLY)
+ {
+ //
+ // force EARLY (alternate) timing
+ //
+ EPRO_RD_PORT_UCHAR(adapter, I82595_ALT_RDY_REG, &result);
+ result |= I82595_ALT_IOCHRDY;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_ALT_RDY_REG, result);
+ }
+
+ //
+ // Configure the card's IOCHRDY setting if we're forcing it
+ //
+ if (adapter->IoChannelReady == EPRO_IOCHRDY_LATE)
+ {
+ //
+ // Force LATE (isa compatible) timing
+ //
+ EPRO_RD_PORT_UCHAR(adapter, I82595_ALT_RDY_REG, &result);
+ result &= ~I82595_ALT_IOCHRDY;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_ALT_RDY_REG, result);
+ }
+ }
+ //
+ // Do we have to use 8-bit?
+ //
+ if (adapter->Use8Bit)
+ {
+ EPRO_DPRINTF_INIT(("Using 8 bits\n"));
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_ALT_RDY_REG, &result);
+ result &= ~I82595_USE_8_BIT_FLAG;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_ALT_RDY_REG, result);
+ }
+
+ //
+ // Set the buffer limit registers...
+ //
+ EPRO_WR_PORT_UCHAR(adapter, I82595_TX_LOWER_LIMIT_REG, EPRO_TX_LOWER_LIMIT);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_TX_UPPER_LIMIT_REG, EPRO_TX_UPPER_LIMIT);
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_RX_LOWER_LIMIT_REG, EPRO_RX_LOWER_LIMIT);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_RX_UPPER_LIMIT_REG, EPRO_RX_UPPER_LIMIT);
+
+ //
+ // Tell the card what Interrupt to use, default to 5. RM: Added check for V4.
+ // Default bad IRQs to 5 (mask 2 for all steppings).
+ //
+
+ switch (adapter->InterruptNumber)
+ {
+ case 3:
+ intMask = (adapter->EProStepping == 4)? 0x0 : 0x1;
+ break;
+
+ case 4:
+ intMask = (adapter->EProStepping == 4)? 0x1 : 0x2;
+ break;
+
+ case 5:
+ intMask = 0x2;
+ break;
+
+ case 7:
+ intMask = (adapter->EProStepping == 4)? 0x3 : 0x2;
+ break;
+
+ case 9:
+ //
+ // note that this is out of order - because the epro
+ // uses the 0 to indicate 2/9 (2 on an 8-bit bus in DOS mode
+ // and 9 otherwise...or something like that) Anyways, it is
+ // 9 under NT.
+ //
+ intMask = (adapter->EProStepping == 4)? 0x4 : 0x0;
+ break;
+
+ case 10:
+ intMask = (adapter->EProStepping == 4)? 0x5 : 0x3;
+ break;
+
+ case 11:
+ intMask = (adapter->EProStepping == 4)? 0x6 : 0x4;
+ break;
+
+ case 12:
+ intMask = (adapter->EProStepping == 4)? 0x7 : 0x2;
+ break;
+
+ default:
+
+ EPRO_DPRINTF_INIT(("EPRO: invalid interrupt selected using interrupt 5."));
+ intMask = 0x2;
+ break;
+ }
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_INT_SELECT_REG, &result);
+
+ result &= ~(I82595_INTERRUPT_SELECT_MASK);
+ result |= intMask;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_INT_SELECT_REG, result);
+
+ //
+ // Read the card's ethernet address out of the eeprom.
+ //
+ if (!EProCardReadEthernetAddress(adapter))
+ {
+ EPRO_DPRINTF_INIT(("EPRO: Could not read the EPro card's ethernet address.\n"));
+ return(NDIS_STATUS_SOFT_ERRORS);
+ }
+
+ if (adapter->UseDefaultAddress == TRUE)
+ {
+ //
+ // Copy the permanent address to the current address
+ //
+ NdisMoveMemory(
+ &adapter->CurrentIndividualAddress,
+ &adapter->PermanentIndividualAddress,
+ EPRO_LENGTH_OF_ADDRESS);
+ }
+
+ //
+ // Set the card's ethernet address to the one specified in
+ // adapter->current...
+ //
+ if (!EProSetEthernetAddress(adapter))
+ {
+ return(NDIS_STATUS_SOFT_ERRORS);
+ }
+
+ EPRO_SWITCH_BANK_1(adapter);
+
+ //
+ // flip the interrupt tri-state bit...
+ //
+ EPRO_RD_PORT_UCHAR(adapter, I82595_INTENABLE_REG, &result);
+ result|=I82595_ENABLE_INTS_FLAG;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_INTENABLE_REG, result);
+
+ EPRO_SWITCH_BANK_0(adapter);
+
+ if (!EProWaitForExeDma(adapter))
+ {
+ return(NDIS_STATUS_SOFT_ERRORS);
+ }
+
+ //
+ // bank0
+ //
+ EPRO_SWITCH_BANK_0(adapter);
+
+ //
+ // Set the interrupt mask...
+ //
+ adapter->CurrentInterruptMask = EPRO_DEFAULT_INTERRUPTS;
+
+ //
+ // Register the interrupt.
+ //
+ status = NdisMRegisterInterrupt(
+ &adapter->Interrupt,
+ adapter->MiniportAdapterHandle,
+ adapter->InterruptNumber,
+ adapter->InterruptNumber,
+ FALSE,
+ FALSE,
+ NdisInterruptLatched);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ EPRO_DPRINTF_INIT(("Register Interrupts FAILED\n"));
+ return(status);
+ }
+
+ //
+ // Enable interrupts...
+ //
+ EProEnableInterrupts((NDIS_HANDLE)adapter);
+
+ EProSelReset(adapter);
+
+ EPRO_DPRINTF_INIT(("EtherExpress Pro: configuration complete\n"));
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+BOOLEAN
+EProVerifyRoundRobin(
+ IN UCHAR *buf
+ )
+/*++
+
+ Routine Description:
+
+ This routine takes a sequence of 4 bytes passed in as the
+ result of 4 consecutive reads from the possible card's register
+ at address 2 (ie if base port is 0x300, 4 reads from 0x302) and
+ determines if the four constitute the EPro's ID signature. If they
+ do (epro identified) this returns TRUE, otherwise FALSE.
+
+ The 7th and 8th bits of these 4 should count 00 01 10 11 or some
+ permutation....
+
+ NOTE - if this code changes (because of chip updates, whatever) make
+ sure you change this function in the net-detection code (this function
+ is cut-and-pasted into detepro.c)
+
+ Arguments:
+
+ buf - a 4-byte character array with the four results in it...
+
+ Return Values:
+
+ TRUE if this is the 82595's signature
+ FALSE if it is not.
+
+--*/
+{
+ UCHAR ch;
+ int i, i1;
+
+ // Don't even bother. This works, take my word for it.
+ //
+ i1 = buf[0] >> 6;
+
+ for (i = 1; i < 4; i++)
+ {
+ i1 = (i1 > 2) ? 0 : i1 + 1;
+ if ((buf[i] >> 6) != i1)
+ {
+ return(FALSE);
+ }
+ }
+
+ return(TRUE);
+}
+
+BOOLEAN
+EProPowerupBoard(
+ IN PEPRO_ADAPTER adapter
+ )
+/*++
+
+ Routine Description:
+
+ The 82595 has a "powered down" state which could be why it didn't
+ respond correctly to the ID register probe.
+
+ Try the power up sequence. Return TRUE if the board responds
+ after the sequence, FALSE otherwise.
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ Return Values:
+
+ TRUE - if the board was found after the power up sequence
+ FALSE - if it was not
+
+--*/
+{
+ UCHAR buf[4];
+ UINT i;
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, 0);
+
+ // 32ms
+ //
+ NdisStallExecution(32000);
+
+ // Make sure we're in bank 0
+ //
+ EPRO_SWITCH_BANK_0(adapter);
+
+ for (i = 0; i < 4; i++)
+ {
+ EPRO_RD_PORT_UCHAR(adapter, I82595_ID_REG, &buf[i]);
+ }
+
+ return(EProVerifyRoundRobin(buf));
+}
+
+BOOLEAN
+EProCardReadEthernetAddress(
+ IN PEPRO_ADAPTER adapter
+ )
+{
+ USHORT data;
+
+ // EPRO_DPRINTF_INIT(("EProReadEthernetAddress\n"));
+
+#ifdef EPRO_DUMP_EEPROM
+ // Dump the eeprom...
+ {
+ USHORT i;
+
+ for (i = 0; i < 64; i++)
+ {
+ if ((i % 16) == 0)
+ {
+ DbgPrint("\n");
+ }
+
+ EProEERead(adapter, i, &data);
+ DbgPrint("%x ", data);
+ }
+
+ DbgPrint("\n");
+ }
+#endif
+
+ //
+ // Read the ethernet address out of the card. Also swap endian
+ // as you do it...
+ //
+ EProEERead(adapter, EPRO_ETHERNET_ADDR_H, &data);
+ adapter->PermanentIndividualAddress[4] = (UCHAR)(data >> 8);
+ adapter->PermanentIndividualAddress[5] = (UCHAR)(data & 0x00ff);
+
+ EProEERead(adapter, EPRO_ETHERNET_ADDR_M, &data);
+ adapter->PermanentIndividualAddress[2] = (UCHAR)(data >> 8);
+ adapter->PermanentIndividualAddress[3] = (UCHAR)(data & 0x00ff);
+
+ EProEERead(adapter, EPRO_ETHERNET_ADDR_L, &data);
+ adapter->PermanentIndividualAddress[0] = (UCHAR)(data >> 8);
+ adapter->PermanentIndividualAddress[1] = (UCHAR)(data & 0x00ff);
+
+ EPRO_DPRINTF_INIT(("MAC address read: %x %x %x %x %x %x\n",
+ adapter->PermanentIndividualAddress[0],
+ adapter->PermanentIndividualAddress[1],
+ adapter->PermanentIndividualAddress[2],
+ adapter->PermanentIndividualAddress[3],
+ adapter->PermanentIndividualAddress[4],
+ adapter->PermanentIndividualAddress[5]));
+
+ return(TRUE);
+}
+
+
+BOOLEAN EProSetEthernetAddress(PEPRO_ADAPTER adapter)
+/*++
+
+ Routine Description:
+
+ The EPro's ethernet address is read out of the EEPROM by the driver
+ in EProReadEthernetAddress. It is stored by the driver in the
+ adapter->PermanentIndividualAddress array. This function takes the
+ address stored there (presumably set by ReadEthernetAddress) and
+ configures the board to use that address. It could also be used
+ to software-override the default ethernet address.
+
+ Note that the software does not support multiple IA addresses
+ (multiple non-multicast addresses) although the hardware does.
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ Return Value:
+
+ TRUE if the operation was successful
+ FALSE if it failed
+
+--*/
+{
+ UCHAR result;
+ UINT i = 0;
+
+// switch to bank2
+ EPRO_SWITCH_BANK_2(adapter);
+
+// write out the ethernet address. Make sure you write to reg 9 last:
+ EPRO_WR_PORT_UCHAR(adapter, I82595_IA_REG_0, adapter->PermanentIndividualAddress[0]);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_IA_REG_1, adapter->PermanentIndividualAddress[1]);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_IA_REG_2, adapter->PermanentIndividualAddress[2]);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_IA_REG_3, adapter->PermanentIndividualAddress[3]);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_IA_REG_4, adapter->PermanentIndividualAddress[4]);
+
+// switch to bank0
+ EPRO_SWITCH_BANK_0(adapter);
+
+ if (!EProWaitForExeDma(adapter)) {
+ return(FALSE);
+ }
+
+// switch to bank2
+ EPRO_SWITCH_BANK_2(adapter);
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_IA_REG_5, adapter->PermanentIndividualAddress[5]);
+
+ return(TRUE);
+}
+
+BOOLEAN EProAltIOCHRDYTest(PEPRO_ADAPTER adapter)
+/*++
+
+ Routine Description:
+
+ Check the current IOCHRDY timing and see if it is compatible.
+ if not, see if it can be changed and made compatible
+ otherwise fail.
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ Return Values:
+
+ TRUE if the card can be configured properly to the way the machine
+ machine asserts the IOCHRDY line.
+
+ FALSE if the card could NOT be configured appropriately - the machine
+ is broken and we'll have to use 8-bit mode.
+
+--*/
+{
+ BOOLEAN testPending = TRUE, testResult, firstTime = TRUE;
+ UCHAR result;
+
+ // switch to bank 1
+ EPRO_SWITCH_BANK_1(adapter);
+
+ do
+ {
+ // Enter test mode...
+ EPRO_RD_PORT_UCHAR(adapter, I82595_IOCHRDY_TEST_REG, &result);
+ result |= I82595_IOCHRDY_TEST_FLAG;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_IOCHRDY_TEST_REG, result);
+
+ // Read from 0,1
+ EPRO_RD_PORT_UCHAR(adapter, I82595_CMD_REG, &result);
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_IOCHRDY_TEST_REG, &result);
+
+ if (result & I82595_IOCHRDY_PASS_FLAG)
+ {
+ testPending = FALSE;
+ testResult = TRUE;
+ }
+ else
+ {
+ // test failed
+ if (firstTime)
+ {
+ // try it again - flip the current IOCHRDY timing and try again.
+ firstTime = FALSE;
+ EPRO_RD_PORT_UCHAR(adapter, I82595_ALT_RDY_REG, &result);
+
+ // toggle alt-rdy bit
+ result = (result & I82595_ALT_RDY_FLAG)?
+ result & (~I82595_ALT_RDY_FLAG) :
+ result | I82595_ALT_RDY_FLAG;
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_ALT_RDY_REG, result);
+ }
+ else
+ {
+ // nope, failed twice, can't do it.
+ testPending = FALSE;
+ testResult = FALSE;
+ }
+ }
+ } while (testPending);
+
+ // turn the test off
+ EPRO_RD_PORT_UCHAR(adapter, I82595_IOCHRDY_TEST_REG, &result);
+ result &= ~I82595_IOCHRDY_TEST_FLAG;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_IOCHRDY_TEST_REG, result);
+
+ return(testResult);
+}
+
diff --git a/private/ntos/ndis/ieepro/makefile b/private/ntos/ndis/ieepro/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/ndis/ieepro/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 OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/ndis/ieepro/request.c b/private/ntos/ndis/ieepro/request.c
new file mode 100644
index 000000000..995b8c0f2
--- /dev/null
+++ b/private/ntos/ndis/ieepro/request.c
@@ -0,0 +1,989 @@
+#include <ndis.h>
+#include "82595.h"
+#include "eprohw.h"
+#include "eprosw.h"
+#include "epro.h"
+#include "eprodbg.h"
+
+static UINT EProSupportedOids[] = {
+ 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_MAXIMUM_LIST_SIZE,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_RCV_ERROR_ALIGNMENT,
+ OID_802_3_XMIT_ONE_COLLISION,
+ OID_802_3_XMIT_MORE_COLLISIONS
+};
+
+NDIS_STATUS EProQueryInformation(IN NDIS_HANDLE miniportAdapterContext,
+ IN NDIS_OID oid,
+ IN PVOID informationBuffer,
+ IN ULONG informationBufferLength,
+ OUT PULONG bytesWritten,
+ OUT PULONG bytesNeeded)
+/*++
+
+ Routine Description:
+
+ This is the query configuration handler for the EPro
+
+ Arguments:
+
+ miniportAdapterContext - really a pointer to our adapter structure
+
+ oid - the oid we are querying
+
+ informationBuffer - The buffer to copy the queried info into
+
+ informationLength - how much room is there in the buffer
+
+ bytesWritten - the number of bytes we actually wrote into
+ informationBuffer
+
+ bytesNeeded - only valid if we return not enough space error --
+ how much more space do we need to be able to give
+ you that data?
+
+ Return Values:
+
+ NDIS_STATUS_SUCCESS - operation successful
+ NDIS_STATUS_INALID_OID - invalid oid, or we don't support it
+ NDIS_STATUS_INVALID_LENGTH - not enough room in informationbuffer
+ see bytesNeeded for more info
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
+ UINT bytesToMove = 0;
+ PVOID moveSource = NULL;
+// since we can't transfer #define'd constants the way they want us to...
+ ULONG GenericUL;
+ USHORT GenericUS;
+ NDIS_STATUS statusToReturn = NDIS_STATUS_SUCCESS;
+
+ EPRO_DPRINTF_REQ(("EProQueryInformation. Oid = %lx\n", oid));
+
+// the oid's are documented in the DDK. See that for info on all of them
+ switch(oid) {
+ case OID_GEN_SUPPORTED_LIST:
+ EPRO_DPRINTF_REQ((" querying oid: OID_GEN_SUPPORTED_LIST\n"));
+ moveSource = &EProSupportedOids;
+ bytesToMove = sizeof(EProSupportedOids);
+ break;
+ case OID_GEN_HARDWARE_STATUS:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_HARDWARE_STATUS\n"));
+ moveSource = &adapter->CurrentHardwareStatus;
+ bytesToMove = sizeof(adapter->CurrentHardwareStatus);
+ break;
+ case OID_GEN_MEDIA_SUPPORTED:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MEDIA_SUPPORTED\n"));
+ GenericUL = EPRO_GEN_MEDIA_SUPPORTED;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_MEDIA_IN_USE:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MEDIA_IN_USE\n"));
+ GenericUL = EPRO_GEN_MEDIA_IN_USE;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MAXIMUM_LOOKAHEAD\n"));
+ GenericUL = EPRO_GEN_MAXIMUM_LOKAHEAD;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MAXIMUM_FRAME_SIZE\n"));
+ GenericUL = EPRO_GEN_MAXIMUM_FRAME_SIZE;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MAXIMUM_TOTAL_SIZE\n"));
+ GenericUL = EPRO_GEN_MAXIMUM_TOTAL_SIZE;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_MAC_OPTIONS:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_MAC_OPTIONS\n"));
+ GenericUL = EPRO_GEN_MAC_OPTIONS;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_PROTOCOL_OPTIONS:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_PROTOCOL_OPTIONS\n"));
+ moveSource = NULL;
+ bytesToMove = 0;
+ break;
+ case OID_GEN_LINK_SPEED:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_LINK_SPEED\n"));
+ GenericUL = EPRO_GEN_LINK_SPEED;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_TRANSMIT_BUFFER_SPACE\n"));
+ GenericUL = EPRO_GEN_TRANSMIT_BUFFER_SPACE;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RECEIVE_BUFFER_SPACE\n"));
+ GenericUL = EPRO_GEN_RECEIVE_BUFFER_SPACE;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_TRANSMIT_BLOCK_SIZE\n"));
+ GenericUL = EPRO_TX_BUF_SIZE;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(ULONG);
+ break;
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RECEIVE_BOCK_SIZE\n"));
+ GenericUL = EPRO_RX_BUF_SIZE;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(ULONG);
+ break;
+ case OID_GEN_VENDOR_ID:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_VENDOR_ID\n"));
+ moveSource = &adapter->vendorID;
+ bytesToMove = sizeof(adapter->vendorID);
+ break;
+ case OID_GEN_VENDOR_DESCRIPTION:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_VENDOR_DESCRIPTION\n"));
+ moveSource = EPRO_VENDOR_DESC;
+ bytesToMove = sizeof(EPRO_VENDOR_DESC);
+ break;
+ case OID_GEN_DRIVER_VERSION:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_DRIVER_VERSION\n"));
+ GenericUS = ((USHORT)EPRO_DRIVER_VER_MAJOR << 8) |
+ EPRO_DRIVER_VER_MINOR;
+ moveSource = &GenericUS;
+ bytesToMove = sizeof(GenericUS);
+ break;
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_CURRENT_PACKET_FILTER\n"));
+ moveSource = &adapter->CurrentPacketFilter;
+ bytesToMove = sizeof(adapter->CurrentPacketFilter);
+ break;
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_CURRENT_LOOKAHEAD\n"));
+ GenericUL = adapter->RXLookAheadSize;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_GEN_XMIT_OK:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_XMIT_OK\n"));
+ moveSource = &adapter->FramesXmitOK;
+ bytesToMove = sizeof(adapter->FramesXmitOK);
+ break;
+ case OID_GEN_RCV_OK:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RCV_OK\n"));
+ moveSource = &adapter->FramesRcvOK;
+ bytesToMove = sizeof(adapter->FramesRcvOK);
+ break;
+ case OID_GEN_XMIT_ERROR:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_XMIT_ERROR\n"));
+ moveSource = &adapter->FramesXmitErr;
+ bytesToMove = sizeof(adapter->FramesXmitErr);
+ break;
+ case OID_GEN_RCV_ERROR:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RCV_ERROR\n"));
+ moveSource = &adapter->FramesRcvErr;
+ bytesToMove = sizeof(adapter->FramesRcvErr);
+ break;
+ case OID_GEN_RCV_NO_BUFFER:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_GEN_RCV_NO_BUFFER\n"));
+ moveSource = &adapter->FramesMissed;
+ bytesToMove = sizeof(adapter->FramesMissed);
+ break;
+ case OID_802_3_PERMANENT_ADDRESS:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_PERMANENT_ADDRESS\n"));
+ moveSource = &adapter->PermanentIndividualAddress;
+ bytesToMove = sizeof(adapter->PermanentIndividualAddress);
+ break;
+ case OID_802_3_CURRENT_ADDRESS:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_CURRENT_ADDRESS\n"));
+ moveSource = &adapter->CurrentIndividualAddress;
+ bytesToMove = sizeof(adapter->CurrentIndividualAddress);
+ break;
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ EPRO_DPRINTF_REQ(("Querying Maximum Multicast List Size....\n"));
+ GenericUL = EPRO_MAX_MULTICAST;
+ moveSource = &GenericUL;
+ bytesToMove = sizeof(GenericUL);
+ break;
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_RCV_ERROR_ALIGNMENT\n"));
+ moveSource = &adapter->FrameAlignmentErrors;
+ bytesToMove = sizeof(adapter->FrameAlignmentErrors);
+ break;
+ case OID_802_3_XMIT_ONE_COLLISION:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_XMIT_ONE_COLLISION\n"));
+ moveSource = &adapter->FramesXmitOneCollision;
+ bytesToMove = sizeof(adapter->FramesXmitOneCollision);
+ break;
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ EPRO_DPRINTF_REQ(("Querying oid - OID_802_3_XMIT_MORE_COLLISION\n"));
+ moveSource = &adapter->FramesXmitManyCollisions;
+ bytesToMove = sizeof(adapter->FramesXmitManyCollisions);
+ break;
+ default:
+ EPRO_DPRINTF_REQ(("Invalid Oid in Query.\n"));
+ EPRO_DPRINTF_REQ(("iq"));
+ statusToReturn = NDIS_STATUS_INVALID_OID;
+ }
+
+ if (statusToReturn == NDIS_STATUS_SUCCESS) {
+ if (bytesToMove > informationBufferLength) {
+ *bytesNeeded = bytesToMove;
+ statusToReturn = NDIS_STATUS_INVALID_LENGTH;
+ EPRO_DPRINTF_REQ(("Invalid Length in Query\n"));
+ } else {
+ NdisMoveMemory(informationBuffer, moveSource, bytesToMove);
+ (*bytesWritten)+=bytesToMove;
+ }
+ }
+
+ EPRO_DPRINTF_REQ(("EProQueryInfo - Done\n"));
+
+ EPRO_DPRINTF_REQ(("returning: 0x%lx\n", statusToReturn));
+ return(statusToReturn);
+}
+
+NDIS_STATUS EProSetInformation(IN NDIS_HANDLE miniportAdapterContext,
+ IN NDIS_OID oid,
+ IN PVOID informationBuffer,
+ IN ULONG informationLength,
+ OUT PULONG bytesRead,
+ OUT PULONG bytesNeeded)
+/*++
+
+ Routine Description:
+
+ This is the MiniportSetInformation Handler for the EPro driver
+
+ Arguments:
+
+ miniportAdapterContext - really a pointer to our adapter structure
+
+ oid - the oid to set
+
+ informationBuffer - the buffer which contains the information we need
+ to carry out the set
+
+ informationLength - the length of the informationBuffer's data
+
+ bytesRead - how many bytes did we actually read out of informationBuffer
+
+ bytesNeeded - if we failed -- how many bytes do we need to complete
+ the call?
+
+ Return Values:
+
+ NDIS_STATUS_SUCCESS - set completed OK
+ NDIS_STATUS_NOT_ACCEPTED - too many MC addresses set
+ NDIS_STATUS_INVALID_DATA - tried to set MC list, buf inf. buffer not
+ an integral multiple of 6 (len of 802_3 address)
+ NDIS_STATUS_PENDING - set PENDED (completed in EProHandleInterrupt)
+ NDIS_STATUS_INVALID_OID - the oid was bad, or we don't support it.
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
+ NDIS_STATUS statusToReturn = NDIS_STATUS_SUCCESS;
+ ULONG genericUL;
+ BOOLEAN fReturn;
+
+ EPRO_DPRINTF_REQ(("EProSetInformation. Oid = %lx\n", oid));
+
+ switch(oid)
+ {
+ case OID_802_3_MULTICAST_LIST:
+ EPRO_DPRINTF_REQ(("setting: OID_802_3_MULTICAST_LIST\n"));
+
+ if (informationLength % EPRO_LENGTH_OF_ADDRESS != 0)
+ {
+ *bytesNeeded = EPRO_LENGTH_OF_ADDRESS;
+ EPRO_DPRINTF_REQ(("INVALID data length...\n"));
+ return(NDIS_STATUS_INVALID_DATA);
+ }
+
+ if ((informationLength / EPRO_LENGTH_OF_ADDRESS) > EPRO_MAX_MULTICAST)
+ {
+ EPRO_DPRINTF_REQ(("Attempted to set too many multicasts....\n"));
+ return(NDIS_STATUS_NOT_ACCEPTED);
+ }
+
+ *bytesRead = informationLength;
+ *bytesNeeded = 0;
+
+ //
+ // If they are trying to clear the multicast list and none
+ // have been set then we are done!
+ //
+ if ((0 == (informationLength / EPRO_LENGTH_OF_ADDRESS)) &&
+ (0 == adapter->NumMCAddresses))
+ {
+ return(NDIS_STATUS_SUCCESS);
+ }
+
+ fReturn = EProChangeMulticastList(
+ adapter,
+ informationLength / EPRO_LENGTH_OF_ADDRESS,
+ informationBuffer);
+ if (adapter->fMulticastEnable)
+ {
+ BOOLEAN fReturnStatus;
+
+ fReturnStatus = EProSetCardMulticastList(
+ adapter,
+ (fReturn) ? EPRO_CLEAR_CARD_MC : EPRO_SET_CARD_MC);
+ if (!fReturnStatus)
+ {
+ statusToReturn = NDIS_STATUS_NOT_ACCEPTED;
+ }
+ else
+ {
+ statusToReturn = NDIS_STATUS_PENDING;
+ }
+ }
+
+ break;
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ EPRO_DPRINTF_REQ(("setting: OID_GEN_CURRENT_PACKET_FILTER\n"));
+ if (informationLength < 4)
+ {
+ EPRO_DPRINTF_REQ(("INVALID data length...\n"));
+ return(NDIS_STATUS_INVALID_LENGTH);
+ }
+
+ NdisMoveMemory(&genericUL, informationBuffer, sizeof(ULONG));
+
+ *bytesRead = sizeof(ULONG);
+ *bytesNeeded = 0;
+ statusToReturn = EProSetPacketFilter(adapter, genericUL);
+
+ break;
+
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ if (informationLength < 4)
+ {
+ return(NDIS_STATUS_INVALID_LENGTH);
+ }
+
+ EPRO_DPRINTF_REQ(("EPRO: Attempting to set lookahead size\n"));
+
+ NdisMoveMemory(&genericUL, informationBuffer, sizeof(ULONG));
+
+ *bytesRead = sizeof(ULONG);
+ *bytesNeeded = 0;
+
+ if (genericUL <= EPRO_GEN_MAXIMUM_LOKAHEAD)
+ {
+ EPRO_DPRINTF_REQ(("EPRO: Current lookahead is now %d bytes\n", adapter->RXLookAheadSize));
+ adapter->RXLookAheadSize = (USHORT)genericUL;
+ statusToReturn = NDIS_STATUS_SUCCESS;
+ }
+ else
+ {
+ statusToReturn = NDIS_STATUS_FAILURE;
+ }
+ break;
+
+ default:
+ EPRO_DPRINTF_REQ(("Invalid oid in setinformation\n"));
+ EPRO_DPRINTF_REQ(("inv"));
+ statusToReturn = NDIS_STATUS_INVALID_OID;
+ }
+
+ return(statusToReturn);
+}
+
+NDIS_STATUS EProSetPacketFilter(PEPRO_ADAPTER adapter, ULONG newFilter)
+/*++
+
+ Routine Description:
+
+ This routine, invoked from EProSetInformation, is called to do the
+ real work of setting a packet filter.
+
+ Arguments:
+
+ Return Values:
+
+--*/
+{
+ // reg2flags are the flags currently set in the configuration register in
+ // bank2 (bank 2, reg 2). This is used when we twiddle with the bank
+ //
+ UCHAR reg2Flags = 0, result;
+
+ // Do we need to update the CONFIG registers in bank2? (iff broadcast or
+ // promiscuous setting are changed only) If so, then we will need to do
+ // a synchronized call, and also a reset...
+ //
+ BOOLEAN fUpdateConfig = FALSE;
+ ULONG oldFilter;
+
+ NDIS_STATUS Status;
+
+ EPRO_DPRINTF_REQ(("SetPacketFilter: %lx", newFilter));
+
+ //
+ // Validate the new packet filter that was passed in to be set.
+ //
+ if (newFilter & ~(NDIS_PACKET_TYPE_DIRECTED |
+ NDIS_PACKET_TYPE_PROMISCUOUS |
+ NDIS_PACKET_TYPE_BROADCAST |
+ //NDIS_PACKET_TYPE_ALL_MULTICAST |
+ NDIS_PACKET_TYPE_MULTICAST))
+ {
+ EPRO_DPRINTF_REQ(("PacketFilter NOT SUPPORTED!\n"));
+ EPRO_DPRINTF_REQ(("Not Supported\n"));
+
+ return(NDIS_STATUS_NOT_SUPPORTED);
+ }
+
+ //
+ // Save the new packet filter.
+ //
+ oldFilter = adapter->CurrentPacketFilter;
+ adapter->CurrentPacketFilter = newFilter;
+
+
+ //
+ // Ooh, here's a good hardware weirdness. If you issue the rcv enable
+ // command to the 82595tx when it is already in receive-enable mode,
+ // it munges the next received packet. no joke. So we always
+ // temporarily disable receives here.
+ //
+ EProReceiveDisable(adapter);
+
+ EPRO_DPRINTF_REQ(("Setting filter...\n"));
+
+ Status = NDIS_STATUS_SUCCESS;
+
+ do
+ {
+ //
+ // Now, if we've modified the PROMISCUOUS or BROADCAST
+ // settings, we have to re-configure the card....
+ //
+ if (((oldFilter & NDIS_PACKET_TYPE_PROMISCUOUS) ^ (newFilter & NDIS_PACKET_TYPE_PROMISCUOUS)) ||
+ ((oldFilter & NDIS_PACKET_TYPE_BROADCAST) ^ (newFilter & NDIS_PACKET_TYPE_BROADCAST)))
+ {
+ //
+ // Are we supposed to set or clear the promiscuous bit?
+ //
+ if (newFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
+ {
+ EPRO_DPRINTF_REQ(("Promiscuous mode set...\n"));
+
+ adapter->fPromiscuousEnable = TRUE;
+ reg2Flags |= I82595_PROMISCUOUS_FLAG;
+ }
+ else
+ {
+ //
+ // Promiscuous mode bit NOT set - do we need to turn it off?
+ //
+ adapter->fPromiscuousEnable = FALSE;
+ }
+
+ //
+ // Are we supposed to set or clear the broadcast bit?
+ //
+ if (newFilter & NDIS_PACKET_TYPE_BROADCAST)
+ {
+ adapter->fBroadcastEnable = TRUE;
+ }
+ else
+ {
+ adapter->fBroadcastEnable = FALSE;
+ reg2Flags |= I82595_NO_BROADCAST_FLAG;
+ }
+
+ //
+ // okay, we're going to have to modify the config, so we better stop
+ // receives to get ready for the reset...
+
+ // Okay, we're going to have to modify the configuration...
+ // So wait for any receives or sends to finish so the card is
+ // idle...
+ //
+ if (!EProWaitForExeDma(adapter))
+ {
+ EPRO_DPRINTF_RX(("FAILURE waiting for exedma....\n"));
+ Status = NDIS_STATUS_NOT_ACCEPTED;
+ break;
+ }
+
+ //
+ // This gets expanded to a Sync (synchronizedwithinterrupt) call --
+ // since it changes banks, it can NOT happen at the same time as the
+ // ISR (which requires bank0)
+ //
+ EProBroadcastPromiscuousChange(adapter, reg2Flags);
+
+ //
+ // Okay, make sure the card is idle again before we enable receives...
+ //
+ if (!EProWaitForExeDma(adapter))
+ {
+ adapter->fHung = TRUE;
+ return(NDIS_STATUS_HARD_ERRORS);
+// EPRO_ASSERT(FALSE);
+ }
+ }
+
+ //
+ // Enable receives.
+ //
+ EProReceiveEnable(adapter);
+
+ //
+ // Has the multicast bit changed?
+ //
+ if ((oldFilter & NDIS_PACKET_TYPE_MULTICAST) ^
+ (newFilter & NDIS_PACKET_TYPE_MULTICAST))
+ {
+ //
+ // Was the bit set or turned off?
+ //
+ if (newFilter & NDIS_PACKET_TYPE_MULTICAST)
+ {
+ adapter->fMulticastEnable = TRUE;
+
+ //
+ // If there are no multicast addresses to set then we are done.
+ //
+ if (0 == adapter->NumMCAddresses)
+ {
+ Status = NDIS_STATUS_SUCCESS;
+ break;
+ }
+
+ //
+ // Set the multicast addresses to the card.
+ //
+ if (!EProSetCardMulticastList(adapter, EPRO_SET_CARD_MC))
+ {
+ EPRO_DPRINTF_REQ(("ERROR setting multicastlist on card\n"));
+ return(NDIS_STATUS_NOT_ACCEPTED);
+ }
+ else
+ {
+ Status = NDIS_STATUS_PENDING;
+ break;
+ }
+ }
+ else
+ {
+ //
+ // If they haven't set the MC bit, we check to see if we think
+ // it is on and turn it off if need be...
+ //
+ adapter->fMulticastEnable = FALSE;
+
+ //
+ // If there are no multicast addresses set on the card
+ // the we are done.
+ //
+ if (0 == adapter->NumMCAddresses)
+ {
+ Status = NDIS_STATUS_SUCCESS;
+ break;
+ }
+
+ //
+ // Clear any multicast addresses that are currently on the
+ // adapter.
+ //
+ if (!EProSetCardMulticastList(adapter, EPRO_CLEAR_CARD_MC))
+ {
+ EPRO_DPRINTF_REQ(("ERROR setting Multicast List on card...\n"));
+
+ Status = NDIS_STATUS_NOT_ACCEPTED;
+ break;
+ }
+ else
+ {
+ Status = NDIS_STATUS_PENDING;
+ break;
+ }
+ }
+ }
+
+
+ } while (FALSE);
+
+
+
+ //
+ // if the filter = 0, then we are leaving with receives disabled
+ //
+ if (0 == newFilter)
+ {
+ //
+ // Make sure that
+ //
+ EProReceiveDisable(adapter);
+ adapter->CurrentPacketFilter = newFilter;
+ return(NDIS_STATUS_SUCCESS);
+ }
+
+ // This is probably a NOTREACHED...
+
+ return(NDIS_STATUS_SUCCESS);
+
+}
+
+BOOLEAN EProSyncBroadcastPromiscuousChange(PVOID context)
+/*++
+
+ Routine Description:
+
+ This routine is called by a macro expansion of the function
+ EProBroadcastPromiscuousChange -- the macro expands that call to
+ a NdisMSynchronizeWithInterrupt call to this function. This function
+ CANNOT BE CALLED DIRECTLY WHERE THERE IS A CHANCE IT CAN RUN CONCURRENTLY
+ WITH EProDisableInterrupts. Very Bad Things will happen if the two run
+ concurrently (only on an MP machine - on a UP machine, the syncwithint
+ call can be avoided - but alas we don't have the luxury of having
+ seperate binaries for each...
+
+ Arguments:
+
+ context - a EPRO_BRDPROM_CONTEXT which is basically just a strucutre
+ holding all the parameters to the EProBroadcastPromiscuousChange
+ macro (adapter structure pointer and reg2flags settings)
+
+ Return Values:
+
+ always TRUE...
+
+--*/
+{
+ PEPRO_ADAPTER adapter = ((PEPRO_BRDPROM_CONTEXT)context)->Adapter;
+ UCHAR reg2flags = ((PEPRO_BRDPROM_CONTEXT)context)->Reg2Flags;
+ UCHAR result;
+
+ EPRO_SWITCH_BANK_2(adapter);
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_CONFIG2_REG, &result);
+ result &= ~(I82595_PROMISCUOUS_FLAG | I82595_NO_BROADCAST_FLAG);
+ result |= reg2flags;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CONFIG2_REG, result);
+
+ // according to the docs, the configure is triggered by a write to reg 3, so we just
+ // read and write to it...
+ //
+ EPRO_RD_PORT_UCHAR(adapter, I82595_CONFIG3_REG, &result);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CONFIG3_REG, result);
+
+ // Probably don't need this (82595 is supposed to default to bank0 after
+ // a reset or sel-reset
+ //
+ EPRO_SWITCH_BANK_0(adapter);
+
+ // need to do a selreset after a config register modification
+ // per 82595 docs...
+ //
+ EProSelReset(adapter);
+
+ EPRO_ASSERT_BANK_0(adapter);
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+EProChangeMulticastList(
+ IN PEPRO_ADAPTER adapter,
+ IN UINT addressCount,
+ IN UCHAR addresses[][EPRO_LENGTH_OF_ADDRESS])
+/*++
+
+ Routine Description:
+
+ This routine changed the multicast list as stored by the driver.
+ IT DOES NOT ACTUALLY MODIFY THE MULTICAST LIST IN THE HARDWARE ---
+ EProSetCardMulticastList does that.
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ addressCount - how many addresses to set
+
+ addresses[] - the data...
+
+ Return Values:
+
+ NDIS_STATUS_NOT_ACCEPTED - tried to set too many (notreached b/c
+ setpacketfilter checks this too)
+ NDIS_STATUS_SUCCESS - operation completed ok.
+
+--*/
+{
+ UINT i;
+ BOOLEAN fReturn = FALSE;
+
+ EPRO_DPRINTF_REQ(("EProChangeMulticastList. Setting %d addresses...\n",
+ addressCount));
+
+ // now, put the multicast list into the adapter structure...
+ //
+ for (i = 0; i < addressCount; i++)
+ {
+ NdisMoveMemory(
+ &adapter->MCAddress[i],
+ &addresses[i],
+ EPRO_LENGTH_OF_ADDRESS);
+ }
+
+ //
+ // If we just cleared the multicast address list then we need to
+ // return the fact.
+ //
+ if ((adapter->NumMCAddresses != 0) && (0 == addressCount))
+ {
+ fReturn = TRUE;
+ }
+
+ //
+ // Save the new number of multicast addresses.
+ //
+ adapter->NumMCAddresses = addressCount;
+
+ return(fReturn);
+}
+
+
+BOOLEAN EProSetCardMulticastList(PEPRO_ADAPTER adapter, int operation)
+/*++
+
+ Routine Description:
+
+ This is the routine which takes the driver's MC list and copies it down
+ to the card. The MC list must already be set in the driver with
+ EProChangeMulticastList.
+
+ Arguments:
+
+ adapter - pointer to our adapter structure
+
+ operation - see epro.h for the definitions. Basically SET or CLEAR
+ either we are turning off MC or re-entering the list.
+
+ Return Values:
+
+ TRUE - MC list set okay and has been PENDED (completed in EProHandleInterrupt)
+ FALSE - MC list didn't set okay and was not pended
+
+--*/
+{
+ // The header for the MC_SETUP structure
+ EPRO_MC_HEADER mcHead;
+
+ // Setting the MC list uses a transmit buffer.
+ PEPRO_TRANSMIT_BUFFER curTBuf = adapter->CurrentTXBuf;
+
+ // look variable...
+ BOOLEAN fGotBuffer = FALSE;
+
+ USHORT lengthNeeded = I82595_TX_FRM_HDR_SIZE +
+ (adapter->NumMCAddresses * EPRO_LENGTH_OF_ADDRESS) + 2;
+ USHORT timeout = 0;
+
+ EPRO_ASSERT_BANK_0(adapter);
+ EPRO_DPRINTF_REQ(("Setting the MC list on the card...%d\n", operation));
+
+ // Make sure we have a free buffer pointer structure.
+ //
+ if (!curTBuf->fEmpty)
+ {
+ while (!EProCheckTransmitCompletion(adapter, curTBuf))
+ {
+ timeout++;
+
+ if (timeout > EPRO_TX_TIMEOUT)
+ {
+ return(FALSE);
+ }
+
+ NdisStallExecution(1);
+ }
+ }
+
+ // Is there a transmit in progress? If not, then we can just
+ // set the buffer to address zero and go
+ //
+ if (adapter->TXChainStart == NULL)
+ {
+ curTBuf->TXBaseAddr = EPRO_TX_LOWER_LIMIT_SHORT;
+ }
+ else
+ {
+ // Okay, there is a transmit in progress. Let's see if there is enough
+ // transmit buffer space.
+ //
+ USHORT freeSpace = 0;
+
+ // are we above the free space?
+ //
+ if (adapter->TXChainStart->TXBaseAddr < curTBuf->TXBaseAddr)
+ {
+ freeSpace = EPRO_TX_UPPER_LIMIT_SHORT - curTBuf->TXBaseAddr;
+ freeSpace += adapter->TXChainStart->TXBaseAddr -
+ EPRO_TX_LOWER_LIMIT_SHORT;
+ }
+ else
+ {
+ freeSpace = adapter->TXChainStart->TXBaseAddr -
+ curTBuf->TXBaseAddr;
+ }
+
+
+ while (freeSpace < lengthNeeded)
+ {
+ UINT timeout1;
+
+ while (!EProCheckTransmitCompletion(adapter, adapter->TXChainStart))
+ {
+ if (timeout1++ > EPRO_TX_TIMEOUT)
+ {
+ return(FALSE);
+ }
+
+ NdisStallExecution(1);
+ }
+
+ if (adapter->TXChainStart->TXBaseAddr < curTBuf->TXBaseAddr)
+ {
+ freeSpace = EPRO_TX_UPPER_LIMIT_SHORT - curTBuf->TXBaseAddr;
+ freeSpace += adapter->TXChainStart->TXBaseAddr -
+ EPRO_TX_LOWER_LIMIT_SHORT;
+ }
+ else
+ {
+ freeSpace = adapter->TXChainStart->TXBaseAddr -
+ curTBuf->TXBaseAddr;
+ }
+ }
+ }
+
+ //
+ // Okay, now we have to make sure we've got enough space to actually
+ // put the data in the transmit area...
+ //
+
+ // Now we've got a buffer....
+ //
+ EPRO_ASSERT(curTBuf->fEmpty);
+
+ mcHead.CommandField = I82595_CMD_MC_SETUP;
+
+ // Clear the header
+ //
+ NdisZeroMemory(mcHead.NullBytes, 5);
+
+ // Okay, are we setting or clearing? If we're clearing then the byte count
+ // is 0, if we're setting, then its a function of the number of addresses...
+ //
+ if (operation != EPRO_CLEAR_CARD_MC)
+ {
+ mcHead.ByteCountLo = (adapter->NumMCAddresses * EPRO_LENGTH_OF_ADDRESS) & 0xff;
+ mcHead.ByteCountHi = (adapter->NumMCAddresses * EPRO_LENGTH_OF_ADDRESS) >> 8;
+ }
+ else
+ {
+ mcHead.ByteCountLo = 0;
+ mcHead.ByteCountHi = 0;
+ }
+
+ EPRO_DPRINTF_REQ(("There are %d MC addresses.\n", adapter->NumMCAddresses));
+ EPRO_DPRINTF_REQ(("There are %x%x bytes of MC addresses at %lx\n", mcHead.ByteCountHi,
+ mcHead.ByteCountLo, &adapter->MCAddress));
+ EPRO_DPRINTF_REQ(("Sizeof MCHEAD is %x\n", sizeof(mcHead)));
+
+ // bank0
+ //
+ EPRO_ASSERT_BANK_0(adapter);
+
+ EPRO_DPRINTF_REQ(("Address on card is %lx\n", curTBuf->TXBaseAddr));
+ EPRO_SET_HOST_ADDR(adapter, curTBuf->TXBaseAddr);
+ EPRO_COPY_BUFFER_TO_NIC_USHORT(adapter, ((USHORT *)(&mcHead)), sizeof(mcHead) >> 1);
+
+ if (operation != EPRO_CLEAR_CARD_MC)
+ {
+ // since we know the len_of_address is an even #, we make the
+ // assumption here that the amount of memory to copy is divisible
+ // by two (so the shift is safe)
+ //
+ EPRO_COPY_BUFFER_TO_NIC_USHORT(
+ adapter,
+ (USHORT *)(&adapter->MCAddress),
+ (adapter->NumMCAddresses * 3)); // 3 shorts...
+ }
+
+
+ // okay, set up to and pend this thing....
+
+ if (!EProWaitForExeDma(adapter))
+ {
+ // we're in trouble if this happens...
+ //
+ adapter->fHung = TRUE;
+ return(FALSE);
+// EPRO_ASSERT(FALSE);
+ }
+
+ adapter->IntPending = EPRO_INT_MC_SET_PENDING;
+ adapter->IntContext = (PVOID)curTBuf;
+
+ // enable EXE interrupts so we can do this asynchronously...
+ //
+ EProSetInterruptMask(adapter, EPRO_RX_TX_EXE_INTERRUPTS);
+
+ // set the BAR and go....
+ //
+ EPRO_WR_PORT_USHORT(adapter, I82595_TX_BAR_REG, curTBuf->TXBaseAddr);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_CMD_MC_SETUP);
+
+ // Move the currenttxbuf pointer forward...
+ //
+ adapter->CurrentTXBuf = curTBuf->NextBuf;
+
+ return(TRUE);
+}
+
+
diff --git a/private/ntos/ndis/ieepro/sndrcv.c b/private/ntos/ndis/ieepro/sndrcv.c
new file mode 100644
index 000000000..a32d4098c
--- /dev/null
+++ b/private/ntos/ndis/ieepro/sndrcv.c
@@ -0,0 +1,1178 @@
+#include <ndis.h>
+#include "82595.h"
+#include "eprohw.h"
+#include "eprosw.h"
+#include "epro.h"
+#include "eprodbg.h"
+
+//////////////////////////////////////////////////////////////////////
+// SEND code
+//////////////////////////////////////////////////////////////////////
+
+ULONG numberOfResources = 0;
+
+NDIS_STATUS EProSend(IN NDIS_HANDLE miniportAdapterContext,
+ IN PNDIS_PACKET packet,
+ IN UINT flags)
+/*++
+Routine Description:
+
+ The MiniportSend handler for the EPro. About 18 million different
+ things happen here:
+
+ 1) We need to see if there are free transmit buffer pointer for
+ this packet.
+ 2) Once we've got a tx buffer pointer, we then see if we have enough
+ physical memory space for this transmit. If we don't, then
+ we resources out
+ 3) We need to copy the 82595 frame header, then the packet to the card
+ 4) We need to start the transmit if none are in progress
+ 5) We need to update some structures to keep track of the transmit
+
+Arguments:
+ miniportAdapterContext - Really a pointer to our EPRO_ADAPTER structure
+
+ packet - the packet to send
+
+ flags - an optional FLAGS field - not used currently in NDIS
+
+Return Value:
+
+ NDIS_STATUS_RESOURCES - no free transmit buffers. Please hang up and then
+ dial again. If you need help, please dial your operator
+ NDIS_STATUS_PENDING - The packet is on the card and is being sent.
+
+--*/
+
+{
+ PEPRO_ADAPTER adapter = (EPRO_ADAPTER *)miniportAdapterContext;
+// This is the adapter's current transmit buffer...
+ PEPRO_TRANSMIT_BUFFER curTBuf = adapter->CurrentTXBuf;
+ USHORT freeSpace;
+ UINT totalPacketLength;
+ USHORT result;
+
+// If we're currently executing an MC_SETUP command, we can't
+// handle any transmits. The reason is that the MC_SETUP uses
+// a transmit buffer, and we will have problems trying to complete
+// transfers if we do both at the same time. There are a few ways
+// we could get around this, but they'd make things more complicated,
+// and don't gain us much if we go by the assumption that in "normal"
+// use we won't get that many MC-setups...
+ if (adapter->IntPending == EPRO_INT_MC_SET_PENDING) {
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+// Check for free buffer. If can't find one, then return
+// NDIS_STATUS_RESOURCES.
+// is the current buffer free?
+ if (!curTBuf->fEmpty) {
+// nope. can we free it?
+ if (!EProCheckTransmitCompletion(adapter, curTBuf)) {
+ numberOfResources++;
+ return(NDIS_STATUS_RESOURCES);
+ }
+ }
+
+// Get the total length of this packet so we can see if we have
+// room for it.
+ NdisQueryPacket(packet, NULL, NULL, NULL, &totalPacketLength);
+
+ curTBuf->TXSize = totalPacketLength;
+
+// Add in the 82595's tx memory structure plus 2 bytes padding
+// between frames
+ totalPacketLength+=(I82595_TX_FRM_HDR_SIZE + 2);
+
+// is there a transmit in progress?
+ if (adapter->TXChainStart == NULL) {
+ curTBuf->TXBaseAddr = EPRO_TX_LOWER_LIMIT_SHORT;
+ curTBuf->NextBuf->TXBaseAddr = totalPacketLength;
+ } else {
+// Do we have free space for this packet?
+ EPRO_ASSERT(adapter->TXChainStart != curTBuf);
+ EPRO_ASSERT(curTBuf->TXBaseAddr >= EPRO_TX_LOWER_LIMIT_SHORT);
+
+// Although TxBaseAddr == upper limit is NOT LEGAL, we allow it in
+// this assert because it will fall through the next if statement
+// and be dealt with properly. (freespace will = 0 and then we will wrap)
+ EPRO_ASSERT(curTBuf->TXBaseAddr <= EPRO_TX_UPPER_LIMIT_SHORT);
+
+// Now we need to know if the current buffer position is above or
+// below the space in use.
+ if (adapter->TXChainStart->TXBaseAddr >= curTBuf->TXBaseAddr) {
+// We're BELOW the in-use space
+ freeSpace = adapter->TXChainStart->TXBaseAddr -
+ curTBuf->TXBaseAddr;
+ } else {
+ freeSpace = EPRO_TX_UPPER_LIMIT_SHORT -
+ curTBuf->TXBaseAddr;
+ freeSpace += (adapter->TXChainStart->TXBaseAddr -
+ EPRO_TX_LOWER_LIMIT_SHORT);
+ }
+
+ if (freeSpace < totalPacketLength) {
+ return(NDIS_STATUS_RESOURCES);
+ }
+ }
+
+// Now, the set the next buffer's address:
+ curTBuf->NextBuf->TXBaseAddr = curTBuf->TXBaseAddr +
+ totalPacketLength;
+
+ if (curTBuf->NextBuf->TXBaseAddr >= EPRO_TX_UPPER_LIMIT_SHORT)
+ curTBuf->NextBuf->TXBaseAddr -= EPRO_TX_UPPER_LIMIT_SHORT;
+
+// Okay, when we've gotten to this point, it's because we've determined
+// that there is enough space on the card for the packet. So, now we
+// set the current transmit buffer to be empty.
+ curTBuf->fEmpty = FALSE;
+// move the current buffer pointer forward
+ adapter->CurrentTXBuf = curTBuf->NextBuf;
+
+// bank 0
+ EPRO_ASSERT_BANK_0(adapter);
+
+// set our packet pointer so we can ethindicatereceive later.
+ curTBuf->TXPacket = packet;
+
+// This is a double-check that the txbuffer structure was freed
+// correctly -- this is set in checktransmitcompletion
+ EPRO_ASSERT(curTBuf->TXSendAddr == 0xffff);
+
+// We make a backup copy of the TXBaseAddr, in case we use up all
+// of our buffer pointer strucutres and wrap around and overwrite the
+// TXBaseAddr of this buffer....
+ curTBuf->TXSendAddr = curTBuf->TXBaseAddr;
+
+// Set the address on the card to copy to
+ EPRO_SET_HOST_ADDR(adapter, curTBuf->TXBaseAddr);
+ EProCopyPacketToCard(adapter, packet);
+
+// Is there a transmit already going?
+ if (!adapter->TXChainStart) {
+// Nope - queue this one up and let it rip..
+ {
+ UINT i;
+ UCHAR result;
+
+ for (i=0;i<I82595_SPIN_TIMEOUT;i++) {
+ EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &result);
+ if (!(result &I82595_EXEC_STATE)) {
+ if (result & I82595_EXEC_INT_RCVD) {
+ EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG,
+ I82595_EXEC_INT_RCVD);
+ }
+ break;
+ }
+ }
+ }
+
+ // Set up and start the transmit
+ EPRO_WR_PORT_USHORT(adapter, I82595_TX_BAR_REG, curTBuf->TXBaseAddr);
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_XMT);
+
+ adapter->TXChainStart = curTBuf;
+ } else {
+// If chainstart != NULL (ie is pointing to a buffer) and there is no tx
+// in progress - we're hosed....
+// if (curTBuf->LastBuf->TXSendAddr + 4 >= EPRO_TX_UPPER_LIMIT_SHORT) {
+// EPRO_SET_HOST_ADDR(adapter, ((curTBuf->LastBuf->TXSendAddr + 4) -
+// EPRO_TX_UPPER_LIMIT_SHORT));
+// } else {
+// EPRO_SET_HOST_ADDR(adapter, (curTBuf->LastBuf->TXSendAddr + 4));
+// }
+// EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG,
+// curTBuf->TXSendAddr);
+// EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG,
+// curTBuf->LastBuf->TXSize | 8000);
+//
+// EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, &result);
+//
+// EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_XMT_RESUME);
+ }
+
+// okay, we're PENDING...
+ return(NDIS_STATUS_PENDING);
+}
+
+
+
+VOID EProCopyPacketToCard(PEPRO_ADAPTER adapter,
+ PNDIS_PACKET packet)
+/*++
+
+Routine Description:
+
+ This routine copies a packet down to the card. We assume the card's IO port
+ has been set to the correct address at function entry.
+
+Parameters:
+
+ adapter - Pointer to our EPRO_ADAPTER structure
+
+ packet - pointer to the NDIS_PACKET we are copying down.
+
+Return Values:
+
+ none
+
+--*/
+{
+// frame header....
+ EPRO_TX_FRAME_HEADER txFrameHeader;
+// This is a hack to transfer buffers of odd lengths
+ BOOLEAN fForward = FALSE;
+// this is the
+ USHORT forwardedShort;
+// The physical address of the buffer to copy out of...
+ PVOID bufferAddr;
+// packet information
+ UINT bufferCount, totalPacketLength, bufferLen, currentOffset;
+// This is the current buffer of the packet that is passed in...
+ PNDIS_BUFFER curBuffer;
+
+// Get the first buffer out of the packet.
+ NdisQueryPacket(packet, NULL, &bufferCount,
+ &curBuffer, &totalPacketLength);
+
+// Copy the TX header down to the card.
+ EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, I82595_XMT_SHORT);
+ EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, 0);
+ EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, 0);
+ EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, totalPacketLength);
+
+/////////////////////////////////////////////////////
+// LOOP on all the buffers in the packet...
+/////////////////////////////////////////////////////
+ do {
+ NdisQueryBuffer(curBuffer, &bufferAddr, &bufferLen);
+
+// skip over zero-length buffers.
+ if (bufferLen == 0) {
+ NdisGetNextBuffer(curBuffer, &curBuffer);
+ continue;
+ }
+
+// BEGIN fix for odd-length buffers
+ if (fForward) {
+ fForward = FALSE;
+ forwardedShort |= ((*((UCHAR *)bufferAddr)) << 8);
+ ((UCHAR *)bufferAddr)++;
+ bufferLen--;
+ EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, forwardedShort);
+ }
+
+ if (bufferLen & 1) {
+ fForward = TRUE;
+ forwardedShort =*(UCHAR *)( ((UCHAR *)bufferAddr) + (bufferLen-1) );
+ }
+// END fix for odd-length buffers...
+
+#ifndef EPRO_USE_32_BIT_IO
+ EPRO_COPY_BUFFER_TO_NIC_USHORT(adapter,
+ ((UNALIGNED USHORT *)bufferAddr),
+ ((ULONG)bufferLen>>1));
+#else
+// using 32-bit
+ if (adapter->EProUse32BitIO) {
+ if (bufferLen & 2) {
+ EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG,
+ *((UNALIGNED USHORT *)bufferAddr));
+ (UCHAR *)bufferAddr += 2;
+ EPRO_COPY_BUFFER_TO_NIC_ULONG(adapter, ((UNALIGNED ULONG *)bufferAddr),
+ ((ULONG)bufferLen >> 2));
+ } else {
+ EPRO_COPY_BUFFER_TO_NIC_ULONG(adapter, ((UNALIGNED ULONG *)bufferAddr),
+ ((ULONG)bufferLen >> 2));
+ }
+ } else {
+// This is an older version of the 82595 - we need to use 16-bit anyway
+ EPRO_COPY_BUFFER_TO_NIC_USHORT(adapter,
+ (USHORT *)bufferAddr,
+ ((ULONG)bufferLen>>1));
+ }
+#endif
+
+ NdisGetNextBuffer(curBuffer, &curBuffer);
+
+ } while (curBuffer);
+////////////////////////////////////////////////////////
+// END of loop for all buffers in packet
+////////////////////////////////////////////////////////
+
+// copy down a trailing byte
+ if (fForward) {
+ EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, forwardedShort);
+ }
+}
+
+
+
+
+BOOLEAN EProCheckTransmitCompletion(PEPRO_ADAPTER adapter,
+ PEPRO_TRANSMIT_BUFFER txBuf)
+/*++
+Routine Description:
+
+ This routine takes the transmit buffer pointed to by txBuf and tries to
+ free it. This can be called from two places. On an adapter that is very
+ very busy transmitting, it can get called from our send handler if the send
+ handler is called and all the transmit buffers on the card are full. This
+ routine is called directly from the send handler to minimize the latency of
+ the returning NDIS_STATUS_RESOURCES----free buffer in interrupt handler dpc---
+ ---ndis calls back down in it's send handler. There is the possibility here
+ that packets will be sent out of order in this, but it doesn't matter, let the
+ protocols figure that out.
+
+ This routine is also called by our handleinterrupt handler where it does the
+ exact same thing, except in response to a transmit interrupt.
+
+Arguments:
+
+ adapter - a pointer to our EPRO_ADAPTER structure
+
+ txBuf - this is a pointer to the transmit buffer we are checking
+
+Return Value:
+
+ TRUE if the buffer is already free or has been indicated and now is free.
+ FALSE if the buffer is not finished being transmitted.
+
+--*/
+{
+ UCHAR result;
+ USHORT status;
+// NDIS_STATUS returnStatus = NDIS_STATUS_FAILURE;
+
+ if (!txBuf) {
+ return(FALSE);
+ }
+
+ if (txBuf->fEmpty) {
+ return(TRUE);
+ }
+
+// if we got through the first if, then there must be a non-empty
+// buffer. Therefore, we have to assume that there is a transmit in
+// progress (txchainstart is set to the tx in progress) - if there
+// is not one in progress, then something is screwed.
+ EPRO_ASSERT(adapter->TXChainStart != NULL);
+
+// bank0
+ EPRO_ASSERT_BANK_0(adapter);
+
+// Check and see if this transmit has completed...
+ EPRO_SET_HOST_ADDR(adapter, txBuf->TXSendAddr);
+
+// check DN (tx done) flag...
+ EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, &status);
+
+// See if the TX_DONE bit is set...
+ if (!(status & I82595_TX_DN_BYTE_MASK)) {
+ return(FALSE);
+ }
+
+// Check the status of the transmition
+ EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, &status);
+
+ if (status & I82595_TX_OK_SHORT_MASK) {
+// returnStatus = NDIS_STATUS_SUCCESS;
+ adapter->FramesXmitOK++;
+ if ((status & I82595_NO_COLLISIONS_MASK) > 0) {
+ adapter->FramesXmitOneCollision++;
+ if ((status & I82595_NO_COLLISIONS_MASK) > 1) {
+ adapter->FramesXmitManyCollisions++;
+ }
+ }
+ } else {
+ adapter->FramesXmitErr++;
+
+// D---it, the frame errored out...
+// Just re-send it.
+ EPRO_SET_HOST_ADDR(adapter, adapter->TXChainStart->TXSendAddr);
+
+ EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, I82595_XMT);
+ EPRO_WR_PORT_USHORT(adapter, I82595_MEM_IO_REG, 0);
+
+ if (!EProWaitForExeDma(adapter)) {
+ adapter->fHung = TRUE;
+// EPRO_ASSERT(FALSE);
+ }
+
+ EPRO_WR_PORT_USHORT(adapter, I82595_TX_BAR_REG,
+ adapter->TXChainStart->TXSendAddr);
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_XMT);
+
+ return(FALSE);
+ }
+
+// move the chain forward b/c this buffer has been freed....
+#if DBG
+ adapter->TXChainStart->TXSendAddr = 0xffff;
+#endif
+ adapter->TXChainStart = adapter->TXChainStart->NextBuf;
+
+ if (adapter->TXChainStart == adapter->CurrentTXBuf) {
+// since we just moved the chain FORWARD one, if these
+// two pointers are equal it means the buffer is EMPTY, not full...
+ adapter->TXChainStart = NULL;
+ } else {
+
+// Make sure the card is idle
+// EProWaitForExeDma(adapter);
+ {
+ UINT i;
+
+ for (i=0;i<I82595_SPIN_TIMEOUT;i++) {
+ EPRO_RD_PORT_UCHAR(adapter, I82595_STATUS_REG, &result);
+ if (!(result &I82595_EXEC_STATE)) {
+ if (result & I82595_EXEC_INT_RCVD) {
+ EPRO_WR_PORT_UCHAR(adapter, I82595_STATUS_REG,
+ I82595_EXEC_INT_RCVD);
+ }
+ break;
+ }
+ }
+ }
+
+// Get the next TX going....
+ EPRO_WR_PORT_USHORT(adapter, I82595_TX_BAR_REG,
+ adapter->TXChainStart->TXSendAddr);
+
+ EPRO_WR_PORT_UCHAR(adapter, I82595_CMD_REG, I82595_XMT);
+ }
+
+// this buffer is empty now.
+ txBuf->fEmpty = TRUE;
+
+// Yes, here's the deep and dark secret: either we succeed a packet,
+// or we re-send it, so whenever packets complete, they ALWAYS
+// succeed :)
+ NdisMSendComplete(adapter->MiniportAdapterHandle,
+ txBuf->TXPacket, NDIS_STATUS_SUCCESS);
+
+ return(TRUE);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+// RECEIVE code...
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+
+
+
+UINT EProHandleReceive(PEPRO_ADAPTER adapter)
+/*++
+Routine Description:
+
+ This is the dpc-level code that really handles a receive interrupt.
+
+Arguments:
+
+ adapter - pointer to the adapter structure.
+
+Return Value:
+
+ the number of packets received
+
+--*/
+{
+ // The 82595s RCV header
+ EPRO_RCV_HEADER header;
+
+ // the Ethernet header to indicate up
+ EPRO_ETH_HEADER ethHeader;
+
+ // temp variable to figure out how much to copy up
+ USHORT bytesToCopy;
+
+ // Our context to pass in NdisMEthIndicateReceive...
+ EPRO_RCV_CONTEXT context;
+
+ // Use this to loop and handle multiple receives in one int...
+ //
+ UCHAR tempCopy;
+ UINT numRcvd = 0;
+
+ // bank0
+ // EPRO_SWITCH_BANK_0(adapter);
+ //
+ EPRO_ASSERT_BANK_0(adapter);
+
+ if ((adapter->RXCurrentAddress < EPRO_RX_LOWER_LIMIT_SHORT) ||
+ (adapter->RXCurrentAddress > EPRO_RX_UPPER_LIMIT_SHORT))
+ {
+ adapter->fHung = TRUE;
+#if DBG
+ DbgPrint("the RxCurrentAddress is not within acceptable limits: 0x%x\n", adapter->RXCurrentAddress);
+// EPRO_ASSERT(FALSE);
+#endif
+
+ return(0);
+ }
+
+ // Read the header...
+ EPRO_SET_HOST_ADDR(adapter, adapter->RXCurrentAddress);
+
+ EPRO_READ_BUFFER_FROM_NIC_USHORT(
+ adapter,
+ (USHORT *)&header,
+ ((ULONG)sizeof(EPRO_RCV_HEADER) >> 1));
+
+ // Process one or more received frames...
+ while ((header.Event == I82595_RX_EOF) && !adapter->fHung)
+ {
+ // Was the transmit OK?
+ if (!header.Status1 & I82595_RX_OK)
+ {
+ adapter->FramesRcvErr++;
+ // Since we configure the 82595 to discard bad frames, we know we've reached the
+ // latest received frame when we hit a bad one -- since the card will "reclaim"
+ // the space filled by the bad frame as soon as it gets another one.
+ break;
+ }
+ else
+ {
+ numRcvd++;
+
+ // Fill in our receive context - to be passed in to TransferData
+ context.RXFrameSize = (USHORT)((USHORT)header.ByteCountLo) | (((USHORT)header.ByteCountHi) << 8);
+
+ // Figure out how many bytes to indicate up. Either the size of the current lookahead
+ // or the entire frame - whichever is smaller.
+ bytesToCopy = ((context.RXFrameSize-sizeof(EPRO_ETH_HEADER)) > adapter->RXLookAheadSize) ?
+ adapter->RXLookAheadSize :
+ (context.RXFrameSize - sizeof(EPRO_ETH_HEADER));
+
+ EPRO_READ_BUFFER_FROM_NIC_USHORT(
+ adapter,
+ (USHORT *)(&ethHeader),
+ sizeof(EPRO_ETH_HEADER) >> 1);
+
+#ifndef EPRO_USE_32_BIT_IO
+ EPRO_READ_BUFFER_FROM_NIC_USHORT(adapter, &adapter->RXLookAhead, bytesToCopy >> 1);
+#else
+ if (adapter->EProUse32BitIO)
+ {
+ if (bytesToCopy & 2)
+ {
+ EPRO_RD_PORT_USHORT(
+ adapter,
+ I82595_MEM_IO_REG,
+ (UNALIGNED USHORT *)(&adapter->RXLookAhead));
+
+ EPRO_READ_BUFFER_FROM_NIC_ULONG(
+ adapter,
+ (UNALIGNED ULONG *)(((UCHAR *)&(adapter->RXLookAhead)) + 2),
+ bytesToCopy >> 2);
+ }
+ else
+ {
+ EPRO_READ_BUFFER_FROM_NIC_ULONG(
+ adapter,
+ (UNALIGNED ULONG *)(&(adapter->RXLookAhead)),
+ bytesToCopy >> 2);
+ }
+ }
+ else
+ {
+ // This is an old version of the 82595 - we have to use 16-bit IO
+ EPRO_READ_BUFFER_FROM_NIC_USHORT(
+ adapter,
+ (USHORT *)&adapter->RXLookAhead,
+ bytesToCopy>>1);
+ }
+#endif
+
+ if (bytesToCopy & 1)
+ {
+ // just read the low-order byte here....
+ EPRO_RD_PORT_UCHAR(adapter, I82595_MEM_IO_REG, &tempCopy);
+
+ adapter->RXLookAhead[bytesToCopy-1] = tempCopy;
+ }
+
+ context.RXCurrentAddress = adapter->RXCurrentAddress;
+ context.LookAheadSize = bytesToCopy;
+
+ // indicate packet
+ NdisMEthIndicateReceive(adapter->MiniportAdapterHandle,
+ (NDIS_HANDLE)&context,
+ (PCHAR)&ethHeader,
+ sizeof(EPRO_ETH_HEADER),
+ &adapter->RXLookAhead,
+ bytesToCopy,
+ context.RXFrameSize - sizeof(EPRO_ETH_HEADER));
+
+ // verify bank0
+ EPRO_ASSERT_BANK_0(adapter);
+ }
+
+{
+ USHORT temp = (USHORT)header.NextFrmLo | (((USHORT)header.NextFrmHi) << 8);
+
+ if ((temp < EPRO_RX_LOWER_LIMIT_SHORT) ||
+ (temp > EPRO_RX_UPPER_LIMIT_SHORT))
+ {
+ adapter->fHung = TRUE;
+#if DBG
+ DbgPrint("The receive header has an invalid next frame pointer!\n");
+ DbgPrint("current rx: %lx, rx: %lx, hi: %x, lo: %x hdr: %lx\n",
+ adapter->RXCurrentAddress,
+ temp,
+ header.NextFrmHi,
+ header.NextFrmLo,
+ &header);
+
+// EPRO_ASSERT(FALSE);
+#endif
+
+ break;
+ }
+}
+
+ adapter->RXCurrentAddress = (USHORT)header.NextFrmLo | (((USHORT)header.NextFrmHi) << 8);
+
+ // Seek to the next frame
+ EPRO_SET_HOST_ADDR(adapter, adapter->RXCurrentAddress);
+
+ // Read the header...
+ EPRO_READ_BUFFER_FROM_NIC_USHORT(
+ adapter,
+ (USHORT *)(&header),
+ sizeof(EPRO_RCV_HEADER) >> 1);
+ }
+
+ // now, update the stop reg to = the bottom of the received frame....
+ if (numRcvd > 0)
+ {
+ USHORT value;
+
+ value = context.RXCurrentAddress + context.RXFrameSize;
+
+ // wrap around...
+ if (value >= EPRO_RX_UPPER_LIMIT_SHORT)
+ {
+ value -= (EPRO_RX_UPPER_LIMIT_SHORT - EPRO_RX_LOWER_LIMIT_SHORT);
+ }
+
+ if (!((value <= EPRO_RX_UPPER_LIMIT_SHORT) &&
+ (value >= EPRO_RX_LOWER_LIMIT_SHORT)))
+ {
+ adapter->fHung = TRUE;
+#if DBG
+ DbgPrint("ca: %lx, fs: %lx, val: %lx",
+ context.RXCurrentAddress,
+ context.RXFrameSize,
+ value);
+// EPRO_ASSERT(FALSE);
+#endif
+ }
+
+ EPRO_WR_PORT_USHORT(adapter, I82595_RX_STOP_REG, value);
+ }
+
+ adapter->FramesRcvOK += numRcvd;
+
+ return(numRcvd);
+}
+
+#if 0
+// You know. This code PASSES all the stress tests. Passes everything the
+// tester can throw out, but still is broken when I try to make it work
+// in real life. <sigh>. Look at this later.
+
+NDIS_STATUS EProTransferData(OUT PNDIS_PACKET packet,
+ OUT PUINT bytesTransferred,
+ IN NDIS_HANDLE miniportAdapterContext,
+ IN NDIS_HANDLE miniportReceivedContext,
+ IN UINT byteOffset,
+ IN UINT bytesToTransfer)
+/*++
+
+Routine Description:
+
+ The transferdata handler for the EPro.
+
+Arguments:
+
+ packet - The packet to transfer the data into
+
+ bytesTransferred - The number of bytes actually copied into packet.
+
+ miniportAdapterContext - Reallly a pointer to our EPRO_ADAPTER structure
+
+ miniportReceivedContext - This is our EPRO_RCV_CONTEXT, which basically just
+ has the packet length and pointer to where it lies
+ in the card's address space.
+
+ byteOffset - where in the frame to begin trasferring from
+
+ bytesToTransfer - how many bytes to transfer.
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS - data transfered OK
+ NDIS_STATUS_FAILURE - tried to transfer off end of frame
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
+// The 82595's on-card RCV memory structure
+ EPRO_RCV_HEADER header;
+// An 802.3 ethernet header.
+ EPRO_ETH_HEADER ethHeader;
+// How many bytes have we copied, how many are left to copy
+ USHORT byteCount, bytesToCopy;
+ PEPRO_RCV_CONTEXT pcontext = (PEPRO_RCV_CONTEXT)miniportReceivedContext;
+// The current buffer we are copying into.
+ PNDIS_BUFFER curDestBuf;
+// The physical address of the buffer we are currently copying into
+ PVOID curDestBufAddr;
+// The length of that buffer
+ UINT curDestBufLen;
+// Two bytes used when we have to transfer in to odd-length buffers (since
+// accesses to the EPro's memory are only by-word.
+ UCHAR tempCopy[2];
+// This is TRUE if we are "forwarding" a single byte from an odd-length transfer
+ BOOLEAN fForward = FALSE;
+// the address to read from on the card
+ USHORT cardAddress;
+ UINT bytesWriteThisPacket;
+
+// TODO - copy first lookahead size bytes out of lookahead buffer.
+
+ *bytesTransferred = 0;
+
+// switch to bank0 for mem io
+ EPRO_ASSERT_BANK_0(adapter);
+
+// Make sure they're not seeking past the end of the frame
+ if (byteOffset > pcontext->RXFrameSize) {
+ return(NDIS_STATUS_FAILURE);
+ }
+
+// get the first buffer
+ NdisQueryPacket(packet, NULL, NULL, &curDestBuf, NULL);
+
+// copy the amount requested, or the entire packet - whichever is smaller
+ if ((bytesToTransfer + byteOffset) <= pcontext->RXFrameSize) {
+ bytesToCopy = bytesToTransfer;
+ } else {
+ bytesToCopy = (pcontext->RXFrameSize - byteOffset);
+ }
+
+// first loop -- copy up to the end of the lookahead buffer's worth:
+ if (byteOffset < adapter->RXLookAheadSize) {
+ UINT laOffset = byteOffset;
+ UINT laToCopy = adapter->RXLookAheadSize - laOffset;
+
+ if (laToCopy > bytesToCopy) {
+ laToCopy = bytesToCopy;
+ }
+
+ *bytesTransferred+=laToCopy;
+ bytesToCopy-=laToCopy;
+
+ while (laToCopy > 0) {
+ NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
+
+ if (curDestBufLen == 0) {
+ continue;
+ }
+
+ // We either write the entire buffer size bytes or the number of bytes
+ // remaining to copy - whichever is smaller.
+ bytesWriteThisPacket = (laToCopy > curDestBufLen) ?
+ curDestBufLen : laToCopy;
+
+ EPRO_ASSERT(bytesWriteThisPacket <= laToCopy);
+
+ NdisMoveMemory(curDestBufAddr, &adapter->RXLookAhead[laOffset],
+ bytesWriteThisPacket);
+
+ laToCopy-=bytesWriteThisPacket;
+ laOffset+=bytesWriteThisPacket;
+ }
+
+ byteOffset = adapter->RXLookAheadSize;
+
+ EPRO_ASSERT(bytesToCopy >= laToCopy);
+
+ if (bytesToCopy == 0) {
+ EProLogStr(" 1BytesTo:");
+ EProLogLong(bytesToTransfer);
+ EProLogStr("BytesTransf:");
+ EProLogLong(*bytesTransferred);
+ return(NDIS_STATUS_SUCCESS);
+ }
+
+ if (curDestBufLen > bytesWriteThisPacket) {
+ (UCHAR *)curDestBufAddr += bytesWriteThisPacket;
+ } else {
+ curDestBufLen = 0;
+ while (curDestBufLen == 0) {
+ NdisGetNextBuffer(curDestBuf, &curDestBuf);
+ if (!curDestBuf) {
+ EProLogStr(" 2BytesTo:");
+ EProLogLong(bytesToTransfer);
+ EProLogStr("BytesTransf:");
+ EProLogLong(*bytesTransferred);
+ return(NDIS_STATUS_SUCCESS);
+ }
+ NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
+ }
+ }
+ } else {
+ NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
+ }
+
+// set our memory address on the card...
+ cardAddress = (pcontext->RXCurrentAddress + sizeof(EPRO_RCV_HEADER) +
+ sizeof(EPRO_ETH_HEADER) + byteOffset);
+
+// Set the address on the card. Note that you can do sequential reads
+// from the IO port which WRAP around the memory boundry, but if you
+// manually set the address, you have to wrap manually.
+ if (cardAddress >= EPRO_RX_UPPER_LIMIT_SHORT) {
+ cardAddress -= (EPRO_RX_UPPER_LIMIT_SHORT - EPRO_RX_LOWER_LIMIT_SHORT);
+ }
+
+// Are we starting of reading from an odd address?
+ if (cardAddress & 1) {
+// yes; odd offset -- forward a byte in...
+ fForward = TRUE;
+ cardAddress--;
+ }
+
+// Okay, now seek to the right address on the card
+ EPRO_SET_HOST_ADDR(adapter, cardAddress);
+
+// Are we forwarding a byte in? If so, fetch it now....
+ if (fForward == TRUE) {
+ EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, (USHORT *)(&tempCopy));
+ }
+
+
+// continue until we either run out of buffers, or out of bytes....
+ while((bytesToCopy > 0) && (curDestBuf!=NULL)) {
+// We either write the entire buffer size bytes or the number of bytes
+// remaining to copy - whichever is smaller.
+ bytesWriteThisPacket = (bytesToCopy > curDestBufLen) ?
+ curDestBufLen : bytesToCopy;
+ bytesToCopy-=bytesWriteThisPacket;
+
+// Ooh, we're going to transfer some bytes...
+ *bytesTransferred+=bytesWriteThisPacket;
+
+// Okay. Did we have to forward a byte in? Copy it to the buffer NOW..
+ if (fForward == TRUE) {
+ *(UCHAR *)curDestBufAddr = tempCopy[1];
+ fForward = FALSE;
+ ((UCHAR *)curDestBufAddr)++;
+ bytesWriteThisPacket--;
+ }
+
+// Copy the bulk of the data...
+#ifndef EPRO_USE_32_BIT_IO
+ EPRO_READ_BUFFER_FROM_NIC_USHORT(adapter, curDestBufAddr,
+ bytesWriteThisPacket>>1);
+#else
+ if (adapter->EProUse32BitIO) {
+ if (bytesWriteThisPacket & 2) {
+ EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, (USHORT *)curDestBufAddr);
+ EPRO_READ_BUFFER_FROM_NIC_ULONG(adapter,
+ (UNALIGNED ULONG *)((UCHAR *)curDestBufAddr +2),
+ bytesWriteThisPacket >> 2);
+ } else {
+ EPRO_READ_BUFFER_FROM_NIC_ULONG(adapter,
+ (UNALIGNED ULONG *)curDestBufAddr,
+ bytesWriteThisPacket >> 2);
+ }
+ } else {
+ EPRO_READ_BUFFER_FROM_NIC_USHORT(adapter, curDestBufAddr,
+ bytesWriteThisPacket>>1);
+ }
+#endif
+
+// Okay, the rshift in the last call will lose the odd byte. If there is one, we need
+// to read it and possibly forward the second byte....
+ if (bytesWriteThisPacket & 1) {
+ fForward = TRUE;
+ // Read the LOW order byte.
+ EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, (USHORT *)(&tempCopy));
+ ((UCHAR *)curDestBufAddr)[bytesWriteThisPacket-1] = tempCopy[0];
+ }
+ NdisGetNextBuffer(curDestBuf, &curDestBuf);
+ if (curDestBuf != NULL) {
+ NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
+ }
+ }
+
+ EProLogStr(" 3BytesTo:");
+ EProLogLong(bytesToTransfer);
+ EProLogStr("BytesTransf:");
+ EProLogLong(*bytesTransferred);
+ return(NDIS_STATUS_SUCCESS);
+}
+
+#else
+
+
+NDIS_STATUS EProTransferData(OUT PNDIS_PACKET packet,
+ OUT PUINT bytesTransferred,
+ IN NDIS_HANDLE miniportAdapterContext,
+ IN NDIS_HANDLE miniportReceivedContext,
+ IN UINT byteOffset,
+ IN UINT bytesToTransfer)
+/*++
+
+Routine Description:
+
+ The transferdata handler for the EPro.
+
+Arguments:
+
+ packet - The packet to transfer the data into
+
+ bytesTransferred - The number of bytes actually copied into packet.
+
+ miniportAdapterContext - Reallly a pointer to our EPRO_ADAPTER structure
+
+ miniportReceivedContext - This is our EPRO_RCV_CONTEXT, which basically just
+ has the packet length and pointer to where it lies
+ in the card's address space.
+
+ byteOffset - where in the frame to begin trasferring from
+
+ bytesToTransfer - how many bytes to transfer.
+
+Return Value:
+
+ NDIS_STATUS_SUCCESS - data transfered OK
+ NDIS_STATUS_FAILURE - tried to transfer off end of frame
+
+--*/
+{
+ PEPRO_ADAPTER adapter = (PEPRO_ADAPTER)miniportAdapterContext;
+
+ // The 82595's on-card RCV memory structure
+ EPRO_RCV_HEADER header;
+
+ // An 802.3 ethernet header.
+ EPRO_ETH_HEADER ethHeader;
+
+ // How many bytes have we copied, how many are left to copy
+ USHORT byteCount, bytesToCopy;
+ PEPRO_RCV_CONTEXT pcontext = (PEPRO_RCV_CONTEXT)miniportReceivedContext;
+
+ // The current buffer we are copying into.
+ PNDIS_BUFFER curDestBuf;
+
+ // The physical address of the buffer we are currently copying into
+ PVOID curDestBufAddr;
+
+ // The length of that buffer
+ UINT curDestBufLen;
+
+ // Two bytes used when we have to transfer in to odd-length buffers (since
+ // accesses to the EPro's memory are only by-word.
+ UCHAR tempCopy[2];
+
+ // This is TRUE if we are "forwarding" a single byte from an odd-length transfer
+ BOOLEAN fForward = FALSE;
+
+ // the address to read from on the card
+ USHORT cardAddress;
+
+ // TODO - copy first lookahead size bytes out of lookahead buffer.
+
+ *bytesTransferred = 0;
+
+ // switch to bank0 for mem io
+ // EPRO_SWITCH_BANK_0(adapter);
+ EPRO_ASSERT_BANK_0(adapter);
+
+ // Make sure they're not asking for too much.
+ // if (bytesToTransfer + byteOffset > pcontext->RXFrameSize)
+ // {
+ // return(NDIS_STATUS_FAILURE);
+ // }
+
+ // Make sure they're not seeking past the end of the frame
+ if (byteOffset > pcontext->RXFrameSize)
+ {
+ return(NDIS_STATUS_FAILURE);
+ }
+
+
+ // copy the amount requested, or the entire packet - whichever is smaller
+ if ((bytesToTransfer + byteOffset) <= pcontext->RXFrameSize)
+ {
+ bytesToCopy = bytesToTransfer;
+ }
+ else
+ {
+ bytesToCopy = (pcontext->RXFrameSize - byteOffset);
+ }
+
+// set our memory address on the card...
+ cardAddress = (pcontext->RXCurrentAddress +
+ sizeof(EPRO_RCV_HEADER) +
+ sizeof(EPRO_ETH_HEADER) +
+ byteOffset);
+
+ if (cardAddress >= EPRO_RX_UPPER_LIMIT_SHORT)
+ {
+ // cardAddress = EPRO_RX_LOWER_LIMIT_SHORT + (cardAddress - EPRO_RX_UPPER_LIMIT_SHORT);
+ // Go algebraic simplification:
+ cardAddress -= (EPRO_RX_UPPER_LIMIT_SHORT - EPRO_RX_LOWER_LIMIT_SHORT);
+ }
+
+
+ // Are we starting of reading from an odd address?
+ if (cardAddress & 1)
+ {
+ // yes; odd offset -- forward a byte in...
+ fForward = TRUE;
+ cardAddress--;
+ }
+
+ // Okay, now seek to the right address on the card
+ EPRO_SET_HOST_ADDR(adapter, cardAddress);
+
+ // Are we forwarding a byte in? If so, fetch it now....
+ if (fForward == TRUE)
+ {
+ EPRO_RD_PORT_USHORT(adapter, I82595_MEM_IO_REG, (USHORT *)(&tempCopy));
+ }
+
+ // get the first buffer
+ NdisQueryPacket(packet, NULL, NULL, &curDestBuf, NULL);
+
+ // continue until we either run out of buffers, or out of bytes....
+ while((bytesToCopy > 0) && (curDestBuf!=NULL))
+ {
+ UINT bytesWriteThisPacket;
+
+ NdisQueryBuffer(curDestBuf, &curDestBufAddr, &curDestBufLen);
+
+ // We either write the entire buffer size bytes or the number of bytes
+ // remaining to copy - whichever is smaller.
+ bytesWriteThisPacket =
+ (bytesToCopy > curDestBufLen) ? curDestBufLen : bytesToCopy;
+
+ // Ooh, we're going to transfer some bytes...
+ *bytesTransferred+=bytesWriteThisPacket;
+
+ // Okay. Did we have to forward a byte in? Copy it to the buffer NOW..
+ if (fForward == TRUE)
+ {
+ *(UCHAR *)curDestBufAddr = tempCopy[1];
+ fForward = FALSE;
+ ((UCHAR *)curDestBufAddr)++;
+ bytesWriteThisPacket--;
+ }
+
+ // Copy the bulk of the data...
+#ifndef EPRO_USE_32_BIT_IO
+ EPRO_READ_BUFFER_FROM_NIC_USHORT(adapter, curDestBufAddr, bytesWriteThisPacket>>1);
+#else
+ if (adapter->EProUse32BitIO)
+ {
+ if (bytesWriteThisPacket & 2)
+ {
+ EPRO_RD_PORT_USHORT(
+ adapter,
+ I82595_MEM_IO_REG,
+ (UNALIGNED USHORT *)curDestBufAddr);
+
+ EPRO_READ_BUFFER_FROM_NIC_ULONG(
+ adapter,
+ ((UCHAR *)curDestBufAddr +2),
+ bytesWriteThisPacket >> 2);
+ }
+ else
+ {
+ EPRO_READ_BUFFER_FROM_NIC_ULONG(
+ adapter,
+ curDestBufAddr,
+ bytesWriteThisPacket >> 2);
+ }
+ }
+ else
+ {
+ EPRO_READ_BUFFER_FROM_NIC_USHORT(
+ adapter,
+ curDestBufAddr,
+ bytesWriteThisPacket >> 1);
+ }
+#endif
+
+ // Okay, the rshift in the last call will lose the odd byte. If there is one, we need
+ // to read it and possibly forward the second byte....
+ if (bytesWriteThisPacket & 1)
+ {
+ fForward = TRUE;
+
+ // Read the LOW order byte.
+ EPRO_RD_PORT_USHORT(
+ adapter,
+ I82595_MEM_IO_REG,
+ (USHORT *)(&tempCopy));
+
+ ((UCHAR *)curDestBufAddr)[bytesWriteThisPacket-1] = tempCopy[0];
+ }
+ NdisGetNextBuffer(curDestBuf, &curDestBuf);
+ bytesToCopy -= curDestBufLen;
+ }
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+#endif
+
+
+BOOLEAN EProSyncCopyBufferToNicUlong(PVOID context)
+{
+ UCHAR result;
+ PEPRO_ADAPTER adapter = ((PEPRO_COPYBUF_CONTEXT)context)->Adapter;
+// PVOID buffer = ((PEPRO_COPYBUF_CONTEXT)context)->Buffer;
+// UINT len = ((PEPRO_COPYBUF_CONTEXT)context)->Len;
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_32IOSEL_REG, &result);
+// result |= I82595_32IOSEL;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_32IOSEL_REG, (result | I82595_32IOSEL));
+ NdisRawWritePortBufferUlong(adapter->IoPAddr + I82595_32MEM_IO_REG,
+ ((PEPRO_COPYBUF_CONTEXT)context)->Buffer,
+ ((PEPRO_COPYBUF_CONTEXT)context)->Len);
+// result &= ~I82595_32IOSEL;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_32IOSEL_REG, result);
+
+ return(TRUE);
+}
+
+
+BOOLEAN EProSyncReadBufferFromNicUlong(PVOID context)
+{
+ UCHAR result;
+ PEPRO_ADAPTER adapter = ((PEPRO_COPYBUF_CONTEXT)context)->Adapter;
+// PVOID buffer = ((PEPRO_COPYBUF_CONTEXT)context)->Buffer;
+// UINT len = ((PEPRO_COPYBUF_CONTEXT)context)->Len;
+
+ EPRO_RD_PORT_UCHAR(adapter, I82595_32IOSEL_REG, &result);
+// result |= I82595_32IOSEL;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_32IOSEL_REG, (result | I82595_32IOSEL));
+ NdisRawReadPortBufferUlong(adapter->IoPAddr + I82595_32MEM_IO_REG,
+ ((PEPRO_COPYBUF_CONTEXT)context)->Buffer,
+ ((PEPRO_COPYBUF_CONTEXT)context)->Len);
+// result &= ~I82595_32IOSEL;
+ EPRO_WR_PORT_UCHAR(adapter, I82595_32IOSEL_REG, result);
+
+ return(TRUE);
+}
+
diff --git a/private/ntos/ndis/ieepro/sources b/private/ntos/ndis/ieepro/sources
new file mode 100644
index 000000000..e950c6ce5
--- /dev/null
+++ b/private/ntos/ndis/ieepro/sources
@@ -0,0 +1,48 @@
+!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=ieepro
+TARGETPATH=\nt\public\sdk\lib
+TARGETTYPE=DRIVER
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib
+
+C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER
+
+INCLUDES=..\..\inc
+
+SOURCES=epro.c \
+ init.c \
+ request.c \
+ eeprom.c \
+ sndrcv.c \
+ eprodbg.c \
+ epro.rc
+
+RELATIVE_DEPTH=..\..
+
+MSC_WARNING_LEVEL=/W3 /WX