| 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 |