From 9a1e13b7d826570adb32b5d293d2e6bae85be81c Mon Sep 17 00:00:00 2001 From: Casper Hornstrup Date: Sun, 27 Aug 2000 16:35:31 +0000 Subject: [PATCH] Added Novell Eagle 2000 Driver svn path=/trunk/; revision=1319 --- reactos/Makefile | 25 +- reactos/drivers/net/dd/ne2000/DIRS | 1 + reactos/drivers/net/dd/ne2000/Makefile | 118 ++ reactos/drivers/net/dd/ne2000/include/8390.h | 157 ++ reactos/drivers/net/dd/ne2000/include/debug.h | 92 ++ .../drivers/net/dd/ne2000/include/ne2000.h | 249 +++ reactos/drivers/net/dd/ne2000/ne2000.def | 7 + reactos/drivers/net/dd/ne2000/ne2000.rc | 38 + reactos/drivers/net/dd/ne2000/ne2000/8390.c | 1343 +++++++++++++++++ reactos/drivers/net/dd/ne2000/ne2000/MAKEFILE | 6 + .../drivers/net/dd/ne2000/ne2000/RESOURCE.RC | 10 + reactos/drivers/net/dd/ne2000/ne2000/SOURCES | 15 + reactos/drivers/net/dd/ne2000/ne2000/main.c | 806 ++++++++++ reactos/drivers/net/dd/ne2000/readme.txt | 18 + 14 files changed, 2881 insertions(+), 4 deletions(-) create mode 100644 reactos/drivers/net/dd/ne2000/DIRS create mode 100644 reactos/drivers/net/dd/ne2000/Makefile create mode 100644 reactos/drivers/net/dd/ne2000/include/8390.h create mode 100644 reactos/drivers/net/dd/ne2000/include/debug.h create mode 100644 reactos/drivers/net/dd/ne2000/include/ne2000.h create mode 100644 reactos/drivers/net/dd/ne2000/ne2000.def create mode 100644 reactos/drivers/net/dd/ne2000/ne2000.rc create mode 100644 reactos/drivers/net/dd/ne2000/ne2000/8390.c create mode 100644 reactos/drivers/net/dd/ne2000/ne2000/MAKEFILE create mode 100644 reactos/drivers/net/dd/ne2000/ne2000/RESOURCE.RC create mode 100644 reactos/drivers/net/dd/ne2000/ne2000/SOURCES create mode 100644 reactos/drivers/net/dd/ne2000/ne2000/main.c create mode 100644 reactos/drivers/net/dd/ne2000/readme.txt diff --git a/reactos/Makefile b/reactos/Makefile index b0d586dd3ea..0b0b62edec5 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -14,7 +14,7 @@ include rules.mak # 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 # @@ -41,11 +41,13 @@ FS_DRIVERS = vfat # ndis tdi tcpip tditest NET_DRIVERS = ndis tcpip tditest -KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) $(NET_DRIVERS) +# ne2000 +NET_DEVICE_DRIVERS = ne2000 + +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 - + pteb consume dump_shared_data vmtest wstest # objdir all: buildno $(COMPONENTS) $(DLLS) $(SUBSYS) $(LOADERS) $(KERNEL_SERVICES) $(APPS) @@ -183,6 +185,21 @@ $(NET_DRIVERS:%=%_dist): %_dist: .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 # diff --git a/reactos/drivers/net/dd/ne2000/DIRS b/reactos/drivers/net/dd/ne2000/DIRS new file mode 100644 index 00000000000..98e9381dc59 --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/DIRS @@ -0,0 +1 @@ +DIRS= ne2000 diff --git a/reactos/drivers/net/dd/ne2000/Makefile b/reactos/drivers/net/dd/ne2000/Makefile new file mode 100644 index 00000000000..3a2f68fc4df --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/Makefile @@ -0,0 +1,118 @@ +# $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 diff --git a/reactos/drivers/net/dd/ne2000/include/8390.h b/reactos/drivers/net/dd/ne2000/include/8390.h new file mode 100644 index 00000000000..f1e0f7b1dce --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/include/8390.h @@ -0,0 +1,157 @@ +/* + * 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 */ diff --git a/reactos/drivers/net/dd/ne2000/include/debug.h b/reactos/drivers/net/dd/ne2000/include/debug.h new file mode 100644 index 00000000000..5b96c6fb9cc --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/include/debug.h @@ -0,0 +1,92 @@ +/* + * 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 */ diff --git a/reactos/drivers/net/dd/ne2000/include/ne2000.h b/reactos/drivers/net/dd/ne2000/include/ne2000.h new file mode 100644 index 00000000000..b630afe075c --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/include/ne2000.h @@ -0,0 +1,249 @@ +/* + * 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 +#else +#include +#endif +#include <8390.h> +#include + +/* 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 */ diff --git a/reactos/drivers/net/dd/ne2000/ne2000.def b/reactos/drivers/net/dd/ne2000/ne2000.def new file mode 100644 index 00000000000..cb1da925a43 --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/ne2000.def @@ -0,0 +1,7 @@ +; Novell Eagle 2000 driver - ReactOS Operating System + +LIBRARY NE2000.SYS + +EXPORTS + +; EOF diff --git a/reactos/drivers/net/dd/ne2000/ne2000.rc b/reactos/drivers/net/dd/ne2000/ne2000.rc new file mode 100644 index 00000000000..d345102f38b --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/ne2000.rc @@ -0,0 +1,38 @@ +#include +#include + +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 + diff --git a/reactos/drivers/net/dd/ne2000/ne2000/8390.c b/reactos/drivers/net/dd/ne2000/ne2000/8390.c new file mode 100644 index 00000000000..9de55f7d930 --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/ne2000/8390.c @@ -0,0 +1,1343 @@ +/* + * 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 + + +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 */ diff --git a/reactos/drivers/net/dd/ne2000/ne2000/MAKEFILE b/reactos/drivers/net/dd/ne2000/ne2000/MAKEFILE new file mode 100644 index 00000000000..6ee4f43fa46 --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/ne2000/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/reactos/drivers/net/dd/ne2000/ne2000/RESOURCE.RC b/reactos/drivers/net/dd/ne2000/ne2000/RESOURCE.RC new file mode 100644 index 00000000000..cc44c94142f --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/ne2000/RESOURCE.RC @@ -0,0 +1,10 @@ +#include +#include + +#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" diff --git a/reactos/drivers/net/dd/ne2000/ne2000/SOURCES b/reactos/drivers/net/dd/ne2000/ne2000/SOURCES new file mode 100644 index 00000000000..852122d74af --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/ne2000/SOURCES @@ -0,0 +1,15 @@ +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 diff --git a/reactos/drivers/net/dd/ne2000/ne2000/main.c b/reactos/drivers/net/dd/ne2000/ne2000/main.c new file mode 100644 index 00000000000..7f673d79fb4 --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/ne2000/main.c @@ -0,0 +1,806 @@ +/* + * 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 + + +#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 */ diff --git a/reactos/drivers/net/dd/ne2000/readme.txt b/reactos/drivers/net/dd/ne2000/readme.txt new file mode 100644 index 00000000000..368289c123e --- /dev/null +++ b/reactos/drivers/net/dd/ne2000/readme.txt @@ -0,0 +1,18 @@ +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