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 |