ne2000.386
Warning: This file has been marked up for HTML
page ,130
;
; $name: NE2000.386
; $version: 5
; $date_modified: 12181998
; $description: Novell NE2000 Driver Code for NetWare 386.
; $owner: ODI LAN Driver Manager
; Copyright (c) 1990 - 1998 Novell, Inc. All Rights Reserved.
; THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
; TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE
; AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS
; THIS WORK. PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS
; TO DEVELOPER A ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S
; SAMPLE CODE IN ITS PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE
; DISTRIBUTION RIGHTS TO MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE
; AS A COMPONENT OF DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO
; OBLIGATIONS TO DEVELOPER OR DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS
; CODE.
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( History, NE2000/HISTORY )
;
; Novell NE2000 Driver Code for NetWare 386.
; This driver must be loaded after MSM.NLM and ETHERNET.NLM.
;
; Written by: DFS
; Date: November, 1990
;
;***********************************************************************
;
; History Log:
;
; 01-11-91 dfs Disabled BackToBackSends to fix hang-up problems with
; Compaq 486/33s.
;
; 06-10-91 dfs Modified driver to new MSM spec and enabled interrupts.
;
; 09-03-91 dfs Converted to NLM.(Version 3.20)
;
; 12-14-92 dfs Added Shared RAM addresses FC0000, FC4000, FC8000, and
; FCC000 and added shared RAM auto detect.(Version 3.21)
;
; 12-16-92 dfs Deleted Shared RAM addresses FC0000 thru FCC000.
; Added Shared RAM addresses E00000,E20000...FC0000.
;
; 01-04-92 dfs Filled in MemoryDecode0 and Length0 if MEM= on command line
; to prevent ParseDriverParameters from asking for frame type.
;
; 01-05-93 dfs Added support for DriverEnableInterrupt/DriverDisableInterrupt.
;
; 01-07-93 dfs Added shared interrupt support to DriverDisableInterrupt.
; (Version 3.22)
;
; 01-20-93 dfs Cleared Interrupt Status in DriverISR if in shutdown state.
; (Version 3.23)
;
; 03-03-93 dfs Skipped Checksum bytes when searching for NE2000 signature
; at init.(Version 3.24)
;
; 06-17-93 dfs - Used MLIDMemoryDecode0 instead of MLIDLinearyMemory0
; when calculating Shared RAM control 1 and 2 value.
; - Disabled control 1 Memory enable bit at DriverShutdown.
; (Version 3.25)
;
; 10-06-93 akw - Modified packet reception to copy the exact Rx packet
; into memory (using PIO), previously 802.2 (odd) header packets
; and odd length packets were copying in 1 extra byte before
; and after the valid packet respectively.
;
; 11-03-93 akw - Took out hard-coded 17 byte look ahead for 802.2 use
; look ahead bytes copied value instead.
;
; 03-14-94 akw - Added HSM_SPEC_VERSION string.
; - When adjusting TotalBytes we subtract the frag size from it.
; If the frag size is bogus (> 80000000) we overwrite memory
; because the jump logic should be JNC instead of JNS.
; (version 3.28)
;
; 11-08-94 jcp Version 3.50 (Post NetWare 4.10 release)
; - One of the variable "TransmitPage1" does not has Adapter
; Data Space pointer [EBP].
; - Removed 0 dup (0).
; - Replaced ReadTickCounter with MSMGetMicroTimer. Function
; ReadTickCounter can not be ported to different platform,
; like UnixWare.
;
; 02-08-95 tnl Added "slow" code to DoRAMTest write/read loops to fix
; occasional RAM Failure errors when loading driver on Compaq
; XL Pentium machines.
;
; 02-16-95 tnl Added VerifyIRQ code which is called at DriverInit time to
; verify that INT specified by user on load command line
; matches that of the hardware. If there is a mismatch we
; display message and error out.
; (version 3.51)
;
; 03-02-95 tnl Added to 2-16-95 changes additional code to verify IRQ when
; in shared RAM mode.
; (version 3.51)
;
; 03-03-95 tnl Fixed problem in DriverISR receive path where bytes to copy =
; 0 case wasn't being handled properly.
; (version 3.51)
;
; 03-16-95 tnl Changed call to MSMPrintString to MSMPrintStringFatal
; in DriverInit as requested by NT team.
; (version 3.51)
;
; 03-20-95 tnl Added 3/3/95 fix to shared RAM send path.
; (version 3.51)
;
; 03-27-95 tnl Changed call to MSMAlertFatal to MSMAlertWarning in DriverSend
; code on DMANotCompleteError.
;
; 05-02-95 tnl Took outdated APIs out of DRIVER.INC and makefile
;
; 06-07-95 tnl Added code based on CNE2000 (MCD) code which checks to see if
; any NE2000 cards exist before checking for SharedRAM mode.
; (version 3.52)
;
; 06-21-95 tnl Changed DriverInit error paths to correctly call
; MSMReturnDriverResources in all applicable cases.
; (version 3.53)
;
; 5 July 1995 13:47 DGM
; Corrected some DriverInit error paths to correctly call
; MSMReturnDriverResources in all applicable cases.
; (version 3.54)
;
; 07-14-95 tnl Modified VerifyIRQ to detect whether NIC is AT/LANIC or 8390.
; If AT/LANIC (NE2000+) then we won't do any loopback testing
; since AT/LANIC has problems with loopback mode.
; (version 3.55)
;
; 08-22-95 tnl Modified DriverReset to set TxFreeCount. This is to solve
; problems where DriverReset is called internally while
; TxFreeCount is less than max and TxFreeCount not getting
; set correctly; causes driver to stop transmitting.
; (version 3.56)
;
; 25 August 1995 17:53 DGM
; Added DriverAES and MSMScheduleAESCallBack for it in DriverInit
; to try to overcome 8390 IMR glitch by occasionally causing
; disableing/enabling NIC functions to be called.
;
; 13 September 1995 14:00 MPK
; Made changes to make code compatable with 3.3 specification.
; Includes changes to DriverConfigTemplate (versions and Scatter
; gap count, Also added changes to intialization, to determine
; BUS by use of NBI calls
;
; 01 December 1995 TNL
; Modify CheckForSharedRAM code to fix problem where driver won't
; load for PIO mode card after shared RAM card was loaded first.
;
; 12 February 1996 TNL
; Modify Config Table template to initialize MlidSlot field to -1 in
; accordance with 3.3 spec.
;
; 13 February 1996 TNL
; Modified DriverInit to call MSMScheduleIntTimeCallback and
; MSMSetHardwareInterrupt in the correct sequence as per HSM spec
; (SPDs #115634/#117316). By doing this we can also safely remove
; 25 August 1995 DGM code change.
;
; Also modified VerifyIRQ slightly to accomodate
; NE2000 clone cards that aren't completely 100% NE2000 compatible.
;
; 28 March 1996 TNL
; Modified DriverInit to call MSMReturnDriverResources only when
; appropriate as shown in 3.3 spec. SPD #121140.
;
; 07 May 1996 TNL
; Added code to DriverInit/DriverISR to take care of SMP load hang
; problems due to DriverInit being unprotected on SMP. SPD 125034.
;
; 09 May 1996 TNL
; Added code to CheckForSharedRAM to handle case where bogus prompt
; for MEM is made sometimes when card is in PIO mode. SPD 124386.
;
; 04 June 1996 TNL
; Modified VerifyIRQ code to not do explicit sti. It now calls
; MSMYieldWithDelay which will enable ints momentarily.
; SPD 127484.
;
; 30 October 1996 ZA
; The following changes were made in updating the DriverConfiguration
; Table to 3.31 specs :-
;
; -Set MLIDCFG_MinorVersion to 14 instead of 13.
; -splitted the MLIDReserved field to
; MLIDReserved1
; MLIDPrioritySup
; MLIDReserved2
;
; Also the following changes were made to the Driver Parameter Table
; updating it to 3.31 specs:-
;
; -The following fields were added and initialised to NULL
; i)DriverISR2Ptr ii)DriverReserved2 iii)DriverPriorityQueuePtr
; iv)DriverDisableInterrupt2Ptr
; -HSMSPEC field is modified to 'HSM_SPEC_VERSION: 3.31',0
; -A new field HSMSpecVerString is entered and initialised to HSMSPEC
; SPD 140020
;
; 22 November 1996 ZA
; The DriverPromiscuousChange was modified to include RemoteMultiCast
; in order to conform to the 3.31 specs.
;
;
; 22 November 1996 ZA
; Modified DriverReset and DriverShutdown routines to add
; operation scope parameter.
;
; 04 July 1997 JCJ Version 3.64
; -Changed MLIDBusTag to 0 if found bus type is ISA. SPD#160730
; -IODetachedBit checking is removed from DriverISR since partial shutdown
; need to be supported. Instead now we check for MSMStatusFlags SHUTDOWN bit
; SPD#158389
; AYD -Verify IRQ only if it is Shared RAM card SPD#132446
;
; 18 December 1997 WTT Version 3.65
; Fixed code to initialized all fields to a known state in
; the AdapterOptions structure AdapterOptionDefinitionStructure.
; The specification states that all unused fields must be set to
; zero. The code was assuming that the assembler would set all
; fields that did not have a specified value to zero. Newer
; versions of the assembler are not doing this.
; SPD 174346
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
name NE2000
title NE2000 LAN Driver (HSM Version)
subttl -- Structures and Equate Values --
page
include driver.inc
subttl -- NE2000 Specific Equates --
page
;
BackToBackSends equ -1
UseFastCalls equ -1
;
;***********************************************************************\
; *
; Equates. *
; *
;***********************************************************************/
;
; Command Register Bits.
;
NIC_Page0 equ 22h
NIC_Page1 equ 62h
NIC_Page0DMAWrite equ 12h
NIC_Page2DMAWrite equ 92h
NIC_RemoteDmaWr equ 12h
NIC_RemoteDmaRd equ 0ah
NIC_AbortDmaWr equ 32h
NIC_AbortDmaRd equ 2ah
NIC_Page0Stop equ 21h
NIC_Page1Stop equ 61h
NIC_Transmit equ 26h
NIC_TxInProgress equ 04h
;
; Interrupt Mask Register Bits.
;
NIC_MaskByte equ 00h
NIC_UnmaskByte equ 1fh
;
; Interrupt Status Register Bits.
;
NIC_PacketReady equ 15h
NIC_RecvError equ 14h
NIC_TxComplete equ 0ah
NIC_TransmitError equ 08h
;
; Transmit Status Register Bits.
;
NIC_Collisions equ 04h
NIC_ExcessCollisions equ 08h
NIC_CarrierSenseLost equ 10h
NIC_FIFO_Underrun equ 20h
NIC_CDHeartBeat equ 40h
NIC_OutOfWindowColl equ 80h
;
; Receive Status Register Bits.
;
CRCErrorBit equ 02h
FrameCRCErrorBits equ 06h
FIFOOverrunErrorBit equ 08h
MissedPacketErrorBit equ 10h
;
; Receive Configuration Bits.
;
NIC_Save_Errors equ 01h
NIC_Save_Runts equ 02h
NIC_Broadcast equ 04h
NIC_Multicast equ 08h
NIC_Promiscuous equ 10h
NIC_Monitor equ 20h
;
PSTART equ 4Ch ;12 pages for send (enough for 2 buffers)
PSTOP equ 80h
;
RAMPSTART equ 0Ch ;12 pages for send (enough for 2 buffers)
RAMPSTOP equ 40h
;
; More NIC Register Equates...
;
PhysicalReg0 equ PageStart
TransmitPage equ TransmitStatus
NumberCollisions equ TransmitByteCount0
FIFO equ TransmitByteCount1
Current equ InterruptStatus
ReceiveStatus equ ReceiveConfiguration
CurrentDMA0 equ RemoteStartAddress0
CurrentDMA1 equ RemoteStartAddress1
MultiCastAddrReg equ RemoteStartAddress0
TallyCounter0 equ TransmitConfiguration
TallyCounter1 equ DataConfiguration
TallyCounter2 equ InterruptMask
SizeOfCRCField equ 4
;
; Maximum Send Retries.
;
MaxRetries equ 10
;
; Shared RAM mode INT mask for Mode Configuration Register INT bits 3-5.
;
IntMask equ 38h
PUBLIC DriverCallBack
PUBLIC DriverISR
PUBLIC DriverMulticastChange
PUBLIC DriverReset
PUBLIC DriverSend
PUBLIC DriverShutdown
PUBLIC DriverPromiscuousChange
PUBLIC DriverEnableInterrupt
PUBLIC DriverDisableInterrupt
subttl -- NE2000 Specific Structures --
page
;
;***********************************************************************\
; *
; NE2000 Structures. *
; *
;***********************************************************************/
;
;
;***************************************************************\
; *
; MulticastTableStructure. *
; *
;***************************************************************/
;
MulticastTableStructure struc
MulticastAddress db 6 dup (0)
EntryUsed dw 0
MulticastTableStructure ends
;
;***************************************************************\
; *
; NE2000 I/O register structure. *
; *
;***************************************************************/
;
NIC struc
ICommand db ? ; 00h
IPageStart db ? ; 01h
IPageStop db ? ; 02h
IBoundary db ? ; 03h
ITransmitStatus db ? ; 04h
ITransmitByteCount0 db ? ; 05h
ITransmitByteCount1 db ? ; 06h
IInterruptStatus db ? ; 07h
IRemoteStartAddress0 db ? ; 08h
IRemoteStartAddress1 db ? ; 09h
IRemoteByteCount0 db ? ; 0Ah
IRemoteByteCount1 db ? ; 0Bh
IReceiveConfiguration db ? ; 0Ch
ITransmitConfiguration db ? ; 0Dh
IDataConfiguration db ? ; 0Eh
IInterruptMask db ? ; 0Fh
INICData db ? ; 10h
db 14 dup (?) ; 11h
IReset db ? ; 1Fh
NIC ends
NICSharedRAM struc
IControl1 db ? ; 00h
IATDetect db ? ; 01h
db 3 dup (?) ; 02h
IControl2 db ? ; 05h
db 2 dup (?) ; 06h
IProm db 8 dup (?) ; 08h
NICSharedRAM ends
IOConfigurationStructure struc
CLink dd ?
CFlags dw ?
CSlot dw ?
CIOPortsAndLengths dw 4 dup (?)
CMemoryDecode0 dd ?
CMemoryLength0 dw ? ; In Paragraphs
CMemoryDecode1 dd ?
CMemoryLength1 dw ?
CInterrupt db 2 dup (?)
CDMAUsage db 2 dup (?)
CResourceTag dd ?
CDriverConfig dd ?
CCommandString dd ?
CLogicalName db 18 dup (?)
CLinearMemory dd 2 dup (?)
CChannelNumber dw ?
CIOReserved db 6 dup (?)
IOConfigurationStructure ends
ITransmitPage equ ITransmitStatus
;
;***************************************************************\
; *
; Ethernet Receive Header Structure. *
; *
;***************************************************************/
;
ReceiveHeaderStructure struc
RReceiveStatus db ?
RNextBuffer db ?
RByteCount dw ?
ReceiveHeaderStructure ends
;
;***************************************************************\
; *
; Start of the Adapter Data Space structure for NE2000. *
; *
;***************************************************************/
;
;JCP
GenericVariableBegin equ offset TotalTxPacketCount ;941108 *Begin*
GenericVariableEnd equ offset CustomVariableCount
CustomVariableBegin equ offset UnderrunErrorCount
CustomVariableEnd equ offset VectorToTheStrings ;941108 *End*
DriverAdapterDataSpace struc
TxStartTime dd 0 ; Used to detect timeouts.
TransmitSize1 dd 0 ; Used to store Page 1 Tx size.
TransmitSize2 dd 0 ; Used to store Page 2 Tx size.
;
;***************************************************************\
; *
; TransmitStatusFlag tell us the status of the Send buffers. *
; *
; 00x = Sending packet -- waiting for TxComplete. *
; 0x0 = Packet we are sending is in Page2. *
; x00 = Data transferred to board, waiting for send *
; to complete. *
; *
; Example: *
; Start 010 Nothing being sent, page 1 is free. *
; SendPacket 001 Sending Page 1. *
; SendPacket 101 Data transferred to Page 2, still *
; waiting for page 1. *
; TxComplete 011 Sending Page2, page 1 is free. *
; SendPacket 111 Data in Page1, still waiting for *
; Page 2 to complete send. *
; etc. *
; *
;***************************************************************/
;
TransmitStatusFlag db 00000010b ; Not sending, Page 1 free.
;;InDriverISR db 0 ;; IF NOT UseFastCalls
NextPage db PSTART + 1 ; Used to detect page errors.
;
RxFragments dd 0
OddValue db 0
OddByteValue db 0
RetryTxFlag db 0 ; Used if Receive overflow occurs
OverflowRestartFlag db 0 ; Used if Receive overflow occurs.
FirstTimeInit db 1 ; Start out in driver init.
RetryCounter dd MaxRetries ; Tx Retry counter.
NICRAMSegmentBase dd 0 ; Shared RAM base.
NICRAMSegmentLimit dd 0 ; Recieve ring limit.
NICRAMReceiveRingStart dd 0 ; Receive ring start.
TransmitPage0 db 0c0h ; 1st I/O Transmit Page.
TransmitPage1 db 0c6h ; 2nd I/O Transmit Page.
CRCWorkArea db 6 dup (0) ;Used for multicast hashing.
ReceiveStatusTest db 4eh ; Test Receive Status.
TotalBytes dd 0 ; Receive Bytes var.
Control1Value db 0 ; For shared RAM.
Control2Value db 0
CurrentPacketPointer dd 0 ; Holds packet address during Rx.
CurrentECB dd 0 ; Holds ECB during Frag Receive.
; 0 dup (0) generate a warning message. Therefore we need a value here to
; prevent AlignIOFour get into this condition. JCP, 941108.
AllowAlignIOFour db 1 dup (0) ; Can be 1 or 3 dup (0). JCP.
AlignIOFour db (4 - offset (AlignIOFour and 3)) and 3 dup (?) ; Align 4
;
;***************************************************************\
; *
; NE2000 I/O Register Values. *
; *
;***************************************************************/
;
Control1 dd ? ; Shared RAM
Control2 dd ? ; Shared RAM
Prom dd ? ; Shared RAM
Command dd ? ; I/O Base + 00h
PageStart dd ? ; I/O Base + 01h
PageStop dd ? ; I/O Base + 02h
Boundary dd ? ; I/O Base + 03h
TransmitStatus dd ? ; I/O Base + 04h
TransmitByteCount0 dd ? ; I/O Base + 05h
TransmitByteCount1 dd ? ; I/O Base + 06h
InterruptStatus dd ? ; I/O Base + 07h
RemoteStartAddress0 dd ? ; I/O Base + 08h
RemoteStartAddress1 dd ? ; I/O Base + 09h
RemoteByteCount0 dd ? ; I/O Base + 0ah
RemoteByteCount1 dd ? ; I/O Base + 0bh
ReceiveConfiguration dd ? ; I/O Base + 0ch
TransmitConfiguration dd ? ; I/O Base + 0dh
DataConfiguration dd ? ; I/O Base + 0eh
InterruptMask dd ? ; I/O Base + 0fh
NICData dd ? ; I/O Base + 10h
Reset dd ? ; I/O Base + 1fh
;
;***************************************************************\
; *
; Look ahead buffer. *
; *
;***************************************************************/
;
ReceiveHeader db 128+22+4 dup (0)
;
;***************************************************************\
; *
; Error Counters. *
; *
;***************************************************************/
;
StatisticsVersion db 03, 00
GenericVariableCount dw (GenericVariableEnd - GenericVariableBegin) / 4
NotSupportedMask0 dd 11111011110010000000000000000011b
;GenericVariableBegin db 0 dup (?) ; JCP, 941108.
TotalTxPacketCount dd 0 ; 1 - (Used by MSM)
TotalRxPacketCount dd 0 ; 1 - (Used by MSM)
NoECBAvailableCount dd 0 ; 1 - (Used by MSM)
PacketTxTooBigCount dd 0 ; 1 - not used
PacketTxTooSmallCount dd 0 ; 1 - not used
PacketRxOverflowCount dd 0 ; 0 - Used by driver
PacketRxTooBigCount dd 0 ; 1 - not used
PacketRxTooSmallCount dd 0 ; 1 - not used
PacketTxMiscErrorCount dd 0 ; 1 - not used
PacketRxMiscErrorCount dd 0 ; 1 - not used
RetryTxCount dd 0 ; 0 - Used by driver
ChecksumErrorCount dd 0 ; 0 - Used by driver
HardwareRxMismatchCount dd 0 ; 1 - (Used by MSM)
TotalTxOKByteCountLow dd 0 ; 0 - Used by MSM
TotalTxOKByteCountHigh dd 0 ; 0 - Used by MSM
TotalRxOKByteCountLow dd 0 ; 0 - Used by MSM
TotalRxOKByteCountHigh dd 0 ; 0 - Used by MSM
TotalGroupAddrTxCount dd 0 ; 0 - Used by MSM
TotalGroupAddrRxCount dd 0 ; 0 - Used by MSM
AdapterResetCount dd 0 ; 0 - Used by driver
AdapterOprTimeStamp dd 0 ; 0 - Used by MSM
QDepth dd 0 ; 0 - Used by MSM
TxOKSingleCollision dd 0 ; 0 - Used by driver
TxOKMultipleCollisions dd 0 ; 0 - Used by driver
TxOKButDeferred dd 0 ; 0 - not used
TxAbortLateCollision dd 0 ; 0 - Used by driver
TxAbortExcessCollisions dd 0 ; 0 - Used by driver
TxAbortCarrierSense dd 0 ; 0 - Used by driver
TxAbortExDeferral dd 0 ; 0 - not used
RxAbortFrameAlignment dd 0 ; 0 - Used by driver
;GenericVariableEnd db 0 dup (?) ; JCP, 941108
CustomVariableCount dw (CustomVariableEnd - CustomVariableBegin) / 4
;CustomVariableBegin db 0 dup (?) ; JCP, 941108.
UnderrunErrorCount dd 0 ; Tx FIFO Underrun
TransmitTimeoutCount dd 0 ; Tx Timeouts
RxPagingErrorCount dd 0 ; Rx Paging Errors
RxFIFOOverrunErrorCount dd 0 ; Rx FIFO Overrun
RxMissedPacketCount dd 0 ; Rx Missed Packet
GotNothingCount dd 0 ; Rx Got Nothing
UnsupportedFrameCount dd 0 ; Frame not registered counter.
UnsupportedMulticastCount dd 0 ; Bad multicast received.
BackToBackSendCount dd 0 ; Back to Back send counter.
EnqueueSendCount dd 0 ; Tx Queue counter.
;CustomVariableEnd db 0 dup (?) ;JCP, 941108
VectorToTheStrings dd offset DiagnosticsStrings
AllowAlignDEndVA db 1 dup (0) ;JCP, 941108. Refer AlignIOFour.
AlignDEndVA db (4 - offset (AlignDEndVA and 3)) and 3 dup (?) ; Align 4 for MOVSD
DriverAdapterDataSpace ends
subttl -- OSDATA Data Segment --
page
assume cs: OSCODE, ds: OSDATA, es: OSDATA, ss: OSDATA
;
;***********************************************************************\
; *
; The following variables are common to the entire driver. *
; *
;***********************************************************************/
;
OSDATA segment rw public 'DATA'
HSMSPEC db 'HSM_SPEC_VERSION: 3.31',0
;
;***************************************************************\
; *
; Statistic Diagnostic Strings. *
; *
;***************************************************************/
;
DiagnosticsStrings dw (EndOfStrings-DiagnosticsStrings)
db 'UnderrunErrorCount',0
db 'TransmitTimeoutCount',0
db 'RxPagingErrorCount', 0
db 'ReceiveFIFOOverrunErrorCount', 0
db 'ReceiverMissedPacketCount', 0
db 'GotNothingCount',0
db 'UnsupportedFramePacketCount',0
db 'UnsupportedMulticastCount', 0
db 'BackToBackSendCount', 0
db 'EnqueuedSendsCount', 0
db 0,0
EndOfStrings equ $
;
;***************************************************************\
; *
; Driver Parameter Block to pass to MSM. *
; *
;***************************************************************/
;
align 4
DriverParameterBlock label dword
DriverParameterSize dd DriverParameterBlockSize
DriverStackPointer dd 0
DriverModuleHandle dd 0
DriverBoardPointer dd 0
DriverAdapterPointer dd 0
DriverConfigTemplatePtr dd DriverConfigTemplate
DriverFirmwareSize dd 0
DriverFirmwareBuffer dd 0
DriverNumKeywords dd 1
DriverKeywordText dd NE2000KeywordText
DriverKeywordTextLen dd NE2000TextLen
DriverProcessKeywordTab dd NE2000ProcessKeywordTab
DriverAdapterDataSpaceSize dd SIZE DriverAdapterDataSpace
DriverAdapterTemplate dd DriverAdapterDataSpaceTemplate
DriverStatisticsTable dd StatisticsVersion
DriverEndOfChainFlag dd 0
DriverSendWantsECBs dd 0
DriverMaxMulticast dd -1
DriverNeedsBelow16Meg dd 0
DriverAESPtr dd 0
DriverCallBackPtr dd offset DriverCallBack
DriverISRPtr dd offset DriverISR
DriverMulticastChangePtr dd offset DriverMulticastChange
DriverPollPtr dd 0
DriverResetPtr dd offset DriverReset
DriverSendPtr dd offset DriverSend
DriverShutdownPtr dd offset DriverShutdown
DriverTxTimeoutPtr dd 0
DriverPromiscuousChangePtr dd offset DriverPromiscuousChange
DriverStatisticsChangePtr dd 0
DriverRxLookAheadChangePtr dd 0
DriverManagementPtr dd 0
DriverEnableInterruptPtr dd offset DriverEnableInterrupt
DriverDisableInterruptPtr dd offset DriverDisableInterrupt
DriverISR2Ptr dd 0
DriverReserved2 dd 0
HSMSpecVerString dd HSMSPEC
DriverPriorityQueuePtr dd 0
DriverDisableInterrupt2Ptr dd 0
DriverParameterBlockSize equ $ - DriverParameterBlock
;
;***************************************************************\
; *
; Copy of Virtual Adapter Data area to be copied at *
; initialization. *
; *
;***************************************************************/
DriverAdapterDataSpaceTemplate DriverAdapterDataSpace <>
;DriverConfigTemplate db 0 dup (?) ; JCP, 941108
DriverConfigTemplate label byte ; JCP, 941108
db 'HardwareDriverMLID ' ; [ebx].MLIDCFG_Signature
db 01 ; [ebx].MLIDCFG_MajorVersion
db 14 ; [ebx].MLIDCFG_MinorVersion
db 6 dup (0ffh) ; [ebx].MLIDNodeAddress
dw 0010010001001001b ; [ebx].MLIDModeFlags
dw 0000 ; [ebx].MLIDBoardNumber
dw 0000 ; [ebx].MLIDBoardInstance
dd 00000000 ; [ebx].MLIDMaximumSize
dd 00000000 ; [ebx].MLIDMaxRecvSize
dd 00000000 ; [ebx].MLIDRecvSize
dd 00000000 ; [ebx].MLIDCardName
dd DriverNICShortName ; [ebx].MLIDshortName
dd 00000000 ; [ebx].MLIDFrameType
dw 0000 ; [ebx].MLIDReserved0
dw 0000 ; [ebx].MLIDFrameID
dw 0001 ; [ebx].MLIDTransportTime
dd 000000000 ; [ebx].MLIDRouteHandler
dw 10 ; [ebx].MLIDLineSpeed
dw 0000 ; [ebx].MLIDLookAheadSize
db 02 ; [ebx].MLIDCFG_SGCount
db 00 ; [ebx].MLIDReserved1
dw 0000 ; [ebx].MLIDPrioritySup
dd 00000000 ; [ebx].MLIDReserved2
db 00 ; [ebx].MLIDMajorVersion
db 00 ; [ebx].MLIDMinorVersion
dw 0000000000000000b ; [ebx].MLIDFlags
dw 0010 ; [ebx].MLIDSendRetries
dd 00000000 ; [ebx].MLIDLink
dw 0000 ; [ebx].MLIDSharingFlags
dw 0FFFFh ; [ebx].MLIDSlot
dw 0300h, 32, 0, 0 ; [ebx].MLIDIOPortsAndLengths
dd 00000000 ; [ebx].MLIDMemoryDecode0
dw 0000 ; [ebx].MLIDLength0
dd 00000000 ; [ebx].MLIDMemoryDecode1
dw 0000 ; [ebx].MLIDLength1
db 03, 0FFh ; [ebx].MLIDInterrupt
db 0FFh, 0FFh ; [ebx].MLIDDMAUsage
dd 00000000 ; [ebx].MLIDResourceTag
dd 00000000 ; [ebx].MLIDConfiguration
dd 00000000 ; [ebx].MLIDCommandString
db 18 dup (0) ; [ebx].MLIDLogicalName
dd 00000000 ; [ebx].MLIDLinearMemory0
dd 00000000 ; [ebx].MLIDLinearMemory1
dw 0000 ; [ebx].MLIDChannelNumber
dd 00000000 ; [ebx].MLIDBusTag
db 00 ; [ebx].MLIDIOCfgMajorVersion
db 00 ; [ebx].MLIDIOCfgMinorVersion
Message DriverNICShortName, 'NE2000'
;
;***************************************************************\
; *
; Parameters required by ParseDriverParameters. *
; *
;***************************************************************/
;
IOPort0Data dd 7, 300h, 320h, 340h, 360h, 240h, 280h, 2C0h
Interrupt0Data dd 8, 2, 3, 4, 5, 10, 11, 12, 15
MemoryDecode0Data dd 24, 0d0000h, 0d4000h, 0d8000h, 0dc000h
dd 0c0000h, 0c4000h, 0c8000h, 0cc000h
dd 0e00000h, 0e20000h, 0e40000h, 0e60000h
dd 0e80000h, 0ea0000h, 0ec0000h, 0ee0000h
dd 0f00000h, 0f20000h, 0f40000h, 0f60000h
dd 0f80000h, 0fa0000h, 0fc0000h, 0fe0000h
AdapterOptions AdapterOptionDefinitionStructure <0,IOPort0Data,0,0,0,MemoryDecode0Data,0,0,0,Interrupt0Data,0,0,0,0>
;
;***************************************************************\
; *
; Custom Keyword information. *
; *
;***************************************************************/
;
MemText db 'MEM' ; Break into debugger keyword.
MemTextLen equ $-MemText OR T_HEX_NUMBER
dd 000C0000h ; Minimum.
dd 00FE0000h ; Maximum.
dd MemDefault ; Default String.
dd MemValid ; Valid Characters string.
dd MemPrompt ; Prompt String.
NE2000KeywordText dd MemText ; First Keyword.
NE2000TextLen dd MemTextLen ; First Keywords length.
NE2000ProcessKeywordTab dd MemRoutine ; First Keyword routine.
MemDefault db "D0000", 0
MemValid db "02468ACDEF", 0
MemPrompt db "Supported memory address values are "
MemPromptValues db 256 dup (0)
MemPromptStrings db "D0000"
db "D4000"
db "D8000"
db "DC000"
db "C0000"
db "C4000"
db "C8000"
db "CC000"
db "E00000"
db "E20000"
db "E40000"
db "E60000"
db "E80000"
db "EA0000"
db "EC0000"
db "EE0000"
db "F00000"
db "F20000"
db "F40000"
db "F60000"
db "F80000"
db "FA0000"
db "FC0000"
db "FE0000"
MemPromptTail db CR, LF, "Memory address : ", 0
MemPromptTailSize equ $ - MemPromptTail
MemOnCommandLine db 0
InitMem dd 0
AdapterIsSharedRAM db 0
InDriverInit db 0 ;SPD 125034
;
;***************************************************************\
; *
; Interrupt lookup table for Shared RAM mode. Indexed by the *
; value of bits 3-5 of the ATLANTIC Mode Config register A. *
; *
;***************************************************************/
;
SharedRAMIntTable db 3, 4, 5, 2, 10, 11, 12 ,15
;
;
;***************************************************************\
; *
; Message equates. *
; *
;***************************************************************/
;
CR equ 13
LF equ 10
;
;***************************************************************\
; *
; Run-time error message strings. *
; NE2000 error messages. *
; *
;***************************************************************/
;
TransmitTimeoutMessage db 66, 00, 'The cable might be disconnected on the board.', CR, LF, 0
DMANotCompleteError db 200, 00, "The board's DMA did not complete the write.", CR, LF, 0
;
;***************************************************************\
; *
; InitNIC error message strings. *
; *
;***************************************************************/
;
NICNotInSlotMessage db 50, 00, 'The board cannot be found.', CR, LF, 0
PortFailMessage db 54, 00, 'The board did not respond to the initialization command.', CR, LF, 0
BufferMemoryFailMessage db 51, 00, 'Board RAM failed the memory test.', CR, LF, 0
NICIn8BitSlotMessage db 223, 00, 'The board must be placed in a 16-bit slot.', CR, LF, 0
NICIsNE1000Message db 224, 00, 'This board is configured as an NE1000.', CR, LF, 0
NICBadConfiguration db 80, 00, 'The board could not be configured.', CR, LF, 0
IRQInvalidMessage db 91, 00, 'The hardware configuration conflicts.', CR, LF, 0
;
OSDATA ends
subttl -- DriverChangeMulticast --
page
OSCODE segment er public 'CODE'
DEBUG equ 0
if DEBUG
extrn OutChar: near
endif
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverMulticastChange, NE2000/API/MULTI )
;
; Name: DriverMulticastChange
;
; Description: This routine will modify the NIC's multicast registers to
; enable it to receive the multicast addresses listed in
; the multicast table. Each entry in the multicast table is as
; follows:
;
; bytes 0-5 = Multicast Address.
; bytes 6-7 = Entry used(Non zero if used).
;
; On Entry: EAX N/A
; EBX N/A
; ECX # of Entries in Table( 0 if empty )
; EDX N/A
; EBP @ Adapter Data Space
; ESI @ Multicast Table
; EDI N/A
;
; Note: Interrupts are in any state.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Destroyed
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts preserved.
;
; Remarks: This routine is called by the ethernet media module.
; It can be called at process or interrupt time.
;
; See Also: ETHERTSM\EtherTSMAddMulticastAddress
; ETHERTSM\EtherTSMDeleteMulticastAddress
; ETHERTSM\EtherTSMUpdateMulticast
; CalculateHash
; ModifyNICHashTableBit
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
DriverMulticastChange proc
;
;***************************************************************\
; *
; First reset Multicast Address Registers. *
; *
;***************************************************************/
;
mov edx, [ebp].Command ; Set for page one (62h)
mov al, NIC_Page1
out dx, al
xor al, al ; Set all bits to zero.
mov edx, [ebp].MultiCastAddrReg ; Point at NIC address.
mov edi, 8
SetAllBits:
out dx,al ; Send it out.
inc dx ; Go to next register
dec edi
jnz short SetAllBits ; and send it out.
mov edx, [ebp].Command ; Set back to page 0 (22h)
mov al,NIC_Page0
out dx, al
or ecx, ecx
jz short MulticastChangeExit ; Leave if table is empty.
;
;***************************************************************\
; *
; Now Loop thru each table entry and set multicast addresses *
; that use used. *
; *
;***************************************************************/
;
ChangeMulticastLoop:
;
;***************************************************************\
; *
; Get value to put into controllers multicast hash table. *
; *
;***************************************************************/
;
push ecx ; Save loop counter.
call CalculateHash
;
;***************************************************************\
; *
; Tell NIC to allow this address. *
; *
;***************************************************************/
;
call ModifyNICHashTableBit
pop ecx ; Restore loop counter.
NextMulticastEntry:
add esi, SIZE MulticastTableStructure ; Get next entry.
dec ecx
jnz short ChangeMulticastLoop
MulticastChangeExit:
mov edx, [ebp].ReceiveConfiguration
mov al, NIC_Multicast OR NIC_Broadcast
out dx, al
ret
DriverMulticastChange endp
subttl -- CalculateHash --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( CalculateHash, NE2000/INTERNAL/HASH )
;
; Name: CalculateHash
;
; Description: This routine will take the 6-byte multicast address
; pointed to by ESI and calculate a CRC as the 8390 would. It
; will return in EAX the upper 6-bits of the CRC. This is used
; as an index into the 8390 multicast hash address table.
;
; On Entry: EAX N/A
; EBX N/A
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI @ Multicast Address
; EDI N/A
;
; Note: Interrupts are in any state.
;
; On Return: EAX Upper 6 bits of CRC
; EBX Preserved
; ECX Preserved
; EDX Destroyed
; EBP Preserved
; ESI Preserved
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts preserved.
;
; Remarks: This routine is called by DriverMulticastChange.
; It can be called at process or interrupt time.
;
; See Also: DriverMulticastChange.
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
CalculateHash proc
push esi ; Save -> to buffer.
push ebx
mov eax, [esi] ; Copy of address into a
mov dword ptr [ebp].CRCWorkArea, eax
mov ax, [esi + 4] ; work area.
mov word ptr [ebp].CRCWorkArea + 4, ax
;
;***************************************************************\
; *
; EBX = CRC = 0xFFFFFFFFh *
; *
;***************************************************************/
;
mov ebx, 0ffffffffh
;
;***************************************************************\
; *
; for (index=0; index< HASHNUMBER(6); ++ index) *
; *
;***************************************************************/
;
mov ecx, 6 ; Outer loop = bytes in addr.
lea esi, [ebp].CRCWorkArea ; Initate index to nic address.
FilterOuterLoop:
push ecx ; Save outer loop counter.
;
;***************************************************************\
; *
; for (j=0; j<8; ++j) *
; *
;***************************************************************/
;
mov ecx, 8 ; Set innerloop count.
FilterInnerLoop:
;
;***************************************************************\
; *
; carry = ( (crc&0x80000000) ? 1 : 0) ^ (multaddress[i] & 01) *
; *
;***************************************************************/
;
mov edx, 80000000h
and edx, ebx ; EDX = CRC AND 80000000h.
rcl edx, 2 ; Convert result to a 1 or 0.
mov ax, 1
and ax, [esi] ; Multaddress[i] & 01.
cwde ; Convert to doubleword.
xor eax, edx
;
;***************************************************************\
; *
; crc <<= 1 *
; *
;***************************************************************/
;
rcl ebx, 1
;
;***************************************************************\
; *
; Multaddress[i] >>= 1 *
; *
;***************************************************************/
;
shr byte ptr [esi], 1
;
;***************************************************************\
; *
;if(carry) *
; crc = ((crc^POLYNOMIAL) | carry) *
; *
;***************************************************************/
;
cmp eax, 0 ; AX has carry in it.
jz short FinshInnerFilterPass ; Jump if no carry.
;
;***************************************************************\
; *
; crc = crc ^ Polynomial *
; *
;***************************************************************/
;
xor ebx, 04c11db6h
;
;***************************************************************\
; *
; crc = crc | carry *
; *
;***************************************************************/
;
or ebx, eax
FinshInnerFilterPass:
dec ecx
jnz FilterInnerLoop
inc esi ; Point to next multicast byte.
pop ecx ; Get outer loop counter.
dec ecx
jnz FilterOuterLoop
;
;***************************************************************\
; *
; crc = crc & 0x0ff000000h *
; *
;***************************************************************/
;
and ebx, 0ff000000h
;
;***************************************************************\
; *
; crc = crc >> 26 *
; *
;***************************************************************/
;
rcr ebx, 26
;
;***************************************************************\
; *
; AX has the filterbit. *
; *
;***************************************************************/
;
movzx eax, bx ; Make a 32bit number.
pop ebx
pop esi ; Restore pointer.
ret
CalculateHash endp
subttl -- ModifyNICHashTableBit --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( ModifyNICHashTableBit, NE2000/INTERNAL/HASHBIT )
;
; Name: ModifyNICHashTableBit
;
; Description: This routine will modify a bit in the 8390 multicast hash
; table.
;
; On Entry: EAX 6 bit index value
; EBX N/A
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are in any state.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Preserved
; EDX Destroyed
; EBP Preserved
; ESI Preserved
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts preserved.
;
; Remarks: This routine is called by DriverMulticastChange.
; It can be called at process or interrupt time.
;
; See Also: DriverMulticastChange
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
ModifyNICHashTableBit proc
mov edi, eax ; Get copy of index.
mov al, 62h ; Tell nic that we want to
mov edx, [ebp].Command ; select the page1 registers.
out dx, al ; Issue the command.
mov eax, edi ; Get the index back.
shr edi, 3 ; Divide it by 8. This
; gives us which NIC Multicast
; address register to use.
mov edx, [ebp].MultiCastAddrReg ; Point at appro. nic address.
add edx, edi
shl edi, 3 ; Get back register index .
xor edi, eax ; Get bit index into register.
in al, dx ; Get current reg bit settings.
bts eax, edi ; Set approriate bit.
out dx, al ; Write new value.
mov edx, [ebp].Command ; Set nic back to page0 regs.
mov al, 22h
out dx, al
ret ;Done
ModifyNICHashTableBit endp
subttl -- DriverPromiscuousChange --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverPromiscuousChange, NE2000/API/PROMISCU )
;
; Name: DriverPromiscuousChange
;
; Description: This routine will enable/disable the Promiscuous Mode.
;
; On Entry: EAX N/A
; EBX N/A
; ECX 0 to disable the Promiscuous mode
; EDX N/A
; EBP @ Adapter Data Space
; ESI @ Multicast Table
; EDI N/A
;
; Note: Interrupts are in any state.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Destroyed
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts preserved.
;
; Remarks: This routine is called by the ethernet media module.
; It can be called at process or interrupt time.
;
; See Also: ETHERTSM\EtherTSMPromiscuousChange
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
DriverPromiscuousChange proc
mov edx, [ebp].ReceiveConfiguration
mov al, NIC_Multicast OR NIC_Broadcast
mov [ebp].ReceiveStatusTest, 4eh ; Assume Promiscuous off.
or ecx, ecx ; Disable Promiscuous?
je short DriverPromiscuousModify ; Jump if so.
test ecx , PROM_MODE_RMC
jnz Enable_RMC
or al, NIC_Promiscuous or NIC_Save_Errors OR NIC_Save_Runts
mov [ebp].ReceiveStatusTest, 40h
Enable_RMC:
mov ecx, -1
DriverPromiscuousModify:
out dx, al
mov edx, [ebp].Command ; Set for page one (62h)
mov al, NIC_Page1
out dx, al
mov al, cl ; Set all bits to cl.
mov edx, [ebp].MultiCastAddrReg ; Point at NIC address.
mov ecx, 8
SetHashTable:
out dx,al ; Send it out.
inc dx ; Go to next register
loop SetHashTable
mov edx, [ebp].Command ; Set back to page 0 (22h)
mov al,NIC_Page0
out dx, al
ret
DriverPromiscuousChange endp
subttl -- DriverCallBack --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverCallBack, NE2000/API/CALLBACK )
;
; Name: DriverCallBack
;
; Description: This routine will be executed once every second. It will
; detect if the hardware does not ack a transmission. If the
; hardware didn't ack then it will be reset, the transmission
; of that packet will be aborted and the next packet in the
; queue will be sent if there is one.
;
; On Entry: EAX N/A
; EBX @ Frame Data Space
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Destroyed
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts disabled.
;
; Remarks: This routine is called by the MSM.
; After this call returns, the MSM will schedule another
; call back.
; It is called at interrupt time.
;
; See Also: MSM\MSMCallBackProcedure
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
align 16
DriverCallBack proc
mov ecx, [ebp].TxStartTime ; ECX -> current Tx ECB.
or ecx, ecx ; Any transmits active?
jz short NoTxActive ; Jump if not.
MSMGetCurrentTime ; EAX = Current Time.
sub eax, ecx ; EAX = Current Time - TxStartTime.
cmp eax, 36 ; More than 2 seconds passed?
jg short DidntGetTxCompleteInterrupt ; Process timeout if so.
NoTxActive:
ret ; Done.
;
;***************************************************************\
; *
; TransmitBufferEmpty didn't set in time. Reset NIC and try *
; again. *
; *
;***************************************************************/
;
DidntGetTxCompleteInterrupt:
mov edx, [ebp].NumberCollisions ; Find out if transmission
in al, dx ; experienced any collisions.
movzx eax, al ; Clear upper bits.
cmp eax, 1 ; Single collision?
je short DidntGetTxSingleCol ; jump if so.
add [ebp].TxOKMultipleCollisions, eax ; Add to statistics.
jmp short DidntGetTxReadCom
DidntGetTxSingleCol:
inc [ebp].TxOKSingleCollision
DidntGetTxReadCom:
mov edx, [ebp].Command ; Read command port.
in al, dx
test al, NIC_TxInProgress ; Transmit still in progress?
jz short NotCableDisconnect ; Jump if not.
;
;***************************************************************\
; *
; The transmit is still in progress. There is the possibility *
; that the thin cable has been disconnected. Queue a warning *
; message to the console. *
; *
;***************************************************************/
;
lea esi, TransmitTimeoutMessage
call MSMAlertWarning
NotCableDisconnect:
mov eax, OP_SCOPE_ADAPTER
call DriverReset ; Hard reset the card.
;
;***************************************************************\
; *
; Forget this packet and go to the next one. *
; *
;***************************************************************/
;
inc [ebp].TransmitTimeoutCount ; Inform diagnostics.
inc [ebp].PacketTxMiscErrorCount
mov [ebp].TxStartTime, 0 ; Set Tx no longer active.
mov edx, [EBP].InterruptStatus ; Reset all trasmit bits.
mov al, 0Ah
out dx, al
IF BackToBackSends
test [ebp].TransmitStatusFlag, 0100b ; Another Tx buffer waiting?
jz short TimoutCheckQueue ; Jump if not.
;
;***************************************************************\
; *
; We just terminated the previous send, but another packet is *
; already transfered to the board. We just need to initiate the *
; send. *
; *
;***************************************************************/
;
inc [ebp].BackToBackSendCount ; Inform diagnostics.
mov al, [ebp].TransmitPage0 ; Assume Page #1.
mov ecx, [ebp].TransmitSize1 ; Assume Size for Page #1.
test [ebp].TransmitStatusFlag, 0010b ; Use page #1?
jnz short TimeoutIssueTheSend ; Jump if so.
mov al, [ebp].TransmitPage1 ; Page #2.
mov ecx, [ebp].TransmitSize2 ; Size for Page #2.
TimeoutIssueTheSend:
mov edx, [ebp].TransmitPage ; EDX = TxPage register.
out dx, al ; Send Transmit Page #.
mov eax, ecx ; EAX = Transmit Size.
inc edx ; EDX = TxByteCount0 register.
out dx, al ; Send LSB to register.
inc edx ; EDX = txByteCount1 register.
mov al, ah ; AL = MSB.
out dx, al ; Send MSB to register.
sub edx, ITransmitByteCount1 - ICommand
mov al, NIC_Transmit ; Send the Tx Command to
out dx, al ; the command register.
MSMGetCurrentTime ; EAX = Current Time.
mov [ebp].TxStartTime, eax ; Store it for later.
xor [ebp].TransmitStatusFlag, 0110b ; 5->3, 7->1.
jmp short TimeoutCheckForMoreSends ; Try to queue another Tx.
TimoutCheckQueue:
mov [ebp].TransmitStatusFlag, 0010b ; No Tx in progress.
; Buffer #1 is free.
TimeoutCheckForMoreSends:
ENDIF
test [ebp].MSMStatusFlags, TXQUEUED ; Any ECB's waiting.
jz short TimeoutReturn ; Jump if not.
inc [ebp].EnqueueSendCount ; Increment statistics.
call EtherTSMGetNextSend ; Get next send if any.
jne short TimeoutReturn ; Jump if no send
push ebp
push offset TimeoutSendReturn
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
jne DriverSendSharedRAM ; Jump if so.
inc [ebp].EnqueueSendCount ; Increment statistics. JCP
jmp DriverSend
TimeoutSendReturn:
pop ebp
TimeoutReturn:
ret ; Otherwise get out.
DriverCallBack endp
subttl -- DriverSend --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverSend, NE2000/API/SEND )
;
; Name: DriverSend
;
; Description: This routine will transfer the packet described in the
; TCB to the NIC and initiate the send. TxStartTime and
; RetryCounter must be set to enable the deadman timer.
;
; On Entry: EAX N/A
; EBX @ Frame Data Space
; ECX Padded Packet Length
; EDX N/A
; EBP @ Adapter Data Space
; ESI @ TCB
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Destroyed
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts disabled.
;
; Remarks: This routine is called by the MSM media module.
; It is called at process or interrupt time.
;
; See Also: ETHERTSM\EtherTSMDriverSend
; ETHERTSM\MediaSendRaw8023
; ETHERTSM\MediaSendEthernetII
; ETHERTSM\MediaSend8022Over8023
; ETHERTSM\MediaSend8022Snap
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
align 16
DriverSend proc
mov edx, [ebp].InterruptStatus ; Clear DMA complete
mov al, 40h ; left by any completed
out dx, al ; transmission.
IF BackToBackSends
test [ebp].TransmitStatusFlag, 0010b ; Use Buffer #1?
jnz short IsPageOne ; Jump if so.
mov [ebp].TransmitSize2, ecx ; Store for size &
mov eax, 4600h ; set remote address
jmp short TxSizeSaved ; for page 2.
IsPageOne:
mov [ebp].TransmitSize1, ecx ; Store for size &
mov eax, 4000h ; set remote address
; for page 1.
TxSizeSaved:
ELSE
mov [ebp].TransmitSize1, ecx ; Store Size.
mov eax, 4000h ; EAX = Remote @.
ENDIF
;
;***************************************************************\
; *
; Set RemoteStartAddress and RemoteByteCount and DMA Write. *
; EDX = [EBP].InterruptStatus. *
; EAX = Remote Start Address. *
; *
;***************************************************************/
;
inc edx ; EDX = RemoteStartAddress0.
out dx, al ; Write LSB of Remote Address.
inc edx ; EDX = RemoteStartAddress1.
mov al, ah ; AL = MSB of Remote Address.
out dx, al
mov ecx, [esi].TCBDataLen ; ECX = Exact Packet Length.
inc ecx ; Evenize it since the NE2000
and cl, 0FEh ; can only handle word I/O.
mov eax, ecx ; EAX = Length.
inc edx ; EDX = RemoteByteCount0.
out dx, al ; Write LSB of length.
inc edx ; EDX = RemoteByteCount1.
mov al, ah ; AL = MSB of length.
out dx, al ; Write MSB of length.
sub edx, IRemoteByteCount1 - ICommand ; EDX = Command.
mov al, NIC_RemoteDmaWr ; Command NIC to Write Data
out dx, al ; to buffer via DMA.
;
;***************************************************************\
; *
; Set up EDX and EDI here because of the Raw Send jump. *
; *
;***************************************************************/
;
add edx, INICData - ICommand ; EDX = NICData.
mov edi, esi ; EDI -> TCB.
;
;***************************************************************\
; *
; Copy the Frame header to the NIC. *
; *
;***************************************************************/
;
mov ecx, [edi].TCBMediaHeaderLen ; ECX = Frame Length.
lea esi, [edi].TCBMediaHeader ; ESI-> Frame.
shr ecx, 1 ; Copy Frame.
rep outsw
jc SendOddMediaSetup ; Jump if extra byte.
;
;***************************************************************\
; *
; Copy the fragments to the NIC. *
; *
;***************************************************************/
;
push ebp ; Save Adapter Base.
push edi ; Save TCB.
mov edi, [edi].TCBFragStrucPtr ; EDI -> Fragments.
mov ebp, [edi + 0] ; EBP = Number of Fragments.
lea ebx, [edi + 4] ; EBX -> Fragment Descriptor.
or ebp, ebp ; Any fragments?
je EverythingDone ; Jump if not.
FragmentOutLoop:
mov ecx, [ebx].FragmentLength ; ECX = Fragment x Size.
mov esi, [ebx].FragmentOffset ; ESI -> Fragment x.
shr ecx, 1 ; Copy fragment.
rep outsw
jc short IsAOddLengthFragment ; Jump if odd fragment.
add ebx, SIZE FragmentStructure ; EBX -> Next Fragment Descriptor.
dec ebp ; More fragments?
jnz FragmentOutLoop ; Yes. Send it.
jmp short EverythingDone ; Finished all fragments.
;
;***************************************************************\
; *
; Add last byte of odd fragment to beginning of next fragment. *
; *
;***************************************************************/
;
IsAOddLengthFragment:
lodsb ; Load up the odd ball byte into AL.
SkipTheNullFragment:
add ebx, SIZE FragmentStructure ; EBX -> Next Fragment descriptor.
dec ebp ; Any more fragments?
jz short FragmentsAllDone ; Jump if not.
mov ecx, [ebx].FragmentLength ; ECX = Next fragment size.
or ecx, ecx ; Null fragment?
jz SkipTheNullFragment ; Jump if so.
mov esi, [ebx].FragmentOffset ; ESI -> Next fragment.
mov ah, al ; AH = odd ball byte.
;
;***************************************************************\
; *
; Enter here if AH contains byte to get added to fragment *
; output. *
; *
;***************************************************************/
;
SendOddMediaEntry:
or ecx, ecx ; Check fragment size.
lodsb ; Pick up first byte of fragment.
xchg al, ah ; Swap it with odd ball byte.
out dx, ax ; Send both to NIC.
jz short SendOddNext ; Jump if next fragment zero.
dec ecx ; Adjust fragment count.
;
;***************************************************************\
; *
; Odd byte from last fragment and first byte of current fragment*
; have been sent to NIC. Now send rest of fragment normally. *
; *
;***************************************************************/
;
shr ecx, 1 ; Send out rest of
rep outsw ; fragment.
jc IsAOddLengthFragment ; Jump if it was odd.
SendOddNext:
add ebx, SIZE FragmentStructure ; EBX -> Next fragment descriptor.
dec ebp ; Any more fragments.
jnz FragmentOutLoop ; Yes. Send it.
jmp short EverythingDone ; No. All done.
;
;***************************************************************\
; *
; Enter here if AL contains odd byte with no more fragments to *
; follow. *
; *
;***************************************************************/
;
FragmentsAllDone:
out dx, ax ; Put out the last byte plus garbage.
EverythingDone:
;
;***************************************************************\
; *
; All fragments have been sent to NIC. *
; *
;***************************************************************/
;
pop esi ; Restore TCB into ESI.
pop ebp ; Restore Virtual Adapter base.
sub edx, INICData - IInterruptStatus ; EDX = Interrupt Status.
in al, dx ; AL = Interrupt Status.
test al, 40h ; Tx Complete?
jz short TestDMAAgain ; No. Wait for it.
DMAOK:
IF BackToBackSends
test [ebp].TransmitStatusFlag, 0001b ; Waiting for Tx Complete?
jnz short DontIssueSend ; Jump if so.
ENDIF
;
;***************************************************************\
; *
; Initiate the transmit. *
; *
;***************************************************************/
;
mov edx, [ebp].TransmitPage ; Make sure we Tx buffer #1.
IF BackToBackSends
mov al, [ebp].TransmitPage0 ; JCP, 941108.
out dx, al
ENDIF
mov eax, [ebp].TransmitSize1 ; EAX = Tx size for Buffer #1.
inc edx ; EDX = TxByteCount0.
out dx, al ; Send LSB of Tx Byte Count.
inc edx ; EDX = TxByteCount1.
mov al, ah ; AL = MSB of Tx Byte Count.
out dx, al ; Send MSB of Tx Byte Count.
sub edx, ITransmitByteCount1 - ICommand ; EDX = Command.
mov al, NIC_Transmit ; Send packet.
out dx, al
MSMGetCurrentTime ; EAX = Current Time.
mov [ebp].TxStartTime, eax ; Store it for later.
mov [ebp].RetryCounter, MaxRetries ; MAX retries.
IF BackToBackSends
mov [ebp].TransmitStatusFlag, 0001b ; Sending Page 1 status.
ENDIF
;
;***************************************************************\
; *
; Give TCB back to MSM. (Lying Send) *
; *
;***************************************************************/
;
IF NOT UseFastCalls
cmp [ebp].InDriverISR, 0 ; In DriverISR?
jnz EtherTSMSendComplete ; Jump if so.
ENDIF
jmp EtherTSMFastSendComplete ; Otherwise service events.
IF BackToBackSends
DontIssueSend:
or [ebp].TransmitStatusFlag, 0100b ; Set 2nd send buffer waiting.
IF NOT UseFastCalls
cmp [ebp].InDriverISR, 0 ; In DriverISR?
jnz EtherTSMSendComplete ; Jump if so.
ENDIF
jmp EtherTSMFastSendComplete ; Otherwise service events.
ENDIF
;
;***************************************************************\
; *
; Send last header byte with first fragment. *
; *
;***************************************************************/
;
SendOddMediaSetup:
mov ah, [esi] ; esi -> Last byte of header.
push ebp ; Save Adapter Base.
push edi ; Save TCB.
mov edi, [edi].TCBFragStrucPtr ; EDI -> Fragments.
mov ebp, [edi + 0] ; EBP = Number of Fragments.
lea ebx, [edi + 4] ; EBX -> Fragment Descriptor.
mov ecx, [ebx].FragmentLength ; ECX = Fragment 0 length.
mov esi, [ebx].FragmentOffset ; ESI -> Fragment 0.
;
;***************************************************************\
; *
; Start sending fragments with AH = last byte of the header. *
; *
;***************************************************************/
;
jmp SendOddMediaEntry
;
;***************************************************************\
; *
; Control is transfered here if DMA complete bit hasn't set. *
; *
;***************************************************************/
;
TestDMAAgain:
mov ecx, 10000h ; ECX = Loop counter.
TryItAgain:
in al, dx ; AL = Interrupt Status.
test al, 40h ; Tx Complete?
jnz DMAOK
dec ecx
jnz TryItAgain ; No. Wait some more.
;
;***************************************************************\
; *
; Tx DMA complete wouldn't set. Manufacture claims it really *
; was so we'll reset it manually, display message and continue. *
; *
;***************************************************************/
;
mov al, 40h ; Clear the interrupt
out dx, al ; DMA complete bit.
push esi
lea esi, DMANotCompleteError
call MSMAlertWarning
mov eax, OP_SCOPE_ADAPTER
call DriverReset ; Reset the NIC.
pop esi
jmp DriverSend ; Try sending again.
DriverSend endp
align 16
DriverSendSharedRAM proc
mov edi, [ebp].NICRAMSegmentBase ; Load Tx segment for page #1.
if BackToBackSends
test [ebp].TransmitStatusFlag, 0010b ; Use Buffer #1?
jnz short RAMIsPageOne ; Jump if so.
mov [ebp].TransmitSize2, ecx ; Store size & adjust
add edi, 600h ; Tx segment
jmp short RAMTxSizeSaved ; for page 2.
RAMIsPageOne:
mov [ebp].TransmitSize1, ecx ; Store size
; for page 1.
RAMTxSizeSaved:
else
mov [ebp].TransmitSize1, ecx
endif
mov edx, esi ; EDX -> TCB.
;
;***************************************************************\
; *
; Copy the Frame header to the NIC. *
; *
;***************************************************************/
;
mov ecx, [edx].TCBMediaHeaderLen ; ECX = Media Header size.
lea esi, [edx].TCBMediaHeader ; ESI -> Media Header.
shr ecx, 2 ; ECX = Media size / 4.
rep movsd ; Copy Header in DWORDs.
mov ecx, [edx].TCBMediaHeaderLen ; ECX = Media size && 3.
and ecx, 3
rep movsb ; Copy remaining bytes.
;
;***************************************************************\
; *
; Copy the Fragments to the NIC. *
; *
;***************************************************************/
;
mov esi, [edx].TCBFragStrucPtr ; ESI -> Fragment Count.
mov eax, [esi + 0] ; EAX = Fragment Count.
lea ebx, [esi + 4] ; EBX -> First Fragment struc.
or eax, eax ; Any Fragments?
je short RAMEverythingDone ; Jump if not.
RAMFragmentOutLoop:
mov ecx, [ebx].FragmentLength ; ECX = Fragment x Size.
mov esi, [ebx].FragmentOffset ; ESI -> Fragment x.
cmp ecx, 4 ; Less than four bytes?
jb short RAMDontAlignMidgets ; Skip if so.
test edi, 1 ; Off by a byte?
jz short RAMDontAdjustByte ; Jump if not.
movsb ; Take off of byte alignment.
dec ecx ; Adjust counter.
RAMDontAdjustByte:
test edi, 2 ; Off by a word?
jz short RAMDontAdjustWord ; Jump if not.
movsw ; Take off of word alignment.
sub ecx, 2 ; Adjust counter.
RAMDontAdjustWord:
RAMDontAlignMidgets:
push ecx ; Save Length
shr ecx, 2 ; Copy fragment in DWORDs.
rep movsd
pop ecx
and ecx, 3 ; & 3.
rep movsb ; Copy remaining bytes.
add ebx, SIZE FragmentStructure ; EBX -> Next Fragment Descriptor.
dec eax ;
jnz RAMFragmentOutLoop ; Yes. Send it.
;
;***************************************************************\
; *
; All fragments have been sent to NIC. *
; *
;***************************************************************/
;
RAMEverythingDone:
mov esi, edx ; ESI -> TCB.
if BackToBackSends
test [ebp].TransmitStatusFlag, 0001b ; Waiting for Tx Complete?
jnz short RAMDontIssueSend ; Jump if so.
endif
;
;***************************************************************\
; *
; Initiate the transmit. *
; *
;***************************************************************/
;
mov edx, [ebp].TransmitPage ; Make sure we Tx buffer #1.
mov al, 0h
out dx, al
mov eax, [ebp].TransmitSize1 ; EAX = Tx size for Buffer #1.
inc edx ; EDX = TxByteCount0.
out dx, al ; Send LSB of Tx Byte Count.
inc edx ; EDX = TxByteCount1.
mov al, ah ; AL = MSB of Tx Byte Count.
out dx, al ; Send MSB of Tx Byte Count.
sub edx, ITransmitByteCount1 - ICommand ; EDX = Command.
mov al, NIC_Transmit ; Send packet.
out dx, al
MSMGetCurrentTime ; EAX = Current Time.
mov [ebp].TxStartTime, eax ; Store it for later.
mov [ebp].RetryCounter, MaxRetries ; Initialize retry counter.
if BackToBackSends
mov [ebp].TransmitStatusFlag, 0001b ; Sending Page 1 status.
endif
;
;***************************************************************\
; *
; Give TCB back to LSL. (Lying Send) *
; *
;***************************************************************/
;
IF NOT UseFastCalls
cmp [ebp].InDriverISR, 0 ; In DriverISR?
jnz EtherTSMSendComplete ; Jump if so.
ENDIF
jmp EtherTSMFastSendComplete ; Otherwise service events.
RAMDontIssueSend:
or [ebp].TransmitStatusFlag, 0100b ; Set 2nd send buffer waiting.
IF NOT UseFastCalls
cmp [ebp].InDriverISR, 0 ; In DriverISR?
jnz EtherTSMSendComplete ; Jump if so.
ENDIF
jmp EtherTSMFastSendComplete ; Otherwise service events.
DriverSendSharedRAM endp
subttl -- DriverISR --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverISR, NE2000/API/ISR )
;
; Name: DriverISR
;
; Description: This routine handles packet reception and transmit complete
; interrupts.
;
; On Entry: EAX N/A
; EBX N/A
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX Destroyed
; EBX Destroyed
; ECX Destroyed
; EDX Destroyed
; EBP Destroyed
; ESI Destroyed
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts disabled.
;
; Remarks: This routine is called by the MSM.
; It is called at interrupt time.
;
; See Also: MSM\MSMInterruptProcedure
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
PagingError:
;
;***************************************************************\
; *
; The receive buffers have been corrupted. Reset the NIC. *
; *
;***************************************************************/
;
inc [ebp].PacketRxMiscErrorCount
inc [ebp].RxPagingErrorCount ; Inform diagnostics.
mov eax, OP_SCOPE_ADAPTER
call DriverReset ; Re-initialize card.
jmp GetOut ; Leave ISR.
align 16
DriverISR proc
IF NOT UseFastCalls
inc [ebp].InDriverISR ; Set for DriverSend.
ENDIF
;JCJ 04-July-1997 SPD#158389 IODetachBit checking is removed to support
; partial shutdown
test [ebp].MSMStatusFlags, SHUTDOWN ; Complete Shutdown?
;JCJ 04-July-1997 End
jne ClearIntsAndGetOut ; Jump if so.
;
;***************************************************************\
; *
; ISR will branch and keep returning here until card is fully *
; serviced. *
; *
;***************************************************************/
;
PollAgain:
cmp InDriverInit, 0 ;SPD 125034
jne ClearIntsAndGetOut ;SPD 125034
mov edx, [ebp].InterruptStatus ; Read the NIC ISR.
in al,dx ; AL and
mov ah, al ; AH contain Interrupt Status.
test al, NIC_PacketReady ; Receiver needs servicing(15h)?
jz CheckForTransmit ; No. Check for Transmit Complete.
;
;***************************************************************\
; *
; Receive status bits set. *
; 01h - Packet Received with no error. *
; 04h - Receive Error. *
; 10h - Receive Buffer Overflow. *
; *
;***************************************************************/
;
test ah, NIC_RecvError ; Was it a successful read(14h)?
jnz HandleRxErrors ; Jump if not.
sub edx, IInterruptStatus - ICommand ; EDX = Command.
mov al, NIC_Page1 ; Switch to page 1 registers.
out dx, al
add edx, IInterruptStatus - ICommand ; EDX = Current.
in al, dx ; AL = NIC's current page.
cmp al, [ebp].NextPage ; Any more Rx buffers?
mov edx, [ebp].Command ; Switch to page 0 registers
mov al, NIC_Page0 ; before jumping.
out dx, al
jz DidntGetAnything ; No. Done receiving.
;
;***************************************************************\
; *
; Time to read in the packet received. *
; *
; Read in 4 byte buffers header, 14 byte Ethernet header and *
; following 8 bytes into ReceiveHeader to properly analyse *
; packet length and media type. *
; *
;***************************************************************/
;
ReceiveNextPacket:
add edx, IInterruptStatus - ICommand ; EDX = Int status.
mov al, 1 ; Reset the RX Bit.
out dx, al
;
;***************************************************************\
; *
; Set up the REMOTE START ADDDRESS of NIC. *
; *
;***************************************************************/
;
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
jne DriverISRSharedRAM ; Jump if so.
mov edx, [ebp].RemoteStartAddress0 ; EDX = RemoteStartAddress0.
xor al, al ; Zero out lower byte.
out dx, al
inc edx ; EDX = RemoteStartAddress1.
mov al, [ebp].NextPage ; AL = Next_page.
out dx, al ; Set to read next page.
;
;***************************************************************\
; *
; Set up the REMOTE BYTE COUNT. *
; *
;***************************************************************/
;
inc edx ; EDX = RemoteByteCount0.
mov al, byte ptr [ebp].MSMMaxFrameHeaderSize ; AL = Header Size.
add al, 5 ; Add 4-byte 8390 header
and al, 0feh ; and evenize it.
out dx, al ; Send Size (LO).
movzx ecx, al ; Save count for later.
inc edx ; EDX = RemoteByteCount1.
xor al, al
out dx, al ; Send Size (HI).
;
;***************************************************************\
; *
; Issue the Remote Read DMA command to the NIC. *
; *
;***************************************************************/
;
sub edx, IRemoteByteCount1 - ICommand ; EDX = Command.
mov al, NIC_RemoteDmaRd
out dx, al ; Command NIC to Read from memory.
add edx, INICData - ICommand ; EDX = NICData.
lea edi, [ebp].ReceiveHeader ; EDI -> Where to read data int0.
shr ecx, 1 ; Convert count to words.
rep insw ; Read Header and Frame info.
mov al, [ebp].ReceiveStatusTest
test [ebp].ReceiveHeader.RReceiveStatus, al ; Rx error?
jnz PagingError ; Jump if so.
movzx ecx, [ebp].ReceiveHeader.RByteCount ; ECX = Packet Length.
movzx eax, [ebp].ReceiveHeader.RNextBuffer ; AL = Next Page.
cmp al, [ebp].NextPage ; Did Next Page wrap?
jae short CheckForLong ; Jump if not.
add al, PSTOP - PSTART ; Set AL higher.
CheckForLong:
sub al, [ebp].NextPage ; AL = Number of Pages.
cmp al, 8 ; > 1792?
ja PacketTooLong ; Jump if so.
PacketTooLongReturn:
mov eax, ecx ; EAX = PacketLength.
;
;***************************************************************\
; *
; Use ByteCount and NextPage to determine any Paging errors. *
; *
;***************************************************************/
;
add eax, 4 - 1 + 100h ; (4 - 1 + 100h) where the last byte
add ah, [ebp].NextPage ; was plus round up.
cmp ah, PSTOP ; Wrap to beginning of ring?
jb short NoOverflow ; No. Jump.
add ah, PSTART - PSTOP ; Adjust to front of ring.
NoOverflow:
cmp [ebp].ReceiveHeader.RNextBuffer, ah ; Does header agree?
jnz PagingError ; No. Paging error.
mov [ebp].NextPage, ah ; Save new NextPage.
;
;***************************************************************\
; *
; Now let the MSM decide if we should accept the packet. *
; *
;***************************************************************/
;
lea esi, [ebp].ReceiveHeader.ReceiveHeaderStructure
sub ecx, SizeOfCRCField ; Subtract CRC length.
movzx eax, [ebp].ReceiveHeader.RReceiveStatus
shr al, 1
and al, 03h ; Save CRC error bits.
call EtherTSMGetRCB ; Get an ECB.
jnz PacketNotReceived ; Jump if error.
or ecx, ecx ;
jz ReturnRCBToMSM ; Jump if nothing to copy
;
;***************************************************************\
; *
; ESI -> ECB. *
; EDI -> Place in ECB to resume reading in data from NIC. *
; ECX = Bytes remaining to be read from NIC. *
; EBX = Bytes in packet to skip over. *
; *
;***************************************************************/
;
mov [ebp].TotalBytes, ecx ; Save UN-EVENIZED for later.
mov [ebp].OddValue, 0 ; clear odd byte flag.
inc ecx ; prepare for evenization.
add ebx, SIZE ReceiveHeaderStructure ; EBX = Bytes to skip + 4.
test ebx, 1 ; Even offset?
jz short SkipValueEven ; Jump if so.
mov al, byte ptr [ebp + ebx].ReceiveHeader
mov [ebp].OddByteValue, al ; copy already i/o'd byte
mov [ebp].OddValue, 1 ; tell loop to copy this loner.
dec ecx ; already got byte
inc ebx ; already got byte
SkipValueEven:
mov edx, [ebp].RemoteStartAddress0 ; EDX = RemoteStartAddress0.
mov al, bl ; BL = Bytes to skip.
out dx, al
and cl, 0FEh
mov eax, ecx ; EAX = evenized length.
inc edx ; EDX = RemoteStartAddress1.
inc edx ; EDX = RemoteByteCount0.
out dx, al ; Send LSB of Count.
inc edx ; EDX = RemoteByteCount1.
mov al, ah ; AL = MSB of Count.
out dx, al ; Send MSB of Count.
;
;***************************************************************\
; *
; Issue the remote read DMA command to the card. *
; *
;***************************************************************/
;
sub edx, IRemoteByteCount1 - ICommand ; EDX = Command.
mov al, NIC_RemoteDmaRd ; Remote read DMA.
out dx, al
add edx, INICData - ICommand ; EDX = NICData.
;
;***************************************************************\
; *
; Copy data into ECB packet data. *
; *
;***************************************************************/
;
mov ebx, edi ; EBX -> Frag Count.
mov eax, [ebx] ; EAX = Frag Count.
mov [ebp].RxFragments, eax ; Save fragment count.
add ebx, 4 ; EBX -> Frag structs.
ReadNextFragmentStructure:
mov edi, [ebx+0] ; EDI -> Frag offset.
mov ecx, [ebx+4] ; ECX = Frag size.
jecxz MoveWasEven
sub [ebp].TotalBytes, ecx ; adjust total remaining
jnc UseOneFromRCB
add ecx, [ebp].TotalBytes ; ECX = bytes left.
mov [ebp].TotalBytes, 0 ; Don't read any more.
UseOneFromRCB:
cmp [ebp].OddValue, 0 ; check if odd value
jz ReadNextFragment
mov al, [ebp].OddByteValue ; Get odd value
stosb ; copy it into RCB frag
dec ecx ; adjust count
mov [ebp].OddValue, 0 ; clear flag
ReadNextFragment:
shr ecx, 1 ; Divide by 2.
rep insw ; Read words.
jnc MoveWasEven ; Jump if extra byte left.
in ax, dx ; AL = Next Byte.
stosb ; Store into fragment.
mov [ebp].OddByteValue, ah ; save odd value
mov [ebp].OddValue, 1 ; set flag
MoveWasEven:
cmp [ebp].TotalBytes, 0 ; More bytes to read?
je short ReturnRCBToMSM ; Jump out if so.
add ebx, 8 ; EBX -> Next Frag struct.
dec [ebp].RxFragments ; Decrement fragment count.
jne ReadNextFragmentStructure ; Jump if more frags.
ReturnRCBToMSM:
IF UseFastCalls
push ebp
call EtherTSMFastRcvComplete ; Give ECB to protocol stack.
pop ebp
ELSE
call EtherTSMRcvComplete ; Give ECB back to LSL.
ENDIF
;
;***************************************************************\
; *
; Update Boundry register here in case the NIC is inserting *
; packets into the ring while we are reading them. *
; *
;***************************************************************/
;
FinishUp:
mov al, [ebp].NextPage ; AL = Page of next buffer.
mov ah, al ; Save for TestForReceive.
dec al ; Boundary = NextPage - 1.
cmp al, PSTART ; Still within Rx boundary.
jae short LoadNewBoundary ; Yes. Use it.
mov al, PSTOP - 1 ; No. Move to end of ring.
LoadNewBoundary:
mov edx, [ebp].Boundary
out dx, al ; BOUNDARY <- NextPage ptr - 1
;
;***************************************************************\
; *
; Check to see if more packets are waiting to be received. *
; *
;***************************************************************/
;
TestForReceive:
mov edx, [ebp].Command ; EDX = Command.
mov al, NIC_Page1 ; Go into page 1 registers.
out dx, al
add edx, IInterruptStatus - ICommand ; EDX = Current.
in al, dx
cmp al, ah ; Any more Rx buffers?
mov edx, [ebp].Command ; Return to page 0 registers
mov al, NIC_Page0 ; before jumping.
out dx, al
jnz ReceiveNextPacket ; Yes. Get next packet.
;
;***************************************************************\
; *
; Now see if we're in an Overflow loopback mode. *
; *
;***************************************************************/
;
cmp [ebp].OverflowRestartFlag, 0 ; In overflow mode?
jz PollAgain ; No. Poll status port again.
;
;***************************************************************\
; *
; Now that receive buffers are empty, we can finish handling *
; the Buffer Overflow error by placing the NIC out of the *
; loopback mode and sending out the current Tx buffer if it had *
; been active at the time of overflow and got cancelled by the *
; stop command. *
; *
;***************************************************************/
;
mov edx, [ebp].TransmitConfiguration
xor al, al ; Take card out of loopback.
out dx, al
mov [ebp].OverflowRestartFlag, al
cmp [ebp].RetryTxFlag, al ; Restart Tx flag?
je PollAgain ; Finished if not.
;
;***************************************************************\
; *
; A transmit was cancelled during overflow condition. *
; Re-send it. *
; *
;***************************************************************/
;
mov [ebp].RetryTxFlag, al ; Clear restart flag.
IF BackToBackSends
mov al, [ebp].TransmitPage0 ; Assume Page #1.
mov ecx, [ebp].TransmitSize1 ; Assume size for Page #1.
test [ebp].TransmitStatusFlag, 0010b ; Use Page #1?
jz short RestartIssueTheSend ; Jump if so.
;JCP mov al, TransmitPage1 ; Set Page #2.
mov al, [ebp].TransmitPage1 ; Set Page #2. JCP, 941108.
mov ecx, [ebp].TransmitSize2 ; Set size for Page #2.
RestartIssueTheSend:
mov edx, [ebp].TransmitPage ; EDX = TxPage register.
out dx, al ; Set Page register.
inc edx ; EDX = TxCount0 register.
mov eax, ecx ; EAX = Transmit size.
ELSE
mov edx, [ebp].TransmitByteCount0
mov eax, [ebp].TransmitSize1
ENDIF
out dx, al ; Send LSB of TxByteCount.
inc edx ; EDX = TxCount1 register.
mov al, ah ; AL = MSB of TxByteCount.
out dx, al ; Send MSB of TxByteCount.
sub edx, ITransmitByteCount1 - ICommand ; EDX = Command port.
mov al, NIC_Transmit ; Issue the Tx command.
out dx, al
MSMGetCurrentTime ; EAX = Current Time.
mov [ebp].TxStartTime, eax ; Store for later.
mov [ebp].RetryCounter, MaxRetries ; Page #2.
jmp PollAgain ; Return.
PacketTooLong:
dec al
shr al, 3 ; AL = (AL - 1) / 8.
shl eax, 11 ; EAX = EAX * 2048.
add ecx, eax ; Add to total count.
jmp PacketTooLongReturn
SharedPacketTooLong:
dec al
shr al, 3 ; AL = (AL - 1) / 8.
shl eax, 11 ; EAX = EAX * 2048.
add ecx, eax ; Add to total count.
jmp short SharedPacketTooLongReturn
;
;***************************************************************\
; *
; Read packet from shared RAM adapter. *
; *
;***************************************************************/
;
DriverISRSharedRAM:
;
;***************************************************************\
; *
; Read in Receive Header from next packet in the ring. *
; *
;***************************************************************/
;
xor eax, eax ; Prepare EAX to point
mov ah, [ebp].NextPage ; to the next Rx page.
add eax, [ebp].NICRAMSegmentBase ; Add Shared mem offset.
mov esi, eax ; ESI->Next Rx Packet.
mov al, [ebp].ReceiveStatusTest
test [esi].RReceiveStatus, al ; Rx error?
jnz PagingError ; Jump if so.
movzx ecx, [esi].RByteCount ; ECX = Packet Length.
movzx eax, [esi].RNextBuffer ; AL = Next Page.
cmp al, [ebp].NextPage ; Did Next Page wrap?
jae short SharedCheckForLong ; Jump if not.
add al, PSTOP - PSTART ; Set AL higher.
SharedCheckForLong:
sub al, [ebp].NextPage ; AL = Number of Pages.
cmp al, 8 ; > 1792?
ja SharedPacketTooLong ; Jump if so.
SharedPacketTooLongReturn:
mov eax, ecx ; EAX = PacketLength.
;
;***************************************************************\
; *
; Use ByteCount and NextPage to determine any Paging errors. *
; *
;***************************************************************/
;
add eax, 4 - 1 + 100h ; (4 - 1 + 100h) where the last byte
add ah, [ebp].NextPage ; was plus round up.
cmp ah, RAMPSTOP ; Wrap to beginning of ring?
jb short RAMNoOverflow ; No. Jump.
add ah, RAMPSTART - RAMPSTOP ; Adjust to front of ring.
RAMNoOverflow:
cmp ah, [esi].RNextBuffer ; Does header agree?
jnz PagingError ; No. Paging error.
mov [ebp].NextPage, ah ; Save for next time.
;
;***************************************************************\
; *
; Now let the MSM decide if we should accept the packet. *
; *
;***************************************************************/
;
movzx eax, [esi].RReceiveStatus
shr al, 1
and al, 03h ; Save CRC error bits.
sub ecx, SizeOfCRCField ; Subtract CRC length.
add esi, SIZE ReceiveHeaderStructure ; ESI -> Dest addr.
mov [ebp].CurrentPacketPointer, esi ; Save position.
call EtherTSMGetRCB ; Get an ECB.
jnz PacketNotReceived ; Jump if error.
or ecx, ecx
jz RxReturnECB ; Jump if nothing to copy
mov [ebp].CurrentECB, esi ; Save ECB.
;
;***************************************************************\
; *
; EDX -> ECB. *
; EDI -> Place in ECB to resume reading in data from NIC. *
; ECX = Bytes remaining to be read from NIC. *
; EBX = Bytes in packet to skip over. *
; *
;***************************************************************/
;
mov esi, [ebp].CurrentPacketPointer ; ESI -> Next Rx Data to read.
add esi, ebx ; Add bytes to skip.
;
;***************************************************************\
; *
; Copy the rest of the packet into ECB packet data. *
; *
;***************************************************************/
;
mov [ebp].TotalBytes, ecx ; Save for later.
mov ebx, edi ; EBX -> Frag Count.
mov eax, [ebx] ; EAX = Frag Count.
add ebx, 4 ; EBX -> 1st Frag Structure.
mov edx, [ebp].NICRAMSegmentLimit ; EDX = End of RAM.
sub edx, esi ; EDX = EDX - Our current pos.
cmp ecx, edx ; Are we going to go over?
jg AdjustToRingTop ; Jump if so.
RxFragmentLoop:
mov edi, [ebx+0] ; EDI -> Frag offset.
mov ecx, [ebx+4] ; ECX = Frag size.
sub [ebp].TotalBytes, ecx
js SharedReadNextFragOverrun
SharedReadNextFragment:
shr ecx, 2 ; Copy dwords.
rep movsd
mov ecx, [ebx+4] ; ECX = Frag size.
and ecx, 3 ; Copy leftover bytes.
rep movsb
RxNextFragment:
cmp [ebp].TotalBytes, 0 ; More bytes to read?
je short RxReturnECB ; Jump out if so.
add ebx, 8 ; EBX -> Next Frag struct.
dec eax ; More fragments?
jne RxFragmentLoop ; Jump if not.
RxReturnECB:
mov esi, [ebp].CurrentECB ; ESI -> ECB.
IF UseFastCalls
push ebp
call EtherTSMFastRcvComplete ; Give ECB to protocol stack.
pop ebp
ELSE
call EtherTSMRcvComplete ; Give ECB back to LSL.
ENDIF
RAMFinishUp:
mov al, [ebp].NextPage ; AL = Page of next buffer.
mov ah, al ; Save for TestForReceive.
dec al ; Boundary = NextPage - 1.
cmp al, RAMPSTART ; Still within Rx boundary.
jae short RAMLoadNewBoundary ; Yes. Use it.
mov al, RAMPSTOP - 1 ; No. Move to end of ring.
RAMLoadNewBoundary:
mov edx, [ebp].Boundary
out dx, al ; BOUNDARY <- NextPage ptr - 1
jmp TestForReceive
SharedReadNextFragOverrun:
add ecx, [ebp].TotalBytes ; ECX = bytes left.
rep movsb ; Copy remaining bytes.
jmp RxReturnECB ; We're finished.
AdjustToRingTop:
mov edi, [ebx+0] ; EDI -> Frag offset.
mov ecx, [ebx+4] ; ECX = Frag size.
cmp ecx, edx ; Small fragment?
jb short CantReachRingTop ; Jump if so.
mov ecx, edx ; ECX = bytes left.
sub [ebp].TotalBytes, ecx
js SharedReadNextFragOverrun
shr ecx, 2 ; Copy dwords.
rep movsd
mov ecx, edx ; ECX = bytes left.
and ecx, 3 ; Copy leftover bytes.
rep movsb
mov ecx, [ebx+4] ; ECX = Frag size.
sub ecx, edx ; Subtract what we've copied.
mov esi, [ebp].NICRAMReceiveRingStart
sub [ebp].TotalBytes, ecx
js SharedReadNextFragOverrun
shr ecx, 2 ; Copy dwords.
rep movsd
mov ecx, [ebx+4] ; ECX = Frag size.
sub ecx, edx ; Subtract what we've copied.
and ecx, 3 ; Copy leftover bytes.
rep movsb
jmp RxNextFragment
CantReachRingTop:
sub [ebp].TotalBytes, ecx
js SharedReadNextFragOverrun
sub edx, ecx ; EDX = New length to end.
shr ecx, 2 ; Copy dwords.
rep movsd
mov ecx, [ebx+4] ; ECX = Frag size.
and ecx, 3 ; Copy leftover bytes.
rep movsb
add ebx, 8 ; EBX -> Next Frag structure.
dec eax ; Any more fragments?
jne AdjustToRingTop ; Jump if so.
jmp RxReturnECB ; Jump if not.
;
;***************************************************************\
; *
; Unable to receive packet. Increment proper statistic counter. *
; *
;***************************************************************/
;
PacketNotReceived:
dec eax ; Was EAX == 1?
jnz short BadMulticastError ; Jump if not.
inc [ebp].UnsupportedFrameCount ; Update stat counter.
jmp RxFinishUp ; Skip receiving this packet.
BadMulticastError:
dec eax ; Was EAX == 2?
jnz RxFinishUp ; Jump if not.
inc [ebp].UnsupportedMulticastCount ; Update stat counter.
RxFinishUp:
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
jne RAMFinishUp ; Jump if so.
jmp FinishUp ; Skip receiving this packet.
;
;***************************************************************\
; *
; Receive error paths. *
; *
;***************************************************************/
;
HandleRxErrors:
test ah, 10h ; Buffer Overflow?
jnz short HandleBufferOverflowCase ; Jump if so.
;
;***************************************************************\
; *
; Handle Receive Errors. *
; *
;***************************************************************/
;
mov al, 4 ; Reset the RX Error Bit.
out dx, al
mov edx, [ebp].ReceiveStatus ; Find out which type
in al, dx ; caused receive error.
test al, FIFOOverrunErrorBit ; FIFO overrun?
jz short NotOverrunError ; Jump if not.
inc [ebp].RxFIFOOverrunErrorCount ; Inform diagnostics.
inc [ebp].PacketRxMiscErrorCount
NotOverrunError:
xor eax, eax ; Clear accumulator.
mov edx, [ebp].TallyCounter0 ; Frame Alignment error counter.
in al, dx ; Read counter.
add [ebp].RxAbortFrameAlignment, eax ; Add to statistics.
add [ebp].PacketRxMiscErrorCount, eax
inc edx ; CRC error counter.
in al, dx ; Read counter.
add [ebp].ChecksumErrorCount, eax ; Add to statistics.
inc edx ; Missed Packet error counter.
in al, dx ; Read counter.
add [ebp].RxMissedPacketCount, eax ; Add to statistics.
add [ebp].PacketRxMiscErrorCount, eax
jmp PollAgain ; Test for other interrupts.
;
;***************************************************************\
; *
; Handle Receive Buffer Overflow errors. *
; *
;***************************************************************/
;
HandleBufferOverflowCase:
inc [ebp].PacketRxOverflowCount ; Inform diagnostics.
mov edx, [ebp].Command ; Read Command port.
in al, dx
mov cl, al ; Save Tx Active bit.
mov al, NIC_Page0Stop ; Put NIC in STOP mode.
out dx, al
add edx, IRemoteByteCount0 - ICommand ; EDX = RemoteByteCount0.
xor eax, eax ; Clear RemoteByteCount
out dx, al ; Clear LSB of Count.
inc edx ; EDX = RemoteByteCount1.
out dx, al ; Clear MSB of Count.
; JCP, 941108 *Begin*
; call ReadTickCounter ; Get initial tick.
; mov ebx, eax ; EBX = Initial tick value.
;
;***************************************************************\
; *
; Idle about 1.6ms to allow current Tx or Rx to finish. *
; *
;***************************************************************/
;
;WaitForTxOrRxToFinish:
; call ReadTickCounter ; Get current tick.
; neg eax
; add eax, ebx ; EAX = Current-Initial Tick.
; cmp eax, 4096 ; 1.7ms passed yet?
; jb WaitForTxOrRxToFinish ; Jump if not
call MSMGetMicroTimer ; EAX = current count.
mov ebx, eax ; ESI = current tick.
neg ebx ; Set to negative value.
WaitForTxOrRxToFinish:
call MSMGetMicroTimer ; EAX = current count.
add eax, ebx ; Time yet ?
cmp eax, 1600 ; 1.6 msec.
jb WaitForTxOrRxToFinish ; Jump if below 1.6 msec.
; JCP, 941108 *End*
mov edx, [ebp].InterruptStatus
mov al, 10h ; Reset the overflow bit.
out dx, al
test cl, NIC_TxInProgress ; Txing during overflow?
jz short NoTxActiveAtOverflow ; Jump if not.
in al, dx ; Read Interrupt Status.
test al, NIC_TxComplete ; TxComplete or TxError?
jnz short NoTxActiveAtOverflow ; Jump if so.
inc [ebp].RetryTxFlag ; Set Tx cancelled flag so we
; can restart transmit later.
;
;***************************************************************\
; *
; Put NIC into LoopBack mode until we empty receive buffers. *
; *
;***************************************************************/
;
NoTxActiveAtOverflow:
mov edx, [ebp].TransmitConfiguration
mov al, 4 ; Using external loopback fixes
; overflow hangs on rev C 8390
; parts on IPXLoad test.
out dx, al
;
;***************************************************************\
; *
; Re-enable card in loopback mode. *
; *
;***************************************************************/
;
sub edx, ITransmitConfiguration - ICommand ; EDX = Command register.
mov al, NIC_Page0 ; Reenable card in loopback
out dx, al ; mode.
inc [ebp].OverflowRestartFlag ; Set restart flag.
mov ah, [ebp].NextPage ; AL = Page of next buffer.
jmp TestForReceive ; Empty packets from ring.
;
;***************************************************************\
; *
; Received packet bit was set but no packet where in the ring. *
; *
;***************************************************************/
;
DidntGetAnything:
add edx, IInterruptStatus - ICommand ; EDX = Int status.
mov al, 1 ; Reset the RX Bit.
out dx, al
inc [ebp].GotNothingCount ; Increment Stat counter.
jmp PollAgain ; Check for more interrupts.
;
;***************************************************************\
; *
; Check For Transmit Complete or Transmit Error. *
; *
;***************************************************************/
;
CheckForTransmit:
test ah, NIC_TxComplete ; Tx finished? (0Ah)
jz GetOut ; No. Must be finished.
mov al, 0Ah ; EDX = Interrupt Status Port.
out dx, al ; Reset the transmit bits.
test ah, NIC_TransmitError ; Was it a bad TX? (08h)
jnz Bad_Transmit ; Jump if so.
mov edx, [ebp].NumberCollisions ; Find out if transmission
in al, dx ; experienced any collisions.
movzx ecx, al ; Clear upper bits.
cmp ecx, 1 ; Single collision?
je short CheckTxSingleCol ; Jump if so.
add [ebp].TxOKMultipleCollisions, ecx ; Add to statistics.
jmp short TransmitNextPacket
CheckTxSingleCol:
inc [ebp].TxOKSingleCollision ; Inc single col stat.
TransmitNextPacket:
inc [ebp].MSMTxFreeCount ; Free up transmit buffer.
mov [ebp].TxStartTime, 0 ; Zero out Tx Start time.
IF BackToBackSends
test [ebp].TransmitStatusFlag, 0100b ; Another Tx waiting?
jz short NothingQueuedOnCard ; Jump if not.
;
;***************************************************************\
; *
; We just completed this send, but there is already another *
; packet transfered to the board. We just need to issue the *
; send for it. *
; *
;***************************************************************/
;
inc [ebp].BackToBackSendCount ; Inform diagnostics.
mov al, [ebp].TransmitPage0 ; Assume Page #1.
mov ecx, [ebp].TransmitSize1 ; Assume TxSize #1.
test [ebp].TransmitStatusFlag, 0010b ; Were we sending to page #2?
jnz short IssueTheSend ; Jump if so.
mov al, [ebp].TransmitPage1 ; AL = Page #2.
mov ecx, [ebp].TransmitSize2 ; ECX = TxSize #2.
IssueTheSend:
mov edx, [ebp].TransmitPage ; EDX = TxPage Register.
out dx, al ; Send Tx Page.
mov eax, ecx ; EAX = TxSize.
inc edx ; EDX = TxByteCount0 register.
out dx, al ; Send LSB of TxByteCount.
inc edx ; EDX = TxByteCount1 register.
mov al, ah ; AL = MSB of TxByteCount.
out dx,al ; Send MSB of TxByteCount.
sub edx, ITransmitByteCount1 - ICommand ; EDX = Command port.
mov al, NIC_Transmit ; Initiate Transmit.
out dx, al
MSMGetCurrentTime ; EAX = CurrentTime.
mov [ebp].TxStartTime, eax ; Record current time.
mov [ebp].RetryCounter, MaxRetries ; Page 1.
xor [ebp].TransmitStatusFlag, 0110b ; 5->3, 7->1.
jmp short CheckForMoreSends ; Try to queue another Tx.
NothingQueuedOnCard:
mov [ebp].TransmitStatusFlag, 0010b ; No Tx in progress.
; Buffer #1 is free.
CheckForMoreSends:
ENDIF
;
;***************************************************************\
; *
; See if there is something else that needs to be transmitted. *
; *
;***************************************************************/
;
;JCP test [ebp].MSMStatusFlags, TXQUEUED ; Anything in send queue.
;JCP jz PollAgain ; Jump to Polling if not.
;JCP inc [ebp].EnqueueSendCount ; Increment statistics.
call EtherTSMGetNextSend ; Send next ECB enqueued.
jnz PollAgain ; Poll if nothing queued.
inc [ebp].EnqueueSendCount ; Increment statistics. JCP
if UseFastCalls
push ebp
push offset DriverISRSendReturn
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
jne DriverSendSharedRAM ; Jump if so.
jmp DriverSend ; Send it.
DriverISRSendReturn:
pop ebp
else
call DriverSend ; Send it.
endif
jmp PollAgain ; Check for receives.
;
;***************************************************************\
; *
; Tx error path. *
; *
;***************************************************************/
;
Bad_Transmit:
sub edx, IInterruptStatus - ITransmitStatus ; EDX = Tx Status Reg.
in al,dx ; Get TX status.
test al, NIC_ExcessCollisions ; Excess collisions?
jz short CheckFIFO ; Jump if not.
inc [ebp].TxAbortExcessCollisions ; Increment stat counter.
inc [ebp].PacketTxMiscErrorCount
jmp short FinishUpTransmit ; Retry transmit.
CheckFIFO:
test al, NIC_FIFO_Underrun ; FIFO Underrun?
jz short CheckCollisions ; Jump if not.
inc [ebp].UnderrunErrorCount ; Increment stat counter.
inc [ebp].PacketTxMiscErrorCount
CheckCollisions:
test al, NIC_Collisions ; Any Collisions?
jz short FinishUpTransmit ; Jump if not.
mov edx, [ebp].NumberCollisions ; Find out how many collisions
in al, dx ; were detected.
movzx eax, al ; Clear upper bits.
cmp eax, 1 ; Single collision?
je CheckColSingleCol ; Jump if so.
add [ebp].TxOKMultipleCollisions, eax ; Add to statistics.
jmp short FinishUpTransmit
CheckColSingleCol:
inc [ebp].TxOKSingleCollision ; Inc single col stat.
;
;***************************************************************\
; *
; Attempt to retry this transmission. *
; *
;***************************************************************/
;
FinishUpTransmit:
dec [ebp].RetryCounter ; Any more retries?
jz TransmitNextPacket ; Give up if not.
inc [ebp].RetryTxCount ; Inform diagnostics.
;
;***************************************************************\
; *
; Program the NIC to re-start the transmit. *
; *
;***************************************************************/
;
IF BackToBackSends
mov al, [ebp].TransmitPage0 ; Assume Page #1.
mov ecx, [ebp].TransmitSize1 ; EAX = Tx size for page #1.
test [ebp].TransmitStatusFlag, 0010b ; Need to send to page #1?
jz short ReTxSizeSet ; Jump if so.
mov al, [ebp].TransmitPage1 ; Set to Page #2.
mov ecx, [ebp].TransmitSize2 ; EAX = Tx size for page #2.
ReTxSizeSet:
out dx, al ; Set TxPage register.
mov eax, ecx ; EAX = Transmit Size.
inc edx ; EDX = TxByteCount0 register.
ELSE
mov edx, [ebp].TransmitByteCount0
mov eax, [ebp].TransmitSize1
ENDIF
out dx, al ; Send LSB of TxByteCount.
inc edx ; EDX = TxByteCount1 register.
mov al, ah ; AL = MSB of TxByteCount.
out dx, al ; Send MSB of TxByteCount.
sub edx, ITransmitByteCount1 - ICommand
mov al, NIC_Transmit ; Issue Tx command.
out dx, al
MSMGetCurrentTime ; EAX = Current Time.
mov [ebp].TxStartTime, eax ; Record Tx Start.
jmp PollAgain ; Check status again.
;
;***************************************************************\
; *
; Time to exit ISR. *
; *
;***************************************************************/
;
GetOut:
IF NOT UseFastCalls
dec [ebp].InDriverISR ; Not in ISR.
ENDIF
IF UseFastCalls
ret
ELSE
MSMServiceEventsAndRet ; Let LSL unqueue returned
;ret ; ECB's and return.
ENDIF
ClearIntsAndGetOut:
mov edx, [ebp].InterruptStatus ; Read the NIC ISR.
in al,dx ; AL and
out dx, al
IF NOT UseFastCalls
dec [ebp].InDriverISR ; Not in ISR.
ENDIF
IF UseFastCalls
ret
ELSE
MSMServiceEventsAndRet ; Let LSL unqueue returned
;ret ; ECB's and return.
ENDIF
DriverISR endp
subttl -- DriverDisableInterrupt --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverDisableInterrupt, NE2000/API/DISINT )
;
; Name: DriverDisableInterrupt
;
; Description: This routine will disable the adapters ability to
; interrupt the host.
;
; On Entry: EAX N/A
; EBX N/A
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Preserved
; EDX Destroyed
; EBP Preserved
; ESI Preserved
; EDI Preserved
;
; Flags:
;
; Note: Interrupts disabled.
;
; Remarks: This routine is called by the MSM.
;
; See Also: DriverEnableInterrupt
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
align 16
DriverDisableInterrupt proc
if DEBUG
push eax
mov al, 'D'
call OutChar
pop eax
endif
mov edx, [ebp].InterruptMask
mov al, NIC_MaskByte
out dx, al
xor eax, eax
ret
DriverDisableInterrupt endp
subttl -- DriverEnableInterrupt --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverEnableInterrupt, NE2000/API/ENINT )
;
; Name: DriverEnableInterrupt
;
; Description: This routine will enable the adapters ability to
; interrupt the host.
;
; On Entry: EAX N/A
; EBX N/A
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Preserved
; EDX Destroyed
; EBP Preserved
; ESI Preserved
; EDI Preserved
;
; Flags:
;
; Note: Interrupts disabled.
;
; Remarks: This routine is called by the MSM.
;
; See Also: DriverDisableInterrupt
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
align 16
DriverEnableInterrupt proc
if DEBUG
push eax
mov al, 'E'
call OutChar
pop eax
endif
mov edx, [ebp].InterruptMask
mov al, NIC_UnmaskByte
out dx, al
ret
DriverEnableInterrupt endp
; Removed by JCP. (941108)
;
; subttl -- ReadTickCounter --
; page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( ReadTickCounter, NE2000/INTERNAL/TICK )
;
; Name: ReadTickCounter
;
; Description: This routine reads the timer tick count register which
; decrements by 2 every 65536 to 0 every 1/36.414 times a
; second. Each 2 decrements of the count the count represents
; 838 nsec's.
;
; On Entry: EAX N/A
; EBX N/A
; ECX N/A
; EDX N/A
; EBP N/A
; ESI N/A
; EDI N/A
;
; Note: Interrupts in any state.
;
; On Return: EAX Current Count
; EBX Preserved
; ECX Preserved
; EDX Preserved
; EBP Preserved
; ESI Preserved
; EDI Preserved
;
; Flags:
;
; Note: Interrupts preserved.
;
; Remarks: This routine is called by DriverISR.
; It is called at interrupt time.
;
; See Also: DriverISR.
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
;ReadTickCounter proc near
;
; xor eax, eax ; Clear accumulator.
; mov al, 06h ; Command 8254 to latch T0's count.
; out 43h, al
;
; Now you can read the count.
;
; in al, 40h ; Read LSB of latched count.
; mov ah, al ; Save in AH.
; in al, 40h ; Read MSB of latched count.
; xchg al, ah ; Put into proper order.
; ret
;
;ReadTickCounter endp
public DriverReset
subttl -- DriverReset --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverReset, NE2000/API/RESET )
;
; Name: DriverReset
;
; Description: This routine will reset and initialize the NIC.
;
; On Entry: EAX set to OP_SCOPE_ADAPTER if the adapter specified by EBP
; is to be reset. Otherwise set to OP_SCOPE_LOGICAL_BOARD
; which indicates that only the logical board specified
; by EBX is to be reset.
; EBX @ Frame Data Space
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX 0 if successful(otherwise points to error message)
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Destroyed
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts disabled.
;
; Remarks: This routine is called by the MSM media module.
; It is called at process time.
;
; See Also: ETHERTSM\EtherTSMReset
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
DriverReset proc near
cmp eax, OP_SCOPE_ADAPTER
je ResetAdapter
xor eax, eax
ret
ResetAdapter:
inc [ebp].AdapterResetCount ; Increment stat counter.
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
je DriverResetIO ; Jump if not.
mov edx, [ebp].Control2 ; DX = Control 2.
mov al, [ebp].Control2Value
;; mov eax, 0c1h ; Set to 16 bit mode.
out dx, al
mov edx, [ebp].Control1 ; DX = Control 1.
mov al, [ebp].Control1Value
or al, 10000000b ; Set Reset line.
out dx, al ; Reset adapter.
SLOW
and al, 01111111b ; Release Reset line.
out dx, al
jmp short DriverResetStop
DriverResetIO:
mov edx, [ebp].Reset ; Initialize the NIC.
in al,dx ; Reading this port sets
; a hard reset.
SLOW
out dx,al ; Release reset.
DriverResetStop:
mov edx, [ebp].Command ; EDX = Command register.
mov al, NIC_Page0Stop ; Set to page 0 registers.
out dx,al
cmp [ebp].FirstTimeInit, 1 ; In driver init?
je CheckPort ; Yes. Check command port.
CheckPortReturn:
mov edx,[ebp].DataConfiguration ; EDX = DataConfiguration register.
mov al,49h ; Set to word mode.
out dx,al
mov edx, [ebp].RemoteByteCount0 ; Clear RBCR0 and RBCR1.
xor al, al
out dx, al ; Clear LSB of RemoteByteCount.
inc edx ; EDX = RemoteByteCount1.
out dx, al ; Clear MSB of RemoteByteCount.
mov [ebp].OverflowRestartFlag, al ; Clear in case Paging error
mov [ebp].RetryTxFlag, al ; occured after overflow.
call EtherTSMUpdateMulticast ; Init Multicast registers.
;
;***************************************************************\
; *
; We need to be in loopback mode to prevent getting a receive *
; during the RAM tests. *
; *
;***************************************************************/
;
mov ecx, PSTART ; CL = I/O PSTART.
mov edi, PSTOP ; EDI = I/O PSTOP.
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
je short DriverResetPSTART ; Jump if not.
mov ecx, RAMPSTART ; CL = Shared RAM PSTART.
mov edi, RAMPSTOP ; EDI = Shared RAM PSTOP.
DriverResetPSTART:
mov edx, [ebp].TransmitConfiguration ; EDX = TxConfiguration register.
mov al, 2 ; Put in loopback mode.
out dx, al
mov edx, [ebp].PageStart ; Set RX start to beginning of RAM.
mov al, cl
out dx, al
mov edx, [ebp].Boundary ; Set Boundary to PSTART.
out dx, al
mov edx, [ebp].PageStop ; Set RX stop to end of RAM.
mov eax, edi
out dx, al
mov edx, [ebp].InterruptStatus ; Clear all interrupt bits.
mov al, 0FFh
out dx, al
if DEBUG
push eax
mov al, 'e'
call OutChar
pop eax
endif
mov edx, [ebp].InterruptMask ; EDX = InterruptMask register.
mov al, NIC_UnmaskByte ; Unmask all interrupts.
out dx, al
mov edx, [ebp].Command ; Switch to page 1 registers.
mov al, NIC_Page1Stop
out dx, al
mov edx, [ebp].Current ; Set current page to
lea eax, [ecx + 1] ; Beginning of ring + 1.
out dx, al
mov [ebp].NextPage, al ; Initialize NextPage.
mov edx, [ebp].Command
mov al, NIC_Page0Stop ; Switch back to page 0
out dx, al ; registers.
;
;***************************************************************\
; *
; If this is the first time through, then do some hardware *
; tests and initialize the physical address register. *
; *
;***************************************************************/
;
cmp [ebp].FirstTimeInit,1 ; First time thru?
jne short SkipHardwareTests ; Skip if not.
call DriverTestHardware ; Test the hardware.
or eax, eax ; Error?
jnz short DeadHardware ; Jump if so.
SkipHardwareTests:
IF BackToBackSends
mov edx, [ebp].TransmitPage ; This fix for collisions.
mov al, [ebp].TransmitPage0 ; AL = page C0h.
InitIssueTheSend:
out dx, al ; Set proper Transmit page.
mov [ebp].TransmitStatusFlag, 0010b ; Set to Initial value
mov [ebp].MSMTxFreeCount, 2 ; Allow 2 transmits simultaneously.
ELSE
mov edx, [ebp].TransmitPage
mov al, [ebp].TransmitPage0
out dx, al
mov [ebp].MSMTxFreeCount, 1 ; Allow 1 transmit.
ENDIF
mov edx, [ebp].Command ; EDX = Command register.
mov al, NIC_Page0 ; Start the NIC.
out dx, al
;
;***************************************************************\
; *
; Take NIC out of Loopback mode. *
; *
;***************************************************************/
;
mov edx, [ebp].TransmitConfiguration
xor eax, eax ; Mode 0 transmit.
out dx, al
mov [ebp].OverflowRestartFlag, al ; Reset Overflow flag.
ret ; Init successful.
;
;***************************************************************\
; *
; Check for valid command port response. *
; *
;***************************************************************/
;
CheckPort:
in al, dx ; Read command register.
cmp al, 21h ; Is the i/o port alive ?
je CheckPortReturn ; Yes, proceed.
cmp al, 23h ; Try again.
je CheckPortReturn ; Yes, proceed.
lea eax, PortFailMessage ; EAX -> Error Message.
DeadHardware:
push eax ; Save error message.
mov edx, [ebp].Command ; EDX = Command register.
mov al, NIC_Page0Stop ; Stop the NIC.
out dx, al
pop eax ; Restore error message.
or eax, eax
ret
DriverReset endp
subttl -- DriverTestHardware --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverTestHardware, NE2000/INTERNAL/TEST )
;
; Name: DriverTestHardware
;
; Description: This routine will use either the configuration tables or
; NIC's node address to set the NIC's physical registers and
; test the NIC's static RAM.
;
; On Entry: EAX N/A
; EBX @ Frame Data Space
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX 0 if successful(otherwise points to error message)
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Destroyed
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts disabled.
;
; Remarks: This routine is called by the DriverReset.
; It is called at process time.
;
; See Also: DriverReset
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
DriverTestHardware proc
;
;***************************************************************\
; *
; Now, read my physical address out of the ROM and program the *
; chip as well as saving it for later. *
; *
;***************************************************************/
;
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
jne DriverTestSharedRAM ; Jump if so.
mov edx, [ebp].RemoteStartAddress0 ; EDX = RemoteStartAddress0.
xor al, al ; Start at beginning of ROM.
out dx, al ; Send LSB of RemoteStartAddress.
inc edx ; EDX = RemoteStartAddress1.
out dx, al ; Send MSB of RemoteStartAddress.
inc edx ; EDX = RemoteByteCount0.
mov ax, 16 * 2 ; Read 16 bytes.
out dx, al ; Send LSB of RemoteByteCount.
inc edx ; EDX = RemoteByteCount1.
mov al, ah ; AL = MSB of RemoteByteCount.
out dx, al ; Send MSB of RemoteByteCount.
mov edx, [ebp].Command ; EDX = Command register.
mov al, NIC_RemoteDmaRd ; Issue Remote DMA read
out dx, al ; to card.
mov edx, [ebp].NICData ; EDX = NIC Data port.
lea edi, [ebx].MLIDNodeAddress ; EDI -> Node Address.
mov esi, edi ; ESI -> Node Address.
;
;***************************************************************\
; *
; First make sure node wasn't forced from command line. *
; *
;***************************************************************/
;
cmp dword ptr [ebx].MLIDNodeAddress, -1
jz short GetNodeFromProm
lea edi, [ebp].ReceiveHeader ; Copy PROM's node to dummy.
GetNodeFromProm:
;
;***************************************************************\
; *
; Read Node address from card. *
; *
;***************************************************************/
;
rept 6
in al, dx ; Read PROM's Node byte.
stosb ; Store it.
endm
;
;***************************************************************\
; *
; Make sure this is really an NE2000 by searching for 'WW' in *
; next ten bytes of the PROM. *
; *
;***************************************************************/
;
mov ecx, 10 ; Check next ten bytes.
CheckSignatureLoop:
in al, dx ; Read next byte from PROM.
cmp ecx, 4 ; Checksum?
je short SkipChecksum ; Jump if so.
cmp ecx, 3 ; Checksum?
je short SkipChecksum ; Jump if so.
cmp al, 'W' ; NE2000 in 16-bit slot?
jz short NICMightBeIn16BitSlot ; Jump if so.
cmp al, 'B' ; NE2000 in 8-bit slot?
jz short NICMightBeIn8BitSlot ; Jump if so.
SkipChecksum:
dec ecx
jnz short CheckSignatureLoop ; Check next PROM byte.
jmp NICNotInSlot ; NE2000 not there.
NICMightBeIn16BitSlot:
dec ecx ; Any more bytes to read?
jz NICNotInSlot ; Exit if not.
in al, dx ; Read next byte from PROM.
cmp al, 'W' ; NE2000 in 16-bit slot?
jz short NICIn16BitSlot ; Jump if so.
dec ecx
jnz short CheckSignatureLoop ; Check next PROM byte.
jmp NICNotInSlot ; NE2000 not there.
NICMightBeIn8BitSlot:
dec ecx ; Any more bytes to read?
jz NICIsNE1000 ; Exit if not.
in al, dx ; Read next byte from PROM.
cmp al, 'B' ; NE2000 in 8-bit slot?
jz NICIn8BitSlot ; Jump if so.
jmp NICIsNE1000 ; Trying to access an NE1000.
NICIn16BitSlot:
mov ecx, 6
mov edx, [ebp].Command ; EDX = Command register.
mov al, NIC_Page1Stop ; Stop the NIC and enable
out dx, al ; page 1 registers.
mov edx, [ebp].PhysicalReg0 ; EDX = Physical register 0.
AddressToChipLoop:
lodsb ; Get next byte.
out dx, al ; Send it to card.
rept 10
nop
endm
inc edx ; Go to next Physical reg.
dec ecx
jnz AddressToChipLoop ; Get next node byte.
mov edx, [ebp].Command ; EDX = Command register.
mov al, NIC_Page0Stop ; Set to Page 0.
out dx, al
;
;***************************************************************\
; *
; Now that we know we are really dealing with an NE2000 in the *
; right slot, we can safely test memory. *
; NE2000 contains Static RAM. Running a checkerboard test will *
; catch retention, open or shorted faults common to S-RAM. *
; *
;***************************************************************/
;
push ebx ; Save Board Base.
mov bx, 0a5a5h ; Perform basic checkerboard
call DoRAMTest ; memory test on card.
pop ebx ; Restore Board Base.
jnz short MemoryFailure ; Jump if memory test failed.
push ebx ; Save Board Base.
mov bx, 05a5ah ; Complement pattern and
call DoRAMTest ; test again.
pop ebx ; Restore Board Base.
jnz short MemoryFailure ; Jump if memory test failed.
;
;***************************************************************\
;
; Now verify that the IRQ which was selected matches that of *
; the hardware.
; *
;***************************************************************/
;
xor eax, eax ; Init successful.
ret
DriverTestSharedRAM:
lea edi, [ebx].MLIDNodeAddress
mov esi, edi
cmp dword ptr [ebx].MLIDNodeAddress, -1
jne NICIn16BitSlot
mov edx, [ebp].Prom ; DX = Prom I/O port.
mov ecx, 6
DriverTestSharedLoop:
in al, dx
inc edx
stosb
loop DriverTestSharedLoop
jmp NICIn16BitSlot
;
;***************************************************************\
; *
; DriverTestHardware error paths. *
; *
;***************************************************************/
;
NICIn8BitSlot:
lea eax, NICIn8BitSlotMessage
ret
NICNotInSlot:
lea eax, NICNotInSlotMessage
ret
NICIsNE1000:
lea eax, NICIsNE1000Message
ret
MemoryFailure:
lea eax, BufferMemoryFailMessage
ret
DriverTestHardware endp
subttl -- DoRAMTest --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DoRAMTest, NE2000/INTERNAL/RAMTEST )
;
; Name: DoRAMTest
;
; Description: This routine will test Static RAM by writing the pattern
; provided to all areas of memory and reading them back.
;
; On Entry: EAX N/A
; EBX Test Pattern
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Preserved
; EDI Preserved
;
; Flags:
;
; Note: Interrupts disabled.
;
; Remarks: This routine is called by the DriverTestHardware.
; It is called at process time.
;
; See Also: DriverTestHardware
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
DoRAMTest proc near ; NE2000 RAM Test.
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
jne DoSharedRAMTest ; Jump if so.
;
;***************************************************************\
; *
; Set Remote Start Address = 4000h. *
; *
;***************************************************************/
;
mov edx, [ebp].RemoteStartAddress0 ; EDX = RemoteStartAddress0
mov al, 0 ; AL = LSB of RemoteStartAddress.
out dx, al ; Send LSB of RemoteStartAddress.
inc edx ; EDX = RemoteStartAddress1.
mov al, 40h ; AL = MSB of RemoteStartAddress.
out dx, al ; Sedn MSB of RemoteStartAddress.
;
;***************************************************************\
; *
; Set Remote Byte Count = 4000h. *
; *
;***************************************************************/
;
inc edx ; EDX = RemoteByteCount0.
mov al, 0 ; AL = LSB of RemoteByteCount.
out dx, al ; Send LSB of RemoteByteCount.
inc edx ; EDX = RemoteByteCount1.
mov al, 40h ; AL = MSB of RemoteByteCount.
out dx, al ; Send MSB of RemoteByteCount.
;
;***************************************************************\
; *
; Issue a Remote DMA Write to NIC. *
; *
;***************************************************************/
;
mov edx, [ebp].Command ; EDX = Command port.
mov al, NIC_RemoteDmaWr
out dx, al
mov edx, [ebp].NICData ; EDX = Data port.
mov ecx, 2000h ; Write 2000h bytes.
mov ax, bx ; Write test value.
TestOutLoop:
out dx, ax ; Send test value.
SLOW ;
dec ecx
jnz TestOutLoop ; Send next one.
;
;***************************************************************\
; *
; Now re-read it back in and check for accuracy. *
; *
; Set Remote Start Address = 4000h. *
; *
;***************************************************************/
;
mov edx, [ebp].RemoteStartAddress0 ; EDX = RemoteStartAddress0
mov al, 0 ; AL = LSB of RemoteStartAddress.
out dx, al ; Send LSB of RemoteStartAddress.
inc edx ; EDX = RemoteStartAddress1.
mov al, 40h ; AL = MSB of RemoteStartAddress.
out dx, al ; Sedn MSB of RemoteStartAddress.
;
;***************************************************************\
; *
; Set Remote Byte Count = 4000h. *
; *
;***************************************************************/
;
inc edx ; EDX = RemoteByteCount0.
mov al, 0 ; AL = LSB of RemoteByteCount.
out dx, al ; Send LSB of RemoteByteCount.
inc edx ; EDX = RemoteByteCount1.
mov al, 40h ; AL = MSB of RemoteByteCount.
out dx, al ; Send MSB of RemoteByteCount.
;
;***************************************************************\
; *
; Issue Remote DMA read to NIC. *
; *
;***************************************************************/
;
mov edx, [ebp].Command ; EDX = Command port.
mov al, NIC_RemoteDmaRd
out dx, al
mov edx, [ebp].NICData ; EDX = Data port.
mov ecx, 2000h ; ECX = Bytes to read.
TestInLoop:
in ax, dx ; Read byte from card.
SLOW ;
cmp bx, ax ; Same as test value.
loopz TestInLoop ; Continue if so.
ret
DoSharedRAMTest:
cld
mov edi, [ebp].NICRAMSegmentBase ; EDI -> Cards RAM.
mov ecx, 4000h/4 ; ECX = count.
mov eax, ebx ; EAX = Test value.
rep stosd ; Write it to RAM.
mov edi, [ebp].NICRAMSegmentBase ; EDI -> Cards RAM.
mov ecx, 4000h/4 ; ECX = count.(EAX = test val)
repe scasd ; Scan memory using test value.
ret
DoRAMTest endp
subttl -- VerifyIRQ --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( VerifyIRQ, NE2000/INTERNAL/VERIFY )
;
; Name: VerifyIRQ
;
; Description: This routine will verify that the IRQ level selected by the
; user matches the IRQ that the hardware is configured for.
; We do this by configuring the card for internal loopback
; then we do transmit to force an interrupt event. If our
; ISR gets called then everything's fine, otherwise we flag
; an error condition.
;
; On Entry: EAX N/A
; EBX @ Frame Data Space
; ECX N/A
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Destroyed
; EDI Destroyed
;
; Flags:
;
; Note: Interrupts disabled.
;
; Remarks: This routine is called by the DriverTestHardware.
; It is called at process time.
;
; See Also: DriverTestHardware
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
VerifyIRQ proc near
;AYD Verify IRQ only if it is Shared RAM card SPD#132446
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
je VerifyIRQReturn ; No.
;
;***************************************************************\
;
; For some reason the loopback test won't work for come cases *
; for NE2000+ (AT/LANIC chip). However we can still verify the *
; IRQ for NE2000+ by reading the Mode Configuration Register A.*
; *
;***************************************************************/
;
xor eax, eax ; See if AT/LANIC chip, if so
mov edx, [ebp].RemoteByteCount0 ; a read from RBCR0 will give
in al, dx ; us Mode Config Register A.
mov cl, al ; Save original value
and al, NOT 18h ; Write out new value.
or al, 20h
mov ah, al ; Save new value.
out dx, al
SLOW
in al, dx ; Try to read it back.
cmp ah, al ; Did it stick?
movzx eax, cl ; Restore old value
out dx, al
je VerifyIRQAtlanic ; It stuck, must be AT/LANIC
; Else, 8390.
;
;***************************************************************\
; *
; We need to adjust the Data Configuration, Transmit Config *
; and Receive Configuration registers for loopback testing. *
; *
;***************************************************************/
;
mov edx, [ebp].DataConfiguration ; EDX = DataConfiguration register.
mov al, 41h ; Set to loopback mode.
out dx, al
mov edx, [ebp].ReceiveConfiguration ; EDX = ReceiveConfiguration register.
mov al, 1Fh ; Set to Prom mode temporarily.
out dx, al
mov edx, [ebp].InterruptStatus ; EDX = Interrupt Status Register
mov al, 0ffh ; Make sure all ints cleared
out dx, al
mov edx, [ebp].TransmitConfiguration ; EDX = Transmit Configuration register
mov al, 02h ; Put in loopback for a moment
out dx, al
if BackToBackSends
mov [ebp].MSMTxFreeCount, 2
else
mov [ebp].MSMTxFreeCount, 1
endif
;
;***************************************************************\
; *
; Now we just need to set the Transmit Page and Byte Counts and *
; initiate the transmit. Since we don't really care about the *
; transmit data we won't bother copying any particular data to *
; the NIC. *
; *
;***************************************************************/
;
mov InDriverInit, 0 ;SPD 125034
mov edx, [ebp].TransmitPage ; EDX = Transmit Page Start.
mov al, [ebp].TransmitPage0 ; Set to Tx Page 0
out dx, al
inc edx ; EDX = TxByteCount0.
mov eax, 40h ; EAX = Tx size (use 64 bytes).
out dx, al ; Send LSB of Tx Byte Count.
inc edx ; EDX = TxByteCount1.
mov al, ah ; AL = MSB of Tx Byte Count.
out dx, al ; Send MSB of Tx Byte Count.
sub edx, ITransmitByteCount1 - ICommand ; EDX = Command.
mov al, NIC_Transmit ; Send packet.
out dx, al
;
;***************************************************************\
; *
; Idle about 16ms to allow loopback Tx to finish. If interrupt *
; occurs then TxFreeCount will have incremented *
; *
;***************************************************************/
;
call MSMGetMicroTimer ; EAX = current count.
mov edx, eax ; ESI = current tick.
neg edx ; Set to negative value.
WaitForTxToFinish:
call MSMYieldWithDelay ; This will force an sti.
call MSMGetMicroTimer ; EAX = current count.
add eax, edx ; Time yet ?
cmp eax, 16000 ; 16 msec.
jb WaitForTxToFinish ; Jump if below 16 msec.
mov InDriverInit, 1 ;SPD 125034
if BackToBackSends
cmp [ebp].MSMTxFreeCount, 2 ; Did TxFreeCount go up?
else
cmp [ebp].MSMTxFreeCount, 1 ; Did TxFreeCount go up?
endif
jbe VerifyIRQError ; No, flag error.
;
;***************************************************************\
; *
; The IRQ is correctly configured. Make sure we put NIC back in *
; the state that Driver Reset expects.
; *
;***************************************************************/
;
mov edx, [ebp].InterruptStatus ; EDX = Interrupt Status Register
mov al, 0ffh ; Make sure all ints cleared
out dx, al
mov edx, [ebp].Command ; EDX = Command Register
mov al, NIC_Page0Stop ; set to Page 0.
out dx, al
mov edx, [ebp].DataConfiguration ; EDX = DataConfiguration register.
mov al, 49h ; Set to normal mode.
out dx, al
mov edx, [ebp].TransmitConfiguration ; EDX = Transmit Configuration register
xor al, al ; Set to normal mode.
out dx, al
call EtherTSMUpdateMulticast ; This will set the Receive
; Configuration register to
; default values.
VerifyIRQReturn:
xor eax, eax ; Return Success.
ret
VerifyIRQError:
or eax, 1 ; Clear Z flag
ret
VerifyIRQAtlanic:
and al, IntMask ; Mask off INT bits
shr al, 3 ; Make it an index
mov ah, SharedRAMIntTable[eax] ; Convert to IRQ value
cmp ah, byte ptr [ebx].MLIDInterrupt ; Do they match ?
jne VerifyIRQError ; No. Error.
jmp VerifyIRQReturn
VerifyIRQ endp
subttl -- DriverInit --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverInit, NE2000/API/INIT )
;
; Name: DriverInit
;
; Description: This routine will call EtherTSMRegisterHSM,
; MSMParseDriverParameters, MSMRegisterHardwareOptions,
; MSMSetHardwareInterrupt, MSMRegisterMLID, initialize
; variables in the Adapter Data Space and reset/initialize
; the card.
;
; On Entry: EAX N/A
; EBX N/A
; ECX N/A
; EDX N/A
; EBP N/A
; ESI N/A
; EDI N/A
;
; Note: Interrupts are enabled.
;
; On Return: EAX 0 if successful(otherwise it points to error message)
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Preserved
; EDI Preserved
;
; Flags:
;
; Note: Interrupts preserved.
;
; Remarks: This routine is called by the OS at load time.
; It is called at process time.
;
; See Also: MSM\MSMParseDriverParameters
; MSM\MSMRegisterHardwareOptions
; MSM\MSMSetHardwareInterrupts
; MSM\MSMRegisterMLID
; MSM\MSMScheduleIntTimeCallBack
; MSM\MSMScheduleAESCallBack
; MSM\MSMEnablePolling
; DriverReset
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
DriverInit proc
CPush
mov InDriverInit, 1 ;SPD 125034 BEGIN
call MSMGetMicroTimer
mov edx, eax ; EDX = Current Time.
WaitForDriverISRLoop:
call MSMGetMicroTimer
sub eax, edx
cmp eax, 50000
jb WaitForDriverISRLoop ;SPD 125034 END
;
;***************************************************************\
; *
; Fill in Driver Parameter Block fields. *
; *
;***************************************************************/
;
mov DriverStackPointer, esp ; Fill in stack ->.
and NE2000TextLen, NOT T_REQUIRED ; 'MEM=' not required.
lea esi, DriverParameterBlock ; ESI -> Parm block.
call MSMParseCustomKeywords ; Parse for 'MEM='.
lea esi, DriverParameterBlock ; ESI -> Parm block.
call EtherTSMRegisterHSM ; Get EBX.
jnz DriverInitError ; Jump if error.
;
; 09/13/95 MPK Spec 3.3 changes
;
push ebx ; Save EBX we will need it
mov esi,-1 ; Set Parameter for call
S33_Bus_Scan:
call MSMScanBusInfo ; Find out about Bus
cmp eax,ODI_NBI_SUCCESSFUL ; are we done?
jne S33_Bus_Scan_Done ; Yes, exit
cmp ecx,ODI_BUSTYPE_ISA ; is this ISA, (NE2000 ISA only)
jne S33_Bus_Scan ; no, then keep looking
pop ebx ; Yes, then place tag in param table
;JCJ 03-July-97 SPD#160730
mov [ebx].MLIDBusTag, 00 ; All legacy ISA drivers have BusTag0
;JCJ 03-July-97
push ebx ; Keep BX straight
jmp S33_Bus_Scan ; Keep cycling (for completeness)
S33_Bus_Scan_Done:
pop ebx ; Now we can restore EBX for good
;
; 09/13/95 MPK Spec 3.3 changes End
;
;***************************************************************\
; *
; EBX -> Frame Data Space(Config Table). *
; Let MSM Parse the command line. *
; *
;***************************************************************/
;
mov eax, NeedsIOPort0Bit OR NeedsInterrupt0Bit OR CAN_SET_NODE_ADDRESS
cmp MemOnCommandLine, 0 ; 'MEM=' entered?
je short ParseParms ; Jump if not.
or eax, NeedsMemoryDecode0Bit ; Set so that OS
mov ecx, InitMem
mov [ebx].MLIDMemoryDecode0, ecx ; Set up config so
mov [ebx].MLIDLength0, 400h ; OS doesn't complain.
ParseParms:
lea ecx, AdapterOptions
call MSMParseDriverParameters
jnz DriverInitError ; Jump if error.
;SPD 124386 Remove this next check, we handle all this in CheckForSharedRAM
;now.
;
; Before we go any farther let's check to see if something (anything)
; responds at our PORT address. This prevents us from thinking that there
; is a NE2000+ in shared mem mode present when there is actually no card
; present at all.
;
; movzx edx, [ebx].MLIDIOPortsAndLengths ; DX = Base I/O
; in al, dx ; Get current value.
; mov ah, al ; Save in AH.
; xor al, 1 ; Write out new value.
; mov cl, al ; Save new value
; out dx, al
; SLOW
; in al, dx ; Try to read it back.
; cmp ah, al ; Anything there?
; mov al, ah ; Restore old value
; out dx, al
; jne DoCheckForSharedRAM ; Something is there.
;
; lea eax, NICNotInSlotMessage
; jmp DriverInitResetError ; Bail out
;
DoCheckForSharedRAM:
call CheckForSharedRAM
jne DriverInitResetError ; Jump if error.
;
;***************************************************************\
; *
; Let MSM Register the hardware options. *
; *
;***************************************************************/
;
call MSMRegisterHardwareOptions
cmp eax, 1 ; Error Registering?
ja DriverInitError ; Jump if so.
je DriverInitExit ; Skip if new frame.
;
;***************************************************************\
; *
; Set Ethernet registers from Base IO. *
; *
;***************************************************************/
;
movzx eax, [ebx].MLIDIOPortsAndLengths ; EAX = I/O Base.
cmp DriverSendPtr, offset DriverSend ; I/O adapter?
je short DriverInitIO ; Jump if so.
mov eax, [ebx].MLIDMemoryDecode0 ; EAX = Physical Memory addr.
mov ecx, eax
shr ecx, 13 ; CL = Memory bits 13-18.
or cl, 01000000b ; Set memory bit.
mov [ebp].Control1Value, cl ; Save for DriverReset.
mov ecx, eax
shr ecx, 19
or cl, 0c0h
mov [ebp].Control2Value, cl
mov eax, [ebx].MLIDLinearMemory0 ; EAX = Logical Mem.
mov [ebp].NICRAMSegmentBase, eax ; Store Base.
xor ecx, ecx
mov ch, RAMPSTART
add eax, ecx
mov [ebp].NICRAMReceiveRingStart, eax ; Store Rx Start.
mov ch, RAMPSTOP-RAMPSTART
add eax, ecx
mov [ebp].NICRAMSegmentLimit, eax ; Store Rx End.
movzx eax, [ebx].MLIDIOPortsAndLengths ; EAX = I/O Base.
lea ecx, [eax].IControl1 ; Base + 00h
mov [ebp].Control1, ecx
lea ecx, [eax].IControl2 ; Base + 05h
mov [ebp].Control2, ecx
lea ecx, [eax].IProm ; Base + 08h
mov [ebp].Prom, ecx
mov [ebp].TransmitPage0, 0h
mov [ebp].TransmitPage1, 6h
add eax, 10h ; Adjust Base I/O.
DriverInitIO:
lea ecx, [eax].ICommand ; Base + 00h
mov [ebp].Command, ecx
lea ecx, [eax].IPageStart ; Base + 01h
mov [ebp].PageStart, ecx
lea ecx, [eax].IPageStop ; Base + 02h
mov [ebp].PageStop, ecx
lea ecx, [eax].IBoundary ; Base + 03h
mov [ebp].Boundary, ecx
lea ecx, [eax].ITransmitStatus ; Base + 04h
mov [ebp].TransmitStatus, ecx
lea ecx, [eax].ITransmitByteCount0 ; Base + 05h
mov [ebp].TransmitByteCount0, ecx
lea ecx, [eax].ITransmitByteCount1 ; Base + 06h
mov [ebp].TransmitByteCount1, ecx
lea ecx, [eax].IInterruptStatus ; Base + 07h
mov [ebp].InterruptStatus, ecx
lea ecx, [eax].IRemoteStartAddress0 ; Base + 08h
mov [ebp].RemoteStartAddress0, ecx
lea ecx, [eax].IRemoteStartAddress1 ; Base + 09h
mov [ebp].RemoteStartAddress1, ecx
lea ecx, [eax].IRemoteByteCount0 ; Base + 0ah
mov [ebp].RemoteByteCount0, ecx
lea ecx, [eax].IRemoteByteCount1 ; Base + 0bh
mov [ebp].RemoteByteCount1, ecx
lea ecx, [eax].IReceiveConfiguration ; Base + 0ch
mov [ebp].ReceiveConfiguration, ecx
lea ecx, [eax].ITransmitConfiguration ; Base + 0dh
mov [ebp].TransmitConfiguration, ecx
lea ecx, [eax].IDataConfiguration ; Base + 0eh
mov [ebp].DataConfiguration, ecx
lea ecx, [eax].IInterruptMask ; Base + 0fh
mov [ebp].InterruptMask, ecx
lea ecx, [eax].INICData ; Base + 10h
mov [ebp].NICData, ecx
lea ecx, [eax].IReset ; Base + 1fh
mov [ebp].Reset, ecx
if BackToBackSends
mov [ebp].MSMTxFreeCount, 2 ; Allow 2 transmits simultaneously.
else
mov [ebp].MSMTxFreeCount, 1 ; Allow 1 transmit.
endif
mov eax, OP_SCOPE_ADAPTER
call DriverReset ; Initialize NIC.
jnz short DriverInitResetError ; Exit if error reseting.
mov [ebp].FirstTimeInit, 0 ; Disable DriverReset from
; testing the hardware again.
dec [ebp].AdapterResetCount ; Adjust reset count.
;
;***************************************************************\
; *
; EBX -> Frame Data Space(Config Table). *
; EBP -> Adapter Data Space. *
; *
; Let MSM Set Hardware Interrupt. *
; *
;***************************************************************/
;
call MSMSetHardwareInterrupt
jnz short DriverInitError ; Jump if error.
call VerifyIRQ ; Is hardware interrupt same
lea eax, IRQInvalidMessage ; as what user told us?
jnz short DriverInitResetError ; No, print error msg
call MSMRegisterMLID ; Register MLID.
jnz short DriverInitError ; Jump if error.
mov eax, 18 ; Schedule call back in 18 ticks.
call MSMScheduleIntTimeCallBack
jnz short DriverInitError ; Jump if error.
DriverInitExit:
mov InDriverInit, 0 ;SPD 125034
xor eax, eax
CPop
ret
DriverInitResetError:
push eax ; Save error message.
call MSMReturnDriverResources ; Return resources.
pop eax ; EAX -> Error message.
DriverInitError:
mov InDriverInit, 0 ;SPD 125034
mov esi, eax ; ESI -> Error message.
call MSMPrintStringFatal ; Display message
or eax, 1 ; Do not load return code.
CPop
ret
DriverInit endp
CheckForSharedRAM proc
;
;***************************************************************\
; *
; Since ParseDriverParameters has given us the port number, *
; lets see if we're in I/O or Shared RAM mode. *
; *
;***************************************************************/
;
mov DriverSendPtr, offset DriverSend ; Default to I/O
;SPD 124386 Begin
; Assume for now card is NOT shared RAM, save current value of NICCommand
; register and force to page 0.
movzx edx, [ebx].MLIDIOPortsAndLengths
in al, dx
mov ch, al ; CH = current value.
mov al, NIC_Page0
out dx, al
SLOW
;SPD 124386 End
movzx edx, [ebx].MLIDIOPortsAndLengths ; DX = Base I/O +
add edx, 8 ; RemoteStartAddr.
in al, dx ; Get current value.
mov ah, al ; Save in AH.
inc al
mov cl, al ; CL = New value.
out dx, al ; Write new value.
SLOW
in al, dx
cmp al, cl ; Equal if I/O.
mov al, ah ; Restore old value
out dx, al ; in case it wasn't
; really an NE2000.
mov AdapterIsSharedRAM, 0
je short CheckForMemoryDecode0 ; Jump if I/O.
mov AdapterIsSharedRAM, 1
;SPD 124386 Begin
movzx edx, [ebx].MLIDIOPortsAndLengths ; Restore original
mov al, ch ; value.
out dx, al
SLOW
add edx, 10h ; Save NICCommand
in al, dx ; value in case we
mov ch, al ; we need to restore
mov al, NIC_Page0 ; it later, then force
out dx, al ; to page 0.
SLOW
; We know that if an NE2000 is present it is not in IO mode. Now check to
; see if it is even present.
add edx, 8 ; DX = RemoteStartAddr
in al, dx ; Read current value.
mov ah, al ; Save it.
inc al ; Create test value.
mov cl, al ; CL = New value.
out dx, al ; Write new value.
SLOW
in al, dx
cmp al, cl ; Card present?
mov al, ah ; Restore old value
out dx, al ; in case it wasn't.
je CheckForMemoryDecode0 ; Yes, NE2000 is there.
movzx edx, [ebx].MLIDIOPortsAndLengths ; No card so we better
add edx, 10 ; restore the old
mov al, ch ; value
out dx, al
SLOW
jmp AdapterConfigurationError ; Bail out.
;SPD 124386 End
CheckForMemoryDecode0:
;
; If user already gave us Shared RAM address, get out.
;
cmp [ebx].MLIDMemoryDecode0, 0 ; Shared RAM selected?
jne AdapterSharedRAM ; Get out if so.
;
; If we're in I/O mode, we're done.
;
cmp AdapterIsSharedRAM, 0 ; I/O mode?
je short AdapterIOMode ; Get out if so.
;
;***************************************************************\
; *
; In shared RAM mode and user hasn't given us the shared RAM *
; address yet. Lets see if we're just adding a new frame type. *
; *
;***************************************************************/
;
lea esi, IOConfigurationList
movzx eax, [ebx].MLIDIOPortsAndLengths
SearchForMatchingIO:
cmp [esi].CLink, 0 ; End of list?
je short BuildMemoryList ; Jump out if so.
mov esi, [esi].CLink ; ESI -> next struc.
cmp [esi].CIOPortsAndLengths, ax ; Match?
jne SearchForMatchingIO ; Jump if not.
AdapterIOMode:
mov DriverSendPtr, offset DriverSend
xor eax, eax
ret
;
;***************************************************************\
; *
; We are adding a new physical adapter. Build Memory strings *
; and prompt user for memory address. *
; *
;***************************************************************/
;
BuildMemoryList:
mov MemOnCommandLine, 0 ; Keep count.
lea edi, MemPromptValues ; EDI -> Buffer.
lea edx, MemoryDecode0Data+4 ; EDX -> Values.
lea ebp, MemPromptStrings ; EBP -> Strings.
BuildMemoryListLoop:
mov eax, [edx] ; EAX = Mem address.
mov ecx, 6
test eax, 00f00000h ; Over 1 Meg?
lea esi, IOConfigurationList
jne short SearchForMatchingMem ; Jump if so.
mov ecx, 5
;
; See if anyone else is using it.
;
SearchForMatchingMem:
cmp [esi].CLink, 0 ; End of list?
je short AddMemoryToList ; Jump if so.
mov esi, [esi].CLink ; ESI -> next struc.
cmp [esi].CMemoryDecode0, eax ; Being used.
je short BuildMemoryNext ; Jump if so.
cmp [esi].CMemoryDecode1, eax ; Being used.
je short BuildMemoryNext ; Jump if so.
jmp SearchForMatchingMem
AddMemoryToList:
cmp edi, offset MemPromptValues ; First one?
jne short AddMemoryNow ; Jump if so.
push edi
push ecx
lea edi, MemDefault
mov esi, ebp
rep movsb
pop ecx
pop edi
AddMemoryNow:
push ecx
mov esi, ebp
rep movsb
pop ecx
mov dword ptr [edi], ' ,' ; Add ', '
cmp MemOnCommandLine, 5
jne short BuildMemoryUpdate
mov dword ptr [edi], CR OR (LF SHL 8)
BuildMemoryUpdate:
add edi, 2
BuildMemoryNext:
cmp eax, 0fe0000h ; Last one?
je short BuildMemoryAddTail ; Jump if so.
add edx, 4
add ebp, ecx
inc MemOnCommandLine
jmp BuildMemoryListLoop
BuildMemoryAddTail:
sub edi, 2 ; Overwrite ', '
lea esi, MemPromptTail
mov ecx, MemPromptTailSize
rep movsb
mov MemOnCommandLine, 0
or NE2000TextLen, T_REQUIRED ; 'MEM=' required.
ParseForMem:
mov InitMem, 0
lea esi, DriverParameterBlock ; ESI -> Parm block.
call MSMParseCustomKeywords ; Parse for 'MEM='.
mov eax, InitMem
mov [ebx].MLIDMemoryDecode0, eax
or eax, eax
je short AdapterConfigurationError ; Jump if not entered.
lea esi, IOConfigurationList
SearchForDupMem:
cmp [esi].CLink, 0 ; End of list?
je short CheckForValidMem ; Jump if so.
mov esi, [esi].CLink ; ESI -> next struc.
cmp [esi].CMemoryDecode0, eax ; Being used.
je ParseForMem ; Jump if so.
cmp [esi].CMemoryDecode1, eax ; Being used.
je ParseForMem ; Jump if so.
jmp SearchForDupMem
CheckForValidMem:
lea esi, MemoryDecode0Data+4
mov ecx, MemoryDecode0Data
CheckForValidMemLoop:
cmp [esi], eax
je short AdapterSharedRAM ; Jump if valid.
add esi, 4
dec ecx
jne CheckForValidMemLoop
jmp ParseForMem
AdapterSharedRAM:
cmp AdapterIsSharedRAM, 0 ; Board config match?
je short AdapterConfigurationError ; Jump if not
mov DriverSendPtr, offset DriverSendSharedRAM
mov [ebx].MLIDLength0, 400h ; Store length of memory.
xor eax, eax
ret
AdapterConfigurationError:
lea eax, NICBadConfiguration ; EAX -> Error Message.
or eax, eax
ret
CheckForSharedRAM endp
MemRoutine proc
mov InitMem, eax
mov MemOnCommandLine, dl
ret
MemRoutine endp
subttl -- DriverShutdown --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverShutdown, NE2000/API/SHUTDOWN )
;
; Name: DriverShutdown
;
; Description: This routine will turn off the NIC.
;
; On Entry: EAX set to OP_SCOPE_ADAPTER if the adapter specified by EBP
; is to be shutdown. Otherwise set to OP_SCOPE_LOGICAL_BOARD
; which indicates that only the logical board specified
; by EBX is to be shutdown.
; EBX @ Frame Data Space
; ECX 0 if Permanent Shutdown
; EDX N/A
; EBP @ Adapter Data Space
; ESI N/A
; EDI N/A
;
; Note: Interrupts are disabled.
;
; On Return: EAX 0 if successful
; EBX Preserved
; ECX Preserved
; EDX Destroyed
; EBP Preserved
; ESI Preserved
; EDI Preserved
;
; Flags:
;
; Note: Interrupts preserved.
;
; Remarks: This routine is called by the MSM media module.
; It is called at process time.
;
; See Also: ETHERTSM\EtherTSMShutdown
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
DriverShutdown proc
if DEBUG
push eax
mov al, 'd'
call OutChar
pop eax
endif
cmp eax, OP_SCOPE_ADAPTER
jne DriverShutdownExit
mov edx, [ebp].InterruptMask ; EDX = InterruptMask register.
mov al, NIC_MaskByte ; Unmask all interrupts.
out dx, al
mov edx, [ebp].Command
mov al, 21h
out dx, al ; Stop the NIC.
cmp [ebp].NICRAMSegmentBase, 0 ; Shared RAM?
je short DriverShutdownExit ; Jump if not.
mov edx, [ebp].Control1 ; DX = Control 1.
and cl, NOT 01000000b ; Clear memory bit.
mov al, [ebp].Control1Value
out dx, al ; Reset adapter.
DriverShutdownExit:
xor eax, eax ; Good Return code.
ret
DriverShutdown endp
subttl -- DriverRemove --
page
;
;***********************************************************************\
;
; BEGIN_MANUAL_ENTRY( DriverRemove, NE2000/API/REMOVE )
;
; Name: DriverRemove
;
; Description: This routine call the MSM to return our resources.
;
; On Entry: EAX N/A
; EBX N/A
; ECX N/A
; EDX N/A
; EBP N/A
; ESI N/A
; EDI N/A
;
; Note: Interrupts are in any state.
;
; On Return: EAX Destroyed
; EBX Preserved
; ECX Destroyed
; EDX Destroyed
; EBP Preserved
; ESI Preserved
; EDI Preserved
;
; Flags:
;
; Note: Interrupts preserved.
;
; Remarks: This routine is called by the OS at unload.
; It is called at process time.
;
; See Also: MSM\MSMDriverRemove
;
; END_MANUAL_ENTRY
;
;***********************************************************************/
;
DriverRemove proc
CPush
mov eax, DriverModuleHandle
call MSMDriverRemove
CPop
ret
DriverRemove endp
OSCODE ends
end