adapter.asm
Warning: This file has been marked up for HTML
page ,130
;***********************************************************************
; $version: 1.39
; $date_modified: 121898
; $description: C NE3200 Header file for structures
; $owner: ODI LAN Driver Manager
; Copyright (c) 1991 - 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.
;***********************************************************************
;
; ADAPTER.ASM - NE3200 adapter module.
;
; Written by: DFS
; Date: 04-20-91
;
; 11-30-94 jcp Version 3.50 (Post NetWare 4.10 release)
; - Fixed SPD # 82800: NE3200 fail to reject packets that are
; too big. The maximum data size for ETHERNET is 1500 bytes.
; Therefore, the value in the field of Transmit ECB's PacketLength
; should be 1500 or less, not 1514.
;
; 12-02-94 jcp Version 3.50
; - Fixed SPD # 84935: NE3200 will not allow raw send of frame
; with size equal to max. This bug is caused by odd byte
; fragment length (raw send 802.2 frame). When the firmware
; receive a packet to transmit, it checks the fragment length,
; if it is odd byte, it adds another byte to the fragment
; length field and store the value away. This extra byte
; which stored into the fragment length field has prevented
; NE3200 to transmit a raw send packet with size equal to 1514.
;
; 12-06-94 jcp Version 3.50
; - Fixed transmit stop for no reason problem. This problem is
; caused by some of the error conditions. When the firmware
; is in one of the error condition, (for example, PacketTxTooBig
; condition) it exit without returning Tx buffer back to the
; queue. As soon as it uses up all the available Tx buffer
; (totally 4), it stops transmitting til HSM issue a reset
; command.
; - Removed IF-ELSE-ENDIF condition for AdapterProcessesTx,
; AdapterProcessesRx, TxQueue, AddPolling, CatchIncomplete,
; Channel0 and BusMaster.
; - Cleaned up codes.
;
; 5 May 1995 8:30 DGM
; Done repair on Adapter firmware, as seeing problems with version 3.50.
; Pulled back orig. code 06-28-94 and re-implemented changes and fixes.
;
; Added code to allow for transmitting the last fragment odd byte if
; the last fragment is odd. Added equate TX_BUFFER_SZ_MAX and code at
; label GetlastFragOddByte.
;
; Removed loop timers that was added on Peek, Poke, 586 Command
; completion etc. since this was causing problems with the firmware
; under heavy load.
;
; 26 May 1995 15:28 DGM
; Removed loop count at WaitForTCBPeek.
;
; Added <even> statement in front of all procedures to ensure that they
; were on word boundaries.
;
; DO NOT REMOVE THEM OR ELSE IT WILL BREAK THE DRIVER.
;
; Added packet size check at label <Tx8022Type2> and to take error
; case if packet is too large.
;
; 07 June 1995 15:28 MPK
; Added <even> statement in front of MainPollingLoop to ensure it
; is on a word boundary.
;
; DO NOT REMOVE THE EVEN STATEMENTS OR IT WILL BREAK THE DRIVER.
;
; 18 July 1995 9:05 TNL
; Change Rx code to use ECB Rx Status of ECB_REG_DIRECT instead of
; ECB_DIRECT for a direct packet in accordance with latest spec.
;
; 25 July 1995 3:14 TNL
; Change lines of code which use "size" directive incorrectly. Pharlap
; accepts the bad syntax, TASM doesn't.
;
; 07 August 1995 8:51 TNL
; Undo 18 July 1995 change for backward compatability.
;
; 05 March 1996 12:00 LON
; Single sourced the NE3200 and the NE3200P. Used existing NE3200
; base and added the Promiscuous code.
;
; 08 March 1996 2:10 LON
; A receive frame having a length field of Zero was not detected
; in CopyPacketToHost. Hence the ECB ends up having a PacketLength
; of zero. Also when in promiscuous mode, a rcv frame with a bad CRC
; was not being reported in the ECB status field (SPDs 102228, 119416).
;
; 29 March 1996 1:30 LON
; Corrected another instance of a zero length receive frame (SPD 102225).
; This was due to register CX getting corrupted in CheckHostForRCB.
; Corrected a statistics counter not being incremented for too big
; frames (SPD 121245). Also corrected a possible memory corruption problem
; when the 586 receives receives a large frame (over 2048), it may
; reference the DUMMY_RCB and store into memory using an invalid
; buffer pointer (SPD 121244).
;
; 26 April 1996 3:30 LON
; Ne3200 was always failing Testcon Good Promiscuous test (SPD 124003),
; so the receive code was optimised. Plus further enhancements were
; done to make the Ne3200 have only one binary file to handle both
; promiscuous and non-promiscuous functions.
;
; 02 May 1996 9:30 LON
; Ne3200 was often failing to initialize due to failing to restore
; register BX after calling InitializeRxBuffers from Initialize586.
; Also in CopyPacketToHost, a check for a 22 bytes or less frame size
; caused CopyPacketToHost to incorrectly change the reported data
; size to be the same as the total frame size. This was corrected
; (SPD 124342).
;
; 12 June 1996 2:00 LON
; While preparing to send a RAW 802.3 frame, ReadTCBFromHost failed
; to evenize the byte count of the RAW frame being sent (SPD 128722).
;
; 22-October-97 JCJ
; SPD# 168595 If packet size is lesser than 60 bytes that has
; to be padded in promiscuous mode.
;
; SPD# 168702 Check has been introduced in CopyPacketToHost to see
; whether frame length field in MAC header differs from
; the packet size reported by 82586.
;
; 11-November-97 LON
; The above two fixes were undone because they caused several subtests
; in the Good Promiscuous test to fail.
;
; 04-May-98 LON
; When receiving a frame in promiscuous mode that is less than 60 bytes
; in size, RPacketLength and RPacketSize must both include the pad
; bytes (minus the media hdr size) - SPD 191220.
;
;***********************************************************************/
;
.186
name NE3200_Adapter
DEBUG equ 0
SupportJabber equ -1
DAVID3 equ -1
;***********************************************************************\
; *
; NE3200 adapter structures. *
; *
;***********************************************************************/
include ASTRUCT.INC
;***********************************************************************\
; *
; NE3200 adapter macros. *
; *
;***********************************************************************/
include AMACROS.INC
;***********************************************************************\
; *
; NE3200 adapter equates. *
; *
;***********************************************************************/
;
; NE3200 common equates.
if SupportJabber
MAX_JABBER equ 2048+14
endif
TOTAL_RCBS equ 10h ; In AdapterRCBList on host.
TABLE_SIZE equ 20h
TABLE_MASK equ TABLE_SIZE-1
;
; 82586 memory equates.
;
IFNDEF NE3200P
NUMBER_TX_BUFFERS equ 4
ELSE
NUMBER_TX_BUFFERS equ 10
ENDIF
TX_BUFFER_SIZE equ 1514
MAX_MULTICAST_ADDR equ 20 ; Max addresses allowed.
ifdef DAVID3
MIN_BMIC_XFER_SZ equ 6+2 ; +2 to make eight
;allow for min frag of 6
TX_BUFFER_SZ_MAX equ TX_BUFFER_SIZE + MIN_BMIC_XFER_SZ
endif
;
MEMORY_586_START equ 8000h ; Start at second 32K.
MEMORY_SIZE equ 0ffffh - 7fffh ; Size of 82586 RAM.
PROM_OFFSET equ 4000h ; PROM Node Address.
DUMMY_RCB equ MEMORY_586_START; Resolves a 586 D-Step Errata.
DUMMY_BUFFER equ DUMMY_RCB + size BDStruct ; 16 byte buffer.
SCB equ DUMMY_BUFFER + 16
ISCP equ SCB + size SCBStructure
COMMAND_BUFFER equ ISCP + 8
TX_BUFFERS equ COMMAND_BUFFER + 32 + (MAX_MULTICAST_ADDR * 6)
ifdef DAVID3
RX_BUFFERS equ TX_BUFFERS+(NUMBER_TX_BUFFERS*(TX_BUFFER_SZ_MAX + size TxCStruct + size BDStruct))
else
RX_BUFFERS equ TX_BUFFERS+(NUMBER_TX_BUFFERS*(TX_BUFFER_SIZE + size TxCStruct + size BDStruct))
endif
SCP equ 0FFF6h ; SCP.
MEMORY_END equ SCP ; End at SCP.
SCP_LENGTH equ 10
ISCP_LENGTH equ 8
;
; 82586 equates.
;
CA_PORT equ 180h ; 82586 Channel Attention.
RESET_PORT equ 100h ; 82586 Reset port.
MAX_TX_RETRIES equ 10 ; Maximum Transmit Retries.
CB_MC_SETUP equ 0003h ; Set MC command.
ELBIT equ 8000h ; Last command in CBL.
CX_INTERRUPT equ 8000h ; Tx Interrupt Bit.
FR_INTERRUPT equ 4000h ; Rx Interrupt Bit.
TX_COMPLETE equ 8000h ; Transmit complete Bit.
TX_BUSY equ 4000h ; Transmit busy Bit.
TX_OK equ 2000h ; Transmit successful Bit.
CARRIER_SENSE_ERROR equ 0400h ; Tx Error-Carrier sense loss.
CLEAR_TO_SEND_ERROR equ 0200h ; Tx Error-Clear To Send.
UNDERRUN_ERROR equ 0100h ; Tx Error-Underrun.
TX_DEFERED_ERROR equ 0080h ; Tx Error-Tx defered.
MAX_COLLISION_ERROR equ 0020h ; Tx Error-Max collisions.
CRC_ERROR equ 0800h ; Rx Error-CRC.
ALIGN_ERROR equ 0400h ; Rx Error-Frame Alignment.
NO_RESOURCE_ERROR equ 0200h ; Rx Error-Out of Resources.
OVERRUN_ERROR equ 0100h ; Rx Error-DMA overrun.
RUNT_ERROR equ 0080h ; Rx Error-too short.
NO_EOF_ERROR equ 0040h ; Rx Error-no eof flag.
MAX_FRAGMENTS equ 16 ; Max ECB Fragments.
MAX_ECB_SIZE equ SIZE ATransmitBufferStructure + (MAX_FRAGMENTS*8)
;
; Abend codes.
; Currently, only initialization abend(5) is being used.
;
TRANSFER_HANG_ERROR equ 1
ODD_ADDRESS_ERROR equ 2
INVALID_PACKET_LENGTH equ 3
CHANNEL_ONE_HANG equ 4
BAD_MEMORY_ERROR equ 5
ODD_ADDRESS_DEBUG equ 6
TOO_MANY_FRAGMENTS equ 7
BAD_TRANSFER_ERROR equ 8
BAD_ROM_CHECKSUM equ 9
;
; BMIC equates.
;
BMIC_DATA equ 200h ; BMIC Data port.
BMIC_INDEX equ 202h ; BMIC Index port.
BMIC_STATUS equ 204h ; BMIC Status control port.
AUTO_INC equ 80h ; Index Auto Increment bit.
;
; Bit values for BMIC_STATUS.
;
LOCAL_INT_PENDING equ 80h
CH1_INT_PENDING equ 40h
CH0_INT_PENDING equ 20h
LOCAL_INT_ENABLED equ 10h
LOCAL_INT_ACTIVE equ 08h
PEEK_POKE_PENDING equ 04h
CH1_BASE_BUSY equ 02h
CH0_BASE_BUSY equ 01h
;
; Mailbox index registers.
;
MAIL_0 equ 10h ; BMIC Mailbox 0.
MAIL_4 equ 14h ; BMIC Mailbox 4.
MAIL_8 equ 18h ; BMIC Mailbox 8.
MAIL_C equ 1Ch ; BMIC Mailbox 0C.
;
ABEND_MAILBOX equ MAIL_0 ; BMIC Mailbox 0(init only).
IDLE_MAILBOX equ MAIL_0 + 0 ; BMIC Mailbox 0.
PARM_UPDATE_MAILBOX equ MAIL_0 + 1 ; BMIC Mailbox 1.
STAT_UPDATE_MAILBOX equ MAIL_0 + 2 ; BMIC Mailbox 2.
VALID_TCB_MAILBOX equ MAIL_0 + 3 ; BMIC Mailbox 3.
TCB_MAILBOX equ MAIL_4 ; BMIC Mailbox 4.
POLLING_MAILBOX equ MAIL_4 ; BMIC Mailbox 4.
PARAMETER_MAILBOX equ MAIL_C ; BMIC Mailbox 0C.
;
; Channel 0 index registers
;
CH0_BASE_COUNT equ 40h
CH0_BASE_ADDR equ 43h
CH0_CONFIG equ 48h
CH0_STROBE equ 49h
CH0_STATUS equ 4Ah
CH0_TBI_BASE_ADDR equ 4Bh
;
; Channel 1 index registers
;
CH1_BASE_COUNT equ 60h
CH1_BASE_ADDR equ 63h
CH1_CONFIG equ 68h
CH1_STROBE equ 69h
CH1_STATUS equ 6Ah
CH1_TBI_BASE_ADDR equ 6Bh
;
; Bit values for CHx_BASE_COUNT+2
;
AUTO_START equ 80h
ADAPTER_TO_EISA equ 40h
;
; Bit values for CHx_STATUS
;
FIFO_STALLED equ 10h
TRANSFER_ENABLED equ 08h
TRANSFER_IN_PROGRESS equ 04h
TRANSFER_TERMINATED equ 02h
TRANSFER_COMPLETE equ 01h
;
; Peek/Poke index registers.
;
PEEK_POKE_DATA equ 30h
PEEK_POKE_ADDR equ 34h
PEEK_POKE_CONTROL equ 38h
;
; EISA Doorbell index registers.
;
EISA_DOORBELL_ENABLE equ 0eh
EISA_DOORBELL_STATUS equ 0fh
;
; Bit values for EISA Doorbell registers.
;
TX_COMPLETE_BIT equ 01h
;
; 80186 I/O ports. (Note: The Adapter.asm code is run on the adapter's 80186)
;
PACSReg equ 0ffa4h ; Peripheral chip-select addr.
MPCSReg equ 0ffa8h ; Peripheral chip-select mode.
DMA0Control equ 0ffcah ; DMA 0 Control Word.
DMA0Count equ 0ffc8h ; DMA 0 Transfer Count.
DMA0DestHi equ 0ffc6h ; DMA 0 Dest Ptr upper 4 bits.
DMA0DestLo equ 0ffc4h ; DMA 0 Dest Ptr low 16 bits.
DMA0SourceHi equ 0ffc2h ; DMA 0 Src Ptr upper 4 bits.
DMA0SourceLo equ 0ffc0h ; DMA 0 Src Ptr low 4 bits.
DMA1Control equ 0ffdah ; DMA 1 Control Word.
DMA1Count equ 0ffd8h ; DMA 1 Transfer Count.
DMA1DestHi equ 0ffd6h ; DMA 1 Dest Ptr upper 4 bits.
DMA1DestLo equ 0ffd4h ; DMA 1 Dest Ptr low 16 bits.
DMA1SourceHi equ 0ffd2h ; DMA 1 Src Ptr upper 4 bits.
DMA1SourceLo equ 0ffd0h ; DMA 1 Src Ptr low 4 bits.
T0Control equ 0ff56h ; Timer 0 Control Word.
T0MaxCountB equ 0ff54h ; Timer 0 Max Count B.
T0MaxCountA equ 0ff52h ; Timer 0 Max Count A.
T0Count equ 0ff50h ; Timer 0 Count reg.
T1Control equ 0ff5eh ; Timer 1 Control Word.
T1MaxCountB equ 0ff5ch ; Timer 1 Max Count B.
T1MaxCountA equ 0ff5ah ; Timer 1 Max Count A.
T1Count equ 0ff58h ; Timer 1 Count reg.
T2Control equ 0ff66h ; Timer 2 Control Word.
T2MaxCount equ 0ff62h ; Timer 2 Max Count A.
T2Count equ 0ff60h ; Timer 2 Count reg.
;
; Rx Destination Address Type (First byte of RDriverWorkSpace).
;
ECB_DIRECT equ 0000h ; Physical destination address.
ECB_MULTICAST equ 0001h ; Multicast destination address.
ECB_BROADCAST equ 0002h ; Broadcast destination address.
ECB_REMOTE_UNICAST equ 0004h ; Remote Unicast dest addr.
ECB_REMOTE_MULTICAST equ 0008h ; Remote Multicast dest addr.
ECB_NO_SROUTE equ 0010h ; ROUTE.NLM not loaded.
ECB_ERR_PKT equ 0020h ; Frame is malformed, etc.
ECB_REG_DIRECT equ 0080h ; Register for Direct frames.
ECB_PROMISCUOUS equ ECB_REG_DIRECT OR ECB_MULTICAST OR ECB_BROADCAST OR ECB_REMOTE_UNICAST OR ECB_REMOTE_MULTICAST OR ECB_NO_SROUTE
CODE segment public word 'CODE'
assume CS:CODE, DS:CODE, ES:CODE, SS:CODE
jmp Start ; Jump to code.
org 100h ; Skip over vector table.
;
;***********************************************************************\
; *
; Static Data variables. *
; *
;***********************************************************************/
;
;
;***************************************************************\
; *
; Adapter Parameter Block. Do not change the order of the *
; following 12 variables. *
; *
;***************************************************************/
;
even ; Must be even for BMIC.
AdapterStructure label byte
LogicalToPhysical dw 2 dup (0)
NodeAddressPointer dw 2 dup (0)
BoardNumber8023 dw -1
BoardNumberEII dw -1
BoardNumber8022 dw -1
BoardNumberSNAP dw -1
MaxReceivePacketLength dw 2 dup (0)
GenericStatisticsPointer dw 2 dup (0)
CustomStatisticsCount dw 0
RCBListPointer dw 2 dup (0) ; pts to AdapterRCBList.
MulticastCount dw 0
MulticastListPointer dw 2 dup (0)
HostNodeAddress db 6 dup (0)
PromiscuousMode db 0
PollTimeout dw 0 ;#
db 3 dup (0) ;# dword align
IF DEBUG
DiagnosticBufferPointer dw 2 dup (0) ; Diagnostics buffer
ENDIF
AdapterStructureSize equ $ - AdapterStructure
NextEmptyRCB dw 2 dup (0)
TCBListPointer dw 2 dup (0)
TCBIndex dw 0
even ; Must be even for BMIC.
BoardID db 6 dup (0) ; Individual (MAC) Node Adr.
HostParameterBlock dw 2 dup (0)
RCBListBuffer dw 10h * 2 dup (0) ; TOTAL_RCBS = 10.
KnownRCBCount dw 1
SixteenBytesOfZero db 4 dup (00h)
TwelveBytesOfZeroPlusSignature db 12 dup (00h)
db 4 dup (11h)
InitialSCP db 0
db 5 dup (0)
dw ISCP
dw 0
dw 1 ; Initial ISCP.
dw SCB
dw 0, 0
ConfigLoopback dw 0,8002h,0,080Ch,6640h,6000h,0F200h,00h,40h
ConfigNormal dw 0,8002h,0,080Ch,2640h,6000h,0F200h,00h,40h
ConfigNormalSize equ $ - ConfigNormal ;TNL 7/25/95
IFNDEF NE3200P
;;ConfigPromiscuous dw 0,8002h,0,080Ch,2640h,6000h,0F200h,01h,20
ConfigPromiscuous dw 0,8002h,0,080Ch,26C0h,6000h,0F200h,01h,14
ELSE
ConfigPromiscuous dw 0,8002h,0,080Ch,26C0h,6000h,0F200h,01h,14
; 14 = MinFrmSize 82586 can capture.
ENDIF
DeadMan dw 0
DeadManHigh dw 35 ; Max deadman (~60 seconds).
;;FragLength dw 0
IFDEF NE3200P
;
;***************************************************************\
; *
; Receive ECB structure for Ne3200Promisc. code. *
; *
;***************************************************************/
;
SaveRDBOffset dw 0
;---------------------------------------------------------------\
; *
; The Ne3200Promisc design requires only one RCB Template (which*
; is copied up to the host driver to fill in the real RCB(ECB)).*
; This is better than the Ne3200 design since its UniReceiveBuf *
; structure has an RCB template for every received frame. This *
; wastes memory. *
; *
;---------------------------------------------------------------/
even
RCB_TEMPLATE AReceiveBufferStructure <>
RCVMACDest db 6 dup (0) ; Keep these fields
RCVMACSource db 6 dup (0) ; in order.
RCVMACLength dw 0
TEMPLATE_MAC_SIZE equ size AReceiveBufferStructure + 14
ENDIF
;***************************************************************\
; *
; Multicast Table variables. *
; *
;***************************************************************/
;
even ; Must be even for BMIC.
HostMulticastTable db (MAX_MULTICAST_ADDR * 8) dup (0)
AdapterMulticastLocation dw 0
;***************************************************************\
; *
; Local Transmit buffer variables. *
; *
;***************************************************************/
;
TxFreeHead dw 0
TxCHead dw 0
TxCEnd dw 0
CurrentTCB dw 0
OddByteStorage dw 0
;***************************************************************\
; *
; Local Receive buffer variables. *
; *
;***************************************************************/
;
RCBIndex dw 0
FDHead dw 0
FDEnd dw 0
RcvFrameSize dw 0
IFDEF NE3200P
RBDHead dw 0
RBDEnd dw 0
RBDLast dw 0
RBDTotalSize dw 0
RBDWrappedFlag dw 0
RBDSizeBeforeWrap dw 0
RBDSizeAfterWrap dw 0
BufferHead dw 0
ENDIF
;***************************************************************\
; *
; NOTE: The 7 Sequence Buffers below are presetup values used *
; to program the BMIC I/O port registers to perform a specific *
; byte(s) transfer between us (the adapter or firmware) and the *
; Host HSM driver. *
; *
;***************************************************************/
;***************************************************************\
; *
; To Host Node Addr(IA) Sequence Buffer. Don't change the order.*
; *
;***************************************************************/
;
NodeAddrTransferSequence label byte
NodeAddrTransferCount dw 6
db AUTO_START OR ADAPTER_TO_EISA
NodeAddrTransferOffsetLo dw ?
NodeAddrTransferOffsetHi dw ?
;***************************************************************\
; *
; From Host Parameter Sequence Buffer. Do not change the order. *
; *
;***************************************************************/
;
ParameterTransferSequence label byte
ParameterLocalAddress dw ?
ParameterTransferCount dw AdapterStructureSize
db AUTO_START
ParameterTransferOffsetLo dw ?
ParameterTransferOffsetHi dw ?
;***************************************************************\
; *
; From Host RCB List Sequence Buffer. Do not change the order. *
; Copy down the host driver's AdapterRCBList (ECB) ptr table. *
; *
;***************************************************************/
;
RCBListTransferSequence label byte
RCBListLocalAddress dw ?
RCBListTransferCount dw 10h * 4 ; TOTAL_RCBS = 10h.
db AUTO_START
RCBListTransferOffsetLo dw ? ; Host adr of AdapterRCBList.
RCBListTransferOffsetHi dw ?
;***************************************************************\
; *
; Read TCB Transfer Sequence Buffer. Do not change the order. *
; Copy down the host driver's AdapterTCBList (ECB) ptr table. *
; *
;***************************************************************/
;
ReadTCBTransferSequence label byte
ReadTCBLocalAddress dw ?
ReadTCBTransferCount dw MAX_ECB_SIZE
db AUTO_START
ReadTCBTransferOffsetLo dw ?
ReadTCBTransferOffsetHi dw ?
;***************************************************************\
; *
; To Host Statistic Sequence Buffers. Do not change the order. *
; *
;***************************************************************/
;
StatisticsSequence label byte ; First sequence
StatisticsLocalAddress dw ?
; byte offset below is used as a byte cnt.
dw TotalTxOKByteCountLow
StatisticsDir db AUTO_START OR ADAPTER_TO_EISA
StatisticsOffsetLo dw ?
StatisticsOffsetHi dw ?
StatisticsSequence1 label byte ; Second sequence
StatisticsLocalAddress1 dw ?
dw EndOfStats - TxOKSingleCollision
StatisticsDir1 db AUTO_START OR ADAPTER_TO_EISA
StatisticsOffsetLo1 dw ?
StatisticsOffsetHi1 dw ?
;***************************************************************\
; *
; From Host MC Table Sequence Buffer. Do not change the order. *
; *
;***************************************************************/
;
MCTableSequence label byte
MCTableLocalAddress dw ?
MCTableCount dw 0
db AUTO_START
MCTableOffsetLo dw ?
MCTableOffsetHi dw ?
;***************************************************************\
; *
; To Host Diagnostic Sequence Buffer. Do not change the order. *
; *
;***************************************************************/
;
IF DEBUG
DiagnosticSequence label byte
DiagnosticAddress dw ?
DiagnosticTransferCount dw 10h
db AUTO_START OR ADAPTER_TO_EISA
DiagnosticOffsetLo dw ?
DiagnosticOffsetHi dw ?
;;DiagnosticSequence label byte
;;DiagnosticAddress dw 0 ;Lower 16k RAM
;;DiagnosticTransferCount dw 4000h
;; db AUTO_START OR ADAPTER_TO_EISA
;;DiagnosticOffsetLo dw ?
;;DiagnosticOffsetHi dw ?
;;
;;DiagnosticSequence1 label byte
;;DiagnosticAddress1 dw 8000h/2 ;Upper 32k RAM
;;DiagnosticTransferCount1 dw 8000h
;; db AUTO_START OR ADAPTER_TO_EISA
;;DiagnosticOffsetLo1 dw ?
;;DiagnosticOffsetHi1 dw ?
even
DiagBuffer db 10h dup (' ')
db ? ;for '*'
CurDiagOffset dw 0
HostDiagSegCount dw 1000h/10h
PollLoopCount dw 4000h
ENDIF
;***************************************************************\
; *
; Statistic counter buffer. *
; *
;***************************************************************/
even ; Must be even for BMIC.
StatisticCounters StatisticStructure <>
even
TransmitECB db MAX_ECB_SIZE dup (0)
public AdapterStructure
public LogicalToPhysical
public NodeAddressPointer
public BoardNumber8023
public BoardNumberEII
public BoardNumber8022
public BoardNumberSNAP
public MaxReceivePacketLength
public GenericStatisticsPointer
public CustomStatisticsCount
public RCBListPointer
public MulticastCount
public MulticastListPointer
public HostNodeAddress
public PromiscuousMode
public PollTimeout
IF DEBUG
public DiagnosticBufferPointer
ENDIF
public NextEmptyRCB
public TCBListPointer
public TCBIndex
public BoardID
public HostParameterBlock
public RCBListBuffer
public KnownRCBCount
public SixteenBytesOfZero
public TwelveBytesOfZeroPlusSignature
public InitialSCP
public ConfigLoopback
public ConfigNormal
public ConfigPromiscuous
public DeadMan
public DeadManHigh
;; public FragLength
public HostMulticastTable
public AdapterMulticastLocation
public TxFreeHead
public TxCHead
public TxCEnd
public CurrentTCB
public OddByteStorage
public RCBIndex
public FDHead
public FDEnd
public NodeAddrTransferSequence
public NodeAddrTransferCount
public NodeAddrTransferOffsetLo
public NodeAddrTransferOffsetHi
public ParameterTransferSequence
public ParameterLocalAddress
public ParameterTransferCount
public ParameterTransferOffsetLo
public ParameterTransferOffsetHi
public RCBListTransferSequence
public RCBListLocalAddress
public RCBListTransferCount
public RCBListTransferOffsetLo
public RCBListTransferOffsetHi
public ReadTCBTransferSequence
public ReadTCBLocalAddress
public ReadTCBTransferCount
public ReadTCBTransferOffsetLo
public ReadTCBTransferOffsetHi
public StatisticsSequence
public StatisticsLocalAddress
public StatisticsDir
public StatisticsOffsetLo
public StatisticsOffsetHi
public StatisticsSequence1
public StatisticsLocalAddress1
public StatisticsDir1
public StatisticsOffsetLo1
public StatisticsOffsetHi1
public MCTableSequence
public MCTableLocalAddress
public MCTableCount
public MCTableOffsetLo
public MCTableOffsetHi
IF DEBUG
public DiagnosticSequence
public DiagnosticAddress
public DiagnosticTransferCount
public DiagnosticOffsetLo
public DiagnosticOffsetHi
public DiagBuffer
public CurDiagOffset
public HostDiagSegCount
public PollLoopCount
ENDIF
public StatisticCounters
public TransmitECB
public Start
public MainIdleCommand
public Tx8022
public Tx8022Aware
public Tx8022Type2
public TxSNAP
public SendPacketOK2
public HandleOddLengthFragments
public ReadTCBFromHost
public SendPacketOK3
public TxRawSend
public EverythingDone
public AddToList
;; public FragLengthError
public CopyFragmentsOverLoop
public FragmentAdjustedForMin
public RxMalformedInPromisc
public RxMalformedPacket
public RxDontInterruptHost
public RxCheckMulticastTable
public Rx8022
public Rx8022SNAP
public UpdateHostStatistics
public SetupForMulticastCommand
public Abend
public Initialize586
public Configure586
public InitializeTxBuffers
public InitializeRxBuffers
public Command586NoRestart
public Command586
public ReStart586
public Poll586
public ProcessCXInterrupt
public CopyPacketToHost
public RxEthernetII
;***********************************************************************\
; *
; Start - This routine sets up the segment registers, the stack, tests *
; memory, reads the host parameters, fills in the hosts node address *
; field, sets up the BMIC and jumps to the main loop. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used (Never returns) *
; BX = Not Used *
; CX = Not Used *
; DX = Not Used *
; BP = Not Used *
; SI = Not Used *
; DI = Not Used *
; *
;***********************************************************************/
even
Start proc
;---------------------------------------------------------------\
; *
; Set the flags, segment registers, stack pointer and turn off *
; the prom to recover the last 32k for our data space. *
; *
;---------------------------------------------------------------/
cli ; Disable system interrupts
cld ; set direction forward.
xor ax, ax ; Set all segment registers
mov dx, ax ; to zero.
mov es, ax
mov ss, ax
mov sp, 4000h ; Set stack pointer to top
; of 32k code space.
out 80h, al ; Turn off PROM.
;---------------------------------------------------------------\
; *
; Test static RAM for retention (Test for all ones and zeros). *
; *
;---------------------------------------------------------------/
mov ax, -1 ; AX = 0FFFFh
mov bx, es ; BX = 00000h
MemoryTest1Loop:
mov di, MEMORY_586_START ; DI -> second 32k of memory.
mov cx, MEMORY_SIZE / 4 ; CX = SIZE / 4
WriteMemoryLoop:
stosw ; Store AX pattern.
xchg bx, ax
stosw ; Store BX pattern.
xchg bx, ax
loop WriteMemoryLoop ; Store next 4 bytes.
mov si, MEMORY_586_START ; SI -> second 32k of memory.
mov cx, MEMORY_SIZE / 4 ; CX = SIZE / 4
mov dx, ax ; DX = AX pattern.
ReadMemoryLoop:
lodsw ; AX = first pattern.
cmp ax, dx ; Same as written pattern?
jnz BadMemoryError ; Jump if not.
lodsw ; AX = second pattern.
cmp ax, bx ; Same as written pattern?
jnz BadMemoryError ; Jump if not.
loop ReadMemoryLoop ; Check next 4 bytes.
cmp dx, -1 ; First time thru?
jne MemoryTest2 ; Jump if not.
xchg bx, dx ; BX = 0FFFFh
mov ax, dx ; AX = 00000h
jmp short MemoryTest1Loop ; Run test again.
BadMemoryError:
mov bx, BAD_MEMORY_ERROR ; BX = Error value.
jmp Abend ; Halt initialization.
;---------------------------------------------------------------\
; *
; Test static RAM for opens and shorts. *
; *
;---------------------------------------------------------------/
MemoryTest2:
mov ax, -1 ; AX = 0FFFFh
mov bx, ax ; BX = 0FFFFh
MemoryTest2Loop:
mov si, MEMORY_586_START ; SI -> second 32k of memory.
mov di, si ; DI -> second 32k of memory.
mov cx, MEMORY_SIZE / 2 ; CX = SIZE / 2
MemoryTest2Again:
stosw ; Write pattern.
lodsw ; Read pattern.
cmp ax, bx ; Patterns match?
jnz BadMemoryError ; Jump if not.
loop MemoryTest2Again ; Test next 2 bytes.
cmp ax, -1 ; First time thru?
mov ax, 0 ; Set up for new pattern
mov bx, ax ; of zero.
jne MemoryTest2Loop ; Jump if first time thru.
;---------------------------------------------------------------\
; *
; Zero out all the mailbox registers to signal the driver that *
; I am alive and well. *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX
mov al, CH1_CONFIG
out dx, al
mov dx, BMIC_DATA
mov al, 98h
out dx, al
mov dx, BMIC_INDEX ; Set index to first
mov al, MAIL_0 OR AUTO_INC ; mailbox.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data port.
mov si, offset TwelveBytesOfZeroPlusSignature
mov cx, 16
rep outsb ; Send out 16 bytes.
;---------------------------------------------------------------\
; *
; Wait for the HSM to pass the physical address of its *
; adapter parameter block. *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to parameter
mov al, PARM_UPDATE_MAILBOX ; update mailbox.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data port.
WaitForParameterBlock:
in al, dx ; AL = mailbox value.
or al, al ; Did HSM send us Parm Blk adr?
jz WaitForParameterBlock ; Jump if not.
mov dx, BMIC_INDEX ; Set index to parameter
mov al, PARAMETER_MAILBOX OR AUTO_INC ; mailbox.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data port.
mov di, OFFSET ParameterTransferOffsetLo ; DI -> destination.
mov cx, 4 ; Read 4 bytes of Host's
rep insb ; Parameter Block address.
mov ax, offset AdapterStructure
shr ax, 1 ; Adjust byte adr for BMIC.
mov ParameterLocalAddress, ax ; Save word address.
mov ax, offset HostMulticastTable
shr ax, 1 ; Adjust for BMIC.
mov MCTableLocalAddress, ax ; Store it.
mov ax, offset RCBListBuffer
shr ax, 1 ; Adjust for BMIC.
mov RCBListLocalAddress, ax ; Store it.
;---------------------------------------------------------------\
; *
; Read in the entire adapter parameter block. *
; *
;---------------------------------------------------------------/
call UpdateParameters ; Read block from host HSM.
;---------------------------------------------------------------\
; *
; Read ethernet node address (IA) from PROM or host and save it.*
; *
;---------------------------------------------------------------/
mov di, OFFSET BoardID ; DI -> our data section.
mov cx, 6 ; Read 6 bytes of IA.
cmp word ptr HostNodeAddress, 0ffffh
jne NodeAddressOverride ; Jump if no override.
mov si, PROM_OFFSET ; SI -> 0:4000h
CopyBoardIDLoop:
movsb ; Copy a byte.
inc si ; Skip a byte.
loop CopyBoardIDLoop ; Copy next byte.
jmp short NodeAddressCopied ; Jump when finished.
NodeAddressOverride:
mov si, offset HostNodeAddress ; Use Local Administered addr.
rep movsb
NodeAddressCopied:
;---------------------------------------------------------------\
; *
; Send node (ethernet MAC) address to the host. *
; *
;---------------------------------------------------------------/
mov ax, NodeAddressPointer + 0 ; AX = Dest lo.
mov NodeAddrTransferOffsetLo, ax ; Store Dest Lo.
mov ax, NodeAddressPointer + 2 ; BX = Dest hi.
mov NodeAddrTransferOffsetHi, ax ; Store Dest Hi.
mov di, offset BoardID ; DI -> Source.
mov si, offset NodeAddrTransferSequence ; SI -> Destination.
BMICTransfer
;---------------------------------------------------------------\
; *
; Clear all mailbox registers informing host (HSM driver) that *
; it can continue with its initialization. *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to first mailbox
mov al, MAIL_0 OR AUTO_INC ; register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov si, offset SixteenBytesOfZero ; SI -> Sixteen zeros.
mov cx, 16 ; Write 16 bytes.
rep outsb
;---------------------------------------------------------------\
; *
; Read the host's RCBList (i.e. AdapterRCBList) to get physical *
; address of first RCB (or ECB); the physical adr contained *
; in AdapterRCBList works as a circular queue (see ne3200.386). *
; *
;---------------------------------------------------------------/
mov di, offset NextEmptyRCB ; DI -> Dest.
mov si, offset RCBListPointer ; SI = Src location in HSM.
PeekFromHost
mov ax, RCBListPointer ; low
mov bx, RCBListPointer+2 ; hi adr
add ax, TABLE_SIZE*4 ; This assumes that the host
adc bx, 0 ; AdapterTCBList is directly
mov TCBListPointer, ax ; after the AdapterTCBList.
mov TCBListPointer+2, bx ;
;---------------------------------------------------------------\
; *
; Fixup statistic sequence buffer addresses and copy down part *
; of the Host's Statistic table. *
; *
;---------------------------------------------------------------/
mov ax, CustomStatisticsCount ; AX = Count field.
mov StatisticCounters.CustomCounterCount, ax
mov ax, offset StatisticCounters ; AX -> counters.
shr ax, 1 ; Adjust for BMIC.
mov StatisticsLocalAddress, ax
mov ax, offset StatisticCounters + TxOKSingleCollision
shr ax, 1
mov StatisticsLocalAddress1, ax
mov ax, GenericStatisticsPointer ; Save the address of the
mov StatisticsOffsetLo, ax ; host's stat table.
add ax, TxOKSingleCollision
mov StatisticsOffsetLo1, ax
mov ax, GenericStatisticsPointer + 2
mov StatisticsOffsetHi, ax
adc ax, 0
mov StatisticsOffsetHi1, ax
and StatisticsDir, NOT ADAPTER_TO_EISA ; Copy from host to adapter.
and StatisticsDir1, NOT ADAPTER_TO_EISA
mov si, offset StatisticsSequence ; SI -> Preset sequence.
BMICTransferWithLocal
mov si, offset StatisticsSequence1
BMICTransferWithLocal
or StatisticsDir, ADAPTER_TO_EISA
or StatisticsDir1, ADAPTER_TO_EISA
mov ax, RCBListPointer
mov RCBListTransferOffsetLo, ax
mov ax, RCBListPointer+2
mov RCBListTransferOffsetHi, ax
IF DEBUG
mov ax, offset DiagBuffer
shr ax, 1
mov DiagnosticAddress, ax
mov ax, DiagnosticBufferPointer
mov DiagnosticOffsetLo, ax
mov ax, DiagnosticBufferPointer+2
mov DiagnosticOffsetHi, ax
ENDIF
;---------------------------------------------------------------\
; *
; Fixup multicast sequence buffer addresses. *
; *
;---------------------------------------------------------------/
mov ax, MulticastListPointer ; Save host address MC table.
mov MCTableOffsetLo, ax
mov ax, MulticastListPointer + 2
mov MCTableOffsetHi, ax
;---------------------------------------------------------------\
; *
; Fixup Transmit ECB sequence buffer address. *
; *
;---------------------------------------------------------------/
mov ax, offset TransmitECB
shr ax, 1 ; Adjust for BMIC.
mov ReadTCBLocalAddress, ax ; Store it.
;---------------------------------------------------------------\
; *
; Allow 586 to initialize itself and jump to main loop. *
; *
;---------------------------------------------------------------/
call Initialize586
;
; Fall thru to MainPollingLoop.
;
Start endp
;***********************************************************************\
; *
; MainLoop - This is the main polling loop which the processor runs *
; forever. It will poll the 586 for receives, check the host for the *
; idle adapter command, check the host for update parameters command *
; and check the host for another transmit in that order. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used (Never returns) *
; BX = Not Used *
; CX = Not Used *
; DX = Not Used *
; BP = Not Used *
; SI = Not Used *
; DI = Not Used *
; *
;***********************************************************************/
jmp short MainPollingLoop
IF DEBUG
UpdateDiagBuffer:
mov PollLoopCount, 4000h
; Update diagnostic buffer periodically (approx every 1 sec)
mov si, offset DiagnosticSequence ; SI -> Preset BMIC sequence.
BMICTransferWithLocal
jmp UpdateDiagBufferReturn
ENDIF
MainIdleCommand:
mov dx, BMIC_INDEX ; Set index to the Adapter
mov al, IDLE_MAILBOX ; Idle mailbox.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, es ; Clear it.
out dx, al
jmp IdleAdapter ; Idle the adapter.
UpdateParmCommand:
mov dx, BMIC_INDEX ; Set index to the Update
mov al, PARM_UPDATE_MAILBOX ; Parameter mailbox.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, es ; Clear it.
out dx, al
call UpdateParameters ; Update the parameters.
jmp short MainPollingLoop
UpdateStatCommand:
mov dx, BMIC_INDEX ; Set index to the Update
mov al, STAT_UPDATE_MAILBOX ; Parameter mailbox.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, es ; Clear it.
out dx, al
call UpdateHostStatistics ; Update parameters.
even
MainPollingLoop proc
call Poll586 ; Poll the 82586.
IF DEBUG
dec PollLoopCount
jz UpdateDiagBuffer
UpdateDiagBufferReturn:
ENDIF
mov dx, BMIC_INDEX ; Set index to the adapter
mov al, IDLE_MAILBOX OR AUTO_INC ; idle mailbox.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
in al, dx ; Read Idle mailbox.
or al, al ; Was command(port 10h) issued?
jnz MainIdleCommand ; Jump if so.
in al, dx ; Read Update Parm mailbox.
or al, al ; Was cmd (port 11h) issued?
jnz UpdateParmCommand ; Jump if so.
in al, dx ; Read Update Stat mailbox.
or al, al ; Was cmd (port 12h) issued?
jnz UpdateStatCommand ; Jump if so.
in al, dx ; Read VALID_TCB_MAILBOX.
cmp byte ptr TCBIndex, al ; Has Tx index caught up to
jne TCBReady ; tail queue index? If so,
; then no TCB is waiting.
in al, dx ; Read Polling Status(Port 14h).
or al, al
jz MainPollingLoop
; Handle polling timeout
mov dx, T2Control
in ax, dx
test ax, 20h ; Maximum Count?
je MainPollingLoop
InterruptTheHost
StatisticsUpdate PollingTimeout ; Update counters.
mov dx, BMIC_INDEX ; Set index to the adapter
mov al, POLLING_MAILBOX ; poll mailbox.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, es ; AX = 0.
out dx, al ; Clear Poll mailbox.
MainPollingLoopJMP:
jmp MainPollingLoop
;***************************************************************\
; *
; When the host has another TCB for us to send, the host writes *
; the AdapterTCBList's index to the VALID_TCB_MAILBOX port. *
; *
;***************************************************************/
TCBReady:
cmp TxFreeHead, 0 ; Is Tx memory available to
; copy down next host TCB?
jz MainPollingLoop ; Jump if not.
IF DEBUG
push ax
mov al, 'T'
call OutChar
mov ax, TCBIndex
call OutWord
pop ax
sub ah, ah
call OutWord
ENDIF
mov dx, BMIC_INDEX
mov al, PEEK_POKE_ADDR OR AUTO_INC
out dx, al
mov dx, BMIC_DATA
mov bx, TCBListPointer + 2 ; BX -> host TCB ptr List.
mov ax, TCBIndex ; AX = Index into ptr list.
shl ax, 2 ; AX = Index * 4.
add ax, TCBListPointer ; Add to base(lo adr) of list.
adc bx, 0 ; BX:AX -> Next TCB slot.
out dx, al ; Set addr 0.
mov al, ah ;
out dx, al ; Set addr 1.
mov ax, bx ;
out dx, al ; Set addr 2.
mov al, ah ;
out dx, al ; Set addr 3.
mov dx, BMIC_INDEX ; Set index to Peek/Poke
mov al, PEEK_POKE_CONTROL ; control register.
out dx, al ;
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov al, 01011111b ; Set to peek host memory
out dx, al ; and start it.
mov dx, BMIC_STATUS ; DX = BMIC Status port.
WaitForTCBPeek: ;
in al, dx ; AL = current status.
test al, PEEK_POKE_PENDING ; Peek done?
jnz WaitForTCBPeek ; Jump if not.
mov dx, BMIC_INDEX ; Set index to Peek/Poke
mov al, PEEK_POKE_DATA OR AUTO_INC ; data register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov di, offset ReadTCBTransferOffsetLo; DI -> Next Empty TCB.
mov cx, 4 ; Read 4 bytes of TCB ptr
rep insb ; from host AdapterTCBList.
IFDEF NE3200P ; Ne3200Promisc code
cmp ReadTCBTransferOffsetHi, -1 ; Have a valid TCB ptr?
jne MainPollTxReady ; Jump if yes.
mov dx, BMIC_INDEX ; Set index to Valid TCB
mov al, VALID_TCB_MAILBOX ; mailbox.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data port.
mov ax, es ; Clear Valid TCB Mailbox.
out dx, al ; Attempt to recover from
; a bad index value.
jmp MainPollingLoop
MainPollTxReady:
ENDIF
; Already chk TxFreeHead!=0.
mov di, TxFreeHead ; DI ->FreeList of TxCStruct.
mov ax, [di].TxCLink ; Get ptr to next TxCStruct
mov TxFreeHead, ax ; and save it as new head.
jmp ReadTCBFromHost ; Copy host TCB to our buffers.
MainPollingLoop endp
;***************************************************************\
; *
; Routines for helping to send frames. *
; *
;***************************************************************/
Tx8022:
add word ptr TransmitECB.ATPacketLength, 3 ; Add 802.2 size.
mov ax, word ptr TransmitECB.ATPacketLength ; AX = Packet Length.
cmp ax, 1500
ja TxPacketTooBig
xchg al, ah ; Convert to hi/lo format(Endian).
stosw
lea di, [bx+size TxCStruct + size BDStruct]
cmp byte ptr TransmitECB.ATProtocolID + 0, 00000010b
jae Tx8022Aware
mov al, byte ptr TransmitECB.ATProtocolID + 5
mov ah, al ; AX = DSAP, SSAP.
stosw
mov OddByteStorage, 0103h ; Set odd flag with Ctrl0.
mov si, di ; SI -> Tx Buffer.
mov di, offset TransmitECB.ATPacketOffset
inc word ptr [di + 4] ; Add one to fragment size.
sub word ptr [di + 0], 1 ; Subtract one from
sbb word ptr [di + 2], 0 ; fragment address.
or bp, bp
je EverythingDoneJMP
jmp CopyFragmentsOverLoop ; Copy first fragment.
TxPacketTooBig:
StatisticsUpdate PacketTxTooBigCount ; Update counters.
mov ax, TxFreeHead ; AX -> old Free Head.
mov TxFreeHead, bx ; Free Head = BX.
mov [bx].TxCLink, ax ; Link Old to New.
jmp ClearHostMailbox
EverythingDoneJMP:
jmp EverythingDone
Tx8022Aware:
ja Tx8022Type2
mov ax, word ptr TransmitECB.ATProtocolID + 3
stosw ; Store DSAP, SSAP.
mov al, byte ptr TransmitECB.ATProtocolID + 5
mov ah, 01 ; Set odd flag with Ctrl0.
mov OddByteStorage, ax
mov si, di ; SI -> Tx Buffer.
mov di, offset TransmitECB.ATPacketOffset
inc word ptr [di + 4] ; Add one to fragment size.
sub word ptr [di + 0], 1 ; Subtract one from
sbb word ptr [di + 2], 0 ; fragment address.
or bp, bp
je EverythingDoneJMP
jmp CopyFragmentsOverLoop ; Copy first fragment.
Tx8022Type2:
inc word ptr TransmitECB.ATPacketLength ; Add Ctl1 size.
mov ax, word ptr TransmitECB.ATPacketLength ; AX = Packet Length.
cmp ax, 1500
ja TxPacketTooBig
xchg al, ah ; Change Endian type.
mov [bx].TxLength, ax
mov ax, word ptr TransmitECB.ATProtocolID + 2
stosw ; Store DSAP, SSAP.
mov ax, word ptr TransmitECB.ATProtocolID + 4
stosw ; Store Ctrl0, Ctrl1.
mov si, di ; SI -> Tx Buffer.
mov di, offset TransmitECB.ATPacketOffset
or bp, bp
je EverythingDoneJMP
jmp CopyFragmentsOverLoop ; Copy first fragment.
TxSNAP:
add word ptr TransmitECB.ATPacketLength, 8 ; Add 802.2 SNAP size.
mov ax, word ptr TransmitECB.ATPacketLength ; AX = Packet Length.
cmp ax, 1500
ja TxPacketTooBig
SendPacketOK2:
xchg al, ah ; Convert to hi/lo format.
stosw
lea di, [bx + size TxCStruct + size BDStruct]
mov si, offset TransmitECB.ATProtocolID + 1
mov ax, 0AAAAh ; Send DSAP/SSAP.
stosw
mov al, 03 ; Send Ctrl (UI frame).
stosb
movsb
movsw
movsw
mov si, di ; SI -> Tx Buffer.
mov di, offset TransmitECB.ATPacketOffset
or bp, bp
je EverythingDoneJMP
jmp CopyFragmentsOverLoop ; Copy first fragment.
;---------------------------------------------------------------\
; *
; Misc. code for jumps. *
; *
;---------------------------------------------------------------/
SkipThisFragmentJMP1:
jmp SkipThisFragment ; Go to next fragment.
HandleOddLengthFragments:
cmp bp, 1 ; Last fragment?
je short SkipThisFragmentJMP1 ; Jump if so.
mov cx, bp ; CX = fragments left.
mov bx, [di + 4] ; BX = Fragment length.
mov al, [si + bx - 1] ; AL = Value of odd byte.
mov ah, 1 ; AH = Odd Byte flag.
mov OddByteStorage, ax ; Set odd byte flag.
dec word ptr [di + 4] ; Decrement count.
mov bx, di ; BX -> Descriptor.
add bx, 8 ; BX -> Next Descriptor.
LookForZeroLengthLoop:
cmp word ptr [bx + 4], 0 ; Next descriptor 0 length?
je HandleZeroFragments ; jump if so.
inc word ptr [bx + 4] ; Adjust for extra byte.
sub word ptr [bx + 0], 1 ; Back up the frag pointer.
sbb word ptr [bx + 2], 0
jmp SkipThisFragment ; Go on to next descriptor.
HandleZeroFragments:
add bx, 8 ; BX -> Next descriptor.
dec cx ; CX = Descriptors left.
cmp cx, 1 ; Last descriptor?
jne short LookForZeroLengthLoop ; Jump if not.
jmp SkipThisFragment ; Jump if last one.
Tx8022JMP:
jmp Tx8022 ; Jump to 802.2 handler.
TxSNAPJMP:
jmp TxSNAP ; Jump to SNAP handler.
SendTooBig: ;;dgm - JCP
jmp TxPacketTooBig
;***********************************************************************\
; *
; ReadTCBFromHost - We have a TCB ready at the host (HSM) and a free *
; transmit buffer on the adapter. Transfer the TCB to the adapter and *
; initiate the sending the frame. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = TxFreeHead DI = Destroyed *
; *
;***********************************************************************/
even
ReadTCBFromHost proc
;; mov FragLength, 0 ; LON 1/18/96
mov si, offset ReadTCBTransferSequence
BMICTransferWithLocal ; TransmitECB -> ATransmitBufferStructure
mov bx, di ; BX -> TxCStruct.
mov CurrentTCB, di ; Save it for later.
mov bp, word ptr TransmitECB.ATFragmentCount
and bp, 001Fh ; Protect ourselves!
cmp word ptr TransmitECB.ATLogicalID, 0ffffh ; Raw send?
je TxRawSizeChk ; Jmp if so(Check frame size).
lea di, [bx].TxDestination ; DI -> TxC Destination adr.
lea si, TransmitECB.ATImmediateAddress
mov cx, 3
rep movsw ; Copy destination address.
mov cx, word ptr TransmitECB.ATBoardNumber ; CX = Board Number.
cmp cx, BoardNumber8022 ; 802.2 packet?
je Tx8022JMP ; Jump if so.
cmp cx, BoardNumberSNAP ; 802.2 SNAP packet?
je TxSNAPJMP ; Jump if so.
mov ax, word ptr TransmitECB.ATPacketLength ; AX = Packet Length.
cmp ax, 1500 ; Info field of frame <=1500?
ja SendTooBig ; Jump if no.
SendPacketOK3:
inc ax ; Roundup and evenize the
and al, 0feh ; total byte count.
mov word ptr TransmitECB.ATPacketLength, ax
cmp cx, BoardNumberEII ; EII packet?
je TxEthernetII ; Jump if so.
xchg al, ah ; Convert to hi/lo format
stosw ; (change Endians).
TxIsARawSend: ; JCP, 941202.
lea si, [bx + size TxCStruct + size BDStruct]
mov di, offset TransmitECB.ATPacketOffset
or bp, bp
je EverythingDone
jmp CopyFragmentsOverLoop ; Copy next fragment.
TxEthernetII:
mov ax, word ptr TransmitECB.ATProtocolID + 4
stosw
lea si, [bx + size TxCStruct + size BDStruct]
mov di, offset TransmitECB.ATPacketOffset
or bp, bp
je EverythingDone
CopyFragmentsOverJMP:
jmp CopyFragmentsOverLoop ; Copy next fragment.
TxRawSizeChk:
mov cx, word ptr TransmitECB.ATPacketLength
cmp cx, 1514 ; Raw send <= max frame size?
jbe TxIsARawSend ; Jmp if So (Continue)
jmp TxPacketTooBig ; Exit (Error -pkt too large).
HandleOddLengthFragmentsJMP:
jmp HandleOddLengthFragments
TxRawSend:
mov ax, bx
add ax, SIZE TxCStruct + SIZE BDStruct + 14 ; AX -> TxData.
mov [bx + size TxCStruct].BufPtr, ax
lea si, [bx + SIZE TxCStruct + SIZE BDStruct] ; SI->Dest Adr in frm.
lea di, [bx].TxDestination
movsw
movsw
movsw
add si, 6 ; SI -> Len/type field.
movsw ; Save Len/type into 82586's
; Transmit Cmd Block (TCB).
mov cx, word ptr TransmitECB.ATPacketLength ; CX = Packet Length.
sub cx, 14 ; Subtract header.
mov ax, word ptr TransmitECB.ATBoardNumber ; AX = Board Number.
cmp ax, BoardNumber8022 ; 802.2 packet?
je TxBufPtrSet ; Jump if so (continue).
cmp ax, BoardNumberSNAP ; 802.2 SNAP packet?
je TxBufPtrSet ; Jump if so (continue).
;-----------------------------------------------------------------------\
; *
; Only evenize RAW frames of type 802.3 and EII (not 802.2 & SNAP). *
; *
;-----------------------------------------------------------------------/
inc cx ; Roundup and evenize the
and cl, 0feh ; total byte count.
mov word ptr TransmitECB.ATPacketLength, cx ; Save adjusted size.
jmp short TxBufPtrSet ; Continue.
ProcessNextDescriptor:
test word ptr [di + 4], 1 ; Fragment odd?
jnz HandleOddLengthFragmentsJMP ; Jump if so.
;-----------------------------------------------------------------------\
; *
; For the below code: [di+4] = a pointer to ATPacketSize; *
; 8 = the byte size of ATPacketOffset and ATPacketSize fields; *
; *
;-----------------------------------------------------------------------/
SkipThisFragment:
add si, [di + 4] ; SI -> End of Tx Buffer.
add di, 8 ; DI -> Next Descriptor.
dec bp ; BP = New Descriptor count.
jnz CopyFragmentsOverJMP ; Exit if no more descriptors.
;---------------------------------------------------------------\
; *
; All fragments have been transfered. Prepare Transmit buffer *
; for transmission by the 82586. *
; *
;---------------------------------------------------------------/
EverythingDone:
mov OddByteStorage, es ; Clear (zero) odd byte flag.
mov bx, CurrentTCB ; BX -> TCB.
cmp word ptr TransmitECB.ATLogicalID, 0ffffh ; RAW 802.3 send?
je TxRawSend ; Jump if so.
mov ax, bx
add ax, SIZE TxCStruct + SIZE BDStruct ; AX -> Tx Data.
mov [bx + size TxCStruct].BufPtr, ax
mov cx, word ptr TransmitECB.ATPacketLength ; CX = Packet Length.
TxBufPtrSet:
cmp cx, 60-14 ; Over Minimum Size?
ja TxLengthOK ; Jump if so.
mov cx, 60-14 ; Force to Minimum size.
TxLengthOK:
or cx, 8000h ; Set TBD EL(End of List)bit.
mov [bx + size TxCStruct].BDStatus, cx
mov [bx].TxCLink, 0 ; No next Transmit Cmd Blk(TCB).
mov [bx].TxTries, MAX_TX_RETRIES ; Set Retry count.
mov si, TxCEnd ; Is Tx ptr list empty?
or si, si
jne AddToList ; Jump if not.
mov TxCHead, bx ; Initialize Tx ptr List.
mov TxCEnd, bx
mov DeadManHigh, 5 ; Set Tx Deadman.
mov ax, 100h ; SCB 100 = start exec of CBL.
mov cx, es ; CX = 0.
WaitFor586Loop:
cmp ds:SCB.SCBCommand, 0 ; Status complete?
loopne WaitFor586Loop ; Loop if not.
jne ReStart586FromTx ; Jump if never complete.
mov ds:SCB.SCBCommand, ax ; Command 586.
mov ds:SCB.CBLOffset, bx ; Point to First packet.
mov dx, CA_PORT ; Start the 586.
out dx, al
ClearHostMailbox:
mov dx, BMIC_INDEX ; Set index to Peek/Poke
mov al, PEEK_POKE_DATA OR AUTO_INC ; data register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov al, -1 ; AL = -1.
out dx, al ; A -1 tells the host
out dx, al ; that we've copied its
out dx, al ; RCB and the host can now
out dx, al ; return the RCB to the OS.
mov bx, TCBListPointer + 2 ; BX -> host TCB List.
mov ax, TCBIndex ; AX = Index into list.
shl ax, 2 ; AX = Index * 4.
add ax, TCBListPointer ; Add to base of list.
adc bx, 0 ; BX:AX -> Next TCB slot.
out dx, al ; Set addr 0.
mov al, ah
out dx, al ; Set addr 1.
mov ax, bx
out dx, al ; Set addr 2.
mov al, ah
out dx, al ; Set addr 3.
;---------------------------------------------------------------\
; *
; Indicate to the host that we are done processing an RCB by *
; writing a -1 into its adapterTCBList pointer table. The host *
; can now return the RCB (ECB) back to the the OS for re-use. *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to Peek/Poke
mov al, PEEK_POKE_CONTROL ; control register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov al, 00111111b ; Set poke at host memory
out dx, al ; and start it.
mov dx, BMIC_STATUS ; DX = BMIC Status port.
WaitForTCBPoke:
in al, dx ; AL = current status.
test al, PEEK_POKE_PENDING ; Locked exchange done?
jnz WaitForTCBPoke ; Jump if not.
inc byte ptr TCBIndex
cmp PollTimeout, 0 ;#
jne MainPollingLoopJMP2 ;#
InterruptTheHost
MainPollingLoopJMP2: ;#
jmp MainPollingLoop
AddToList:
mov [si].TxCLink, bx ; Link to end of list.
mov TxCEnd, bx
jmp short ClearHostMailbox
ReStart586FromTx:
call ReStart586 ; 586 might have hung.
jmp MainPollingLoop
SkipThisFragmentJMP:
jmp SkipThisFragment ; Go on to next fragment.
AdjustFragmentForMin:
mov cx, 6 ; Force to minimum size.
jmp short FragmentAdjustedForMin
;;FragLengthError: ; LON 1/18/96
;; StatisticsUpdate BadFragLengthCount ; Update counters.
;; jmp ClearHostMailbox
;***************************************************************\
; *
; Copy the next fragment over from the driver to us (firmware). *
; *
; SI -> Area in Tx Buffer to continue copying into. *
; DI -> Descriptor of next fragment. *
; BP = Descriptors left (counting this one). *
; *
;***************************************************************/
CopyFragmentsOverLoop: ; [di+4] -> ATPacketSize
mov cx, [di + 4] ; CX = Fragment length.
jcxz SkipThisFragmentJMP ; Skip if its zero.
cmp cx, 6 ; Large enough for BMIC?
jb short AdjustFragmentForMin ; Jump if not.
FragmentAdjustedForMin:
;; This check was done previously
;;
;; add FragLength, cx
;; cmp FragLength, 1514 ; Over Max?
;; ja FragLengthError ; Jump if so.
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_TBI_BASE_ADDR OR AUTO_INC ; TBI Base Address register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, si ; AX -> local address.
shr ax, 1 ; Adjust for BMIC.
out dx, al ; Set LSB.
mov al, ah
out dx, al ; Set MSB.
mov dx, BMIC_INDEX ; Set index to channel 1.
mov al, CH1_BASE_COUNT OR AUTO_INC ; base count register(3 bytes)
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, cx ; AX = Fragment length.
out dx, al ; Send LSB of count.
mov al, ah
out dx, al ; Send MSB of count.
mov al, AUTO_START ; Set Auto start, Host to
out dx, al ; adapter byte.
;---------------------------------------------------------------\
; *
; Setup the 4 byte CH1_BASE_ADDR port register *
; *
;---------------------------------------------------------------/
mov ax, [di + 0] ; AX = Host adr low.
out dx, al ; AX = ATPacketOffset low.
mov al, ah
out dx, al
mov ax, [di + 2] ; AX = Host adr hi
out dx, al ; (AX =ATPacketOffset high).
mov al, ah
out dx, al
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_STROBE ; strobe register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
out dx, al ; Strobe channel 1.
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_STATUS ; status register.
out dx, al ;
mov dx, BMIC_DATA ; DX = BMIC Data Port.
WaitForFragmentTransfer: ;
in al, dx ; AL = current status.
test al, TRANSFER_ENABLED OR TRANSFER_IN_PROGRESS
jnz short WaitForFragmentTransfer
and al, 00000011b ; MaskOut reserve bits(sticky)
out dx, al ; Clear the completion bit.
cmp OddByteStorage, 0 ; Last fragment odd?
jnz OddByteFix ; Jump if so.
jmp ProcessNextDescriptor ; Done if not.
OddByteFix:
mov cx, OddByteStorage ; CL = odd byte value.
mov [si], cl ; Store it into buffer.
mov OddByteStorage, es ; Clear (zero) odd byte flag.
jmp ProcessNextDescriptor ; Done with this fragment.
ReadTCBFromHost endp
;***************************************************************\
; *
; Misc. routines for handling exceptions in a received frame. *
; *
;***************************************************************/
GetADefaultBoardNumber:
or byte ptr [bx].ARESREBXValue, 20h ; Error - Set No Registered
mov ax, BoardNumber8023 ; Board error status.
cmp ax, -1
jne FoundADefaultBoardNumber
mov ax, BoardNumberEII
cmp ax, -1
jne FoundADefaultBoardNumber
mov ax, BoardNumber8022
cmp ax, -1
jne FoundADefaultBoardNumber
mov ax, BoardNumberSNAP
FoundADefaultBoardNumber:
IFNDEF NE3200P
ret ; Exit.
CheckForDeformedPacket:
cmp bp, 14 ; Big enough for 802.3 hdr?
jb CheckNotDeformed ; Can't get type if not.
mov cx, [si].UFDLength ; CX = Type/Length field.
xchg cl, ch ; Convert to Intel.
cmp cx, 1500 ; EII Packet?
ja CheckNotDeformed ; Jump if so.
add cx, 14 ; Add 802.3 size.
cmp cx, bp ; Header len > bytes read in?
jbe CheckDeformTooSmall ; Jump if not.
or ax, 400h ; Set ASPEC Malform err status
;; or byte ptr [bx].ARESREBXValue, 40h ; Set CSPEC Malform err Status.
CheckDeformTooSmall:
cmp bp, 22 ; Valid 802.2 header?
jb CheckNotDeformed ; Jump if not.
mov dx, 14 ; DX = Assume 802.3 size.
cmp word ptr [si].DataBuffer, 0ffffh ; RAW 802.3? (Byte 14 of frm).
je CheckDeformHeader ; Jump if so.
mov dx, 22 ; DX = Assume Snap size.
cmp word ptr [si].DataBuffer, 0aaaah ; SNAP? (Byte 14 of frm)
je CheckDeformHeader ; Jump if SNAP.
mov dx, 18 ; DX = Assume 802.2 Type 2 size.
test byte ptr [si].DataBuffer +2, 00000001b ; I-Format PDU?
je CheckDeformHeader ; Jump if so.
test byte ptr [si].DataBuffer +2, 00000010b ; S-Format PDU?
je CheckDeformHeader ; Jump if so.
dec dx ; DX = 17 = 802.2 Type 1 size.
CheckDeformHeader:
sub cx, dx ; Enough for valid header?
jns CheckNotDeformed ; Jump if so.
or ax, 400h ; Set ASPEC Malform error Status.
;; or byte ptr [bx].ARESREBXValue, 40h ; Set CSPEC Malform error Status.
CheckNotDeformed:
ret ; Exit.
ELSE ; Ne3200Promisc. code
CheckForDeformedPacket:
cmp RBDTotalSize, 14 ; Big enough for RAW 802.3 hdr?
jb CheckNotDeformed ; Can't get type if not.
mov cx, [bx +size AReceiveBufferStructure + 12] ; CX = Type/Length field.
xchg cl, ch ; Convert to Intel.
cmp cx, 1500 ; EII Packet?
ja CheckNotDeformed ; Jump if so.
add cx, 14 ; Add 802.3 size.
cmp cx, RBDTotalSize ; Header len > bytes read in?
jbe CheckDeformTooSmall ; Jump if not.
or byte ptr [bx].ARESREBXValue+1, 4 ; Set ASPEC Malform error Status.
;; or byte ptr [bx].ARESREBXValue, 40h ; Set CSPEC Malform error Status.
CheckDeformTooSmall:
cmp RBDTotalSize, 22 ; Valid 802.2 header?
jb CheckNotDeformed ; Jump if not.
mov dx, 14 ; DX = 802.3 size.
mov si, SaveRDBOffset
mov si, [si].RBDBufPtr ; SI -> Data.
cmp word ptr [si], 0ffffh ; RAW 802.3?
je CheckDeformHeader ; Jump if so.
mov dx, 22 ; DX = Snap size.
cmp word ptr [si], 0aaaah ; SNAP?
je CheckDeformHeader ; Jump if SNAP.
mov dx, 18 ; DX = 802.2 Type 2 size.
test byte ptr [si+2], 00000001b ; I-Format PDU?
je CheckDeformHeader ; Jump if so.
test byte ptr [si+2], 00000010b ; S-Format PDU?
je CheckDeformHeader ; Jump if so.
mov dx, 17 ; DX = 802.2 Type 1 size.
CheckDeformHeader:
sub cx, dx ; Enough for valid header?
jns CheckNotDeformed ; Jump if so.
or byte ptr [bx].ARESREBXValue+1, 4 ; Set ASPEC Malform error Status.
;; or byte ptr [bx].ARESREBXValue, 40h ; Set CSPEC Malform error Status.
CheckNotDeformed:
ret ; Exit - return.
;------------------------------------------------------------------------*
;------------------------------------------------------------------------*
SetDestTypeError: ; Only this bit can be set.
mov byte ptr [bx].ARDriverWorkSpace, ECB_ERR_PKT ; Pkt has err(s).
jmp DestTypeErrReturn ; Continue processing.
ENDIF ; End Ne3200Promisc.
RxMalformedInPromisc:
mov ax, bp ; Restore to Total frm size.
or byte ptr [bx].ARESREBXValue+1, 4 ; Set ASPEC Malform Err Status.
;; or byte ptr [bx].ARESREBXValue, 40h ; Set CSPEC Malform Err Status.
jmp RxMalformedPromiscReturn ; Continue processing.
RxMalformedPacket:
StatisticsUpdate HardwareRxMismatchCount
cmp PromiscuousMode, 0 ; In Promiscuous Mode?
jne RxMalformedInPromisc ; Jmp if so (Keep the frame).
ret ; Ret FRInterrupt (Ignore bad frame).
RxMalformedTooSmall:
StatisticsUpdate HardwareRxMismatchCount
cmp PromiscuousMode, 0
jne RxMalformedTooSmallInPromisc
ret ; Return to FRInterrupt.
RxMalformedTooSmallInPromisc:
IFNDEF NE3200P
mov ax, bp ; Restore the total frm size.
ELSE
mov ax, RBDTotalSize ; Restore the total frm size.
ENDIF
mov dx, es ; DX= 0 (Offset to frm start).
or byte ptr [bx].ARESREBXValue+1, 4 ; Set ASPEC Malform Error Status.
;; or byte ptr [bx].ARESREBXValue, 40h ; Set CSPEC Malform Error Status.
; Fall thru.
SetGlobalError:
mov byte ptr [bx].ARDriverWorkSpace, ECB_ERR_PKT ; Pkt has err(s).
IFNDEF NE3200P
cmp bp, 22 ; Frame big enough for largest
jae SetGlobalErrorExit ; possible MediaHdr? Jmp if Yes.
mov dx, es ; Don't guess hdr size so setup DX
; with offset to frame start.
mov ax, bp ; AX = Total frm size (Includes media).
cmp bp, cx ; Is Media Size larger than pkt?
jns SetGlobalErrorExit ; Jmp if no.
mov cx, bp ; Set Media Size = Frame Size.
SetGlobalErrorExit:
ENDIF
jmp RxContinue ; Continue processing.
RxCheckMulticastJMP:
mov byte ptr [bx].ARDriverWorkSpace, ECB_BROADCAST OR ECB_MULTICAST
mov ax, word ptr [bx+size AReceiveBufferStructure+0]
and ax, word ptr [bx+size AReceiveBufferStructure+2]
and ax, word ptr [bx+size AReceiveBufferStructure+4]
cmp ax, 0ffffh ; Broadcast?
je RxBackFromMulticastCheck ; Jump if So (Continue processing).
;-----------------------------------------------------------------------\
; *
; Scan multicast table for a match with the destination address. *
; *
;-----------------------------------------------------------------------/
RxCheckMulticastTable:
mov byte ptr [bx].ARDriverWorkSpace, ECB_MULTICAST ; Maybe multicast.
mov cx, MulticastCount ; CX = addresses in table.
jcxz RxNoMulticastMatch ; Exit if no addresses.
mov di, offset HostMulticastTable ; DI -> MC table.
;-----------------------------------------------------------------------\
; *
; For Non-P Ne3200 code, [bx+size AReceiveBufferStructure+0] points *
; to the UniReceiveBuf.UHeader field (for Ne3200Promisc its RCVMACDest).*
; *
;-----------------------------------------------------------------------/
mov ax, word ptr [bx+size AReceiveBufferStructure+0] ; AX = 1st word.
mov dx, word ptr [bx+size AReceiveBufferStructure+2] ; DX = 2nd word.
mov si, word ptr [bx+size AReceiveBufferStructure+4] ; SI = 3rd word.
CheckMulticastLoop:
cmp word ptr [di+0], ax ; First word match?
jne CheckNextMulticast ; Jump if not.
cmp word ptr [di+2], dx ; Second word match?
jne CheckNextMulticast ; Jump if not.
cmp word ptr [di+4], si ; Third word match?
je RxBackFromMulticastCheck ; Jmp if Yes (Continue processing).
;; jne CheckNextMulticast ; Jump if not.
CheckMulticastFound:
;; jmp RxBackFromMulticastCheck ; Success! Continue processing.
CheckNextMulticast:
add di, 8 ; DI -> Next table address.
loop CheckMulticastLoop ; Try again.
RxNoMulticastMatch:
mov byte ptr [bx].ARDriverWorkSpace, ECB_REMOTE_MULTICAST ; Maybe multicast.
cmp PromiscuousMode, 0 ; In promiscuous mode?
jne RxBackFromMulticastCheck ; Jmp if Yes (Continue processing).
ret ; Ignore frm-Return to FRInterrupt.
RxMalformedPacketJMP:
jmp RxMalformedPacket
Rx8023InPromisc:
call GetADefaultBoardNumber
jmp short Rx8023NotSupportedPromReturn ; Continue processing.
Rx8023NotSupported:
cmp PromiscuousMode, 0 ; In Promiscuous Mode?
jne Rx8023InPromisc ; Jmp if yes.
ret ; Return to FRInterrupt.
RxRemoteUnicast:
mov byte ptr [bx].ARDriverWorkSpace, ECB_REMOTE_UNICAST ; Maybe remote.
jmp short RxBackFromMulticastCheck
RxMalformedTooSmallJMP:
jmp RxMalformedTooSmall
RxEthernetIIJMP:
jmp RxEthernetII ; Jump to Ethernet II handler.
Rx8022JMP:
jmp Rx8022 ; Jump to 802.2 handler.
IFNDEF NE3200P
SetGlobalErrorJMP:
jmp short SetGlobalError ; Set err in destination type.
ENDIF
;***********************************************************************\
; *
; Copy Packet To Host - At this point, a valid packet has been received *
; and the host has an ECB (RCB) available for us to copy it into. *
; *
; Previously FRInterrupt has already copied the frame header (14 bytes) *
; into the UHeader (or RCVMACxxxx) field. This procedure fills in *
; the remainder of the RCB template (AReceiveBufferStructure). *
; Next the template and the frame are copied to the host (driver). The *
; template is copied into the driver's ECB starting at the RProtocolId *
; field, by adding an offset of 16 to the starting address of the ECB. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = @ UniReceiveBuf.URCB (RCBtemplate) BX = Destroyed *
; or @ of RCB_TEMPLATE (Ne3200Promisc). *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Frame Length (Includes header) BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not used DI = Destroyed *
; *
;***********************************************************************/
even
CopyPacketToHost proc
;; mov bp, cx ; BP = Packet size.
IFNDEF NE3200P
;-----------------------------------------------------------------------\
; *
; During frame reception the 82586 copies the frame header into the *
; Frame Descriptor (FD) starting at UniReceiveBuf.UFDDestination. The *
; driver (HSM) requires the header to precede frame data (info field). *
; Therefore we copy the header ahead of the frame's info field. *
; *
;-----------------------------------------------------------------------/
;;;;; ;;LON lea di, [si + 14 + size AReceiveBufferStructure]
;; lea di, [si].UHeader ;
;; lea si, [si].UFDDestination ; SI -> Media header in FDesc.
;; mov cx, 14 / 2 ; Copy 14 bytes of frame hdr.
;; rep movsw ; Movsw increments SI to point
; to UniReceiveBuf.URCB.
;;lea bx, [si].URCB ; BX -> RCB structure template.
ELSE ; Ne3200Promisc code
;; mov di, [si].UFDRBDOffset ; DI -> First RBD.
;; mov SaveRDBOffset, di ; Save ptr to first RBD.
;;lea bx, RCB_TEMPLATE ; BX -> RCB structure template.
;; lea si, [si].UFDDestination ;
;; lea di, [bx+size AReceiveBufferStructure] ; DI -> RCVMACDest.
;; mov cx, 14 / 2 ; Copy 14 bytes of hdr (DA/SA/len).
;; rep movsw
ENDIF
;-----------------------------------------------------------------------\
; *
; On the host (see DriverISR procedure), ARESREBXValue is the first *
; dword of RProtocolWorkspace where the frame's error status is saved. *
; The second dword of RProtocolWorkspace is the frame's byte length. *
; *
;-----------------------------------------------------------------------/
;; xor ah, ah ; Setup Status & Size in template.
;;;;;
; mov word ptr [bx].ARESREBXValue, ax ; RProtocolWorkspace's 1st
; mov word ptr [bx].ARESREBXValue+2, 0 ; dword (error status).
; mov [bx].ARSocket, bp ; RProtocolWorkspace's 2nd
; mov [bx].ARProtocolWorkspaceRest, 0 ; dword (frame size).
;;;;; cmp bp, 1514
;; ja PacketTooLong ; Jump if frame too large.
PacketTooLongReturn:
test byte ptr [bx+size AReceiveBufferStructure], 01 ; Multicast?
jnz RxCheckMulticastJMP ; Jump if so.
mov byte ptr [bx].ARDriverWorkSpace, ECB_DIRECT ; Must be direct unicast.
lea si, [bx+size AReceiveBufferStructure] ; SI->UniReceiveBuf.UHeader
; or RCVMACDest field.
lea di, BoardID ; DI -> Our IA (Node address).
mov cx, 3
repe cmpsw ; Our IA = Destination Adr?
jne RxRemoteUnicast ; Jump if No.
RxBackFromMulticastCheck:
lea di, [bx].ARProtocolID ; DI ->RCB template ProtocolID.
;-----------------------------------------------------------------------\
; *
; For Non-P Ne3200 code, [bx+ size AReceiveBufferStructure +12] points *
; inside the UniReceiveBuf.UHeader field to the frame type/len. *
; For Ne3200Promisc, [bx+....] points to the RCVMACLength field. *
; *
;-----------------------------------------------------------------------/
mov ax, [bx+size AReceiveBufferStructure + 12] ; 12 = DA + SA size.
xchg al, ah ; AX = Ethernet length/type.
cmp ax, 1500 ; Is this EthernetII type?
ja RxEthernetIIJMP ; Jump if So.
;971114 LON Begin
;;JCJ: Start Check whether Frame length is same as packet length
;; add ax, 14 ; add media header size
;; cmp ax, 60 ; Is it padded
;; jbe CheckIfPadded
;;
;; cmp ax, bp ; Is length over the real size
;; ; given by 586 ActualCount?
;; jne RxMalformedPacketJMP ; Jmp if So
;; jmp short RxNotMalformed
;;CheckIfPadded:
;; cmp bp, 60 ; Was it padded to Min. size
;; jne RxMalformedPacketJMP
;;
;;RxNotMalformed:
;; mov bp, ax ; BP = Unpadded length
;;
;;;JCJ: End Check whether Frame length is same as packet length. SPD# 168702
cmp ax, bp ; Is length over the real size
; given by 586 ActualCount?
ja RxMalformedPacketJMP ; Jmp if So (Chk for PromMode).
or ax, ax ; Is the length Zero?
je RxMalformedPacketJMP ; Jmp if So (Chk for PromMode).
mov bp, ax ; BP = Unpadded length plus
add bp, 14 ; the 802.3 header size.
;971114 LON End
RxMalformedPromiscReturn:
;-----------------------------------------------------------------------\
; *
; At this point we know we have a Length field. If the next word after *
; the length is 0xFFFF then the frame is a Raw 802.3 frame (a Novell *
; defined frame). This means we encountered an IPX header (i.e. 0xFFFF) *
; instead of the usual 802.2 DSAP and SSAP header. *
; *
;-----------------------------------------------------------------------/
IFNDEF NE3200P
cmp word ptr [bx+size AReceiveBufferStructure + 14], 0ffffh ; Raw 802.3?
jne Rx8022JMP ; Jump if No (Frame is 802.2).
ELSE
mov si, SaveRDBOffset ; Get ptr to 1st RCB.
mov si, [si].RBDBufPtr ; SI -> First Data buffer.
cmp word ptr [si], 0ffffh ; RAW 802.3
jne Rx8022JMP ; Jump if No (Frame is 802.2).
ENDIF
RxRaw8023: ; Frame is a RAW 802.3 (IPX)
mov ax, es ; AX = 0 (ES is always zero).
stosw ; Clear ARProtocolID in
stosw ; RCB template field.
stosw ; (AX stored into ES[DI] ).
mov ax, BoardNumber8023 ; AX = 802.3 board number.
cmp ax, -1 ; Valid board number?
jz Rx8023NotSupported ; Jmp if No (Chk for PromMode).
Rx8023NotSupportedPromReturn:
stosw ; Save Board # in RCB template.
mov ax, es ; AX = 0.
stosw ; Store into RCB template.
mov dx, size ATransmitBufferStructure + 14 ; DX = Offset to 1st
; data byte in ECB buffer.
;-----------------------------------------------------------------------\
; *
; At label RxBackFromOtherMedia we return from RxEthernetII and Rx8022 *
; where various header sizes (LLC, SNAP, etc.) were taken into account *
; in precalculating the host ECB offset (DX) to the 1st frame data byte.*
; *
; Note: DI -> ARImmediateAddress in RCB template *
; *
;-----------------------------------------------------------------------/
RxBackFromOtherMedia:
lea si, [bx+size AReceiveBufferStructure + 6] ; SI->Source Adr(SA).
mov cx, 3 ; Move 3 words of SA into RCB
rep movsw ; template ARImmediateAddress.
mov cx, dx ; CX= Media Size -includes the
sub cx, size ATransmitBufferStructure; DA, SA, Length/Type and
; any 802.2 LLC or SNAP size.
IFNDEF NE3200P
mov ax, bp ; AX = Total Pkt size (Frame
sub ax, cx ; size minus the media size).
js RxMalformedTooSmallJMP ; Jmp if frame is just a bad header.
RxCheckGlobalError:
cmp word ptr [bx].ARESREBXValue, 0 ; Does frame have any errors?
jne SetGlobalErrorJMP ; Jump if so.
;JCJ 22-October-97 SPD# 168595 If packet size is lesser than 60 bytes that has
; to be padded in promiscuous mode.
cmp PromiscuousMode, 0 ; In Promiscuous Mode?
jz short RxContinue ; Jmp if no.
mov ax, RcvFrameSize ; Promisc needs the frame data
sub ax, cx ; and padding but no header.
;JCJ SPD# 168595 End
ELSE ; Ne3200Promisc code ; (SNAP hdr = 22).
cmp RBDTotalSize, 22 ; Frame big enough for largest
jae RxCalcPacketSize ; possible MediaHdr? Jmp if so.
mov dx, es ; Don't guess hdr size so setup
; DX with Offset to frm start.
mov ax, bp ; AX = Total Frm Size (includes media).
cmp bp, cx ; Is Media Size larger than Pkt?
jns RxMalformedTooSmallPromisc ; Jump if No.
mov cx, bp ; Set Media Size = Frame Size.
jmp short RxMalformedTooSmallPromisc
RxCalcPacketSize:
mov ax, bp ; AX = Total Pkt size (Frame
sub ax, cx ; size minus the media size).
jns RxMalformedTooSmallPromisc ; Jump if frm OK (It has data).
jmp RxMalformedTooSmall ; Frm has just a hdr so setup
; DX with Offset to frm start.
RxMalformedTooSmallPromisc : ; At this label DX = 0 for bad frames.
cmp word ptr [bx].ARESREBXValue, 0 ; Does frame have any errors?
;JCJ 22-October-97 SPD# 168595 If packet size is lesser than 60 bytes that has
; to be padded in promiscuous mode.
jz CheckIfPaddingNeeded ; Jump if No (Frame is OK).
jmp SetDestTypeError ; Change Dest type to Err Pkt.
CheckIfPaddingNeeded:
cmp PromiscuousMode, 0 ; In Promiscuous Mode?
jz short RxContinue ; Jmp if no.
mov ax, RBDTotalSize ; Promisc needs the frame data
sub ax, cx ; and padding but no header.
;JCJ SPD# 168595 End
DestTypeErrReturn:
ENDIF ; End Ne3200Promisc.
RxContinue:
lea di, [bx].ARPacketLength ; DI->Total Length minus media.
stosw ; Save length(AX) in RCB template.
;; 980504 LON Begin
lea di, [bx].ARPacketSize ; DI->Frag Size minus media.
stosw ; Save length(AX) in RCB template.
; Hi wrd of size already zeroed.
;; LON End
IF DEBUG
call OutWord ; Get packet length-header.
ENDIF
lea di, [bx].ARPacketOffset ; DI-> Template's PacketOffset.
mov ax, NextEmptyRCB ; AX->Lo host ECB address plus
add ax, dx ; the offset within host ECB
; to the 1st frame data byte.
stosw ; Save Lo ptr to 1st data byte.
mov ax, NextEmptyRCB + 2 ; AX -> Hi host ECB address.
adc ax, 0
stosw ; Save Hi ptr into RCB template.
;;LON Begin 980504
;; mov ax, bp ; AX = Size of only Fragment
;; sub ax, cx ; minus the media size.
;; stosw ; Save PacketSize in RCB template.
;;LON End ; Hi wrd of size already zeroed.
IFNDEF NE3200P
if SupportJabber
;;;;;
; mov si, FDHead ; SI -> Current Frame Desc.
; mov si, [si].URBDOffset
; mov cx, [si+0] ; CX = EOF/F/ActualCnt of RBD.
; and ch, 3Fh ; Mask off EOF & F bits.
;;;;;
mov cx, RcvFrameSize ; Get the total frame size.
add cx, size AReceiveBufferStructure ; Add RCB template size
; CX=Total bytes for BMIC copy.
mov si, bx ; SI -> RCB template.
else
mov si, bx ; SI -> RCB template.
mov cx, bp ; CX = Packet Size.
add cx, size AReceiveBufferStructure; CX=Total bytes for BMIC copy.
endif
ELSE
mov si, bx ; SI -> RCB template.
mov cx, TEMPLATE_MAC_SIZE ; RCB template size + MAC size.
; CX=Total bytes for BMIC copy.
ENDIF
mov di, NextEmptyRCB ; DI = Host ECB Address Lo.
mov bx, NextEmptyRCB + 2 ; BX = Host ECB Address Hi.
add di, 16 ; DI-> Into ECB (RProtocolID).
adc bx, 0 ; Adjust Hi address.
;------------------------------------------------------------------------\
; *
; Setup BMIC regs to copy the template plus all of the receive frame *
; to the host (HSM) (Unless we are running as an Ne3200Promisc in *
; which case the template and the 14 bytes of the frame header ( DA, *
; SA & len) are first copied then another copy does the remainder). *
; *
; 1. CH1_TBI_BASE_ADDR Reg: port 6B <- source low byte local adr *
; port 6C <- source hi byte local adr *
; 2. CH1_BASE_COUNT Reg: port 60 <- Low count of bytes to xfer *
; port 61 <- Hi byte count *
; 3. CH1_BASE_ADDR Reg: port 63 & 64 <- dest low word host adr *
; port 65 & 66 <- dest. hi word host adr *
; 4. CH1_STROBE Reg: port 69 <-write anything to start xfer *
; *
;------------------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_TBI_BASE_ADDR OR AUTO_INC ; TBI base address register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, si ; AX = Local addr of RCB template.
shr ax, 1 ; Adjust for the BMIC.
out dx, al ; Set LSB of local addr.
mov al, ah
out dx, al ; Set MSB of local addr.
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_BASE_COUNT OR AUTO_INC ; base count register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, cx ; AX = Packet Size.
;;;;;
;;IFNDEF NE3200P ; Non-P Ne3200 LON
;;if SupportJabber
;; add ax, size AReceiveBufferStructure
;;endif
;;ENDIF
out dx, al ; Set lo count in CH1_BASE_COUNT.
mov al, ah
out dx, al ; Set hi count.
mov al, AUTO_START OR ADAPTER_TO_EISA
out dx, al
mov ax, di ; AX = host addr lo.
out dx, al
mov al, ah
out dx, al
mov ax, bx ; AX = host addr hi.
out dx, al
mov al, ah
out dx, al
;---------------------------------------------------------------\
; *
; Tell BMIC to start the copy of the RCB template plus the: *
; 1. entire rcv frame (for Non-P Ne3200 systems). *
; or 2. 14 byte MAC header (for Ne3200Promisc. systems). *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_STROBE ; strobe register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data port.
out dx, al ; Strobe chan 1 (Start copy).
IFNDEF NE3200P ; Non-P Ne3200 code
;---------------------------------------------------------------\
; *
; Set up to perform a Poke operation to inform the host (driver)*
; that the host ECB (RCB) is done having the RCB template plus *
; the frame data copied into it. We notify the host by writing *
; a Zero value into the host's AdapterRCBList pointer table. *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to Peek/Poke
mov al, PEEK_POKE_DATA OR AUTO_INC ; data register.
out dx, al
;;if SupportJabber
;; mov ax, cx ; AX = Packet Length.
;;else
;; sub cx, size AReceiveBufferStructure
;; mov ax, cx ; AX = Packet length.
;;endif
;; mov dx, BMIC_DATA ; DX = BMIC Data Port.
;; out dx, al ; Set Lo length.
;; mov al, ah ; Set Hi length.
;; out dx, al
;; mov ax, es ; Zero out hi word of dword.
;; out dx, al
;; out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, es ; AX = 0.
out dx, al ; Zero out lo word of dword.
out dx, al
out dx, al ; Zero out hi word of dword.
out dx, al
mov bx, RCBListPointer + 2 ; BX -> host ECB (RCB) List.
mov ax, RCBIndex ; AX = Index into list.
shl ax, 2 ; AX = Index * 4.
add ax, RCBListPointer ; Add to base of list.
adc bx, 0 ; BX:AX ->Next ECB (RCB) slot.
out dx, al ; Set addr 0 in BMIC
mov al, ah ; PEEK_POKE_ADDR register.
out dx, al ; Set addr 1.
mov ax, bx
out dx, al ; Set addr 2.
mov al, ah
out dx, al ; Set addr 3.
inc RCBIndex ; Increment host ECB(RCB) index.
and RCBIndex, TABLE_MASK ; Wrap if needed.
;---------------------------------------------------------------\
; *
; Check if the RCB template and the frame data transfer is *
; completed yet (before we later on start a poke operation). *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_STATUS ; status register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data port.
WaitForXferToHost:
in al, dx ; AL = Current status.
test al, TRANSFER_ENABLED OR TRANSFER_IN_PROGRESS
jnz short WaitForXferToHost
and al, 00000011b ; Mask out reserved bits.
out dx, al ; Reset Status bit.
ELSE ; Ne3200Promisc code
;***************************************************************\
; *
; Wait for the RCB template plus the MAC header transfer to *
; the host ECB to complete. *
; bp = packet length in bytes. *
; *
;***************************************************************/
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_STATUS ; status register.
out dx, al
;; LON xor cx, cx
mov dx, BMIC_DATA ; DX = BMIC Data port.
WaitForECBToHost:
in al, dx ; AL = Current status.
test al, TRANSFER_ENABLED OR TRANSFER_IN_PROGRESS ;
jnz short WaitForECBToHost ; Jmp if transfer in progress.
;; LON jz WaitForECBToHostDone
;; loopnz WaitForECBToHost ; Jmp if transfer in progress.
;; StatisticsUpdate PacketRxMiscErrorCount
;; jmp ReStart586FromTx
;; WaitForECBToHostDone:
and al, 00000011b ; Mask out reserved bits.
out dx, al ; Reset Status bit.
;---------------------------------------------------------------\
; *
; Add TEMPLATE_MAC_SIZE to adjust BX/DI (i.e. pointers into the *
; host ECB space) to point to where the 1st byte of frame data *
; is to be copied. The first frame data byte is copied into the *
; host ECB (RCB) right after the MAC ethernet header. *
; di = Host RCB (ECB) address low *
; bx = Host RCB (ECB) address high *
; *
;---------------------------------------------------------------/
add di, TEMPLATE_MAC_SIZE ; DI->past MAC hdr in host ECB.
adc bx, 0 ; Adjust high address.
mov si, FDHead ; SI -> Frame Descriptor.
mov si, [si].UFDRBDOffset ; SI -> First RBD.
mov si, [si].RBDBufPtr ; SI -> First Buffer.
mov cx, RBDSizeBeforeWrap ; CX = Total Packet Size.
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_TBI_BASE_ADDR OR AUTO_INC ; TBI base address register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, si ; AX = Local address of frame.
shr ax, 1 ; Adjust for the BMIC.
out dx, al ; Set LSB of local addr.
mov al, ah
out dx, al ; Set MSB of local addr.
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_BASE_COUNT OR AUTO_INC ; base count register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, cx ; AX = RBDSizeBeforeWrap.
out dx, al ; Set lo count.
mov al, ah
out dx, al ; Set hi count.
mov al, AUTO_START OR ADAPTER_TO_EISA
out dx, al
mov ax, di ; AX = host ECB addr low.
out dx, al
mov al, ah
out dx, al
mov ax, bx ; AX = host ECB addr high.
out dx, al
mov al, ah
out dx, al
mov dx, BMIC_INDEX ; Set index to Channel 1
mov al, CH1_STROBE ; strobe register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data port.
out dx, al ; Strobe channel 1.
;---------------------------------------------------------------\
; *
; Wait for the second part of the rcv frame to complete its *
; transfer to the host ECB. This is the last BMIC transfer *
; needed to copy the whole frame to the host ECB, UNLESS *
; the frame wrapped from the last data buffer to the first. *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_STATUS ; status register.
out dx, al
;; LON xor cx, cx
mov dx, BMIC_DATA ; DX = BMIC Data port.
WaitForDataToHost:
in al, dx ; AL = Current status.
test al, TRANSFER_ENABLED OR TRANSFER_IN_PROGRESS
jnz short WaitForDataToHost
;; LON jz WaitForDataToHostDone
;; loopnz short WaitForDataToHost
;; StatisticsUpdate PacketRxMiscErrorCount
;; jmp ReStart586FromTx
;; WaitForDataToHostDone:
and al, 00000011b ; Mask out reserved bits.
out dx, al ; Reset Status bit.
cmp RBDSizeAfterWrap, 0 ; Did we wrap?
je InformHostItsDone ; Jump if not.
;---------------------------------------------------------------\
; *
; Copy the wrapped frame data to the host ECB. *
; di = Host RCB (ECB) address low *
; bx = Host RCB (ECB) address high *
; *
;---------------------------------------------------------------/
add di, cx ; DI -> next position in ECB.
adc bx, 0 ; Adjust Hi address.
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_TBI_BASE_ADDR OR AUTO_INC ; TBI base address register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, BufferHead ; AX = Local address.
shr ax, 1 ; Adjust for the BMIC.
out dx, al ; Set LSB of local addr.
mov al, ah
out dx, al ; Set MSB of local addr.
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_BASE_COUNT OR AUTO_INC ; base count register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, RBDSizeAfterWrap ; AX = remaining data bytes.
out dx, al ; Set lo count.
mov al, ah
out dx, al ; Set hi count.
mov al, AUTO_START OR ADAPTER_TO_EISA
out dx, al
mov ax, di ; AX = host ECB addr lo.
out dx, al
mov al, ah
out dx, al
mov ax, bx ; AX = host ECB addr hi.
out dx, al
mov al, ah
out dx, al
mov dx, BMIC_INDEX ; Set index to Channel 1
mov al, CH1_STROBE ; strobe register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data port.
out dx, al ; Strobe chan 1 (start copy).
;---------------------------------------------------------------\
; *
; Wait for the wrapped data transfer to complete. *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to channel 1
mov al, CH1_STATUS ; status register.
out dx, al
;; LON xor cx, cx ; JCP, 941205. *Begin*
mov dx, BMIC_DATA ; DX = BMIC Data port.
WaitForXferToHost:
in al, dx ; AL = Current status.
test al, TRANSFER_ENABLED OR TRANSFER_IN_PROGRESS
jnz short WaitForXferToHost
;; LON jz short WaitForTransferToHostDone
;; loopne WaitForTransferToHost
;; StatisticsUpdate PacketRxMiscErrorCount
;; jmp ReStart586FromTx
;; WaitForTransferToHostDone: ; JCP, 941205. *End*
and al, 00000011b ; Mask out reserved bits.
out dx, al ; Reset Status bit.
InformHostItsDone:
;---------------------------------------------------------------\
; *
; Setup for a Poke operation to inform the host driver that the *
; ECB (RCB) is now complete. Informing the host is done by *
; overwriting (poking) the host's physical ECB address (as con- *
; tained in the circular queue, AdapterRCBList, see ne3200.386) *
; with a value of Zero. *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to Peek/Poke
mov al, PEEK_POKE_DATA OR AUTO_INC ; data register.
out dx, al
mov ax, es ; AX = 0.
mov dx, BMIC_DATA ; DX = BMIC Data Port.
out dx, al ; Zero out lo word of dword.
out dx, al
out dx, al ; Zero out hi word of dword.
out dx, al
mov bx, RCBListPointer + 2 ; BX -> host ECB (RCB) List.
mov ax, RCBIndex ; AX = Index into list.
shl ax, 2 ; AX = Index * 4.
add ax, RCBListPointer ; Add to base of list.
adc bx, 0 ; BX:AX ->Next ECB(RCB) slot.
out dx, al ; Set addr 0.
mov al, ah
out dx, al ; Set addr 1.
mov ax, bx
out dx, al ; Set addr 2.
mov al, ah
out dx, al ; Set addr 3.
inc RCBIndex ; Increment index into host
; ECB (RCB) table.
and RCBIndex, TABLE_MASK ; Wrap if needed.
ENDIF ; End of Ne3200Promisc code
;---------------------------------------------------------------\
; *
; Perform the Poke operation to actually inform the host that *
; the ECB (RCB) is completely filled in and ready. *
; Note: The Peek/Poke operation is started by writing to the *
; PEEK_POKE_CONTROL register (using the BMIC_DATA reg). *
; *
;---------------------------------------------------------------/
mov dx, BMIC_INDEX ; Set index to Peek/Poke
mov al, PEEK_POKE_CONTROL ; control register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
;;; mov al, 01111111b ;; Set locked exchange to
mov al, 00111111b ; Set poke (non-locked)
out dx, al ; host memory and start it.
mov dx, BMIC_STATUS ; DX = BMIC Status port.
WaitForExchange:
in al, dx ; AL = current status.
test al, PEEK_POKE_PENDING ; Non-Locked exchange done?
jnz WaitForExchange ; Jump if not.
cmp PollTimeout, 0 ;
jne RxDontInterruptHost ;
InterruptTheHost
jmp short RxGetNextRCBOffset ;
RxDontInterruptHost: ;
mov dx, BMIC_INDEX ; Set index to the adapter
mov al, POLLING_MAILBOX ; poll mailbox.
out dx, al ;
mov dx, BMIC_DATA ; DX = BMIC Data Port.
in al, dx ; Read poll mailbox.
or al, al ; Already waiting for poll?
jne RxGetNextRCBOffset ; Jump if so.
inc al ; Set Poll Mailbox.
out dx, al ; Write a 1 to poll mailbox.
mov ax, PollTimeout ; Set 80186 timer.
mov dx, T2MaxCount ;
out dx, ax ;
mov ax, 0c000h ;
mov dx, T2Control ;
out dx, ax ;
RxGetNextRCBOffset: ;
mov dx, BMIC_INDEX ;
mov al, PEEK_POKE_ADDR OR AUTO_INC ;
out dx, al ;
mov dx, BMIC_DATA ;
mov bx, RCBListPointer + 2 ; BX -> host ECB (RCB) List.
mov ax, RCBIndex ; AX = Index into list.
shl ax, 2 ; AX = Index * 4.
add ax, RCBListPointer ; Add to base of list.
adc bx, 0 ; BX:AX -> Next RCB slot.
out dx, al ; Set addr 0.
mov al, ah ;
out dx, al ; Set addr 1.
mov ax, bx ;
out dx, al ; Set addr 2.
mov al, ah ;
out dx, al ; Set addr 3.
mov dx, BMIC_INDEX ; Set index to Peek/Poke
mov al, PEEK_POKE_CONTROL ; control register.
out dx, al ;
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov al, 01011111b ; Set peek at host memory
out dx, al ; and start it.
mov dx, BMIC_STATUS ; DX = BMIC Status port.
WaitForExchange1:
in al, dx ; AL = current status.
test al, PEEK_POKE_PENDING ; Peek done?
jnz WaitForExchange1 ; Jump if not.
mov dx, BMIC_INDEX ; Set index to Peek/Poke
mov al, PEEK_POKE_DATA OR AUTO_INC ; data register.
out dx, al
;---------------------------------------------------------------\
; *
; BMIC has completed the peek into the AdapterRCBList ptr table *
; on the host side (HSM driver). So now copy in from the BMIC *
; Peek Data register the address of the next empty ECB (RCB). *
; *
;---------------------------------------------------------------/
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov di, offset NextEmptyRCB ; DI -> Next Empty ECB (RCB).
mov cx, 4 ; Read the 4 byte ECB address.
rep insb
;---------------------------------------------------------------\
; *
; The receive frame processing is complete. *
; *
; Now check if polling is enabled. *
; During initialization the HSM driver provides us with a value *
; for PollTimeout. A zero value means no polling is wanted. *
; *
;---------------------------------------------------------------/
cmp PollTimeout, 0 ; Is polling enabled?
jne RxCheckRCBCount ; Jump if yes.
ret ; Done with rcv frame - Exit.
RxCheckRCBCount: ; We just copied into one RCB
dec KnownRCBCount ; (ECB) so decrement the cnt.
;---------------------------------------------------------------\
; *
; When polling, we ought to have a reserve of 8 RCBs (ECBs) *
; waiting for us to copy received frames into. Otherwise we need*
; to interrupt the host to get it processing the recv'd frames. *
; *
;---------------------------------------------------------------/
cmp KnownRCBCount, 8 ; Are enough RCBs(ECB) left?
jbe GetRCBList ; Jump if No.
ret ; Done - Exit.
GetRCBList:
mov si, offset RCBListTransferSequence
;---------------------------------------------------------------\
; *
; Copy from the host, the entire AdapterRCBList ptr table into *
; our RCBListBuffer. Check if the host is keeping up with us. *
; *
;---------------------------------------------------------------/
BMICTransferWithLocal
mov KnownRCBCount, 0 ; Initialize to 0.
mov si, offset RCBListBuffer ; SI -> RCB (ECB) ptr list.
mov cx, TOTAL_RCBS ; TOTAL_RCBS = 10h.
CountRCBsLoop: ; (Note: lodsw increments SI.)
lodsw ; AX =low word of RCB(ECB) ptr.
mov bx, ax
lodsw ; AX =hi word of RCB(ECB) ptr.
cmp ax, -1 ; Currently unused entry if -1.
je CountNextRCB ; Get next RCB(ECB) ptr entry.
or ax, ax ; Is hi word of ptr Non-zero?
jne WeHaveAValidRCB ; Jump if yes.
;----------------------------------------------------------------\
; *
; The high word of the RCB (ECB) pointer is zero. Now check if *
; the low word of the pointer is also zero, meaning that we *
; recently received this frame and already copied it to the host.*
; And to indicate to the host (HSM) that this received frame is *
; waiting for the host to send it on up the protocol stack, we *
; over-wrote the RCB (ECB) pointer with a value of zero. *
; *
;----------------------------------------------------------------/
;;if SupportJabber ; LON 2/15/96
;; cmp bx, 2048+14 ; Is low ptr wrd really a size?
;;else
;; cmp bx, 1514
;;endif
;; jbe CountNextRCB ; Jump if yes.
or bx, bx ; Is low word of ptr also zero?
jz CountNextRCB ; Jump if yes
;---------------------------------------------------------------\
; *
; Indicate another valid pointer to an RCB (ECB) which we can *
; use later to copy the next received frame into. *
; *
;---------------------------------------------------------------/
WeHaveAValidRCB:
inc KnownRCBCount
CountNextRCB:
loop CountRCBsLoop
cmp KnownRCBCount, 8 ; Do we have enough RCBs(ECB)
ja GetRCBListOK ; in reserve? Jump if Yes.
InterruptTheHost ; Otherwise get the host going.
GetRCBListOK:
ret ; Return to FRInterrupt.
RxEIINotSupported:
cmp PromiscuousMode, 0
je GetRCBListOK ; Ignore frm-Return to FRInterrupt.
call GetADefaultBoardNumber ; In promiscuous - Try default.
jmp short RxEIINotSupportedProm ; Continue rcv processing
;***************************************************************\
; *
; Ethernet II packet received. Make sure we support it and fill *
; in the ECB protocol ID and board number field. *
; *
; Note: On return DX is setup with an ECB offset to the first *
; frame data byte following the Type field. *
; *
;***************************************************************/
RxEthernetII:
mov ax, es ; AX = 0.
stosw ; Store Type as a PID in the
stosw ; ARProtocolID RCB template.
mov ax, [bx+size AReceiveBufferStructure+12] ; Load Type field.
stosw
mov ax, BoardNumberEII ; AX = EII board number.
cmp ax, -1 ; Valid board number?
jz RxEIINotSupported ; Jump if not (try a default?).
RxEIINotSupportedProm:
stosw ; Save Board # in RCB template.
mov ax, es ; AX = 0.
stosw ; Store into RCB template.
mov dx, size ATransmitBufferStructure + 14 ; DX = offset into ECB buffer.
jmp RxBackFromOtherMedia ; Continue processing.
;***************************************************************\
; *
; 802.2 packet received. Make sure a SNAP extension hasn't been *
; added, make sure we support it and fill in the ECB protocol *
; ID and board number field. *
; 802.2 = /Len /DSAP /SSAP /UI(03h) /<data>. *
; 802.2 SNAP = /Len /DSAP(AAh) /SSAP(AAh) /UI /<5 byte snap>... *
; *
; Note: On return DX is setup with an ECB offset to the first *
; frame data byte following the 802.2 or 802.2 SNAP hdr. *
; The ECB offset is saved in the RCB template and is used *
; later by the host (HSM) when processing the rcv frame. *
; *
;***************************************************************/
Rx8022:
IFNDEF NE3200P
mov byte ptr [bx].ARDriverWorkSpace + 1, 1 ; Assume 802.2 Type 1
cmp word ptr [bx+size AReceiveBufferStructure+14], 0AAAAh
jne RxMustBe8022 ; Jump if not snap.
cmp byte ptr [bx+size AReceiveBufferStructure+16], 03h ; UI value?
je Rx8022SNAP ; Jump if yes.
RxMustBe8022:
mov dx, size ATransmitBufferStructure + 14 + 4 ; DX = offset in ECB buffer.
inc byte ptr [bx].ARDriverWorkSpace + 1 ; Assume 802.2 Type 2
test byte ptr [bx+size AReceiveBufferStructure+16], 00000001b
je RxMustBe8022Type2 ; Jump if I-Format PDU
test byte ptr [bx+size AReceiveBufferStructure+16], 00000010b
je RxMustBe8022Type2 ; Jump if S-Format PDU
dec byte ptr [bx].ARDriverWorkSpace + 1 ; 802.2 Type 1
dec dx
RxMustBe8022Type2:
mov ax, es ; AX = 0.
stosw ; Store DSAP as a PID into
stosw ; ARProtocolID RCB template.
mov ah, [bx+size AReceiveBufferStructure+14] ; Load the DSAP.
stosw
mov ax, BoardNumber8022 ; AX = 8022 board number.
cmp ax, -1 ; Valid board number?
jz Rx8022NotSupported ; Jump if not (try a default?).
ELSE ; Ne3200Promisc code
mov byte ptr [bx].ARDriverWorkSpace + 1, 1 ; Assume 802.2 Type 1
cmp word ptr [si+0], 0AAAAh
jne RxMustBe8022 ; Jump if not snap.
cmp byte ptr [si+2], 03h
je Rx8022SNAP
RxMustBe8022:
mov dx, size ATransmitBufferStructure + 14 + 4 ; DX = offset in ECB buf.
inc byte ptr [bx].ARDriverWorkSpace + 1 ; Assume 802.2 Type 2
test byte ptr [si+2], 00000001b
je RxMustBe8022Type2 ; Jump if I-Format PDU
test byte ptr [si+2], 00000010b
je RxMustBe8022Type2 ; Jump if S-Format PDU
dec byte ptr [bx].ARDriverWorkSpace + 1 ; 802.2 Type 1
dec dx ; DX =Offset to 1st data byte
; in host ECB buffer.
RxMustBe8022Type2:
mov ax, es ; AX = 0.
stosw ; Store DSAP as a PID into
stosw ; ARProtocolID RCB template.
mov ah, [si+0] ; AH = 802.2 DSAP.
stosw
mov ax, BoardNumber8022 ; AX = 8022 board number.
cmp ax, -1 ; Valid board number?
jz Rx8022NotSupported ; Jump if not (try a default?).
ENDIF
Rx8022NotSupportedProm:
stosw ; Save Board # in RCB template.
mov ax, es ; AX = 0.
stosw ; Store into RCB template.
jmp RxBackFromOtherMedia ; Continue processing.
Rx8022NotSupported:
cmp PromiscuousMode, 0 ; In promiscuous?
je RxSNAPNotSupportedExit ; Jmp if no (Go exit).
mov word ptr es:[di], dx ; Save DX temporarily in RCB.
call GetADefaultBoardNumber ; In promiscuous - Try default.
mov dx, word ptr es:[di] ; Restore DX.
jmp short Rx8022NotSupportedProm
;***************************************************************\
; *
; 802.2 SNAP packet received. Make sure we support it and fill *
; in the ECB protocol ID and board number field. *
; *
; Note: On return DX is setup with an ECB offset to the first *
; frame data byte following the 802.2 SNAP hdr. *
; *
;***************************************************************/
Rx8022SNAP:
IFNDEF NE3200P
mov ax, es ; AX = 0.
mov ah, [bx+size AReceiveBufferStructure+17]
stosw ; Store SNAP addr as PID in
mov ax, [bx+size AReceiveBufferStructure+18]; ARProtocolID.
stosw
mov ax, [bx+size AReceiveBufferStructure+20]
stosw
ELSE ; Ne3200Promisc code
mov ax, es ; AX = 0.
mov ah, [si+3]
stosw ; Store SNAP addr as PID in
mov ax, [si+4] ; ARProtocolID RCB template.
stosw
mov ax, [si+6]
stosw
ENDIF
mov ax, BoardNumberSNAP ; AX = EII board number.
cmp ax, -1 ; Valid board number?
jz RxSNAPNotSupported ; Jump if not.
RxSNAPNotSupportedProm:
stosw ; Save Board # in RCB template.
mov ax, es ; AX = 0.
stosw ; Store into RCB template.
mov dx, size ATransmitBufferStructure + 14 + 8; DX = Offset in ECB buffer.
jmp RxBackFromOtherMedia
RxSNAPNotSupported:
cmp PromiscuousMode, 0
je RxSNAPNotSupportedExit
call GetADefaultBoardNumber
jmp short RxSNAPNotSupportedProm
RxSNAPNotSupportedExit:
ret ; Return to FRInterrupt.
CopyPacketToHost endp
;***********************************************************************\
; *
; UpdateHostStatistics - Transfer statistic buffer to the host. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
UpdateHostStatistics proc
mov ax, es ; AX = 0.
xchg ax, ds:SCB.SCBCRCErrors ; Swap with SCB.
add word ptr StatisticCounters.ChecksumErrorCount, ax
mov ax, es ; AX = 0.
adc word ptr StatisticCounters.ChecksumErrorCount+2, ax
xchg ax, ds:SCB.SCBAlignErrors ; Swap with SCB.
add word ptr StatisticCounters.RxAbortFrameAlignment, ax
add word ptr StatisticCounters.PacketRxMiscErrorCount, ax
mov ax, es ; AX = 0.
adc word ptr StatisticCounters.RxAbortFrameAlignment+2, ax
adc word ptr StatisticCounters.PacketRxMiscErrorCount+2, ax
xchg ax, ds:SCB.SCBResources ; Swap with SCB.
add word ptr StatisticCounters.PacketRxOverflowCount, ax
mov ax, es ; AX = 0.
adc word ptr StatisticCounters.PacketRxOverflowCount+2, ax
xchg ax, ds:SCB.SCBOverruns ; Swap with SCB.
add word ptr StatisticCounters.RxDMAOverrun, ax
add word ptr StatisticCounters.PacketRxMiscErrorCount, ax
adc word ptr StatisticCounters.RxDMAOverrun+2, 0
;; LON adc word ptr StatisticCounters.PacketRxMiscErrorCount, ax
adc word ptr StatisticCounters.PacketRxMiscErrorCount+2, 0
mov si, offset StatisticsSequence ; SI -> Preset sequence.
BMICTransferWithLocal
mov si, offset StatisticsSequence1
BMICTransferWithLocal
ret ; Exit.
UpdateHostStatistics endp
;***********************************************************************\
; *
; SetupForMulticastCommand - Copy multicast table to SCB structure and *
; initialize the remainder of the command block. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = @ MC Command Block *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
SetupForMulticastCommand proc
mov si, offset HostMulticastTable ; SI -> Host table.
mov di, COMMAND_BUFFER + MulticastCmdAddresses
mov cx, MulticastCount ; CX = Addresses in table.
jcxz AddressesCopied ; Jump if No addresses.
CopyFromHostLoop:
movsw ; Copy six bytes.
movsw
movsw
lodsw ; Skip two bytes.
loop CopyFromHostLoop ; Get next address.
AddressesCopied:
mov bx, COMMAND_BUFFER ; BX -> Command Buffer.
mov [bx].MulticastCmdStatus, 0
mov [bx].MulticastCmdCommand, CB_MC_SETUP + ELBIT
mov [bx].MulticastCmdLink, 0
mov ax, MulticastCount ; CX = MC addresses.
mov cl, 6 ; Multiply by 6.
mul cl
mov [bx].MulticastCmdCount, ax
ret ; Exit
SetupForMulticastCommand endp
;***********************************************************************\
; *
; Abend - Set BMIC mailbox 0 to error code and halt. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used (Never returns) *
; BX = Error Code *
; CX = Not Used *
; DX = Not Used *
; BP = Not Used *
; SI = Not Used *
; DI = Not Used *
; *
;***********************************************************************/
even
Abend proc
mov dx, BMIC_INDEX ; Set index to Abend
mov al, ABEND_MAILBOX ; Mailbox register.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov ax, bx ; AX = Error Code.
out dx, al ; Set LSB of error code.
mov al, ah
out dx, al ; Set MSB of error code.
;
; Fall thru to IdleAdapter.
;
Abend endp
;***********************************************************************\
; *
; IdleAdapter - Interrupt should already be disabled. Stay in *
; continuous loop until host resets us. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used (Never returns) *
; BX = Not Used *
; CX = Not Used *
; DX = Not Used *
; BP = Not Used *
; SI = Not Used *
; DI = Not Used *
; *
;***********************************************************************/
even
IdleAdapter proc
jmp short IdleAdapter
IdleAdapter endp
ForceToMaxMulticast:
mov cx, MAX_MULTICAST_ADDR
jmp short MulticastBetweenZeroAndMax
;***********************************************************************\
; *
; UpdateParameters - Read the parameter block from the host and redo *
; our mutlicast table. Next reinitialize control structures and *
; reconfigure the 82586. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
UpdateParameters proc
;---------------------------------------------------------------\
; *
; Copy the adapter parameter block from host. *
; *
;---------------------------------------------------------------/
mov si, offset ParameterTransferSequence ; SI -> Source.
BMICTransferWithLocal ; Copy adapter parm block.
mov cx, MulticastCount ; CX = address count.
jcxz TableTransferedFromHost ; Finished if empty.
cmp cx, MAX_MULTICAST_ADDR ; Over max?
ja ForceToMaxMulticast ; Jump if so.
MulticastBetweenZeroAndMax:
;---------------------------------------------------------------\
; *
; Copy the multicast table from host. *
; *
;---------------------------------------------------------------/
shl cx, 3 ; CX = CX * 8.
mov MCTableCount, cx ; Save the count into sequence.
mov ax, MulticastListPointer ; Save the host address.
mov MCTableOffsetLo, ax
mov ax, MulticastListPointer + 2
mov MCTableOffsetHi, ax
mov si, offset MCTableSequence ; SI -> sequence.
BMICTransferWithLocal
TableTransferedFromHost:
cmp StatisticCounters.CustomCounterCount, 0 ; First time thru?
jz DontAddMulticast ; Jump if so.
IFNDEF NE3200P
if SupportJabber
;---------------------------------------------------------------\
; *
; Note: While attempting to make the Non-Promisc. code *
; consistently handle 2000 or 2048 byte frames (i.e. always *
; copy the frame into a rcv buffer and not ignore it when the *
; PRM and SAV BF bits are configured, we attempted to make it *
; work by skipping Initialize586 and instead using the NE3200P's*
; method of aborting the RU and then re-configuring the 82586. *
; It did not work and in the TESTCON Good/Bad Promiscuous test, *
; the 82586 processed rcv frames much more slowly. *
; *
;---------------------------------------------------------------/
jmp short Initialize586 ; Jmp if Yes.
else
UpdatePromiscConfig:
call SetupForMulticastCommand ; Set up command block.
mov ax, 140h ; Abort the RU and issue
call Command586NoRestart ; multicast change command.
jne WaitForMCError ; Jump if 586 locked.
mov cx, es ; Set loop counter (Init to 0).
WaitForMCCommandLoop:
test word ptr [bx], 8000h ; Command complete?
jnz EnableRU ; Jump if so.
loop WaitForMCCommandLoop ; Loop if not.
WaitForMCError:
call ReStart586 ; Exit - error.
ret
EnableRU:
mov si, offset ConfigNormal ; SI -> Config parms.
cmp PromiscuousMode, 0 ; Promiscuous mode on?
je UpdateConfigNotProm ; Jump if not.
mov si, offset ConfigPromiscuous ; SI -> Config parms.
UpdateConfigNotProm:
mov di, COMMAND_BUFFER ; DI -> command buffer.
mov cx, ConfigNormalSize / 2 ; TNL 7/25/95 CX = words to move.
mov bx, di ; BX -> command buffer.
rep movsw
mov ax, 100h ; SCB 100 = start exec of CBL
call Command586NoRestart ; Issue Command.
jnz short UpdateConfigDone ; Jump if error.
mov cx, es ; Set loop counter (Init to 0).
WaitForConfigUpdateLoop:
test word ptr [bx], 8000h ; Command complete?
jnz UpdateConfigExit ; Jump if so.
loop WaitForConfigUpdateLoop ; Loop if not.
or al, 1 ; Set error flag.
UpdateConfigExit:
jmp ProcessFRInterrupt ; In case we Rx'd something
; and start the RU.
endif
ELSE ; Ne3200Promisc code
call SetupForMulticastCommand ; Set up command block.
mov ax, 140h ; Abort the RU and issue
call Command586NoRestart ; multicast command.
jne WaitForMCError ; Jump if 586 locked.
mov cx, es ; Set loop counter (Init to 0).
WaitForMCCommandLoop:
test word ptr [bx], 8000h ; Command complete?
jnz EnableRU ; Jump if so.
loop WaitForMCCommandLoop ; Loop if not.
WaitForMCError:
call ReStart586
ret ; Exit.
EnableRU:
mov si, offset ConfigNormal ; SI -> Config parms.
cmp PromiscuousMode, 0 ; Promiscuous mode on?
je UpdateConfigNotProm ; Jump if not.
mov si, offset ConfigPromiscuous ; SI -> Config parms.
UpdateConfigNotProm:
mov di, COMMAND_BUFFER ; DI -> command buffer.
mov cx, ConfigNormalSize / 2 ; TNL 7/25/95 CX = words to move.
mov bx, di ; BX -> command buffer.
rep movsw
mov ax, 100h ; SCB 100 = start exec of CBL
call Command586NoRestart ; Issue Command.
jnz short UpdateConfigExit ; Jump if error.
mov cx, es ; Set loop counter (Init to 0).
WaitForConfigUpdateLoop:
test word ptr [bx], 8000h ; Command complete?
jnz UpdateConfigExit ; Jump if so.
loop WaitForConfigUpdateLoop ; Loop if not.
or al, 1 ; Set error flag.
UpdateConfigExit:
jmp ProcessFRInterrupt ; In case we Rx'd something
; and start the RU Unit.
ENDIF
DontAddMulticast :
ret ; Exit.
UpdateParameters endp
;***********************************************************************\
; *
; 82586 specific code. *
; *
;***********************************************************************/
;
;***********************************************************************\
; *
; Initialize586 - Reset and configure the 82586, initialize the *
; transmit buffers, initialize the receive buffers and set the deadman *
; counters. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
; The Zero flag (ZF) is set according to results of RUStart when called *
; by InitializeRxBuffers (ZeroFlag = 1 if successful). *
; *
;***********************************************************************/
even
Initialize586 proc
;---------------------------------------------------------------\
; *
; Reset the 82586. *
; *
;---------------------------------------------------------------/
ResetThe82586 ; Macro to reset 82586.
;---------------------------------------------------------------\
; *
; Configure 586 and setup Tx and Rx buffers. *
; *
;---------------------------------------------------------------/
call Configure586
jnz Initialize586 ; Try again if error.
mov DeadMan, 0 ; Set deadman
mov DeadManHigh, 35 ; counters to max.
ret ; Exit.
Initialize586 endp
;***********************************************************************\
; *
; Configure586 - Send nop command to start 586, set up config command *
; and iasetup command. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
Configure586 proc
;---------------------------------------------------------------\
; *
; Zero out the memory that the 82586 will use for Tx and Rx *
; buffers. *
; *
;---------------------------------------------------------------/
mov di, MEMORY_586_START ; DI -> 8000h.
mov cx, MEMORY_SIZE / 2 ; CX -> 8000h / 2.
mov ax, es ; AX = 0000h.
rep stosw ; Zero out block.
;---------------------------------------------------------------\
; *
; Build up initial SCP and ISCP before starting the 82586. *
; *
;---------------------------------------------------------------/
mov si, offset InitialSCP ; Build our SCP.
mov di, SCP
mov cx, SCP_LENGTH / 2
rep movsw
mov di, offset ISCP ; Build our ISCP.
mov cx, ISCP_LENGTH / 2
rep movsw
;---------------------------------------------------------------\
; *
; Send NOP command to the 82586 to start it. *
; *
;---------------------------------------------------------------/
mov ax, es ; 0 = NOP command.
mov ds:SCB.SCBCommand, ax ; Set command.
mov bx, ax
call Command586NoRestart ; Issue CU NOP Command.
jnz short NOPCommandError ; Jump if error.
mov cx, es ; Set loop counter (Init to 0).
WaitForNOPLoop:
test ds:SCB.SCBStatus, 8000h ; CX bit set?
jne IssueConfigLoopbackCommand ; Jump if so.
loop WaitForNOPLoop ; Loop if not.
NOPCommandError:
ret ; Exit (error).
;---------------------------------------------------------------\
; *
; Send configure command to the 82586 placing it into internal *
; loopback. *
; *
;---------------------------------------------------------------/
IssueConfigLoopbackCommand:
mov si, offset ConfigLoopback ; SI -> Config parms.
mov di, COMMAND_BUFFER ; DI -> Command buffer.
mov cx, ConfigNormalSize / 2 ;TNL 7/25/95 CX = words to move.
mov bx, di ; BX -> Command buffer.
rep movsw
mov ax, 100h
call Command586NoRestart ; Issue Configure Command.
jnz short ConfigCommandError ; Jump if error.
mov cx, es ; Set loop counter (Init to 0).
WaitForConfigLoop:
test word ptr [bx], 8000h ; Command complete?
jnz IssueIACommand ; Jump if so.
loop WaitForConfigLoop ; Loop if not.
or al, 1 ; Set error flag.
ConfigCommandError:
ret ; Exit (error).
;---------------------------------------------------------------\
; *
; Send iasetup (ia = Individual node Address) command to 82586. *
; *
;---------------------------------------------------------------/
IssueIACommand:
mov bx, COMMAND_BUFFER ; BX -> command buffer.
mov di, bx ; DI -> command buffer.
mov ax, es ; AX = 0.
stosw ; Setup for IA command.
mov word ptr [di], 8001h
inc di
inc di
stosw
mov si, offset BoardID ; SI -> Node Address.
movsw
movsw
movsw
mov ax, 100h
call Command586NoRestart ; Issue IA-SETUP Command.
jnz IACommandError
mov cx, es ; Set loop counter (Init to 0).
WaitForIALoop:
test word ptr [bx], 8000h ; Command complete?
jnz IssueMCCommand ; Jump if so.
loop WaitForIALoop ; Loop if not.
or al, 1 ; Set error flag.
IACommandError:
ret ; Exit (error).
;---------------------------------------------------------------\
; *
; Send MC setup command to the 82586. *
; *
;---------------------------------------------------------------/
IssueMCCommand:
call SetupForMulticastCommand ; Set up block.
mov ax, 100h ; AX = Start command.
call Command586NoRestart ; Issue MC-SETUP Command.
jnz IACommandError ; Exit if locked.
mov cx, es ; Set loop counter (Init to 0).
WaitForMCLoop:
test word ptr [bx], 8000h ; Command complete?
jnz IssueConfigNormalCommand ; Jump if so.
loop WaitForMCLoop ; Loop if not.
or al, 1 ; Set error flag.
ret ; Exit (error).
;---------------------------------------------------------------\
; *
; Issue a normal configure command to the 82586 to take it out *
; of internal loopback. Then setup Tx & Rx buffers and start RU.*
; *
;---------------------------------------------------------------/
IssueConfigNormalCommand:
mov si, offset ConfigNormal ; SI -> Config parms.
cmp PromiscuousMode, 0 ; Promiscuous mode on?
je IssueConfigNotProm ; Jump if not.
mov si, offset ConfigPromiscuous ; SI -> Config parms.
IssueConfigNotProm:
mov di, COMMAND_BUFFER ; DI -> command buffer.
mov cx, ConfigNormalSize / 2 ;TNL 7/25/95 CX =Words to move.
mov bx, di ; BX -> command buffer.
rep movsw
mov ax, 100h
call Command586NoRestart ; Issue Configure Command.
jnz short ConfigNormalCommandError ; Jump if error.
;;;;;
mov si, offset ConfigNormal ; SI -> Config parms.
cmp PromiscuousMode, 0 ; Promiscuous mode on?
je IssueConfigNotPromisc ; Jump if not.
mov si, offset ConfigPromiscuous ; SI -> Config parms.
IssueConfigNotPromisc:
mov di, COMMAND_BUFFER ; DI -> command buffer.
mov cx, ConfigNormalSize / 2 ;TNL 7/25/95 CX =Words to move.
mov bx, di ; BX -> command buffer.
rep movsw
mov ax, 100h
call Command586NoRestart ; Issue Configure Command.
jnz short ConfigNormalCommandError ; Jump if error.
call InitializeTxBuffers ;
call InitializeRxBuffers ; (Jumps to RUStart).
jnz ConfigNormalCommandError ; Jump if RUStart failed.
mov bx, COMMAND_BUFFER ; Restore BX -> Command buffer.
mov cx, es ; Set loop counter (Init to 0).
WaitForRUstartLoop:
test word ptr [bx], 8000h ; Start RU Command complete?
jnz ExitConfig ; Jump if so.
loop WaitForRUstartLoop ; Loop if not.
or al, 1 ; Set error flag.
ConfigNormalCommandError:
ret ; Exit.
ExitConfig:
xor ax, ax
ret ; Exit.
Configure586 endp
;***********************************************************************\
; *
; InitializeTxBuffers - Initialize the transmit buffers in the 82586's *
; buffer space. *
; *
; TxBuffers are layed out in the following contiguous order: *
; 1. The 82586 Transmit Command Block (TxCStruct), *
; 2. The 82586 Transmit Buffer Descriptor (BDStruct), *
; 3. The actual data frame sp (1514 or 2048 + extra space for BMIC).*
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Preserved *
; SI = Not Used SI = Preserved *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
InitializeTxBuffers proc
mov TxCHead, 0 ; Clear Tx Head pointer.
mov TxCEnd, 0 ; Clear Tx Tail pointer.
mov di, TX_BUFFERS ; DI -> Tx buffers start adr.
mov cx, NUMBER_TX_BUFFERS ; CX = number of Tx buffers.
mov TxFreeHead, di ; Initialize the free head.
;---------------------------------------------------------------\
; *
; Setup the 82586's Transmit Command Block (i.e. TxCStruct) *
; *
;---------------------------------------------------------------/
TxInitLoop:
mov [di].TxStatus, 0 ; Clear status.
mov [di].TxCmd, 0A004h ; EL & interrupt (4=Xmit Cmd).
mov bx, di
add bx, size TxCStruct ; BX -> BDStruct (i.e. TBD).
mov [di].TBDOffset, bx ; Save TransmitBufferDesc adr.
mov ax, bx
add ax, size BDStruct
mov [bx].BufPtr, ax ; Save ptr. to 1st frame byte.
ifdef DAVID3
add ax, TX_BUFFER_SZ_MAX
else
add ax, TX_BUFFER_SIZE
endif
mov [di].TxCLink, ax ; Save ptr to next TxCStruct.
mov di, ax ; DI -> Next TxCStruct.
;---------------------------------------------------------------\
; *
; Setup the 82586's Transmit Buffer Descriptor (i.e. BDStruct) *
; *
; NOTE: [bx].BufSize is not part of the true 82586 TBD. *
; *
;---------------------------------------------------------------/
mov ax, es ; AX = 0000h.
mov [bx].BDStatus, ax ; Clear Status.
mov [bx].BDLink, ax ; Clear link.
mov [bx].BufPtr + 2, ax ; Clear high offset.
ifdef DAVID3
mov [bx].BufSize, TX_BUFFER_SZ_MAX ; Set buffer size.
else
mov [bx].BufSize, TX_BUFFER_SIZE ; Set buffer size.
endif
loop TxInitLoop
mov [bx - size TxCStruct].TxCLink, ax ; Clear last link.
ret
InitializeTxBuffers endp
;
;***********************************************************************\
; *
; InitializeRxBuffers - *
; *
; Fields in the RCB template are not cleared(e.g. ARPacketLength) since *
; the memory test zeroed out all memory during early initialization. *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Preserved *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
InitializeRxBuffers proc
IFNDEF NE3200P
mov ax, MEMORY_END ; AX = Memory left over for
sub ax, offset RX_BUFFERS ; receive UniRcvBuf buffers.
mov dx, es ; DX = 0 for divide.
mov bx, SIZE UniReceiveBuf ; BX = Size of each UniRcvBuf.
; = 22 + 1558 + 10 = 1590.
if SupportJabber
mov si, (RBuffSize-14) ; RBuffSize = 1500 + 14.
cmp PromiscuousMode, 0 ; Promiscuous mode on?
je BufferSizeNotProm ; Jump if not.
; Note: MAX_JABBER = 2048+14.
add bx, MAX_JABBER - RBuffSize ; Add enough for jabber (+548).
mov si, (MAX_JABBER-14) ; SI = 2048.
BufferSizeNotProm:
endif
div bx ; AX = Total UniRcvBuf buffers.
;
mov di, RX_BUFFERS ; DI -> Start of UniRcvBuffers.
mov FDHead, di ; Save as head of list.
mov cx, ax ; CX = Total UniRcvBuffers cnt.
;-----------------------------------------------------------------\
; *
; Each UniRcvBuffer (Uni means One) contains all the descriptors *
; and buffers needed to hold one entire receive frame. The first *
; part of a UniRcvBuf is the FD (Frame Desc), followed by the *
; RCB template, which gets copied to the host to fill in an ECB. *
; Next is the frame header and data (data buffer). The last part *
; is the RBD (Receive Buffer Descriptor). Note the data buffer *
; size is 1500 bytes or 2048 if jabbering is enabled. *
; *
;-----------------------------------------------------------------/
RxInitLoop:
mov ax, es ; AX = 0000h.
mov [di].UFDStatus, ax ; Zero the status in FD.
mov [di].UFDCommand, ax ; Clear command in FD.
if SupportJabber
lea bx, [di].DataBuffer ; Address of data buffer.
add bx, si ; SI = 2048 (data buffer size).
mov [di].URBDOffset, bx ; Point to start of RBD.
lea dx, [di + SIZE UniReceiveBuf-1500] ; DX -> Next UniRcvBuffer.
add dx, si ; Add data buffer size(jabber).
else
lea bx, [di].RBDStatus ; BX -> RBD struct.
mov [di].URBDOffset, bx ;
lea dx, [di + SIZE UniReceiveBuf] ; DX -> Next UniRcvbuf.
endif
mov [di].UFDLink, dx ; Save ptr. to next
; UniRcvBuf struc.
mov word ptr [di].URCB.ARFragmentCount, 1 ; Force a frag count.
if SupportJabber
lea bx, [di].DataBuffer ; BX -> Data Buffer.
mov di, bx ; DI -> Data Buffer.
add di, si ; DI -> RBD.
mov word ptr [di+0], ax ; Clear EOF, F and ActualCount.
;-----------------------------------------------------------------\
; *
; Note: Every RCB points to the same DummyRCB as the next RCB link*
; because of an 82586 chip errata where an extra RBD prefetch is *
; done when EL (End of List) = 1. *
; *
; Note: Use BDStruct to reference the RBD in UniReceiveBuf struc. *
; *
;-----------------------------------------------------------------/
mov word ptr [di+2], DUMMY_RCB ; Fill in RBDLink.
;; mov word ptr [di+2], 0ffffh ;; Fill in RBDLink.
mov word ptr [di+4], bx ; Fill in RBDBufPtr.
mov word ptr [di+6], ax ; Zero out RBDBufPtr+2.
mov word ptr [di+8], si ; Fill in RBDBufSize.
or word ptr [di+8], 8000h ; Set EL bit (End of List).
else
mov [di].RBDStatus, ax ; Clear EOF, F and ActualCount.
lea bx, [di].DataBuffer ; BX -> Data buffer.
mov [di].RBDBufPtr, bx ; Save pointer.
mov [di].RBDBufPtr + 2, ax ; Zero high word.
mov [di].RBDLink, DUMMY_RCB
mov [di].RBDBufSize, (RBuffSize-14) or 8000h ; Size and EL.
endif
mov di, dx ; DI -> Next UniRcvBuffer.
loop RxInitLoop
if SupportJabber
sub di, SIZE UniReceiveBuf-1500 ; DI -> Last UniRcvBuffer.
sub di, si
else
sub di, SIZE UniReceiveBuf ; DI -> Last UniRcvBuffer.
endif
mov FDEnd, di ; FDEnd -> Last UniRcvBuffer.
mov [di].UFDCommand, 8000h ; Set EL (End of List) bit.
mov ax, FDHead ; Make the last UniRcvBuffer
mov [di].UFDLink, ax ; point to the first.
mov di, DUMMY_RCB ; Fill in Dummy RCB.
mov [di].BDStatus, 0
mov [di].BDLink, -1 ; Indicate this is last RBD.
mov [di].BufPtr, offset DUMMY_BUFFER; Point to zeroed memory.
mov [di].BufPtr+2, 0
mov [di].BufSize, 8000h ; Set EL (End of List) bit.
ELSE ; Ne3200Promisc code
;***************************************************************\
; *
; Figure out how many FD's, RBD's and Buffers we can allocate. *
; We first set up the FD's in one contiguous memory block. Then *
; the RBD's are next set up as a contiguous block. Last the *
; data buffers(256 in size) are also set up as a contiguous blk.*
; *
;***************************************************************/
mov ax, MEMORY_END ; AX = Memory left over for
sub ax, offset RX_BUFFERS ; receive frame area.
mov dx, es ; DX = 0 for divide.
mov bx, size UFDStruct + size RBDStruct + 256
; BX = 22 + 10 + 256 = 288.
div bx ; AX = Total Receive buffers.
mov cx, ax
;---------------------------------------------------------------\
; *
; Link up the Frame Descriptors (FDs). *
; *
;---------------------------------------------------------------/
push cx ; Save count.
mov di, RX_BUFFERS ; DI -> FD Area.
mov FDHead, di ; Initialize FD head pointer.
mov al, size UFDStruct ; AL = Size of Frame Desc.
mul cl ; CL = Number of FD's.
mov dx, ax
add dx, di ; DX -> First RBD.
mov ax, es ; AX = 0.
LinkUpFDsLoop:
mov [di].UFDStatus, ax ; Give ownership to 82586.
mov [di].UFDCommand, ax ; Not End of List(EL), don't suspend.
mov si, di
add si, size UFDStruct ; SI -> Next FD.
mov [di].UFDLink, si ; Link to next FD.
mov [di].UFDRBDOffset, dx ; First RBD or Invalid (-1).
mov di, si ; DI -> Next FD.
mov dx, -1 ; A -1 tells the 82586 that no
; RBDs are linked to this FD.
loop LinkUpFDsLoop ;
pop cx ; Restore total count of FDs.
;---------------------------------------------------------------\
; *
; Set End of List bit (EL) in last Frame Descriptor and link it *
; to the first Frame Descriptor (FD). *
; *
;---------------------------------------------------------------/
;
sub di, size UFDStruct
mov FDEnd, di ; FDEnd -> Last Frame Desc(FD).
mov [di].UFDCommand, 8000h ; Set EL (End of List) bit.
mov ax, FDHead ; Link the last Frame Desc to
mov [di].UFDLink, ax ; the first one.
;---------------------------------------------------------------\
; *
; Link up the Receive Buffer Descriptors (RBD) and data buffers.*
; Rcv frames can consist of multiple data buffers. *
; *
;---------------------------------------------------------------/
mov di, si ; DI -> RBD Area.
mov RBDHead, di ; Setup pointer to RBD head.
mov al, size RBDStruct ; AL = Size of one RBD.
mul cl ; CL = Number of RBDs(previously saved).
mov dx, ax ; DX = Total size of RBD pool.
add dx, di ; DX -> 1st data buffer.
mov ax, es ; AX = 0.
LinkUpRBDsLoop:
mov [di].RBDStatus, 0 ; Clear EOF, F and ActualCount.
add si, size RBDStruct ; SI -> Next RBD.
mov [di].RBDLink, si ; Link in next RBD.
mov [di].RBDBufPtr + 0, dx ; Point to RBD's data buffer.
mov [di].RBDBufPtr + 2, ax
mov [di].RBDBufSize, 256 ; 256 is size of data buffer.
mov di, si ; DI -> Next RBD.
add dx, 256 ; Point to next data buffer.
loop LinkUpRBDsLoop
;---------------------------------------------------------------\
; *
; Set Last RBD bit and link it to the dummy RCB. This is done *
; due to 82586 D-Step Errata 2.3 (Extra RBD Prefetch when EL=1).*
; *
;---------------------------------------------------------------/
mov BufferHead, di ; DI -> 1st Buffer.
sub di, size RBDStruct ; DI -> Last RBD.
mov RBDEnd, di ; RBDEnd -> Last RBD.
or [di].RBDBufSize, 8000h ; Set End of List (EL).
mov [di].RBDLink, DUMMY_RCB ; Link to dummy RBD.
mov di, DUMMY_RCB ; Fill in Dummy RCB.
mov [di].RBDStatus, 0 ; Clear EOF, F and ActualCount.
mov [di].RBDLink, -1 ; Indicate this is last RBD.
mov [di].RBDBufPtr, offset DUMMY_BUFFER; Point to zeroed memory.
mov [di].RBDBufPtr+2, 0
mov [di].RBDBufSize, 8000h ; Set EL bit.
lea di, RCB_TEMPLATE ; DI -> RCB structure template.
mov word ptr [di].ARFragmentCount,1 ; Ensure cnt will be 1 in host ECB.
ENDIF
;---------------------------------------------------------------\
; *
; Tell the 82586 Chip to start the Receive Unit (RU). *
; *
;---------------------------------------------------------------/
jmp RUStart ; Start receive unit.
;; ret
InitializeRxBuffers endp
;
;***********************************************************************\
; *
; Command586NoRestart - Wait for any previous commands to finish and *
; start the next one. Return if the previous command is not cleared. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = SCB Command AX = Preserved *
; BX = @ Command Block BX = Preserved *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Preserved *
; SI = Not Used SI = Preserved *
; DI = Not Used DI = Preserved *
; Zero flag set if successful. *
; *
;***********************************************************************/
even
Command586NoRestart proc
mov cx, es ; Set loop counter (Init to 0).
WaitForPreviousLoop:
cmp ds: SCB.SCBCommand, 0 ; Command finished.
loopne WaitForPreviousLoop ; Loop if not.
jne Command586Exit ; 586 might be hosed.
mov ds: SCB.SCBCommand, ax ; Set 586 command.
mov ds: SCB.CBLOffset, bx ; Set command block pointer.
mov dx, CA_PORT ; Tug on the 82586's
out dx, al ; channel attention.
Command586Exit:
ret ; Exit.
Command586NoRestart endp
;
;***********************************************************************\
; *
; Command586 - Wait for any previous commands to finish and start the *
; next one. Restart the 82586 if the previous command didn't clear. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = SCB Command AX = Preserved *
; BX = @ Command Block BX = Preserved *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Preserved *
; SI = Not Used SI = Preserved *
; DI = Not Used DI = Preserved *
; Zero flag set if successful. *
; *
;***********************************************************************/
even
Command586 proc
mov cx, es ; Set loop counter (Init to 0).
WaitForLastCommandLoop:
cmp ds: SCB.SCBCommand, 0 ; Command finished.
loopne WaitForLastCommandLoop ; Loop if not.
jne ReStart586 ; 586 might be hosed.
mov ds: SCB.SCBCommand, ax ; Set 586 command.
mov ds: SCB.CBLOffset, bx ; Set command block pointer.
mov dx, CA_PORT ; Tug on the 82586's
out dx, al ; channel attention.
ret ; Exit.
Command586 endp
;***********************************************************************\
; *
; ReStart586 - Reset the 82586, re-configure it, start the transmit *
; unit if the transmit list contains pending transmits and re-load *
; the multicast table. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
ReStart586 proc
StatisticsUpdate AdapterReset1 ; Update counters.
call Initialize586
jne ReStart586 ; Reset if error.
ret ; Exit.
ReStart586 endp
DummyRCBError:
StatisticsUpdate DummyRCBCount ; Update counter.
PollRestart586:
call ReStart586 ; Attempt to restart it.
jmp short CheckDeadMan ; Continue polling.
;***********************************************************************\
; *
; Poll586 - Read SCB Status to check for transmit or receive interrupt. *
; If no interrupts from 82586, process deadman timer. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
Poll586 proc
mov cx, es ; Set loop counter (Init to 0).
WaitForCommandEmpty:
cmp ds: SCB.SCBCommand, 0 ; Command finished.
loopne WaitForCommandEmpty ; Loop if not.
jne PollRestart586 ; 586 might be hosed.
;---------------------------------------------------------------\
; *
; When a large received frame (3200 bytes, etc.) is too big for *
; our buffer to hold, the 82586 incorrectly uses the DUMMY_RCB *
; even though its size field is zero. This results in the *
; DUMMY_BUFFER having 8 bytes stored into it and the the 82586 *
; updates the DUMMY_RCB with a new size of 8008h (EL is set). *
; Also the status field (where the ActualCount is) is updated *
; to a value of 8000h. So the 586 set the EOF bit but the F bit *
; is still clear. So a test for 4000h likely does nothing. *
; *
;---------------------------------------------------------------/
test ds:DUMMY_RCB.BDStatus, 4000h ; Was Dummy RCB used?
jne DummyRCBError ; Jump if so.
mov ax, ds: SCB.SCBStatus
mov bx, ax
and ax, 0F000h ; Any interrupts(CX,FR,CNA,RNR)?
jz CheckOutOfResources ; Jump if None.
mov ds: SCB.SCBCommand, ax ; Ack all interrupts that were set.
mov DeadManHigh, 35 ; Set Max deadman.
mov dx, CA_PORT ; Tug on the 82586's
out dx, al ; channel attention.
mov cx, es ; Set loop counter (Init to 0).
WaitForAcknowledge:
cmp ds: SCB.SCBCommand, 0 ; Is command finished?
loopne WaitForAcknowledge ; Loop if not.
jne PollRestart586 ; 586 might be hosed.
test bx, FR_INTERRUPT ; Was a frame received?
jz short NoFrame ; Jump if not.
push bx ; Save SCB status.
call ProcessFRInterrupt ; Process Rx Interrupt.
pop bx
jnz PollRestart586 ; Jump if RUStart failed.
NoFrame:
test bx, CX_INTERRUPT ; Transmit complete?
jz short CheckDeadMan ; Jump if not.
call ProcessCXInterrupt ; Process Tx Interrupt.
CheckDeadMan:
dec DeadMan ; Decrement DeadManLow.
jz DecDeadManHigh ; Jump if zeroed.
ret ; Exit.
DecDeadManHigh:
dec DeadManHigh ; Decrement DeadManHigh.
jz DeadManExpired ; Jump if zeroed.
ret ; Exit.
DeadManExpired:
jmp ReStart586 ; Re-start the 82586.
;ret
CheckOutOfResources:
mov ax, ds: SCB.SCBStatus
and al, 70h
cmp al, 40h ; Is RU still in Ready State?
je CheckDeadMan ; Jump if yes.
jmp ReStart586 ; Start recovery
Poll586 endp
TxSingleCollision:
StatisticsUpdate TxOKSingleCollision ; Update stat counters.
jmp short ErrorReEntry
;***********************************************************************\
; *
; ProcessCXInterrupt - Reset transmit deadman counters. If transmit *
; successful, move it onto free list and exit. If an transmit error *
; occurred, set statistic counter and retry transmission if the retry *
; counter decremented is non-zero. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
ProcessCXInterrupt proc
IF DEBUG
mov al, 'C'
call OutChar
ENDIF
mov bx, TxCHead ; BX -> 1st Tx command block.
or bx, bx ; Empty list?
jz IgnoreCX ; Jump if so.
mov ax, [bx].TxStatus ; AX = Tx Status.
test ah, HIGH TX_BUSY ; Transmit still busy?
jnz IgnoreCX ; Jump if so.
test ah, HIGH TX_OK ; Transmit successful?
jz TxError ; Jump if not.
xor ah, ah ; clear high byte.
and al, 0fh ; AX = Number of collisions.
cmp al, 1 ; Single collision?
je TxSingleCollision ; Jump if so.
add word ptr StatisticCounters.TxOKMultipleCollisions, ax
mov ax, es ; AX = 0.
adc word ptr StatisticCounters.TxOKMultipleCollisions+2, ax
ErrorReEntry:
mov di, [bx].TxCLink ; DI -> Next Tx command block.
or di, di ; End of list?
jnz StartNextCommand ; Jump if not.
mov TxCEnd, di ; Clear Transmit queue
mov TxCHead, di ; pointers.
FreeTxBuff:
mov ax, TxFreeHead ; AX -> old Free Head.
mov TxFreeHead, bx ; Free Head = BX.
mov [bx].TxCLink, ax ; Link Old to New.
IgnoreCX:
ret
;***************************************************************\
; *
; Another transmit is on the list. Start it. *
; *
;***************************************************************/
;
StartNextCommand:
mov DeadManHigh, 5 ; Set Tx Deadman.
xchg di, bx ; DI -> old, BX -> next.
mov TxCHead, bx ; Head = BX.
mov ax, 100h ; AX = SCB command.
call Command586NoRestart ; Issue Start Transmit.
jnz StartNextError ; Jump if 586 locked.
mov bx, di ; BX -> old Tx command block.
jmp FreeTxBuff ; Add it to the free list.
StartNextError:
jmp ReStart586
;---------------------------------------------------------------\
; *
; Transmit error paths. *
; *
;---------------------------------------------------------------/
;
TxError:
test ah, HIGH CARRIER_SENSE_ERROR ; Carrier sense loss error?
jz TxErrorCheckClearToSend ; Jump if not.
StatisticsUpdate TxAbortCarrierSense ; Update counters.
StatisticsUpdate PacketTxMiscErrorCount
jmp short TxErrorCheckCollisions ; Attempt a retry.
TxErrorCheckClearToSend:
test ah, HIGH CLEAR_TO_SEND_ERROR ; Clear to send error?
jz TxErrorCheckUnderRun ; Jump if not.
StatisticsUpdate TxClearToSend ; Update counters.
StatisticsUpdate PacketTxMiscErrorCount
jmp short TxErrorCheckCollisions ; Attempt a retry.
TxErrorCheckUnderRun:
test ah, HIGH UNDERRUN_ERROR ; Under runs?
jz TxErrorCheckTxDefers ; Jump if not.
StatisticsUpdate TxUnderRun ; Update counters.
StatisticsUpdate PacketTxMiscErrorCount
jmp short TxErrorCheckCollisions ; Attempt a retry.
TxErrorCheckTxDefers:
test al, LOW TX_DEFERED_ERROR ; Tx defer error?
jz TXErrorCheckMaxCollisions ; Jump if not.
StatisticsUpdate TxOKButDeferred ; Update counters.
jmp short TxErrorCheckCollisions ; Attempt a retry.
TXErrorCheckMaxCollisions:
test al, LOW MAX_COLLISION_ERROR ; Max collisions error?
jz TxErrorCheckCollisions ; Jump it not.
StatisticsUpdate TxAbortExcessCollisions ; Update counters.
StatisticsUpdate PacketTxMiscErrorCount
TxErrorCheckCollisions:
xor ah, ah ; Clear high byte.
and al, 0fh ; AX = Number of collisions.
cmp al, 1 ; Single collision?
je TxErrorSingleCollision ; Jump if so.
add word ptr StatisticCounters.TxOKMultipleCollisions, ax
mov ax, es ; AX = 0.
adc word ptr StatisticCounters.TxOKMultipleCollisions+2, ax
jmp short TxErrorCheckRetries
TxErrorSingleCollision:
StatisticsUpdate TxOKSingleCollision ; Update stat counters.
TxErrorCheckRetries:
dec [bx].TxTries ; Decrement retry counter.
jnz TransNeedsRetry ; Jump if we can retry.
StatisticsUpdate TxRetryFailure ; Update counters.
jmp ErrorReEntry ; Abort this packet.
TransNeedsRetry:
mov DeadManHigh, 5 ; Set Tx Deadman.
mov [bx].TxStatus, 0 ; Clear status field.
mov ax, 100h ; AX = command start.
call Command586 ; Start transmit.
StatisticsUpdate RetryTxCount ; Update counters.
ret
ProcessCXInterrupt endp
;***********************************************************************\
; *
; Misc. routines used by ProcessFRInterrupt (frame reception) *
; *
;***********************************************************************/
IFNDEF NE3200P
if SupportJabber
FixNoRBDCase:
lea di, [si].DataBuffer ; DI -> Data buffer.
mov bp, (RBuffSize-14)
cmp PromiscuousMode, 0 ; Promiscuous mode on?
je FixNoRBDNotProm ; Jump if not.
mov bp, (MAX_JABBER-14) ; BP = RBDBufSize.
FixNoRBDNotProm:
add di, bp ; DI -> Right RBD.
mov [si].URBDOffset, di ; Fix FD to point to empty RBD.
mov bp, 0c000h ; Set EOF(End Of Frm) & F, but
mov [di+0], bp ; clear ActualCount(zero size).
jmp short FixNoRBDCaseReturn
endif
ENDIF
ReceiveAllTooBig:
StatisticsUpdate PacketRxTooBigCount
or ax, 100h ; Set ASPEC TooBig err Status.
;; or ax, 10h ; Set CSPEC TooBig error Status.
call CheckForDeformedPacket ; Check if pkt also malformed.
jmp ReceiveCheckTooBig ; Continue processing.
ReceiveAllPackets:
test ah, 3 ; Rx Overrun/Frame Overflow?
jne TooLargeAPacket ; Jump if so (Bits S8/S9 set).
IFNDEF NE3200P
if SupportJabber
mov di, [si].URBDOffset
cmp di, -1 ; 14 byte packet?
je FixNoRBDCase ; Jump if so.
mov bp, [di+0] ; CX= EOF/F/ActualCount of RBD.
FixNoRBDCaseReturn:
else
mov bp, [si].RBDStatus ; CX= EOF/F/ActualCount of RBD.
endif
and bp, 3FFFh ; Mask off status to get size.
add bp, 14 ; Add media header size.
mov RcvFrameSize, bp ; Save for CopyPacketToHost.
ENDIF
mov bx, ax ; Get frm status reported by 586.
ReceiveAllCheckAlignCRC:
and ax, 0400h ; Extract Alignment Err bit
shr ax, 9 ; Position Align per ASPEC
and bx, 0800h ; Extract CRC Err bit
shr bx, 11 ; Position CRC per ASPEC
or ax, bx ; AX= Initialize the Status.
ReceiveAllCheckShort:
cmp bp, 60 ; Runt? (64- 4 FCS bytes = 60).
jae ReceiveAllCheckBig ; Jump if not.
or al, 04h ; Set Runt Packet Error.
ReceiveAllCheckBig:
cmp bp, 1514 ; Too Big?
jbe ReceiveCheckTooBig ; Jump if No (Continue processing).
jmp short ReceiveAllTooBig ; Frame is too big (Set err bit).
ErrorPacketSlide:
StatisticsUpdate PacketSlideCount
; 586 accepted a frame where DestAdr(DA) isn't
jmp ReStart586 ; a multicast nor does the DA match our IA.
PacketOverMax:
StatisticsUpdate PacketRxTooBigCount
jmp ReStart586
TooLargeAPacket:
jmp short ReLinkFD
TooShort:
StatisticsUpdate PacketRxTooSmallCount ; Update counters.
StatisticsUpdate PacketRxMiscErrorCount
jmp short ReLinkFD
;***********************************************************************\
; *
; ProcessFRInterrupt - If frame was received successfully, call *
; CopyPacketToHost routine to transfer to the host HSM. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Destroyed *
; SI = Not Used SI = Destroyed *
; DI = Not Used DI = Destroyed *
; *
;***********************************************************************/
even
ProcessFRInterrupt proc
IF DEBUG
mov al, 'R'
call OutChar
ENDIF
mov si, FDHead ; SI -> Next Rx Frame.
mov ax, [si].UFDStatus ; AX = Frame Status.
test ah, 80h ; Frame Complete ?
jz short PFRIntExit ; Jump if no.
ReceiveLoop:
IFNDEF NE3200P
cmp PromiscuousMode, 0
jne ReceiveAllPackets ; Jump if in promiscuous.
call CheckPacketSlide ; Is frame Broad/MultiCast or
; matches our IA (node adr)?
jne ErrorPacketSlide ; Restart the 586 (hardware err).
ELSE
call ProcessRBDLenCopyFrameHdr ; BP = Packet size (Actual-
; counts + hdr size of 14).
cmp PromiscuousMode, 0
jne ReceiveAllPackets ; Jump if in promiscuous.
ENDIF
cmp ax, 0A000h ; Frame received OK ?
jne ReLinkFD ; Jump if not.
ReceiveOK:
mov ax, es ; AX = 0 (Init to good status).
IFNDEF NE3200P
if SupportJabber
mov di, [si].URBDOffset
mov bp, [di+0] ; BP= EOF/F/ActualCount of RBD.
else
mov bp, [si].RBDStatus ; BP= EOF/F/ActualCount of RBD.
endif
and bp, 3FFFh ; Mask off the EOF/F bits.
add bp, 14 ; Add media hdr for total
; byte size of frame.
mov RcvFrameSize, bp ; Save for CopyPacketToHost.
ENDIF
cmp bp, 60 ; Frm too short? (64-4 FCS bytes).
IF DEBUG
jae NotTooShort
jmp TooShort
NotTooShort:
ELSE
jb TooShort ; Jump if so.
ENDIF
cmp bp, 1514
ja PacketOverMax
ReceiveCheckTooBig: ; AX = Frame error status
IFNDEF NE3200P ; Ne3200P already tested this.
cmp bp, MaxReceivePacketLength ; Over max allowed by the OS?
ja ReLinkFD; TooLargeAPacket ; Jump if so (ReLink the FD).
;-----------------------------------------------------------------------\
; *
; During frame reception the 82586 copies the frame header into the *
; Frame Descriptor (FD) starting at UniReceiveBuf.UFDDestination. The *
; HSM driver requires the header to precede frame data (info field). *
; Therefore we copy the header ahead of the frame's info field. *
; *
;-----------------------------------------------------------------------/
lea di, [si].UHeader ;
lea si, [si].UFDDestination ; SI -> Media header in FDesc.
mov cx, 14 / 2 ; Copy 14 bytes of frame hdr.
rep movsw ; Movsw increments SI to point
; to UniReceiveBuf.URCB.
mov word ptr [si].ARDriverWorkSpace, es ; Assume Non 802.2 (2nd byte=0).
;-----------------------------------------------------------------------\
; *
; On the host (see DriverISR procedure), ARESREBXValue is the first *
; dword of RProtocolWorkspace where the frame's error status is saved. *
; The second dword of RProtocolWorkspace is the frame's byte length. *
; *
;-----------------------------------------------------------------------/
mov word ptr [si].ARESREBXValue, ax ; RProtocolWorkspace's 1st
mov word ptr [si].ARESREBXValue+2, es ; dword (error status).
mov [si].ARSocket, bp ; RProtocolWorkspace's 2nd
mov [si].ARProtocolWorkspaceRest, es ; dword (frame size).
ELSE ; NE3200Promisc. code
or word ptr RCB_TEMPLATE.ARESREBXValue, ax ; Save any error status.
; (Other values already setup).
ENDIF
cmp NextEmptyRCB+2, -1 ; Hi adr of host ECB (RCB) -1?
je CheckHostForRCB ; Jump if yes (We need an RCB!).
ReceiveECBsOK:
IFNDEF NE3200P
mov bx, si ; BX -> RCB structure template.
; BP = Frame size (AX=Err Status).
call CopyPacketToHost ; Setup to copy packet to host.
ReLinkFD:
mov si, FDHead ; SI ->Just processed Rx Frame.
;;;;;
;;if SupportJabber
; mov ax, (RBuffSize-14) or 8000h ; Setup Non-jabber buff size.
; cmp PromiscuousMode, 0 ; Promiscuous mode on?
; je ReLinkSizeNotProm ; Jump if not.
;
; mov ax, (MAX_JABBER-14) or 8000h ; AX = RBDBufSize (jabber).
;
;ReLinkSizeNotProm:
; mov di, [si].URBDOffset ; Setup data buffer size.
; mov [si+8], ax ;;; Should be di not si.
;else
; mov [si].RBDBufSize, RBuffSize or 8000h ; Set Size/EL.
;endif
ELSE ; Ne3200Promisc code
; BP = Frame size (AX=Err Status).
lea bx, RCB_TEMPLATE ; BX -> RCB structure template.
call CopyPacketToHost ; Setup to copy packet to host.
ReLinkFD:
cmp RBDTotalSize, 14 ; Very small runt with no RBD?
jbe short LinkRBDDone ; Jump if Yes.
mov si, RBDEnd ; Get last RBD of previous rcv frm.
lea di, [si + size RBDStruct] ; DI->1st RBD of just processed frm.
cmp di, BufferHead ; Past the last RBD? (Do we
; need to wrap the RBD ptr?).
jb LinkToNextRBD ; Jump if not.
mov di, RBDHead ; DI -> Start of RBD buffers.
LinkToNextRBD:
mov [si].RBDLink, di ; Link last RBD of previous rcv
; frm to 1st RBD of just processed.
mov [si].RBDBufSize, 256 ; Clear EL bit in previous RCB.
mov si, RBDLast ; Last RBD of just processed frm.
mov RBDEnd, si ; RBDEnd->New last RBD of
; previous rcv frame.
LinkRBDDone:
mov si, FDHead ; SI->FD of just processed frm.
mov [si].UFDRBDOffset, -1 ; Indicate no RBD is linked.
ENDIF
mov [si].UFDCommand, 8000h ; Just processed frm is the
; new EL (End of List).
mov [si].UFDStatus, es ; Zero status of just processed.
mov bx, FDEnd ; BX -> Get old last frame.
mov [bx].UFDCommand, es ; Zero EL bit in old last frm.
mov FDEnd, si ; FDEnd-> Just processed frame.
mov si, [si].UFDLink ; SI -> Next new frame rec'd.
mov FDHead, si ; Save new rcv frame list head.
mov ax, [si].UFDStatus ; AX = Status of new rcv frame.
test ah, 80h ; New frame completely rec'd?
jnz ReceiveLoop ; Jmp if so (Process new frm).
PFRIntExit:
;
; Fall thru to RUStart.
;
ProcessFRInterrupt endp
;***********************************************************************\
; *
; RUStart - Start the Receive Unit. We only attempt to start the RU if *
; it is Not already in the READY state. *
; *
;***********************************************************************<
; *
; On Entry: On Exit: *
; AX = Not Used AX = Destroyed *
; BX = Not Used BX = Destroyed *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Destroyed *
; BP = Not Used BP = Preserved *
; SI = Not Used SI = Preserved *
; DI = Not Used DI = Preserved *
; *
; On Exit: If the RU was started okay or if it was already in the *
; READY state then the ZeroFlag (ZF) = 1 indicating success. *
; *
;***********************************************************************/
even
RUStart proc
mov ax, ds:SCB.SCBStatus ; AX = SCB Status.
and al, 70h ; Extract the RUStatus bits.
cmp al, 40h ; Is RecUnit already Ready?
je RUStartExit ; Jmp if So (We're done).
mov bx, FDHead ; BX -> First frame.
mov cx, es ; Set loop counter (Init to 0).
RUWaitForCommand:
cmp ds: SCB.SCBCommand, 0 ; Previous command finished?
loopne RUWaitForCommand ; Loop if not (CX !=0 & ZF=0).
jne RUStartExit ; 586 might be hosed.
mov ds: SCB.RFAOffset, bx ; Set RFA offset.
mov ds: SCB.SCBCommand, 10h ; Start RU command.
mov dx, CA_PORT ; Tug on the 82586's
out dx, al ; channel attention.
RUStartExit:
ret ; Exit
RUStart endp
;***********************************************************************\
; *
; CheckHostForRCB *
; *
;***********************************************************************<
CheckHostForRCB:
; BP= Frame size (Don't use it).
mov dx, BMIC_INDEX ; We need more RCBs from
mov al, PEEK_POKE_ADDR OR AUTO_INC ; the host or we discard
out dx, al ; this frame.
mov dx, BMIC_DATA ;
mov bx, RCBListPointer + 2 ; BX -> host RCB List.
mov ax, RCBIndex ; AX = Index into list.
shl ax, 2 ; AX = Index * 4.
add ax, RCBListPointer ; Add to base of list.
adc bx, 0 ; BX:AX -> Next RCB slot.
out dx, al ; Set addr 0.
mov al, ah ;
out dx, al ; Set addr 1.
mov ax, bx ;
out dx, al ; Set addr 2.
mov al, ah ;
out dx, al ; Set addr 3.
mov dx, BMIC_INDEX ; Set index to peek poke
mov al, PEEK_POKE_CONTROL ; control register.
out dx, al ;
mov dx, BMIC_DATA ; DX = BMIC Data Port.
mov al, 01011111b ; Set Peek and
out dx, al ; start it.
mov dx, BMIC_STATUS ; DX = BMIC Status/Control.
WaitForPeek1: ;
in al, dx ; Read BMIC status.
test al, PEEK_POKE_PENDING ; Peek/Poke pending?
jnz WaitForPeek1 ; Jump if so.
mov al, PEEK_POKE_DATA OR AUTO_INC ; Set index to Peek Poke
mov dx, BMIC_INDEX ; data port.
out dx, al
mov dx, BMIC_DATA ; DX = BMIC Data port.
mov di, offset NextEmptyRCB ; DI -> Local buffer.
mov cx, 4 ;
rep insb ; Read four bytes of RCB adr.
cmp NextEmptyRCB+2, -1 ; Does host have a valid RCB
; for us to copy rcv frame to?
je NoRCBAvailable ; Jump if No
jmp ReceiveECBsOK ; Jump if Yes.
NoRCBAvailable:
InterruptTheHost ; Still need an RCB.
IFDEF NE3200P
StatisticsUpdate PacketRxOverflowCount
StatisticsUpdate PacketRxMiscErrorCount
ENDIF
jmp ReLinkFD ; Discard this frame and exit.
IFNDEF NE3200P
;***********************************************************************\
; *
; CheckPacketSlide - verify the 586 hardware correctly received a frm. *
; This check is done due to an Errata condition. *
; *
;***********************************************************************/
; *
; On Entry: On Exit: *
; AX = Not Used AX = Unused *
; BX = Not Used BX = Unused *
; CX = Not Used CX = Destroyed *
; DX = Not Used DX = Unused *
; BP = Not Used BP = Unused *
; SI = @ UniReceiveBuf struct SI = Preserved *
; DI = Not Used DI = Unused *
; *
;***********************************************************************/
; *
even
CheckPacketSlide proc
test [si].UFDDestination+0, 01 ; Group bit set?
jne ReceiveCheckOK ; Jump if yes.
mov cx, word ptr [si].UFDDestination+0
cmp cx, word ptr BoardID+0
jne CheckSlideError
mov cx, word ptr [si].UFDDestination+2
cmp cx, word ptr BoardID+2
jne CheckSlideError
mov cx, word ptr [si].UFDDestination+4
cmp cx, word ptr BoardID+4
CheckSlideError:
ret
ReceiveCheckOK:
xor cl, cl
ret ; return
CheckPacketSlide endp
ENDIF
IFDEF NE3200P
;***********************************************************************\
; *
; ProcessRBDLenCopyFrameHdr - Ne3200Promisc code. *
; Follow the RBD links to add up the total frame size (ActualCounts). *
; Note: RBD's point to data buffers of 256 bytes in size. *
; Then check frame size and copy the frame hdr into the RCB template *
; Setting up some of the RCB template helps out CopyPacketToHost *
; *
;***********************************************************************/
; *
even
ProcessRBDLenCopyFrameHdr proc
mov di, [si].UFDRBDOffset ; DI -> First RBD.
mov bp, 14 ; Start with size of MAC hdr.
mov RBDSizeBeforeWrap, 0
mov RBDSizeAfterWrap, 0
mov RBDWrappedFlag, 0
cmp di, -1 ; Did the FD use an RBD?
je ProcessRBDSmallRunt ; Jump if NO (Very short runt).
ProcessRBDLoop:
mov dx, [di].RBDStatus ; DX= EOF/F/ActualCount of RBD.
and dh, 3fh ; Remove EOF(End Of Frame) & F.
add bp, dx ; BP = Total byes so far.
cmp RBDWrappedFlag, 0 ; Did data buffers wrap from
; last one to the 1st yet?
jne ProcessRBDWrapped ; Jump if so.
add RBDSizeBeforeWrap, dx ; Add to before wrap value.
ProcessRBDBackFromWrap:
test [di].RBDStatus, 8000h ; End Of Frame (EOF)?
jne ProcessRBDFoundEOF ; Jump if so.
cmp [di].RBDLink, di ; Will RBD wrap next time?
ja ProcessRBDLink ; Jump if not
mov RBDWrappedFlag, 1 ; Set the wrapped flag.
StatisticsUpdate RBDWrappedCount
ProcessRBDLink:
mov di, [di].RBDLink ; DI -> Next RBD.
jmp ProcessRBDLoop ; Jump if not.
ProcessRBDWrapped:
add RBDSizeAfterWrap, dx ; Add to after wrap value.
jmp ProcessRBDBackFromWrap
ProcessRBDFoundEOF:
mov RBDTotalSize, bp ; Save total frame size.
mov [di].RBDBufSize, 256 OR 8000h ; Set EL (End of List) bit.
mov [di].RBDLink, DUMMY_RCB
mov RBDLast, di ; Save for receive complete.
cmp bp, MaxReceivePacketLength ; Over max allowed by the OS?
ja ProcessRBDOverMax ; Jump if So (Ignore Frame).
ProcessRBDSetup:
mov di, [si].UFDRBDOffset ; DI -> First RBD.
mov SaveRDBOffset, di ; Save ptr to first RBD.
lea bx, RCB_TEMPLATE ; BX -> RCB structure template.
lea si, [si].UFDDestination ;
lea di, [bx+size AReceiveBufferStructure] ; DI -> RCVMACDest.
mov cx, 14 / 2 ; Copy 14 bytes of hdr (DA/SA/len).
rep movsw
mov word ptr [bx].ARDriverWorkSpace + 1, es ; Assume Non 802.2. frm.
mov word ptr [bx].ARESREBXValue, es ; RProtocolWorkspace's 1st
mov word ptr [bx].ARESREBXValue+2, es ; dword (assume no err status).
mov [bx].ARSocket, bp ; RProtocolWorkspace's 2nd
mov [bx].ARProtocolWorkspaceRest, es ; dword (frame size).
ret ; Exit - Continue processing.
ProcessRBDOverMax:
jmp ReLinkFD ; Ignore frame -Relink the FD.
;---------------------------------------------------------------\
; *
; The 82586 does not accept frames that are smaller than 14 *
; bytes. So if the FD does not point to a RBD (i.e. -1) then *
; the frame only had a DA, SA and a Length field (frm size =14).*
; *
;---------------------------------------------------------------/
ProcessRBDSmallRunt:
mov RBDTotalSize, bp ; 14 = Save total Frame size.
mov [si].UFDRBDOffset, DUMMY_RCB ; DI -> Dummy First RBD.
jmp short ProcessRBDSetup ;
ProcessRBDLenCopyFrameHdr endp
ENDIF
IF DEBUG
;
; OutChar
;
; AL = Debug Char
;
; Register AX modified
;
even
OutChar proc
push si
mov si, CurDiagOffset
mov DiagBuffer[si], al
mov byte ptr DiagBuffer[si+1], '*'
inc si
and si, 0fh
mov CurDiagOffset, si
jz UpdateHostDebugBuffer
pop si
ret
UpdateHostDebugBuffer:
push cx
push dx
mov si, offset DiagnosticSequence ; SI -> Preset sequence.
BMICTransferWithLocal
pop dx
pop cx
;; add word ptr StatisticCounters.RxAbortFrameAlignment, 1
;; adc word ptr StatisticCounters.RxAbortFrameAlignment+2, 0
add DiagnosticOffsetLo, 10h
adc DiagnosticOffsetHi, 0
dec HostDiagSegCount
jz ResetHostDiagOffset
pop si
ret
ResetHostDiagOffset:
mov ax, DiagnosticBufferPointer
mov DiagnosticOffsetLo, ax
mov ax, DiagnosticBufferPointer+2
mov DiagnosticOffsetHi, ax
mov HostDiagSegCount, 1000h/10h
pop si
ret
OutChar endp
;
; OutWord
;
; Put a word value to the screen
;
; AX = word value
;
even
OutWord proc
push cx
push dx
mov dx, ax
; Now output the counter
mov cx, 0404h
PrintWordLoop:
rol dx, cl
mov al, dl
and al, 0Fh
add al, 90h ; Convert hex digit to ascii
daa
adc al, 40h
daa
call OutChar
dec ch
jnz PrintWordLoop
pop dx
pop cx
ret
OutWord endp
ENDIF
CODE ends
end