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