# Required to run the system
#
COMPONENTS = iface_native iface_additional ntoskrnl
-DLLS = ntdll kernel32 crtdll advapi32 fmifs gdi32 secur32
+DLLS = ntdll kernel32 crtdll advapi32 fmifs gdi32 secur32 user32
SUBSYS = smss win32k csrss
#
# ndis tdi tcpip tditest
NET_DRIVERS = ndis tcpip tditest
-KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) $(NET_DRIVERS)
+# ne2000
+NET_DEVICE_DRIVERS = ne2000
-APPS = args hello shell test cat bench apc shm lpc thread event file gditest \
- pteb consume dump_shared_data vmtest
+KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) $(NET_DRIVERS) $(NET_DEVICE_DRIVERS)
+APPS = args hello shell test cat bench apc shm lpc thread event file gditest \
+ pteb consume dump_shared_data vmtest wstest
# objdir
all: buildno $(COMPONENTS) $(DLLS) $(SUBSYS) $(LOADERS) $(KERNEL_SERVICES) $(APPS)
.PHONY: $(NET_DRIVERS) $(NET_DRIVERS:%=%_clean) $(NET_DRIVERS:%=%_install) \
$(NET_DRIVERS:%=%_dist)
+$(NET_DEVICE_DRIVERS): %:
+ make -C services/net/dd/$*
+
+$(NET_DEVICE_DRIVERS:%=%_clean): %_clean:
+ make -C services/net/dd/$* clean
+
+$(NET_DEVICE_DRIVERS:%=%_install): %_install:
+ make -C services/net/dd/$* install
+
+$(NET_DEVICE_DRIVERS:%=%_dist): %_dist:
+ make -C services/net/dd/$* dist
+
+.PHONY: $(NET_DEVICE_DRIVERS) $(NET_DEVICE_DRIVERS:%=%_clean) \
+ $(NET_DEVICE_DRIVERS:%=%_install) $(NET_DEVICE_DRIVERS:%=%_dist)
+
#
# Kernel loaders
#
--- /dev/null
+DIRS= ne2000
--- /dev/null
+# $Id: Makefile,v 1.1 2000/08/27 16:35:04 chorns Exp $
+#
+# NE2000.SYS build spec
+#
+
+TARGETNAME=ne2000
+
+BASE_CFLAGS = -I./include -I../../../../include -DNDIS_MINIPORT_DRIVER
+
+RESOURCE_OBJECT = $(TARGETNAME).coff
+NE2000_OBJECTS = ne2000/main.o ne2000/8390.o
+IMPORT_LIBS = ../../ndis/ndis.a ../../../../ntoskrnl/ntoskrnl.a
+
+
+all: objects $(TARGETNAME).sys
+
+objects:
+ mkdir objects
+
+objects/ne2000.o: $(NE2000_OBJECTS)
+ $(LD) -r $(NE2000_OBJECTS) -o objects/ne2000.o
+
+OBJECTS = objects/ne2000.o
+
+$(TARGETNAME).coff: $(TARGETNAME).rc ../../../include/reactos/resource.h
+
+ifeq ($(DOSCLI),yes)
+CLEAN_FILES = \
+ *.o ne2000\*.o objects\*.o $(TARGETNAME).coff \
+ $(TARGETNAME).a junk.tmp base.tmp temp.exp \
+ $(TARGETNAME).sys $(TARGETNAME).sym
+else
+CLEAN_FILES = \
+ *.o ne2000\*.o objects/*.o $(TARGETNAME).coff \
+ $(TARGETNAME).a junk.tmp base.tmp temp.exp \
+ $(TARGETNAME).sys $(TARGETNAME).sym
+endif
+
+
+$(TARGETNAME).sys: $(OBJECTS) $(TARGETNAME).def
+ $(LD) -r $(OBJECTS) -o $(TARGETNAME).o
+ $(DLLTOOL) \
+ --dllname $(TARGETNAME).sys \
+ --def $(TARGETNAME).def \
+ --output-lib $(TARGETNAME).a \
+ --kill-at
+ $(CC) \
+ -specs=../../../../specs \
+ --subsystem=native \
+ -mdll \
+ --dll \
+ -e _DriverEntry@8 \
+ -o junk.tmp \
+ -Wl,--image-base,0x10000 \
+ -Wl,--file-alignment,0x1000 \
+ -Wl,--section-alignment,0x1000 \
+ -Wl,--defsym,_end=end \
+ -Wl,--defsym,_edata=__data_end__ \
+ -Wl,--defsym,_etext=etext \
+ -Wl,--base-file,base.tmp \
+ $(TARGETNAME).o \
+ $(IMPORT_LIBS)
+ - $(RM) junk.tmp
+ $(DLLTOOL) \
+ --dllname $(TARGETNAME).sys \
+ --base-file base.tmp \
+ --output-exp temp.exp \
+ --def $(TARGETNAME).def \
+ --kill-at
+ - $(RM) base.tmp
+ $(CC) \
+ -specs=../../../../specs \
+ --subsystem=native \
+ -mdll \
+ --dll \
+ -e _DriverEntry@8 \
+ -o $(TARGETNAME).sys \
+ -Wl,--image-base,0x0 \
+ -Wl,--file-alignment,0x1000 \
+ -Wl,--section-alignment,0x1000 \
+ -Wl,--defsym,_end=end \
+ -Wl,--defsym,_edata=__data_end__ \
+ -Wl,--defsym,_etext=etext \
+ -Wl,temp.exp \
+ $(TARGETNAME).o \
+ $(IMPORT_LIBS)
+ - $(RM) temp.exp
+ $(NM) --numeric-sort $(TARGETNAME).sys > $(TARGETNAME).sym
+
+clean: $(CLEAN_FILES:%=%_clean)
+
+$(CLEAN_FILES:%=%_clean): %_clean:
+ - $(RM) $*
+
+.PHONY: clean $(CLEAN_FILES:%=%_clean)
+
+install: $(FLOPPY_DIR)/drivers/$(TARGETNAME).sys
+
+$(FLOPPY_DIR)/drivers/$(TARGETNAME).sys: $(TARGETNAME).sys
+ifeq ($(DOSCLI),yes)
+ $(CP) $(TARGETNAME).sys $(FLOPPY_DIR)\drivers\$(TARGETNAME).sys
+else
+ $(CP) $(TARGETNAME).sys $(FLOPPY_DIR)/drivers/$(TARGETNAME).sys
+endif
+
+dist: $(DIST_DIR)/drivers/$(TARGETNAME).sys
+
+$(DIST_DIR)/drivers/$(TARGETNAME).sys: $(TARGETNAME).sys
+ifeq ($(DOSCLI),yes)
+ $(CP) $(TARGETNAME).sys ..\..\$(DIST_DIR)\drivers\$(TARGETNAME).sys
+else
+ $(CP) $(TARGETNAME).sys ../../$(DIST_DIR)/drivers/$(TARGETNAME).sys
+endif
+
+#WITH_DEBUGGING = yes
+#WIN32_LEAN_AND_MEAN = yes
+#WARNINGS_ARE_ERRORS = yes
+include ../../../../rules.mak
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Novell Eagle 2000 driver
+ * FILE: include/8390.h
+ * PURPOSE: National Semiconductor 8390 NIC definitions
+ */
+#ifndef __8390_H
+#define __8390_H
+
+/* Page 0 register layout (PS1 = 0, PS0 = 0) */
+#define PG0_CR 0x00 /* Command Register (R/W) */
+#define PG0_CLDA0 0x01 /* Current Local DMA Address 0 (R) */
+#define PG0_PSTART 0x01 /* Page Start Register (W) */
+#define PG0_CLDA1 0x02 /* Current Local DMA Address 1 (R) */
+#define PG0_PSTOP 0x02 /* Page Stop Register (W) */
+#define PG0_BNRY 0x03 /* Boundary Pointer (R/W) */
+#define PG0_TSR 0x04 /* Transmit Status Register (R) */
+#define PG0_TPSR 0x04 /* Transmit Page Start Register (W) */
+#define PG0_NCR 0x05 /* Number of Collisions Register (R) */
+#define PG0_TBCR0 0x05 /* Transmit Byte Count Register 0 (W) */
+#define PG0_FIFO 0x06 /* FIFO (R) */
+#define PG0_TBCR1 0x06 /* Transmit Byte Count Register 1 (W) */
+#define PG0_ISR 0x07 /* Interrupt Status Register (R/W) */
+#define PG0_CRDA0 0x08 /* Current Remote DMA Address 0 (R) */
+#define PG0_RSAR0 0x08 /* Remote Start Address Register 0 (W) */
+#define PG0_CRDA1 0x09 /* Current Remote DMA Address 1 (R) */
+#define PG0_RSAR1 0x09 /* Remote Start Address Register 1 (W) */
+#define PG0_RBCR0 0x0A /* Remote Byte Count Register 0 (W) */
+#define PG0_RBCR1 0x0B /* Remote Byte Count Register 1 (W) */
+#define PG0_RSR 0x0C /* Receive Status Register (R) */
+#define PG0_RCR 0x0C /* Receive Configuration Register (W) */
+#define PG0_CNTR0 0x0D /* Tally Counter 0 (Frame Alignment Errors) (R) */
+#define PG0_TCR 0x0D /* Transmit Configuration Register (W) */
+#define PG0_CNTR1 0x0E /* Tally Counter 1 (CRC Errors) (R) */
+#define PG0_DCR 0x0E /* Data Configuration Register (W) */
+#define PG0_CNTR2 0x0F /* Tally Counter 2 (Missed Packet Errors) (R) */
+#define PG0_IMR 0x0F /* Interrupt Mask Register (W) */
+
+/* Page 1 register layout (PS1 = 0, PS0 = 1) */
+#define PG1_CR 0x00 /* Command Register (R/W) */
+#define PG1_PAR 0x01 /* Physical Address Registers (6 registers) (R/W) */
+#define PG1_CURR 0x07 /* Current Page Register (R/W) */
+#define PG1_MAR 0x08 /* Multicast Address Registers (8 registers) (R/W) */
+
+/* Page 2 register layout (PS1 = 1, PS0 = 0) */
+#define PG2_CR 0x00 /* Command Register (R/W) */
+#define PG2_PSTART 0x01 /* Page Start Register (R) */
+#define PG2_CLDA0 0x01 /* Current Local DMA Address 0 (W) */
+#define PG2_PSTOP 0x02 /* Page Stop Register (R) */
+#define PG2_CLDA1 0x02 /* Current Local DMA Address 1 (W) */
+#define PG2_RNPP 0x03 /* Remote Next Packet Pointer (R/W) */
+#define PG2_TPSR 0x04 /* Transmit Page Start Address (R) */
+#define PG2_LNPP 0x05 /* Local Next Packet Pointer (R/W) */
+#define PG2_AC1 0x06 /* Address Counter (Upper) (R/W) */
+#define PG2_AC0 0x07 /* Address Counter (Lower) (R/W) */
+#define PG2_RCR 0x0C /* Receive Configuration Register (R) */
+#define PG2_TCR 0x0D /* Transmit Configuration Register (R) */
+#define PG2_DCR 0x0E /* Data Configuration Register (R) */
+#define PG2_IMR 0x0F /* Interrupt Mask Register (R) */
+
+/* Bits in PGX_CR - Command Register */
+#define CR_STP 0x01 /* Stop chip */
+#define CR_STA 0x02 /* Start chip */
+#define CR_TXP 0x04 /* Transmit a frame */
+#define CR_RD0 0x08 /* Remote read */
+#define CR_RD1 0x10 /* Remote write */
+#define CR_RD2 0x20 /* Abort/complete remote DMA */
+#define CR_PAGE0 0x00 /* Select page 0 of chip registers */
+#define CR_PAGE1 0x40 /* Select page 1 of chip registers */
+#define CR_PAGE2 0x80 /* Select page 2 of chip registers */
+
+/* Bits in PG0_ISR - Interrupt Status Register */
+#define ISR_PRX 0x01 /* Packet received, no errors */
+#define ISR_PTX 0x02 /* Packet transmitted, no errors */
+#define ISR_RXE 0x04 /* Receive error */
+#define ISR_TXE 0x08 /* Transmit error */
+#define ISR_OVW 0x10 /* Overwrite warning */
+#define ISR_CNT 0x20 /* Counter overflow */
+#define ISR_RDC 0x40 /* Remote DMA complete */
+#define ISR_RST 0x80 /* Reset status */
+
+/* Bits in PG0_TSR - Transmit Status Register */
+#define TSR_PTX 0x01h /* Packet transmitted without error */
+#define TSR_COL 0x04h /* Collided at least once */
+#define TSR_ABT 0x08h /* Collided 16 times and was dropped */
+#define TSR_CRS 0x10h /* Carrier sense lost */
+#define TSR_FU 0x20h /* Transmit FIFO Underrun */
+#define TSR_CDH 0x40h /* Collision detect heartbeat */
+#define TSR_OWC 0x80h /* Out of window collision */
+
+/* Bits for PG0_RCR - Receive Configuration Register */
+#define RCR_SEP 0x01 /* Save error packets */
+#define RCR_AR 0x02 /* Accept runt packets */
+#define RCR_AB 0x04 /* Accept broadcasts */
+#define RCR_AM 0x08 /* Accept multicast */
+#define RCR_PRO 0x10 /* Promiscuous physical addresses */
+#define RCR_MON 0x20 /* Monitor mode */
+
+/* Bits in PG0_RSR - Receive Status Register */
+#define RSR_PRX 0x01 /* Received packet intact */
+#define RSR_CRC 0x02 /* CRC error */
+#define RSR_FAE 0x04 /* Frame alignment error */
+#define RSR_FO 0x08 /* FIFO overrun */
+#define RSR_MPA 0x10 /* Missed packet */
+#define RSR_PHY 0x20 /* Physical/multicast address */
+#define RSR_DIS 0x40 /* Receiver disabled (monitor mode) */
+#define RSR_DFR 0x80 /* Deferring */
+
+/* Bits in PG0_TCR - Transmit Configuration Register */
+#define TCR_CRC 0x01 /* Inhibit CRC, do not append CRC */
+#define TCR_LOOP 0x02 /* Set loopback mode */
+#define TCR_LB01 0x06 /* Encoded loopback control */
+#define TCR_ATD 0x08 /* Auto transmit disable */
+#define TCR_OFST 0x10 /* Collision offset enable */
+
+/* Bits in PG0_DCR - Data Configuration Register */
+#define DCR_WTS 0x01 /* Word transfer mode selection */
+#define DCR_BOS 0x02 /* Byte order selection */
+#define DCR_LAS 0x04 /* Long address selection */
+#define DCR_LS 0x08 /* Loopback select (when 0) */
+#define DCR_ARM 0x10 /* Autoinitialize remote */
+#define DCR_FT00 0x00 /* Burst length selection (1 word/2 bytes) */
+#define DCR_FT01 0x20 /* burst length selection (2 words/4 bytes) */
+#define DCR_FT10 0x40 /* Burst length selection (4 words/8 bytes) */
+#define DCR_FT11 0x60 /* Burst length selection (6 words/12 bytes) */
+
+/* Bits in PG0_IMR - Interrupt Mask Register */
+#define IMR_PRXE 0x01 /* Packet received interrupt enable */
+#define IMR_PTXE 0x02 /* Packet transmitted interrupt enable */
+#define IMR_RXEE 0x04 /* Receive error interrupt enable */
+#define IMR_TXEE 0x08 /* Transmit error interrupt enable */
+#define IMR_OVWE 0x10 /* Overwrite warning interrupt enable */
+#define IMR_CNTE 0x20 /* Counter overflow interrupt enable */
+#define IMR_RDCE 0x40 /* Remote DMA complete interrupt enable */
+#define IMR_ALLE 0x7F /* All interrupts enable */
+
+
+/* NIC prepended structure to a received packet */
+typedef struct _PACKET_HEADER {
+ UCHAR Status; /* See RSR_* constants */
+ UCHAR NextPacket; /* Pointer to next packet in chain */
+ USHORT PacketLength; /* Length of packet including this header */
+} PACKET_HEADER, PPACKET_HEADER;
+
+
+#define NICDisableInterrupts(Adapter) \
+ NdisRawWritePortUchar((Adapter)->IOBase + PG0_IMR, 0x00);
+
+#define NICEnableInterrupts(Adapter) \
+ NdisRawWritePortUchar((Adapter)->IOBase + PG0_IMR, (Adapter)->InterruptMask);
+
+VOID MiniportHandleInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext);
+
+#endif /* __8390_H */
+
+/* EOF */
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Novell Eagle 2000 driver
+ * FILE: include/debug.h
+ * PURPOSE: Debugging support macros
+ * DEFINES: DBG - Enable debug output
+ * NASSERT - Disable assertions
+ */
+#ifndef __DEBUG_H
+#define __DEBUG_H
+
+#define NORMAL_MASK 0x000000FF
+#define SPECIAL_MASK 0xFFFFFF00
+#define MIN_TRACE 0x00000001
+#define MID_TRACE 0x00000002
+#define MAX_TRACE 0x00000003
+
+#define DEBUG_MEMORY 0x00000100
+#define DEBUG_ULTRA 0xFFFFFFFF
+
+#ifdef DBG
+
+extern ULONG DebugTraceLevel;
+
+#ifdef _MSC_VER
+
+#define NDIS_DbgPrint(_t_, _x_) \
+ if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
+ ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
+ DbgPrint("(%s:%d) ", __FILE__, __LINE__); \
+ DbgPrint _x_ ; \
+ }
+
+#else /* _MSC_VER */
+
+#define NDIS_DbgPrint(_t_, _x_) \
+ if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \
+ ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \
+ DbgPrint("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \
+ DbgPrint _x_ ; \
+ }
+
+#endif /* _MSC_VER */
+
+
+#ifdef ASSERT
+#undef ASSERT
+#endif
+
+#ifdef NASSERT
+#define ASSERT(x)
+#else /* NASSERT */
+#define ASSERT(x) if (!(x)) { NDIS_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); }
+#endif /* NASSERT */
+
+#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x))
+
+#else /* DBG */
+
+#define NDIS_DbgPrint(_t_, _x_)
+
+#define ASSERT_IRQL(x)
+#define ASSERT(x)
+
+#endif /* DBG */
+
+
+#define assert(x) ASSERT(x)
+#define assert_irql(x) ASSERT_IRQL(x)
+
+
+#ifdef _MSC_VER
+
+#define UNIMPLEMENTED \
+ NDIS_DbgPrint(MIN_TRACE, ("The function at %s:%d is unimplemented, \
+ but come back another day.\n", __FILE__, __LINE__));
+
+#else /* _MSC_VER */
+
+#define UNIMPLEMENTED \
+ NDIS_DbgPrint(MIN_TRACE, ("%s at %s:%d is unimplemented, \
+ but come back another day.\n", __FUNCTION__, __FILE__, __LINE__));
+
+#endif /* _MSC_VER */
+
+
+#define CHECKPOINT \
+ do { NDIS_DbgPrint(MIN_TRACE, ("%s:%d\n", __FILE__, __LINE__)); } while(0);
+
+#endif /* __DEBUG_H */
+
+/* EOF */
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Novell Eagle 2000 driver
+ * FILE: include/ne2000.h
+ * PURPOSE: NE2000 driver definitions
+ */
+#ifndef __NE2000_H
+#define __NE2000_H
+
+#ifdef _MSC_VER
+
+#ifndef ULONG_PTR
+#define ULONG ULONG_PTR
+#endif
+
+#include <ndis.h>
+#else
+#include <net/ndis.h>
+#endif
+#include <8390.h>
+#include <debug.h>
+
+/* Define NOCARD to test NDIS without a card */
+//#define NOCARD
+
+/* NE2000 sepcific constants */
+#define NIC_DATA 0x10 /* Data register */
+#define NIC_RESET 0x1F /* Reset register */
+
+
+/* Global constants */
+
+#define DRIVER_NDIS_MAJOR_VERSION 3
+#define DRIVER_NDIS_MINOR_VERSION 0
+
+#define DRIVER_DEFAULT_IO_BASE_ADDRESS 0x300
+#define DRIVER_DEFAULT_INTERRUPT_NUMBER 10
+
+#define DRIVER_MAX_MULTICAST_LIST_SIZE 8
+
+#define DRIVER_VENDOR_DESCRIPTION "Novell Eagle 2000 Adapter."
+#define DRIVER_VENDOR_DRIVER_VERSION 0x0100 /* 1.0 */
+
+#define DRIVER_FRAME_SIZE 1514 /* Size of an ethernet frame */
+#define DRIVER_HEADER_SIZE 14 /* Size of an ethernet header */
+#define DRIVER_LENGTH_OF_ADDRESS 6 /* Size of an ethernet address */
+
+/* Maximum lookahead buffer size */
+#define DRIVER_MAXIMUM_LOOKAHEAD (252 - DRIVER_HEADER_SIZE)
+
+/* Size of a block in a buffer ring */
+#define DRIVER_BLOCK_SIZE 256
+
+
+/* Default number of transmit buffers */
+#define DRIVER_DEFAULT_TX_BUFFER_COUNT 12
+
+/* Interrupt Mask Register value */
+#define DRIVER_INTERRUPT_MASK IMR_ALLE - IMR_RDCE
+
+
+
+/* Global structures */
+
+typedef struct _MINIPORT_RESERVED
+{
+ PNDIS_PACKET Next;
+} MINIPORT_RESERVED, *PMINIPORT_RESERVED;
+
+#define RESERVED(Packet) ((PMINIPORT_RESERVED)((Packet)->u.s1.MiniportReserved))
+
+typedef UCHAR DRIVER_HARDWARE_ADDRESS[DRIVER_LENGTH_OF_ADDRESS];
+
+/* Information about an adapter */
+typedef struct _NIC_ADAPTER
+{
+ /* Entry on global adapter list */
+ LIST_ENTRY ListEntry;
+ /* Adapter handle */
+ NDIS_HANDLE MiniportAdapterHandle;
+ /* NDIS interrupt object */
+ NDIS_MINIPORT_INTERRUPT Interrupt;
+
+ /* I/O base address and interrupt number of adapter */
+ ULONG IoBaseAddress;
+ ULONG InterruptNumber;
+
+ /* Mapped address of the I/O base port */
+ PUCHAR IOBase;
+
+ /* TRUE if the NIC can transfer in word mode */
+ BOOLEAN WordMode;
+
+ /* Base address and size of the onboard memory window */
+ PUCHAR RamBase;
+ UINT RamSize;
+
+ /* Station Address PROM (SAPROM) */
+ UCHAR SAPROM[16];
+
+ /* Onboard ethernet address from the manufacturer */
+ DRIVER_HARDWARE_ADDRESS PermanentAddress;
+
+ /* Ethernet address currently in use */
+ DRIVER_HARDWARE_ADDRESS StationAddress;
+
+ /* Maximum number of multicast addresses this adapter supports */
+ ULONG MaxMulticastListSize;
+
+ /* List of multicast addresses in use */
+ DRIVER_HARDWARE_ADDRESS Addresses[DRIVER_MAX_MULTICAST_LIST_SIZE];
+
+ /* Current multicast address mask */
+ UCHAR MulticastAddressMask[8];
+
+ /* Masked interrupts (IMR value) */
+ ULONG InterruptMask;
+
+ /* Interrupts that have occurred */
+ UCHAR InterruptStatus;
+
+ /* Current packet filter */
+ ULONG PacketFilter;
+
+ /* Lookahead buffer */
+ UINT LookaheadSize;
+ UCHAR Lookahead[DRIVER_MAXIMUM_LOOKAHEAD + DRIVER_HEADER_SIZE];
+
+ /* Receive buffer ring */
+ UINT PageStart;
+ UINT PageStop;
+ UINT CurrentPage;
+ UINT NextPacket;
+
+ /* TRUE if there was a buffer overflow */
+ BOOLEAN BufferOverflow;
+
+ /* TRUE if an error occurred during reception of a packet */
+ BOOLEAN ReceiveError;
+
+ /* TRUE if an error occurred during transmission of a packet */
+ BOOLEAN TransmitError;
+
+ /* TRUE if a transmit interrupt is pending */
+ BOOLEAN TransmitPending;
+
+ /* Received packet header */
+ PACKET_HEADER PacketHeader;
+
+ /* Offset in onboard RAM of received packet */
+ ULONG PacketOffset;
+
+ /* TRUE if receive indications are done and should be completed */
+ BOOLEAN DoneIndicating;
+
+ /* Transmit buffers */
+ UINT TXStart; /* Start block of transmit buffer ring */
+ UINT TXCount; /* Number of blocks in transmit buffer ring */
+ UINT TXFree; /* Number of free transmit buffers */
+ UINT TXNext; /* Next buffer to use */
+ /* Length of packet. 0 means buffer is unused */
+ INT TXSize[DRIVER_DEFAULT_TX_BUFFER_COUNT];
+ INT TXCurrent; /* Current buffer beeing transmitted. -1 means none */
+
+ /* Head of transmit queue */
+ PNDIS_PACKET TXQueueHead;
+ /* Tail of transmit queue */
+ PNDIS_PACKET TXQueueTail;
+
+ /* Statistics */
+ ULONG FrameAlignmentErrors;
+ ULONG CrcErrors;
+ ULONG MissedPackets;
+
+ /* Flags used for driver cleanup */
+ BOOLEAN IOPortRangeRegistered;
+ BOOLEAN InterruptRegistered;
+} NIC_ADAPTER, *PNIC_ADAPTER;
+
+/* Global driver information */
+typedef struct _DRIVER_INFORMATION
+{
+ NDIS_HANDLE NdisWrapperHandle; /* Returned from NdisInitializeWrapper */
+ NDIS_HANDLE NdisMacHandle; /* Returned from NdisRegisterMac */
+ LIST_ENTRY AdapterListHead; /* Adapters this driver control */
+} DRIVER_INFORMATION, *PDRIVER_INFORMATION;
+
+
+
+/* Global variable */
+
+extern DRIVER_INFORMATION DriverInfo;
+extern NDIS_PHYSICAL_ADDRESS HighestAcceptableMax;
+
+
+
+/* Prototypes */
+
+BOOLEAN NICCheck(
+ PNIC_ADAPTER Adapter);
+
+NDIS_STATUS NICInitialize(
+ PNIC_ADAPTER Adapter);
+
+NDIS_STATUS NICSetup(
+ PNIC_ADAPTER Adapter);
+
+NDIS_STATUS NICStart(
+ PNIC_ADAPTER Adapter);
+
+NDIS_STATUS NICStop(
+ PNIC_ADAPTER Adapter);
+
+NDIS_STATUS NICReset(
+ PNIC_ADAPTER Adapter);
+
+VOID NICUpdateCounters(
+ PNIC_ADAPTER Adapter);
+
+VOID NICReadDataAlign(
+ PNIC_ADAPTER Adapter,
+ PUSHORT Target,
+ ULONG Source,
+ USHORT Length);
+
+VOID NICWriteDataAlign(
+ PNIC_ADAPTER Adapter,
+ ULONG Target,
+ PUSHORT Source,
+ USHORT Length);
+
+VOID NICReadData(
+ PNIC_ADAPTER Adapter,
+ PUCHAR Target,
+ ULONG Source,
+ USHORT Length);
+
+VOID NICWriteData(
+ PNIC_ADAPTER Adapter,
+ ULONG Target,
+ PUCHAR Source,
+ USHORT Length);
+
+VOID NICTransmit(
+ PNIC_ADAPTER Adapter);
+
+#endif /* __NE2000_H */
+
+/* EOF */
--- /dev/null
+; Novell Eagle 2000 driver - ReactOS Operating System
+
+LIBRARY NE2000.SYS
+
+EXPORTS
+
+; EOF
--- /dev/null
+#include <defines.h>
+#include <reactos/resource.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+ PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", RES_STR_COMPANY_NAME
+ VALUE "FileDescription", "Novell NE2000 network driver\0"
+ VALUE "FileVersion", "0.0.0\0"
+ VALUE "InternalName", "ne2000\0"
+ VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
+ VALUE "OriginalFilename", "ne2000.sys\0"
+ VALUE "ProductName", RES_STR_PRODUCT_NAME
+ VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Novell Eagle 2000 driver
+ * FILE: ne2000/8390.c
+ * PURPOSE: DP8390 NIC specific routines
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ * CSH 27/08-2000 Created
+ */
+#include <ne2000.h>
+
+
+BOOLEAN NICCheck(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Tests for a NIC
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * RETURNS:
+ * TRUE if NIC is believed to be present, FALSE if not
+ * NOTES:
+ * If the adapter responds correctly to a
+ * stop command we assume it is present
+ */
+{
+ UCHAR Tmp;
+
+ /* Disable interrupts */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_IMR, 0);
+
+ /* Stop the NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2);
+
+ /* Pause for 1.6ms */
+ NdisStallExecution(1600);
+
+ /* Read NIC response */
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_CR, &Tmp);
+
+ if ((Tmp == (CR_RD2 | CR_STP)) || (Tmp == (CR_RD2 | CR_STP | CR_STA)))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+BOOLEAN NICTestAddress(
+ PNIC_ADAPTER Adapter,
+ ULONG Address)
+/*
+ * FUNCTION: Tests if an address is writable
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * RETURNS:
+ * TRUE if the RAM size was found, FALSE if not
+ * NOTES:
+ * Starts at 1KB and tests every 1KB up to 64KB
+ */
+{
+ USHORT Data;
+ USHORT Tmp;
+
+ /* Read one word */
+ NICReadDataAlign(Adapter, &Data, Address, 0x02);
+
+ /* Alter it */
+ Data ^= 0xFFFF;
+
+ /* Write it back */
+ NICWriteDataAlign(Adapter, Address, &Data, 0x02);
+
+ /* Check if it has changed on the NIC */
+ NICReadDataAlign(Adapter, &Tmp, Address, 0x02);
+
+ return (Data == Tmp);
+}
+
+
+BOOLEAN NICTestRAM(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Finds out how much RAM a NIC has
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * RETURNS:
+ * TRUE if the RAM size was found, FALSE if not
+ * NOTES:
+ * Start at 1KB and test for every 1KB up to 64KB
+ */
+{
+ ULONG Base;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ /* Locate RAM base address */
+ for (Base = 0x0400; Base < 0x10000; Base += 0x0400) {
+ if (NICTestAddress(Adapter, Base))
+ break;
+ }
+
+ if (Base == 0x10000) {
+ /* No RAM on this board */
+ NDIS_DbgPrint(MIN_TRACE, ("No RAM found on board.\n"));
+ return FALSE;
+ }
+
+ Adapter->RamBase = (PUCHAR)Base;
+
+ /* Find RAM size */
+ for (; Base < 0x10000; Base += 0x0400) {
+ if (!NICTestAddress(Adapter, Base))
+ break;
+ }
+
+ Adapter->RamSize = (UINT)(Base - (ULONG_PTR)Adapter->RamBase);
+
+ NDIS_DbgPrint(MID_TRACE, ("RAM is at (0x%X). Size is (0x%X).\n",
+ Adapter->RamBase, Adapter->RamSize));
+
+ return TRUE;
+}
+
+
+VOID NICSetPhysicalAddress(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Initializes the physical address on the NIC
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * NOTES:
+ * The physical address is taken from Adapter.
+ * The NIC is stopped by this operation
+ */
+{
+ UINT i;
+
+ /* Select page 1 */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1);
+
+ /* Initialize PAR - Physical Address Registers */
+ for (i = 0; i < 0x06; i++)
+ NdisRawWritePortUchar(Adapter->IOBase + PG1_PAR + i, Adapter->StationAddress[i]);
+
+ /* Go back to page 0 */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
+}
+
+
+VOID NICSetMulticastAddressMask(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Initializes the multicast address mask on the NIC
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * NOTES:
+ * The multicast address mask is taken from Adapter.
+ * The NIC is stopped by this operation
+ */
+{
+ UINT i;
+
+ /* Select page 1 */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1);
+
+ /* Initialize MAR - Multicast Address Registers */
+ for (i = 0; i < 0x08; i++)
+ NdisRawWritePortUchar(Adapter->IOBase + PG1_MAR + i, Adapter->MulticastAddressMask[i]);
+
+ /* Go back to page 0 */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
+}
+
+
+BOOLEAN NICReadSAPROM(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Reads the Station Address PROM data from the NIC
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * RETURNS:
+ * TRUE if a the NIC is an NE2000
+ * NOTES:
+ * This routine also determines if the NIC can support word mode transfers
+ * and if it does initializes the NIC for word mode.
+ * The station address in the adapter structure is initialized with
+ * the address from the SAPROM
+ */
+{
+ UINT i;
+ UCHAR Buffer[32];
+ UCHAR WordLength;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ /* Read Station Address PROM (SAPROM) which is 16 bytes at remote DMA address 0.
+ Some cards double the data read which we must compensate for */
+
+ /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x20);
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);
+
+ /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, 0x00);
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, 0x00);
+
+ /* Select page 0, read and start the NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0);
+
+ /* Read one byte at a time */
+ WordLength = 2; /* Assume a word is two bytes */
+ for (i = 0; i < 32; i += 2) {
+ NdisRawReadPortUchar(Adapter->IOBase + NIC_DATA, &Buffer[i]);
+ NdisRawReadPortUchar(Adapter->IOBase + NIC_DATA, &Buffer[i + 1]);
+ if (Buffer[i] != Buffer[i + 1])
+ WordLength = 1; /* A word is one byte long */
+ }
+
+ /* If WordLength is 2 the data read before was doubled. We must compensate for this */
+ if (WordLength == 2) {
+ NDIS_DbgPrint(MIN_TRACE, ("NE2000 found.\n"));
+
+ Adapter->WordMode = TRUE;
+
+ /* Move the SAPROM data to the adapter object */
+ for (i = 0; i < 16; i++)
+ Adapter->SAPROM[i] = Buffer[i * 2];
+
+ /* Copy the station address */
+ NdisMoveMemory(
+ (PVOID)&Adapter->StationAddress,
+ (PVOID)&Adapter->SAPROM,
+ DRIVER_LENGTH_OF_ADDRESS);
+
+ /* Initialize DCR - Data Configuration Register (word mode/4 words FIFO) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_WTS | DCR_LS | DCR_FT10);
+
+ return TRUE;
+ } else {
+ NDIS_DbgPrint(MIN_TRACE, ("NE1000 found.\n"));
+
+ Adapter->WordMode = FALSE;
+
+ return FALSE;
+ }
+}
+
+
+NDIS_STATUS NICInitialize(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Initializes a NIC
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * RETURNS:
+ * Status of NIC initialization
+ * NOTES:
+ * The NIC is put into loopback mode
+ */
+{
+ UCHAR Tmp;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ if (!NICCheck(Adapter)) {
+ NDIS_DbgPrint(MIN_TRACE, ("No adapter found at (0x%X).\n", Adapter->IOBase));
+ return NDIS_STATUS_ADAPTER_NOT_FOUND;
+ } else
+ NDIS_DbgPrint(MID_TRACE, ("Adapter found at (0x%X).\n", Adapter->IOBase));
+
+ /* Reset the NIC */
+ NdisRawReadPortUchar(Adapter->IOBase + NIC_RESET, &Tmp);
+
+ /* Wait for 1.6ms */
+ NdisStallExecution(1600);
+
+ /* Write the value back */
+ NdisRawWritePortUchar(Adapter->IOBase + NIC_RESET, Tmp);
+
+ /* Select page 0 and stop NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
+
+ /* Initialize DCR - Data Configuration Register (byte mode/8 bytes FIFO) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_LS | DCR_FT10);
+
+ /* Clear RBCR0 and RBCR1 - Remote Byte Count Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00);
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);
+
+ /* Initialize RCR - Receive Configuration Register (monitor mode) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON);
+
+ /* Enter loopback mode (internal NIC module loopback) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP);
+
+ /* Read the Station Address PROM */
+ if (!NICReadSAPROM(Adapter))
+ return NDIS_STATUS_ADAPTER_NOT_FOUND;
+
+ NDIS_DbgPrint(MID_TRACE, ("Station address is (%02X %02X %02X %02X %02X %02X).\n",
+ Adapter->StationAddress[0], Adapter->StationAddress[1],
+ Adapter->StationAddress[2], Adapter->StationAddress[3],
+ Adapter->StationAddress[4], Adapter->StationAddress[5]));
+
+ /* Select page 0 and start NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0);
+
+ /* Clear ISR - Interrupt Status Register */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, 0xFF);
+
+ /* Find NIC RAM size */
+ NICTestRAM(Adapter);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+NDIS_STATUS NICSetup(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Sets up a NIC
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * RETURNS:
+ * Status of operation
+ * NOTES:
+ * The NIC is put into loopback mode
+ */
+{
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ if (Adapter->WordMode ) {
+ /* Initialize DCR - Data Configuration Register (word mode/4 words FIFO) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_WTS | DCR_LS | DCR_FT10);
+ } else {
+ /* Initialize DCR - Data Configuration Register (byte mode/8 bytes FIFO) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_LS | DCR_FT10);
+ }
+
+ /* Clear RBCR0 and RBCR1 - Remote Byte Count Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00);
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);
+
+ /* Initialize RCR - Receive Configuration Register (monitor mode) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON);
+
+ /* Enter loopback mode (internal NIC module loopback) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP);
+
+ /* Set boundary page */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY, Adapter->NextPacket);
+
+ /* Set start page */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_PSTART, Adapter->PageStart);
+
+ /* Set stop page */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_PSTOP, Adapter->PageStop);
+
+ /* Program our address on the NIC */
+ NICSetPhysicalAddress(Adapter);
+
+ /* Program the multicast address mask on the NIC */
+ NICSetMulticastAddressMask(Adapter);
+
+ /* Select page 1 and stop NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1);
+
+ /* Initialize current page register */
+ NdisRawWritePortUchar(Adapter->IOBase + PG1_CURR, Adapter->PageStart + 1);
+
+ /* Select page 0 and stop NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
+
+ /* Clear ISR - Interrupt Status Register */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, 0xFF);
+
+ /* Initialize IMR - Interrupt Mask Register */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_IMR, Adapter->InterruptMask);
+
+ /* Select page 0 and start NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0);
+
+ Adapter->CurrentPage = Adapter->PageStart + 1;
+ Adapter->NextPacket = Adapter->PageStart + 1;
+ Adapter->BufferOverflow = FALSE;
+ Adapter->ReceiveError = FALSE;
+ Adapter->TransmitError = FALSE;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+NDIS_STATUS NICStart(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Starts a NIC
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * RETURNS:
+ * Status of operation
+ */
+{
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ /* Take NIC out of loopback mode */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, 0x00);
+
+ /* Initialize RCR - Receive Configuration Register (accept all) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_AB | RCR_AM | RCR_PRO);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+NDIS_STATUS NICStop(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Stops a NIC
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * RETURNS:
+ * Status of operation
+ */
+{
+ UCHAR Tmp;
+ UINT i;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ /* Select page 0 and stop NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
+
+ /* Clear Remote Byte Count Register so ISR_RST will be set */
+ NdisRawWritePortUchar( Adapter->IOBase + PG0_RBCR0, 0x00);
+ NdisRawWritePortUchar( Adapter->IOBase + PG0_RBCR0, 0x00);
+
+ /* Wait for ISR_RST to be set, but timeout after 2ms */
+ for (i = 0; i < 4; i++) {
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp);
+ if (Tmp & ISR_RST)
+ break;
+
+ NdisStallExecution(500);
+ }
+
+#ifdef DBG
+ if (i == 4)
+ NDIS_DbgPrint(MIN_TRACE, ("NIC was not reset after 2ms.\n"));
+#endif
+
+ /* Initialize RCR - Receive Configuration Register (monitor mode) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON);
+
+ /* Initialize TCR - Transmit Configuration Register (loopback mode) */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP);
+
+ /* Start NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+NDIS_STATUS NICReset(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Resets a NIC
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * RETURNS:
+ * Status of operation
+ */
+{
+ UCHAR Tmp;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ /* Stop the NIC */
+ NICStop(Adapter);
+
+ /* Reset the NIC */
+ NdisRawReadPortUchar(Adapter->IOBase + NIC_RESET, &Tmp);
+
+ /* Wait for 1.6ms */
+ NdisStallExecution(1600);
+
+ /* Write the value back */
+ NdisRawWritePortUchar(Adapter->IOBase + NIC_RESET, Tmp);
+
+ /* Restart the NIC */
+ NICStart(Adapter);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+VOID NICStartTransmit(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Starts transmitting a packet
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ */
+{
+ UINT Length;
+
+ /* Set start of frame */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_TPSR,
+ Adapter->TXStart + Adapter->TXCurrent * DRIVER_BLOCK_SIZE);
+
+ /* Set length of frame */
+ Length = Adapter->TXSize[Adapter->TXCurrent];
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_TBCR0, Length & 0xFF);
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_TBCR1, Length >> 8);
+
+ /* Start transmitting */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_TXP | CR_RD2);
+
+ NDIS_DbgPrint(MAX_TRACE, ("Transmitting. Buffer (%d) Size (%d).\n",
+ Adapter->TXCurrent,
+ Length));
+
+}
+
+
+VOID NICSetBoundaryPage(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Sets the boundary page on the adapter to be one less than NextPacket
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ */
+{
+ if (Adapter->NextPacket == Adapter->PageStart) {
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY,
+ (UCHAR)(Adapter->PageStop - 1));
+ } else {
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY,
+ (UCHAR)(Adapter->NextPacket - 1));
+ }
+}
+
+
+VOID NICGetCurrentPage(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Retrieves the current page from the adapter
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ */
+{
+ UCHAR Current;
+
+ /* Select page 1 */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1);
+
+ /* Read current page */
+ NdisRawReadPortUchar(Adapter->IOBase + PG1_CURR, &Current);
+
+ /* Select page 0 */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
+
+ Adapter->CurrentPage = Current;
+}
+
+
+VOID NICUpdateCounters(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Updates counters
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ */
+{
+ UCHAR Tmp;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_CNTR0, &Tmp);
+ Adapter->FrameAlignmentErrors += Tmp;
+
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_CNTR1, &Tmp);
+ Adapter->CrcErrors += Tmp;
+
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_CNTR2, &Tmp);
+ Adapter->MissedPackets += Tmp;
+}
+
+
+VOID NICReadDataAlign(
+ PNIC_ADAPTER Adapter,
+ PUSHORT Target,
+ ULONG Source,
+ USHORT Length)
+/*
+ * FUNCTION: Copies data from a NIC's RAM into a buffer
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * Target = Pointer to buffer to copy data into (in host memory)
+ * Source = Offset into NIC's RAM (must be an even number)
+ * Length = Number of bytes to copy from NIC's RAM (must be an even number)
+ */
+{
+ UCHAR Tmp;
+ USHORT Count;
+
+ Count = Length;
+
+ /* Select page 0 and start the NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0);
+
+ /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, (UCHAR)(Source & 0xFF));
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, (UCHAR)(Source >> 8));
+
+ /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, (UCHAR)(Count & 0xFF));
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, (UCHAR)(Count >> 8));
+
+ /* Select page 0, read and start the NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0);
+
+ if (Adapter->WordMode)
+ NdisRawReadPortBufferUshort(Adapter->IOBase + NIC_DATA, Target, Count >> 1);
+ else
+ NdisRawReadPortBufferUchar(Adapter->IOBase + NIC_DATA, Target, Count);
+
+ /* Wait for remote DMA to complete, but timeout after some time */
+ for (Count = 0; Count < 0xFFFF; Count++) {
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp);
+ if (Tmp & ISR_RDC)
+ break;
+
+ NdisStallExecution(4);
+ }
+
+#ifdef DBG
+ if (Count == 0xFFFF)
+ NDIS_DbgPrint(MIN_TRACE, ("Remote DMA did not complete.\n"));
+#endif
+
+ /* Clear remote DMA bit in ISR - Interrupt Status Register */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISR_RDC);
+}
+
+
+VOID NICWriteDataAlign(
+ PNIC_ADAPTER Adapter,
+ ULONG Target,
+ PUSHORT Source,
+ USHORT Length)
+/*
+ * FUNCTION: Copies data from a buffer into the NIC's RAM
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * Target = Offset into NIC's RAM (must be an even number)
+ * Source = Pointer to buffer to copy data from (in host memory)
+ * Length = Number of bytes to copy from the buffer (must be an even number)
+ */
+{
+ UCHAR Tmp;
+ USHORT Count;
+
+ /* Select page 0 and start the NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0);
+
+ /* Handle read-before-write bug */
+
+ /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, (UCHAR)(Target & 0xFF));
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, (UCHAR)(Target >> 8));
+
+ /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x02);
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);
+
+ /* Read and start the NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0);
+
+ /* Read data */
+ NdisRawReadPortUshort(Adapter->IOBase + NIC_DATA, &Count);
+
+ /* Wait for remote DMA to complete, but timeout after some time */
+ for (Count = 0; Count < 0xFFFF; Count++) {
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp);
+ if (Tmp & ISR_RDC)
+ break;
+
+ NdisStallExecution(4);
+ }
+
+#ifdef DBG
+ if (Count == 0xFFFF)
+ NDIS_DbgPrint(MIN_TRACE, ("Remote DMA did not complete.\n"));
+#endif
+
+ /* Clear remote DMA bit in ISR - Interrupt Status Register */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISR_RDC);
+
+
+ /* Now output some data */
+
+ Count = Length;
+
+ /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, (UCHAR)(Target & 0xFF));
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, (UCHAR)(Target >> 8));
+
+ /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, (UCHAR)(Count & 0xFF));
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, (UCHAR)(Count >> 8));
+
+ /* Write and start the NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD1 | CR_PAGE0);
+
+ if (Adapter->WordMode)
+ NdisRawWritePortBufferUshort(Adapter->IOBase + NIC_DATA, Source, Count >> 1);
+ else
+ NdisRawWritePortBufferUchar(Adapter->IOBase + NIC_DATA, Source, Count);
+
+ /* Wait for remote DMA to complete, but timeout after some time */
+ for (Count = 0; Count < 0xFFFF; Count++) {
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp);
+ if (Tmp & ISR_RDC)
+ break;
+
+ NdisStallExecution(4);
+ }
+
+#ifdef DBG
+ if (Count == 0xFFFF)
+ NDIS_DbgPrint(MIN_TRACE, ("Remote DMA did not complete.\n"));
+#endif
+
+ /* Clear remote DMA bit in ISR - Interrupt Status Register */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISR_RDC);
+}
+
+
+VOID NICReadData(
+ PNIC_ADAPTER Adapter,
+ PUCHAR Target,
+ ULONG Source,
+ USHORT Length)
+/*
+ * FUNCTION: Copies data from a NIC's RAM into a buffer
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * Target = Pointer to buffer to copy data into (in host memory)
+ * Source = Offset into NIC's RAM
+ * Length = Number of bytes to copy from NIC's RAM
+ */
+{
+ USHORT Tmp;
+
+ /* Avoid transfers to odd addresses */
+ if (Source & 0x01) {
+ /* Transfer one word and use the MSB */
+ NICReadDataAlign(Adapter, &Tmp, Source - 1, 0x02);
+ *Target = (UCHAR)(Tmp >> 8);
+ Source++;
+ Target++;
+ Length--;
+ }
+
+ if (Length & 0x01) {
+ /* Transfer as many words as we can without exceeding the buffer length */
+ Tmp = Length & 0xFFFE;
+ NICReadDataAlign(Adapter, (PUSHORT)Target, Source, Tmp);
+ Source += Tmp;
+ (ULONG_PTR)Target += Tmp;
+
+ /* Read one word and keep the LSB */
+ NICReadDataAlign(Adapter, &Tmp, Source, 0x02);
+ *Target = (UCHAR)(Tmp & 0x00FF);
+ } else
+ /* Transfer the rest of the data */
+ NICReadDataAlign(Adapter, (PUSHORT)Target, Source, Length);
+}
+
+
+VOID NICWriteData(
+ PNIC_ADAPTER Adapter,
+ ULONG Target,
+ PUCHAR Source,
+ USHORT Length)
+/*
+ * FUNCTION: Copies data from a buffer into NIC's RAM
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * Target = Offset into NIC's RAM to store data
+ * Source = Pointer to buffer to copy data from (in host memory)
+ * Length = Number of bytes to copy from buffer
+ */
+{
+ USHORT Tmp;
+
+ /* Avoid transfers to odd addresses */
+ if (Target & 0x01) {
+ /* Read one word */
+ NICReadDataAlign(Adapter, &Tmp, Target - 1, 0x02);
+
+ /* Merge LSB with the new byte which become the new MSB */
+ Tmp = (Tmp & 0x00FF) | (*Source << 8);
+
+ /* Finally write the value back */
+ NICWriteDataAlign(Adapter, Target - 1, &Tmp, 0x02);
+
+ /* Update pointers */
+ (ULONG_PTR)Source += 1;
+ (ULONG_PTR)Target += 1;
+ Length--;
+ }
+
+ if (Length & 0x01) {
+ /* Transfer as many words as we can without exceeding the transfer length */
+ Tmp = Length & 0xFFFE;
+ NICWriteDataAlign(Adapter, Target, (PUSHORT)Source, Tmp);
+ Source += Tmp;
+ (ULONG_PTR)Target += Tmp;
+
+ /* Read one word */
+ NICReadDataAlign(Adapter, &Tmp, Target, 0x02);
+
+ /* Merge MSB with the new byte which become the new LSB */
+ Tmp = (Tmp & 0xFF00) | (*Source);
+
+ /* Finally write the value back */
+ NICWriteDataAlign(Adapter, Target, &Tmp, 0x02);
+ } else
+ /* Transfer the rest of the data */
+ NICWriteDataAlign(Adapter, Target, (PUSHORT)Source, Length);
+}
+
+
+VOID NICIndicatePacket(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Indicates a packet to the wrapper
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ */
+{
+ UINT IndicateLength;
+
+ IndicateLength = (Adapter->PacketHeader.PacketLength <
+ (Adapter->LookaheadSize + DRIVER_HEADER_SIZE))?
+ (Adapter->PacketHeader.PacketLength) :
+ (Adapter->LookaheadSize + DRIVER_HEADER_SIZE);
+
+ /* Fill the lookahead buffer */
+ NICReadData(Adapter,
+ (PUCHAR)&Adapter->Lookahead,
+ Adapter->PacketOffset + sizeof(PACKET_HEADER),
+ IndicateLength + DRIVER_HEADER_SIZE);
+
+ NDIS_DbgPrint(MAX_TRACE, ("Indicating (%d) bytes.\n", IndicateLength));
+
+#if 0
+ NDIS_DbgPrint(MAX_TRACE, ("FRAME:\n"));
+ for (i = 0; i < (IndicateLength + 7) / 8; i++) {
+ NDIS_DbgPrint(MAX_TRACE, ("%02X %02X %02X %02X %02X %02X %02X %02X\n",
+ Adapter->Lookahead[i*8+0],
+ Adapter->Lookahead[i*8+1],
+ Adapter->Lookahead[i*8+2],
+ Adapter->Lookahead[i*8+3],
+ Adapter->Lookahead[i*8+4],
+ Adapter->Lookahead[i*8+5],
+ Adapter->Lookahead[i*8+6],
+ Adapter->Lookahead[i*8+7]));
+ }
+#endif
+
+ if (IndicateLength >= DRIVER_HEADER_SIZE) {
+ NdisMEthIndicateReceive(Adapter->MiniportAdapterHandle,
+ NULL,
+ (PVOID)&Adapter->Lookahead,
+ DRIVER_HEADER_SIZE,
+ (PVOID)&Adapter->Lookahead[DRIVER_HEADER_SIZE],
+ IndicateLength - DRIVER_HEADER_SIZE,
+ Adapter->PacketHeader.PacketLength - DRIVER_HEADER_SIZE);
+ } else {
+ NdisMEthIndicateReceive(Adapter->MiniportAdapterHandle,
+ NULL,
+ (PVOID)&Adapter->Lookahead,
+ IndicateLength,
+ NULL,
+ 0,
+ 0);
+ }
+}
+
+
+VOID NICReadPacket(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Reads a full packet from the receive buffer ring
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ */
+{
+ UCHAR Tmp;
+ BOOLEAN SkipPacket = FALSE;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ /* Check if receive buffer ring is empty */
+
+ /* Read boundary page */
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_BNRY, &Tmp);
+
+ /* Get the header of the next packet in the receive ring */
+ Adapter->PacketOffset = Adapter->NextPacket << 8;
+ NICReadData(Adapter,
+ (PUCHAR)&Adapter->PacketHeader,
+ Adapter->PacketOffset,
+ sizeof(PACKET_HEADER));
+
+ NDIS_DbgPrint(MAX_TRACE, ("HEADER: (Status) (0x%X)\n", Adapter->PacketHeader.Status));
+ NDIS_DbgPrint(MAX_TRACE, ("HEADER: (NextPacket) (0x%X)\n", Adapter->PacketHeader.NextPacket));
+ NDIS_DbgPrint(MAX_TRACE, ("HEADER: (PacketLength) (0x%X)\n", Adapter->PacketHeader.PacketLength));
+
+ if (Adapter->PacketHeader.PacketLength < 64 ||
+ Adapter->PacketHeader.PacketLength > 1518) {
+ NDIS_DbgPrint(MAX_TRACE, ("Bogus packet size (%d).\n",
+ Adapter->PacketHeader.PacketLength));
+ SkipPacket = TRUE;
+ }
+
+ if (SkipPacket) {
+ /* Skip packet */
+ Adapter->NextPacket = Adapter->CurrentPage;
+ } else {
+ NICIndicatePacket(Adapter);
+
+ /* Go to the next free buffer in receive ring */
+ Adapter->NextPacket = Adapter->PacketHeader.NextPacket;
+ }
+
+ /* Update boundary page */
+ NICSetBoundaryPage(Adapter);
+}
+
+
+VOID NICWritePacket(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Writes a full packet to the transmit buffer ring
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * NOTES:
+ * There must be enough free buffers available in the transmit buffer ring.
+ * The packet is taken from the head of the transmit queue and the position
+ * into the transmit buffer ring is taken from TXNext
+ */
+{
+ PNDIS_BUFFER SrcBuffer;
+ UINT BytesToCopy, SrcSize, DstSize;
+ PUCHAR SrcData;
+ ULONG DstData;
+ UINT TXStart;
+ UINT TXStop;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ TXStart = Adapter->TXStart * DRIVER_BLOCK_SIZE;
+ TXStop = (Adapter->TXStart + Adapter->TXCount) * DRIVER_BLOCK_SIZE;
+
+ NdisQueryPacket(Adapter->TXQueueHead,
+ NULL,
+ NULL,
+ &SrcBuffer,
+ &Adapter->TXSize[Adapter->TXNext]);
+
+ NDIS_DbgPrint(MAX_TRACE, ("Packet Size (%d) is now (%d).\n",
+ Adapter->TXNext,
+ Adapter->TXSize[Adapter->TXNext]));
+
+ NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
+
+ DstData = TXStart + Adapter->TXNext * DRIVER_BLOCK_SIZE;
+ DstSize = TXStop - DstData;
+
+ /* Start copying the data */
+ for (;;) {
+ BytesToCopy = (SrcSize < DstSize)? SrcSize : DstSize;
+
+ NICWriteData(Adapter, DstData, SrcData, BytesToCopy);
+
+ (ULONG_PTR)SrcData += BytesToCopy;
+ SrcSize -= BytesToCopy;
+ DstData += BytesToCopy;
+ DstSize -= BytesToCopy;
+
+ if (SrcSize == 0) {
+ /* No more bytes in source buffer. Proceed to
+ the next buffer in the source buffer chain */
+ NdisGetNextBuffer(SrcBuffer, &SrcBuffer);
+ if (!SrcBuffer)
+ break;
+
+ NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize);
+ }
+
+ if (DstSize == 0) {
+ /* Wrap around the end of the transmit buffer ring */
+ DstData = TXStart;
+ DstSize = Adapter->TXCount * DRIVER_BLOCK_SIZE;
+ }
+ }
+}
+
+
+BOOLEAN NICPrepareForTransmit(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Prepares a packet for transmission
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * NOTES:
+ * There must be at least one packet in the transmit queue
+ * RETURNS:
+ * TRUE if a packet was prepared, FALSE if not
+ */
+{
+ UINT Length;
+ UINT BufferCount;
+ PNDIS_PACKET Packet;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ /* Calculate number of buffers needed to transmit packet */
+ NdisQueryPacket(Adapter->TXQueueHead,
+ NULL,
+ NULL,
+ NULL,
+ &Length);
+
+ BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE;
+
+ if (BufferCount > Adapter->TXFree) {
+ NDIS_DbgPrint(MID_TRACE, ("No transmit resources. Have (%d) buffers, need (%d).\n",
+ Adapter->TXFree, BufferCount));
+ /* We don't have the resources to transmit this packet right now */
+ return FALSE;
+ }
+
+ /* Write the packet to the card */
+ NICWritePacket(Adapter);
+
+ /* If the NIC is not transmitting, reset the current transmit pointer */
+ if (Adapter->TXCurrent == -1)
+ Adapter->TXCurrent = Adapter->TXNext;
+
+ Adapter->TXNext = (Adapter->TXNext + BufferCount) % Adapter->TXCount;
+ Adapter->TXFree -= BufferCount;
+
+ /* Remove the packet from the queue */
+ Packet = Adapter->TXQueueHead;
+ Adapter->TXQueueHead = RESERVED(Packet)->Next;
+
+ if (Packet == Adapter->TXQueueTail)
+ Adapter->TXQueueTail = NULL;
+
+ /* Assume the transmit went well */
+ NdisMSendComplete(Adapter->MiniportAdapterHandle,
+ Packet,
+ NDIS_STATUS_SUCCESS);
+
+ return TRUE;
+}
+
+
+VOID NICTransmit(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Starts transmitting packets in the transmit queue
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * NOTES:
+ * There must be at least one packet in the transmit queue
+ */
+{
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ if (Adapter->TXCurrent == -1) {
+ /* NIC is not transmitting, so start transmitting now */
+
+ /* Load next packet onto the card, and start transmitting */
+ if (NICPrepareForTransmit(Adapter))
+ NICStartTransmit(Adapter);
+ }
+}
+
+
+VOID HandleReceive(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Handles reception of a packet
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ * NOTES:
+ * Buffer overflows are also handled here
+ */
+{
+ UINT i;
+ UCHAR Tmp;
+ UINT PacketCount;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ Adapter->DoneIndicating = FALSE;
+ PacketCount = 0;
+
+ NICGetCurrentPage(Adapter);
+
+ if (Adapter->BufferOverflow) {
+
+ NDIS_DbgPrint(MAX_TRACE, ("Receive ring overflow.\n"));
+
+ /* Select page 0 and stop the NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0);
+
+ /* Clear RBCR0,RBCR1 - Remote Byte Count Registers */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00);
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00);
+
+ /* Wait for ISR_RST to be set, but timeout after 2ms */
+ for (i = 0; i < 4; i++) {
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp);
+ if (Tmp & ISR_RST)
+ break;
+
+ NdisStallExecution(500);
+ }
+
+ if ((Adapter->InterruptStatus & (ISR_PTX | ISR_TXE)) == 0) {
+ /* We may need to restart the transmitter */
+ Adapter->TransmitPending = TRUE;
+ }
+
+ /* Initialize TCR - Transmit Configuration Register to loopback mode 1 */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP);
+
+ /* Start NIC */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2);
+
+ NICStart(Adapter);
+
+ Adapter->BufferOverflow = FALSE;
+ }
+
+ if (Adapter->ReceiveError) {
+ NDIS_DbgPrint(MAX_TRACE, ("Receive error.\n"));
+
+ /* Skip this packet */
+ Adapter->NextPacket = Adapter->CurrentPage;
+ NICSetBoundaryPage(Adapter);
+
+ Adapter->ReceiveError = FALSE;
+ }
+
+ for (;;) {
+ NICGetCurrentPage(Adapter);
+
+ if (Adapter->CurrentPage == Adapter->NextPacket) {
+ NDIS_DbgPrint(MAX_TRACE, ("No more packets.\n"));
+ break;
+ } else {
+ NDIS_DbgPrint(MAX_TRACE, ("Got a packet in the receive ring.\n"));
+
+ /* Read packet from receive buffer ring */
+ NICReadPacket(Adapter);
+
+ Adapter->DoneIndicating = TRUE;
+
+ PacketCount++;
+ if (PacketCount == 10) {
+ /* Don't starve transmit interrupts */
+ break;
+ }
+ }
+ }
+
+ if ((Adapter->TransmitPending) && (Adapter->TXCurrent != -1)) {
+ NDIS_DbgPrint(MAX_TRACE, ("Retransmitting current packet at (%d).\n", Adapter->TXCurrent));
+ /* Retransmit packet */
+ NICStartTransmit(Adapter);
+ Adapter->TransmitPending = FALSE;
+ }
+
+ if (Adapter->DoneIndicating)
+ NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
+}
+
+
+VOID HandleTransmit(
+ PNIC_ADAPTER Adapter)
+/*
+ * FUNCTION: Handles transmission of a packet
+ * ARGUMENTS:
+ * Adapter = Pointer to adapter information
+ */
+{
+ UINT Length;
+ UINT BufferCount;
+
+ if (Adapter->TransmitError) {
+ /* FIXME: Retransmit now or let upper layer protocols handle retransmit? */
+ Adapter->TransmitError = FALSE;
+ }
+
+ /* Free transmit buffers */
+ Length = Adapter->TXSize[Adapter->TXCurrent];
+ BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Freeing (%d) buffers at (%d).\n",
+ BufferCount,
+ Adapter->TXCurrent));
+
+ Adapter->TXFree += BufferCount;
+ Adapter->TXSize[Adapter->TXCurrent] = 0;
+ Adapter->TXCurrent = (Adapter->TXCurrent + BufferCount) % Adapter->TXCount;
+
+ if (Adapter->TXSize[Adapter->TXCurrent] == 0) {
+ NDIS_DbgPrint(MAX_TRACE, ("No more packets in transmit buffer.\n"));
+
+ Adapter->TXCurrent = -1;
+ }
+
+ if (Adapter->TXQueueTail) {
+ if (NICPrepareForTransmit(Adapter))
+ NICStartTransmit(Adapter);
+ }
+}
+
+
+VOID MiniportHandleInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext)
+/*
+ * FUNCTION: Handler for deferred processing of interrupts
+ * ARGUMENTS:
+ * MiniportAdapterContext = Pointer to adapter context area
+ * NOTES:
+ * Interrupt Service Register is read to determine which interrupts
+ * are pending. All pending interrupts are handled
+ */
+{
+ UCHAR ISRValue;
+ UCHAR ISRMask;
+ UCHAR Mask;
+ PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
+
+ ISRMask = Adapter->InterruptMask;
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue);
+
+ NDIS_DbgPrint(MAX_TRACE, ("ISRValue (0x%X).\n", ISRValue));
+
+ Adapter->InterruptStatus = (ISRValue & ISRMask);
+
+ if (ISRValue != 0x00)
+ /* Acknowledge interrupts */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISRValue);
+
+ Mask = 0x01;
+ while (Adapter->InterruptStatus != 0x00) {
+
+ NDIS_DbgPrint(MAX_TRACE, ("Adapter->InterruptStatus (0x%X).\n", Adapter->InterruptStatus));
+
+ while (((Adapter->InterruptStatus & Mask) == 0) && (Mask < ISRMask))
+ Mask = (Mask << 1);
+
+ switch (Adapter->InterruptStatus & Mask) {
+ case ISR_OVW:
+ NDIS_DbgPrint(MAX_TRACE, ("Overflow interrupt.\n"));
+ /* Overflow. Handled almost the same way as a receive interrupt */
+ Adapter->BufferOverflow = TRUE;
+
+ HandleReceive(Adapter);
+
+ Adapter->InterruptStatus &= ~ISR_OVW;
+ break;
+
+ case ISR_RXE:
+ NDIS_DbgPrint(MAX_TRACE, ("Receive error interrupt.\n"));
+ NICUpdateCounters(Adapter);
+
+ Adapter->ReceiveError = TRUE;
+
+ case ISR_PRX:
+ NDIS_DbgPrint(MAX_TRACE, ("Receive interrupt.\n"));
+
+ HandleReceive(Adapter);
+
+ Adapter->InterruptStatus &= ~(ISR_PRX | ISR_RXE);
+ break;
+
+ case ISR_TXE:
+ NDIS_DbgPrint(MAX_TRACE, ("Transmit error interrupt.\n"));
+ NICUpdateCounters(Adapter);
+
+ Adapter->TransmitError = TRUE;
+
+ case ISR_PTX:
+ NDIS_DbgPrint(MAX_TRACE, ("Transmit interrupt.\n"));
+
+ HandleTransmit(Adapter);
+
+ Adapter->InterruptStatus &= ~(ISR_PTX | ISR_TXE);
+ break;
+
+ case ISR_CNT:
+ NDIS_DbgPrint(MAX_TRACE, ("Counter interrupt.\n"));
+ /* Counter overflow. Read counters from the NIC */
+ NICUpdateCounters(Adapter);
+
+ Adapter->InterruptStatus &= ~ISR_CNT;
+ break;
+
+ default:
+ NDIS_DbgPrint(MAX_TRACE, ("Unknown interrupt. Adapter->InterruptStatus (0x%X).\n", Adapter->InterruptStatus));
+ Adapter->InterruptStatus &= ~Mask;
+ break;
+ }
+
+ Mask = (Mask << 1);
+
+ /* Check if new interrupts are generated */
+ NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue);
+ Adapter->InterruptStatus |= (ISRValue & ISRMask);
+
+ if (ISRValue != 0x00) {
+ /* Acknowledge interrupts */
+ NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISRValue);
+ Mask = 0x01;
+ }
+ }
+
+ NICEnableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
+}
+
+/* EOF */
--- /dev/null
+#
+# 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
--- /dev/null
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_NETWORK
+#define VER_FILEDESCRIPTION_STR "Novell NE2000 network driver"
+#define VER_INTERNALNAME_STR "NE2000.SYS"
+#define VER_ORIGINALFILENAME_STR "NE2000.SYS"
+
+#include "common.ver"
--- /dev/null
+TARGETNAME=ne2000
+TARGETPATH=..\objects
+TARGETTYPE=DRIVER
+
+TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib
+
+C_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DDBG
+
+INCLUDES=..\include;..\..\..\..\..\include\net;$(BASEDIR)\inc
+
+SOURCES=main.c \
+ 8390.c \
+ RESOURCE.RC
+
+MSC_WARNING_LEVEL=/W3 /WX
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Novell Eagle 2000 driver
+ * FILE: ne2000/main.c
+ * PURPOSE: Driver entry point
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ * CSH 27/08-2000 Created
+ */
+#include <ne2000.h>
+
+
+#ifdef DBG
+
+/* See debug.h for debug/trace constants */
+ULONG DebugTraceLevel = MIN_TRACE;
+
+#endif /* DBG */
+
+
+/* List of supported OIDs */
+static ULONG MiniportOIDList[] = {
+ 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_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_VENDOR_DRIVER_VERSION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_PROTOCOL_OPTIONS,
+ OID_GEN_MAC_OPTIONS,
+ OID_GEN_MEDIA_CONNECT_STATUS,
+ OID_GEN_MAXIMUM_SEND_PACKETS,
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+ OID_802_3_MAC_OPTIONS
+};
+
+DRIVER_INFORMATION DriverInfo = {0};
+NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
+
+
+BOOLEAN MiniportCheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext)
+/*
+ * FUNCTION: Examines if an adapter has hung
+ * ARGUMENTS:
+ * MiniportAdapterContext = Pointer to adapter context area
+ * RETURNS:
+ * TRUE if the adapter has hung, FALSE if not
+ */
+{
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ return FALSE;
+}
+
+
+VOID MiniportDisableInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext)
+/*
+ * FUNCTION: Disables interrupts from an adapter
+ * ARGUMENTS:
+ * MiniportAdapterContext = Pointer to adapter context area
+ */
+{
+ NDIS_DbgPrint(MAX_TRACE, ("Called. (MiniportDisableInterrupt).\n"));
+#ifndef NOCARD
+ NICDisableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
+#endif
+}
+
+
+VOID MiniportEnableInterrupt(
+ IN NDIS_HANDLE MiniportAdapterContext)
+/*
+ * FUNCTION: Enables interrupts from an adapter
+ * ARGUMENTS:
+ * MiniportAdapterContext = Pointer to adapter context area
+ */
+{
+ NDIS_DbgPrint(MAX_TRACE, ("Called. (MiniportEnableInterrupt).\n"));
+#ifndef NOCARD
+ NICEnableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
+#endif
+}
+
+
+VOID MiniportHalt(
+ IN NDIS_HANDLE MiniportAdapterContext)
+/*
+ * FUNCTION: Deallocates resources for and halts an adapter
+ * ARGUMENTS:
+ * MiniportAdapterContext = Pointer to adapter context area
+ */
+{
+ PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+#ifndef NOCARD
+ /* Stop the NIC */
+ NICStop(Adapter);
+#endif
+ /* Wait for any DPCs to complete. FIXME: Use something else */
+ NdisStallExecution(250000);
+
+ if (Adapter->InterruptRegistered)
+ /* Deregister interrupt */
+ NdisMDeregisterInterrupt(&Adapter->Interrupt);
+
+ if (Adapter->IOPortRangeRegistered)
+ /* Deregister I/O port range */
+ NdisMDeregisterIoPortRange(
+ Adapter->MiniportAdapterHandle,
+ Adapter->IoBaseAddress,
+ 0x20,
+ Adapter->IOBase);
+
+ /* Remove adapter from global adapter list */
+ RemoveEntryList(&Adapter->ListEntry);
+
+ /* Free adapter context area */
+ NdisFreeMemory(Adapter, sizeof(NIC_ADAPTER), 0);
+}
+
+
+NDIS_STATUS MiniportInitialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_HANDLE WrapperConfigurationContext)
+/*
+ * FUNCTION: Adapter initialization function
+ * ARGUMENTS:
+ * OpenErrorStatus = Address of buffer to place additional status information
+ * SelectedMediumIndex = Address of buffer to place selected medium index
+ * MediumArray = Pointer to an array of NDIS_MEDIUMs
+ * MediaArraySize = Number of elements in MediumArray
+ * MiniportAdapterHandle = Miniport adapter handle assigned by NDIS
+ * WrapperConfigurationContext = Handle used to identify configuration context
+ * RETURNS:
+ * Status of operation
+ */
+{
+ UINT i;
+ NDIS_STATUS Status;
+ PNIC_ADAPTER Adapter;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ /* Search for 802.3 media which is the only one we support */
+ for (i = 0; i < MediumArraySize; i++) {
+ if (MediumArray[i] == NdisMedium802_3)
+ break;
+ }
+
+ if (i == MediumArraySize) {
+ NDIS_DbgPrint(MIN_TRACE, ("No supported medias.\n"));
+ return NDIS_STATUS_UNSUPPORTED_MEDIA;
+ }
+
+ *SelectedMediumIndex = i;
+
+ Status = NdisAllocateMemory((PVOID)&Adapter,
+ sizeof(NIC_ADAPTER),
+ 0,
+ HighestAcceptableMax);
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+ return Status;
+ }
+
+ NdisZeroMemory(Adapter, sizeof(NIC_ADAPTER));
+ Adapter->MiniportAdapterHandle = MiniportAdapterHandle;
+ Adapter->IoBaseAddress = DRIVER_DEFAULT_IO_BASE_ADDRESS;
+ Adapter->InterruptNumber = DRIVER_DEFAULT_INTERRUPT_NUMBER;
+ Adapter->MaxMulticastListSize = DRIVER_MAX_MULTICAST_LIST_SIZE;
+ Adapter->InterruptMask = DRIVER_INTERRUPT_MASK;
+ Adapter->LookaheadSize = DRIVER_MAXIMUM_LOOKAHEAD;
+
+ NdisMSetAttributes(
+ MiniportAdapterHandle,
+ (NDIS_HANDLE)Adapter,
+ FALSE,
+ NdisInterfaceIsa);
+
+ Status = NdisMRegisterIoPortRange(
+ (PVOID*)&Adapter->IOBase,
+ MiniportAdapterHandle,
+ Adapter->IoBaseAddress,
+ 0x20);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NDIS_DbgPrint(MIN_TRACE, ("Cannot register port range. Status (0x%X).\n", Status));
+ MiniportHalt((NDIS_HANDLE)Adapter);
+ return Status;
+ }
+
+ Adapter->IOPortRangeRegistered = TRUE;
+
+ /* Initialize NIC */
+#ifndef NOCARD
+ Status = NICInitialize(Adapter);
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NDIS_DbgPrint(MIN_TRACE, ("Cannot find NE2000 NIC. Status (0x%X).\n", Status));
+ MiniportHalt((NDIS_HANDLE)Adapter);
+ return Status;
+ }
+
+ NDIS_DbgPrint(MAX_TRACE, ("BOARDDATA:\n"));
+ for (i = 0; i < 4; i++) {
+ NDIS_DbgPrint(MAX_TRACE, ("%02X %02X %02X %02X\n",
+ Adapter->SAPROM[i*4+0],
+ Adapter->SAPROM[i*4+1],
+ Adapter->SAPROM[i*4+2],
+ Adapter->SAPROM[i*4+3]));
+ }
+
+ /* Setup adapter structure */
+ Adapter->TXStart = ((ULONG_PTR)Adapter->RamBase >> 8);
+ Adapter->TXCount = DRIVER_DEFAULT_TX_BUFFER_COUNT;
+ Adapter->TXFree = DRIVER_DEFAULT_TX_BUFFER_COUNT;
+ Adapter->TXCurrent = -1;
+ Adapter->PageStart = Adapter->TXStart + Adapter->TXCount;
+ Adapter->PageStop = Adapter->TXStart + (Adapter->RamSize >> 8);
+
+ /* Initialize multicast address mask to accept all */
+ for (i = 0; i < 8; i++)
+ Adapter->MulticastAddressMask[i] = 0xFF;
+
+ /* Setup the NIC */
+ NICSetup(Adapter);
+
+ NDIS_DbgPrint(MIN_TRACE, ("TXStart (0x%X) TXCount (0x%X) PageStart (0x%X)\n",
+ Adapter->TXStart,
+ Adapter->TXCount,
+ Adapter->PageStart));
+
+ NDIS_DbgPrint(MIN_TRACE, ("PageStop (0x%X) CurrentPage (0x%X) NextPacket (0x%X).\n",
+ Adapter->PageStop,
+ Adapter->CurrentPage,
+ Adapter->NextPacket));
+#endif
+ /* Register the interrupt */
+ Status = NdisMRegisterInterrupt(
+ &Adapter->Interrupt,
+ MiniportAdapterHandle,
+ Adapter->InterruptNumber,
+ Adapter->InterruptNumber,
+ FALSE,
+ FALSE,
+ NdisInterruptLatched);
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NDIS_DbgPrint(MIN_TRACE, ("Cannot register interrupt. Status (0x%X).\n", Status));
+ MiniportHalt((NDIS_HANDLE)Adapter);
+ return Status;
+ }
+
+ Adapter->InterruptRegistered = TRUE;
+#ifndef NOCARD
+ /* Start the NIC */
+ NICStart(Adapter);
+#endif
+ /* Add adapter to the global adapter list */
+ InsertTailList(&DriverInfo.AdapterListHead, &Adapter->ListEntry);
+
+ NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+VOID MiniportISR(
+ OUT PBOOLEAN InterruptRecognized,
+ OUT PBOOLEAN QueueMiniportHandleInterrupt,
+ IN NDIS_HANDLE MiniportAdapterContext)
+/*
+ * FUNCTION: Interrupt Service Routine for controlled adapters
+ * ARGUMENTS:
+ * InterruptRecognized = Address of buffer to place wether
+ * the adapter generated the interrupt
+ * QueueMiniportHandleInterrupt = Address of buffer to place wether
+ * MiniportHandleInterrupt should be called
+ * MiniportAdapterContext = Pointer to adapter context area
+ * NOTES:
+ * All pending interrupts are handled
+ */
+{
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ NICDisableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
+
+ *InterruptRecognized = TRUE;
+ *QueueMiniportHandleInterrupt = TRUE;
+}
+
+
+NDIS_STATUS MiniportQueryInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded)
+/*
+ * FUNCTION: Handler to process queries
+ * ARGUMENTS:
+ * MiniportAdapterContext = Pointer to adapter context area
+ * Oid = OID code designating query operation
+ * InformationBuffer = Address of return buffer
+ * InformationBufferLength = Length of return buffer
+ * BytesWritten = Address of buffer to place number of bytes returned
+ * BytesNeeded = Address of buffer to place number of bytes needed
+ * in InformationBuffer for specified OID
+ * RETURNS:
+ * Status of operation
+ */
+{
+ NDIS_STATUS Status;
+ PVOID CopyFrom;
+ UINT CopySize;
+ ULONG GenericULONG;
+ USHORT GenericUSHORT;
+ NDIS_MEDIUM Medium = NdisMedium802_3;
+ PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called. Oid (0x%X).\n", Oid));
+
+ Status = NDIS_STATUS_SUCCESS;
+ CopyFrom = (PVOID)&GenericULONG;
+ CopySize = sizeof(ULONG);
+
+ switch (Oid) {
+ case OID_GEN_SUPPORTED_LIST:
+ CopyFrom = (PVOID)&MiniportOIDList;
+ CopySize = sizeof(MiniportOIDList);
+ break;
+ case OID_GEN_HARDWARE_STATUS:
+ GenericULONG = (ULONG)NdisHardwareStatusReady;
+ break;
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ CopyFrom = (PVOID)&Medium;
+ CopySize = sizeof(NDIS_MEDIUM);
+ break;
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+ GenericULONG = DRIVER_MAXIMUM_LOOKAHEAD;
+ break;
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ GenericULONG = DRIVER_FRAME_SIZE - DRIVER_HEADER_SIZE;
+ break;
+ case OID_GEN_LINK_SPEED:
+ GenericULONG = 100000; /* 10Mbps */
+ break;
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+ GenericULONG = Adapter->TXCount * DRIVER_BLOCK_SIZE;
+ break;
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+ GenericULONG = Adapter->RamSize -
+ (ULONG_PTR)Adapter->RamBase -
+ (Adapter->TXCount * DRIVER_BLOCK_SIZE);
+ break;
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ GenericULONG = DRIVER_BLOCK_SIZE;
+ break;
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ GenericULONG = DRIVER_BLOCK_SIZE;
+ break;
+ case OID_GEN_VENDOR_ID:
+ NdisMoveMemory(&GenericULONG, &Adapter->PermanentAddress, 3);
+ GenericULONG &= 0xFFFFFF00;
+ GenericULONG |= 0x01;
+ break;
+ case OID_GEN_VENDOR_DESCRIPTION:
+ CopyFrom = (PVOID)&DRIVER_VENDOR_DESCRIPTION;
+ CopySize = sizeof(DRIVER_VENDOR_DESCRIPTION);
+ break;
+ case OID_GEN_VENDOR_DRIVER_VERSION:
+ GenericUSHORT = (USHORT)DRIVER_VENDOR_DRIVER_VERSION;
+ CopyFrom = (PVOID)&GenericUSHORT;
+ CopySize = sizeof(USHORT);
+ break;
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ GenericULONG = Adapter->PacketFilter;
+ break;
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ GenericULONG = Adapter->LookaheadSize;
+ break;
+ case OID_GEN_DRIVER_VERSION:
+ GenericUSHORT = ((USHORT)DRIVER_NDIS_MAJOR_VERSION << 8) | DRIVER_NDIS_MINOR_VERSION;
+ CopyFrom = (PVOID)&GenericUSHORT;
+ CopySize = sizeof(USHORT);
+ break;
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ GenericULONG = DRIVER_FRAME_SIZE;
+ break;
+ case OID_GEN_PROTOCOL_OPTIONS:
+ NDIS_DbgPrint(MAX_TRACE, ("OID_GEN_PROTOCOL_OPTIONS.\n"));
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ case OID_GEN_MAC_OPTIONS:
+ GenericULONG = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
+ NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+ NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
+ NDIS_MAC_OPTION_NO_LOOPBACK;
+ break;
+ case OID_GEN_MEDIA_CONNECT_STATUS:
+ GenericULONG = (ULONG)NdisMediaStateConnected;
+ break;
+ case OID_GEN_MAXIMUM_SEND_PACKETS:
+ GenericULONG = 1;
+ break;
+ case OID_802_3_PERMANENT_ADDRESS:
+ CopyFrom = (PVOID)&Adapter->PermanentAddress;
+ CopySize = DRIVER_LENGTH_OF_ADDRESS;
+ break;
+ case OID_802_3_CURRENT_ADDRESS:
+ CopyFrom = (PVOID)&Adapter->StationAddress;
+ CopySize = DRIVER_LENGTH_OF_ADDRESS;
+ break;
+ case OID_802_3_MULTICAST_LIST:
+ NDIS_DbgPrint(MAX_TRACE, ("OID_802_3_MULTICAST_LIST.\n"));
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ GenericULONG = Adapter->MaxMulticastListSize;
+ break;
+ case OID_802_3_MAC_OPTIONS:
+ NDIS_DbgPrint(MAX_TRACE, ("OID_802_3_MAC_OPTIONS.\n"));
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ default:
+ NDIS_DbgPrint(MIN_TRACE, ("Unknown OID (0x%X).\n", Oid));
+ Status = NDIS_STATUS_INVALID_OID;
+ break;
+ }
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+ if (CopySize > InformationBufferLength) {
+ *BytesNeeded = (CopySize - InformationBufferLength);
+ *BytesWritten = 0;
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ } else {
+ NdisMoveMemory(InformationBuffer, CopyFrom, CopySize);
+ *BytesWritten = CopySize;
+ *BytesNeeded = 0;
+ }
+ }
+
+ NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status is (0x%X).\n", Status));
+
+ return Status;
+}
+
+
+NDIS_STATUS MiniportReconfigure(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE WrapperConfigurationContext)
+/*
+ * FUNCTION: Reconfigures an adapter
+ * ARGUMENTS:
+ * OpenErrorStatus = Address of buffer to place additional status information
+ * MiniportAdapterContext = Pointer to adapter context area
+ * WrapperConfigurationContext = Handle used to identify configuration context
+ * RETURNS:
+ * Status of operation
+ * NOTES:
+ * Never called by NDIS library
+ */
+{
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ return NDIS_STATUS_FAILURE;
+}
+
+
+
+NDIS_STATUS MiniportReset(
+ OUT PBOOLEAN AddressingReset,
+ IN NDIS_HANDLE MiniportAdapterContext)
+/*
+ * FUNCTION: Resets an adapter
+ * ARGUMENTS:
+ * AddressingReset = Address of a buffer to place value indicating
+ * wether NDIS library should call MiniportSetInformation
+ * to restore addressing information
+ * MiniportAdapterContext = Pointer to adapter context area
+ * RETURNS:
+ * Status of operation
+ */
+{
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ return NDIS_STATUS_FAILURE;
+}
+
+
+NDIS_STATUS MiniportSend(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PNDIS_PACKET Packet,
+ IN UINT Flags)
+/*
+ * FUNCTION: Transmits a packet
+ * ARGUMENTS:
+ * MiniportAdapterContext = Pointer to adapter context area
+ * Packet = Pointer to a packet descriptor specifying
+ * the data to be transmitted
+ * Flags = Specifies optional packet flags
+ * RETURNS:
+ * Status of operation
+ */
+{
+ PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Queueing packet.\n"));
+
+#ifdef NOCARD
+ NdisMSendComplete(Adapter->MiniportAdapterHandle,
+ Packet,
+ NDIS_STATUS_SUCCESS);
+#else
+ /* Queue the packet on the transmit queue */
+ RESERVED(Packet)->Next = NULL;
+ if (Adapter->TXQueueHead == NULL) {
+ Adapter->TXQueueHead = Packet;
+ } else {
+ RESERVED(Adapter->TXQueueTail)->Next = Packet;
+ }
+
+ Adapter->TXQueueTail = Packet;
+
+ /* Transmit the packet */
+ NICTransmit(Adapter);
+#endif
+ return NDIS_STATUS_PENDING;
+}
+
+
+NDIS_STATUS MiniportSetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesRead,
+ OUT PULONG BytesNeeded)
+/*
+ * FUNCTION: Changes state information in the driver
+ * ARGUMENTS:
+ * MiniportAdapterContext = Pointer to adapter context area
+ * Oid = OID code designating set operation
+ * InformationBuffer = Pointer to buffer with state information
+ * InformationBufferLength = Length of InformationBuffer
+ * BytesRead = Address of buffer to place number of bytes read
+ * BytesNeeded = Address of buffer to place number of extra bytes
+ * needed in InformationBuffer for specified OID
+ * RETURNS:
+ * Status of operation
+ */
+{
+ ULONG GenericULONG;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called. Oid (0x%X).\n", Oid));
+
+ switch (Oid) {
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ /* Verify length */
+ if (InformationBufferLength < sizeof(ULONG)) {
+ *BytesRead = 0;
+ *BytesNeeded = sizeof(ULONG) - InformationBufferLength;
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ break;
+ }
+
+ NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG));
+ /* Check for properties the driver don't support */
+ if (GenericULONG &
+ (NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
+ NDIS_PACKET_TYPE_FUNCTIONAL |
+ NDIS_PACKET_TYPE_GROUP |
+ NDIS_PACKET_TYPE_MAC_FRAME |
+ NDIS_PACKET_TYPE_SMT |
+ NDIS_PACKET_TYPE_SOURCE_ROUTING)) {
+ *BytesRead = 4;
+ *BytesNeeded = 0;
+ Status = NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ Adapter->PacketFilter = GenericULONG;
+
+ /* FIXME: Set filter on hardware */
+
+ break;
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ /* Verify length */
+ if (InformationBufferLength < sizeof(ULONG)) {
+ *BytesRead = 0;
+ *BytesNeeded = sizeof(ULONG) - InformationBufferLength;
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ break;
+ }
+
+ NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG));
+ if (GenericULONG > DRIVER_MAXIMUM_LOOKAHEAD)
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ else
+ Adapter->LookaheadSize = GenericULONG;
+ break;
+ case OID_802_3_MULTICAST_LIST:
+ /* Verify length. Must be multiplum of hardware address length */
+ if ((InformationBufferLength % DRIVER_LENGTH_OF_ADDRESS) != 0) {
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+ Status = NDIS_STATUS_INVALID_LENGTH;
+ break;
+ }
+
+ /* Set new multicast address list */
+ NdisMoveMemory(Adapter->Addresses, InformationBuffer, InformationBufferLength);
+
+ /* FIXME: Update hardware */
+
+ break;
+ default:
+ NDIS_DbgPrint(MIN_TRACE, ("Invalid object ID (0x%X).\n", Oid));
+ *BytesRead = 0;
+ *BytesNeeded = 0;
+ Status = NDIS_STATUS_INVALID_OID;
+ break;
+ }
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+ *BytesRead = InformationBufferLength;
+ *BytesNeeded = 0;
+ }
+
+ NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
+
+ return Status;
+}
+
+
+NDIS_STATUS MiniportTransferData(
+ OUT PNDIS_PACKET Packet,
+ OUT PUINT BytesTransferred,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE MiniportReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer)
+/*
+ * FUNCTION: Transfers data from a received frame into an NDIS packet
+ * ARGUMENTS:
+ * Packet = Address of packet to copy received data into
+ * BytesTransferred = Address of buffer to place number of bytes transmitted
+ * MiniportAdapterContext = Pointer to adapter context area
+ * MiniportReceiveContext = Pointer to receive context area (actually NULL)
+ * ByteOffset = Offset within received packet to begin copying
+ * BytesToTransfer = Number of bytes to copy into packet
+ * RETURNS:
+ * Status of operation
+ */
+{
+ PNDIS_BUFFER DstBuffer;
+ UINT BytesCopied, BytesToCopy, DstSize;
+ ULONG SrcData;
+ PUCHAR DstData;
+ UINT RecvStart;
+ UINT RecvStop;
+ PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called. Packet (0x%X) ByteOffset (0x%X) BytesToTransfer (%d).\n",
+ Packet, ByteOffset, BytesToTransfer));
+
+ if (BytesToTransfer == 0) {
+ *BytesTransferred = 0;
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ RecvStart = Adapter->PageStart * DRIVER_BLOCK_SIZE;
+ RecvStop = Adapter->PageStop * DRIVER_BLOCK_SIZE;
+
+ NdisQueryPacket(Packet, NULL, NULL, &DstBuffer, NULL);
+ NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
+
+ SrcData = Adapter->PacketOffset + sizeof(PACKET_HEADER) + ByteOffset;
+ if (ByteOffset + sizeof(PACKET_HEADER) + BytesToTransfer > Adapter->PacketHeader.PacketLength)
+ BytesToTransfer = Adapter->PacketHeader.PacketLength- sizeof(PACKET_HEADER) - ByteOffset;
+
+ /* Start copying the data */
+ BytesCopied = 0;
+ for (;;) {
+ BytesToCopy = (DstSize < BytesToTransfer)? DstSize : BytesToTransfer;
+ if (SrcData + BytesToCopy > RecvStop)
+ BytesToCopy = (RecvStop - SrcData);
+
+ NICReadData(Adapter, DstData, SrcData, BytesToCopy);
+
+ BytesCopied += BytesToCopy;
+ SrcData += BytesToCopy;
+ (ULONG_PTR)DstData += BytesToCopy;
+ BytesToTransfer -= BytesToCopy;
+ if (BytesToTransfer == 0)
+ break;
+
+ DstSize -= BytesToCopy;
+ if (DstSize == 0) {
+ /* No more bytes in destination buffer. Proceed to
+ the next buffer in the destination buffer chain */
+ NdisGetNextBuffer(DstBuffer, &DstBuffer);
+ if (!DstBuffer)
+ break;
+
+ NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
+ }
+
+ if (SrcData == RecvStop)
+ SrcData = RecvStart;
+ }
+
+ NDIS_DbgPrint(MAX_TRACE, ("Transferred (%d) bytes.\n", BytesToTransfer));
+
+ *BytesTransferred = BytesCopied;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+#ifndef _MSC_VER
+STDCALL
+#endif
+DriverEntry(
+ PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Main driver entry point
+ * ARGUMENTS:
+ * DriverObject = Pointer to a driver object for this driver
+ * RegistryPath = Registry node for configuration parameters
+ * RETURNS:
+ * Status of driver initialization
+ */
+{
+ NDIS_STATUS Status;
+ NDIS_HANDLE NdisWrapperHandle;
+ NDIS_MINIPORT_CHARACTERISTICS Miniport;
+
+ NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+ NdisZeroMemory(&Miniport, sizeof(Miniport));
+ Miniport.MajorNdisVersion = DRIVER_NDIS_MAJOR_VERSION;
+ Miniport.MinorNdisVersion = DRIVER_NDIS_MINOR_VERSION;
+ Miniport.CheckForHangHandler = NULL; //MiniportCheckForHang;
+ Miniport.DisableInterruptHandler = MiniportDisableInterrupt;
+ Miniport.EnableInterruptHandler = MiniportEnableInterrupt;
+ Miniport.HaltHandler = MiniportHalt;
+ Miniport.HandleInterruptHandler = MiniportHandleInterrupt;
+ Miniport.InitializeHandler = MiniportInitialize;
+ Miniport.ISRHandler = MiniportISR;
+ Miniport.QueryInformationHandler = MiniportQueryInformation;
+ Miniport.ReconfigureHandler = MiniportReconfigure;
+ Miniport.ResetHandler = MiniportReset;
+ Miniport.u1.SendHandler = MiniportSend;
+ Miniport.SetInformationHandler = MiniportSetInformation;
+ Miniport.u2.TransferDataHandler = MiniportTransferData;
+
+ NdisMInitializeWrapper(&NdisWrapperHandle,
+ DriverObject,
+ RegistryPath,
+ NULL);
+
+ DriverInfo.NdisWrapperHandle = NdisWrapperHandle;
+ DriverInfo.NdisMacHandle = NULL;
+ InitializeListHead(&DriverInfo.AdapterListHead);
+
+ Status = NdisMRegisterMiniport(NdisWrapperHandle,
+ &Miniport,
+ sizeof(NDIS_MINIPORT_CHARACTERISTICS));
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NDIS_DbgPrint(MIN_TRACE, ("NdisMRegisterMiniport() failed with status code (0x%X).\n", Status));
+ NdisTerminateWrapper(NdisWrapperHandle, NULL);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/* EOF */
--- /dev/null
+Build instructions for NE2000 driver
+------------------------------------
+
+Building with Visual C++ and Windows NT DDK:
+
+Variables:
+%BASEDIR% = path to NT4 DDK (e.g. c:\ntddk)
+%DDKBUILDENV% = DDK build environment (free or checked)
+
+DDK environment variables must be set! (run setenv.bat)
+
+ - Create the directory objects/i386/%DDKBUILDENV%
+ - Run "build" to build the driver
+
+
+Building with Mingw32 and ReactOS include files:
+
+ - Run "make ne2000" FROM THE ReactOS ROOT DIRECTORY to build the driver