; ; This file requires NASM 0.97+ to assemble ; ; Currently used only for djgpp + DOS4GW targets ; ; these sizes MUST be equal to the sizes in PKTDRVR.H ; %define ETH_MTU 1500 ; max data size on Ethernet %define ETH_MIN 60 ; min/max total frame size %define ETH_MAX (ETH_MTU+2*6+2) ; =1514 %define NUM_RX_BUF 32 ; # of RX element buffers %define RX_SIZE (ETH_MAX+6) ; sizeof(RX_ELEMENT) = 1514+6 %idefine offset struc RX_ELEMENT .firstCount resw 1 ; # of bytes on 1st call .secondCount resw 1 ; # of bytes on 2nd call .handle resw 1 ; handle for upcall ; .timeStamp resw 4 ; 64-bit RDTSC value .destinAdr resb 6 ; packet destination address .sourceAdr resb 6 ; packet source address .protocol resw 1 ; packet protocol number .rxBuffer resb ETH_MTU ; RX buffer endstruc ;------------------------------------------- [org 0] ; assemble to .bin file _rxOutOfs dw offset _pktRxBuf ; ring buffer offsets _rxInOfs dw offset _pktRxBuf ; into _pktRxBuf _pktDrop dw 0,0 ; packet drop counter _pktTemp resb 20 ; temp work area _pktTxBuf resb (ETH_MAX) ; TX buffer _pktRxBuf resb (RX_SIZE*NUM_RX_BUF) ; RX structures LAST_OFS equ $ screenSeg dw 0B800h newInOffset dw 0 fanChars db '-\|/' fanIndex dw 0 %macro SHOW_RX 0 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 cld ;; Needed? stosw ;; write to screen at ES:EDI inc word [fanIndex] ;; update next index and word [fanIndex], 3 pop bx pop es %endmacro ;PutTimeStamp ; rdtsc ; mov [si].timeStamp, eax ; mov [si+4].timeStamp, edx ; ret ;------------------------------------------------------------------------ ; ; 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 mov bx, cs 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, ETH_MAX ; size OK ? ja @skip ; no, too big mov ax, [_rxInOfs] add ax, RX_SIZE cmp ax, LAST_OFS jb @noWrap mov ax, offset _pktRxBuf @noWrap: cmp ax, [_rxOutOfs] je @dump mov di, [_rxInOfs] ; ES:DI -> _pktRxBuf[n] mov [newInOffset], ax mov [di], cx ; remember firstCount. mov [di+4], bx ; remember handle. add di, 6 ; ES:DI -> _pktRxBuf[n].destinAdr pop ds popf retf ; far return to driver with ES:DI @dump: add word [_pktDrop+0], 1 ; discard the packet on 1st call adc word [_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 @post: or si, si ; DS:SI->_pktRxBuf[n][n].destinAdr jz @discard ; make sure we don't use NULL-pointer ; ; push si ; call bpf_filter_match ; run the filter here some day ; pop si ; cmp ax, 0 ; je @discard mov [si-6+2], cx ; store _pktRxBuf[n].secondCount mov ax, [newInOffset] mov [_rxInOfs], ax ; update _pktRxBuf input offset ; call PutTimeStamp @discard: pop ds popf retf _pktRxEnd db 0 ; marker for end of r-mode code/data END