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