You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.0 KiB
197 lines
6.0 KiB
PAGE 60,132 |
|
NAME PKT_RX |
|
|
|
ifdef ??version ; using TASM |
|
masm |
|
jumps |
|
endif |
|
|
|
PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf, _pktTemp |
|
PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd |
|
|
|
; |
|
; these sizes MUST be equal to the sizes in PKTDRVR.H |
|
; |
|
|
|
RX_BUF_SIZE = 1500 ; max message size on Ethernet |
|
TX_BUF_SIZE = 1500 |
|
|
|
ifdef DOSX |
|
.386 |
|
NUM_RX_BUF = 32 ; # of RX element buffers |
|
_TEXT SEGMENT PUBLIC DWORD USE16 'CODE' |
|
_TEXT ENDS |
|
_DATA SEGMENT PUBLIC DWORD USE16 'CODE' |
|
_DATA ENDS |
|
D_SEG EQU <_TEXT SEGMENT> |
|
D_END EQU <_TEXT ENDS> |
|
ASSUME CS:_TEXT,DS:_TEXT |
|
else |
|
.286 |
|
NUM_RX_BUF = 10 |
|
_TEXT SEGMENT PUBLIC DWORD 'CODE' |
|
_TEXT ENDS |
|
_DATA SEGMENT PUBLIC DWORD 'DATA' |
|
_DATA ENDS |
|
D_SEG EQU <_DATA SEGMENT> |
|
D_END EQU <_DATA ENDS> |
|
ASSUME CS:_TEXT,DS:_DATA |
|
endif |
|
|
|
;------------------------------------------- |
|
|
|
D_SEG |
|
|
|
RX_ELEMENT STRUC |
|
firstCount dw 0 ; # of bytes on 1st call |
|
secondCount dw 0 ; # of bytes on 2nd call |
|
handle dw 0 ; handle for upcall |
|
destinAdr db 6 dup (0) ; packet destination address |
|
sourceAdr db 6 dup (0) ; packet source address |
|
protocol dw 0 ; packet protocol number |
|
rxBuffer db RX_BUF_SIZE dup (0) ; RX buffer |
|
ENDS |
|
align 4 |
|
_rxOutOfs dw offset _pktRxBuf ; ring buffer offsets |
|
_rxInOfs dw offset _pktRxBuf ; into _pktRxBuf |
|
_pktDrop dw 0,0 ; packet drop counter |
|
_pktTemp db 20 dup (0) ; temp work area |
|
_pktTxBuf db (TX_BUF_SIZE+14) dup (0) ; TX buffer |
|
_pktRxBuf RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures |
|
LAST_OFS = offset $ |
|
|
|
screenSeg dw 0B800h |
|
newInOffset dw 0 |
|
|
|
fanChars db '-\|/' |
|
fanIndex dw 0 |
|
|
|
D_END |
|
|
|
_TEXT SEGMENT |
|
|
|
|
|
SHOW_RX MACRO |
|
push es |
|
push bx |
|
mov bx, screenSeg |
|
mov es, bx ;; r-mode segment of colour screen |
|
mov di, 158 ;; upper right corner - 1 |
|
mov bx, fanIndex |
|
mov al, fanChars[bx] ;; get write char |
|
mov ah, 15 ;; and white colour |
|
stosw ;; write to screen at ES:EDI |
|
inc fanIndex ;; update next index |
|
and fanIndex, 3 |
|
pop bx |
|
pop es |
|
ENDM |
|
|
|
;------------------------------------------------------------------------ |
|
; |
|
; This macro return ES:DI to tail of Rx queue |
|
|
|
ENQUEUE MACRO |
|
LOCAL @noWrap |
|
mov ax, _rxInOfs ;; DI = current in-offset |
|
add ax, SIZE RX_ELEMENT ;; point to next _pktRxBuf buffer |
|
cmp ax, LAST_OFS ;; pointing past last ? |
|
jb @noWrap ;; no - jump |
|
lea ax, _pktRxBuf ;; yes, point to 1st buffer |
|
align 4 |
|
@noWrap: cmp ax, _rxOutOfs ;; in-ofs = out-ofs ? |
|
je @dump ;; yes, queue is full |
|
mov di, _rxInOfs ;; ES:DI -> buffer at queue input |
|
mov newInOffset, ax ;; remember new input offset |
|
|
|
;; NOTE. rxInOfs is updated after the packet has been copied |
|
;; to ES:DI (= DS:SI on 2nd call) by the packet driver |
|
|
|
ENDM |
|
|
|
;------------------------------------------------------------------------ |
|
; |
|
; This routine gets called by the packet driver twice: |
|
; 1st time (AX=0) it requests an address where to put the packet |
|
; |
|
; 2nd time (AX=1) the packet has been copied to this location (DS:SI) |
|
; BX has client handle (stored in RX_ELEMENT.handle). |
|
; CX has # of bytes in packet on both call. They should be equal. |
|
; |
|
; A test for equality is done by putting CX in _pktRxBuf [n].firstCount |
|
; and _pktRxBuf[n].secondCount, and CL on first call in |
|
; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive" |
|
; (PKTDRVR.C) |
|
; |
|
;--------------------------------------------------------------------- |
|
|
|
_PktReceiver: |
|
pushf |
|
cli ; no distraction wanted ! |
|
push ds |
|
push bx |
|
ifdef DOSX |
|
mov bx, cs |
|
else |
|
mov bx, SEG _DATA |
|
endif |
|
mov ds, bx |
|
mov es, bx ; ES = DS = CS or seg _DATA |
|
pop bx ; restore handle |
|
|
|
cmp ax, 0 ; first call? (AX=0) |
|
jne @post ; AX=1: second call, do post process |
|
|
|
ifdef DEBUG |
|
SHOW_RX ; show that a packet is received |
|
endif |
|
cmp cx, RX_BUF_SIZE+14 ; size OK ? |
|
ja @skip ; no, packet to large for us |
|
|
|
ENQUEUE ; ES:DI -> _pktRxBuf[n] |
|
|
|
mov [di].firstCount, cx ; remember the first count. |
|
mov [di].handle, bx ; remember the handle. |
|
add di, 6 ; ES:DI -> _pktRxBuf[n].destinAdr |
|
pop ds |
|
popf |
|
retf ; far return to driver with ES:DI |
|
|
|
align 4 |
|
@dump: inc _pktDrop[0] ; discard the packet on 1st call |
|
adc _pktDrop[2], 0 ; increment packets lost |
|
|
|
@skip: xor di, di ; return ES:DI = NIL pointer |
|
xor ax, ax |
|
mov es, ax |
|
pop ds |
|
popf |
|
retf |
|
|
|
align 4 |
|
@post: or si, si ; DS:SI->_pktRxBuf[n][n].destinAdr |
|
jz @discard ; make sure we don't use NULL-pointer |
|
|
|
sub si, 6 ; DS:SI -> _pktRxBuf[n].destinAdr |
|
; |
|
; push si |
|
; push [si].firstCount |
|
; call bpf_filter_match ; run the filter here some day? |
|
; add sp, 4 |
|
; cmp ax, 0 |
|
; je @discard |
|
|
|
mov [si].secondCount, cx |
|
mov ax, newInOffset |
|
mov _rxInOfs, ax ; update _pktRxBuf input offset |
|
|
|
align 4 |
|
@discard:pop ds |
|
popf |
|
retf |
|
|
|
_pktRxEnd db 0 ; marker for end of r-mode code/data |
|
|
|
_TEXT ENDS |
|
|
|
END
|
|
|