1PAGE 60,132 2NAME PKT_RX 3 4ifdef ??version ; using TASM 5 masm 6 jumps 7endif 8 9PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf, _pktTemp 10PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd 11 12; 13; these sizes MUST be equal to the sizes in PKTDRVR.H 14; 15 16RX_BUF_SIZE = 1500 ; max message size on Ethernet 17TX_BUF_SIZE = 1500 18 19ifdef DOSX 20 .386 21 NUM_RX_BUF = 32 ; # of RX element buffers 22 _TEXT SEGMENT PUBLIC DWORD USE16 'CODE' 23 _TEXT ENDS 24 _DATA SEGMENT PUBLIC DWORD USE16 'CODE' 25 _DATA ENDS 26 D_SEG EQU <_TEXT SEGMENT> 27 D_END EQU <_TEXT ENDS> 28 ASSUME CS:_TEXT,DS:_TEXT 29else 30 .286 31 NUM_RX_BUF = 10 32 _TEXT SEGMENT PUBLIC DWORD 'CODE' 33 _TEXT ENDS 34 _DATA SEGMENT PUBLIC DWORD 'DATA' 35 _DATA ENDS 36 D_SEG EQU <_DATA SEGMENT> 37 D_END EQU <_DATA ENDS> 38 ASSUME CS:_TEXT,DS:_DATA 39endif 40 41;------------------------------------------- 42 43D_SEG 44 45RX_ELEMENT STRUC 46 firstCount dw 0 ; # of bytes on 1st call 47 secondCount dw 0 ; # of bytes on 2nd call 48 handle dw 0 ; handle for upcall 49 destinAdr db 6 dup (0) ; packet destination address 50 sourceAdr db 6 dup (0) ; packet source address 51 protocol dw 0 ; packet protocol number 52 rxBuffer db RX_BUF_SIZE dup (0) ; RX buffer 53ENDS 54 align 4 55_rxOutOfs dw offset _pktRxBuf ; ring buffer offsets 56_rxInOfs dw offset _pktRxBuf ; into _pktRxBuf 57_pktDrop dw 0,0 ; packet drop counter 58_pktTemp db 20 dup (0) ; temp work area 59_pktTxBuf db (TX_BUF_SIZE+14) dup (0) ; TX buffer 60_pktRxBuf RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures 61 LAST_OFS = offset $ 62 63 screenSeg dw 0B800h 64 newInOffset dw 0 65 66 fanChars db '-\|/' 67 fanIndex dw 0 68 69D_END 70 71_TEXT SEGMENT 72 73 74SHOW_RX MACRO 75 push es 76 push bx 77 mov bx, screenSeg 78 mov es, bx ;; r-mode segment of colour screen 79 mov di, 158 ;; upper right corner - 1 80 mov bx, fanIndex 81 mov al, fanChars[bx] ;; get write char 82 mov ah, 15 ;; and white colour 83 stosw ;; write to screen at ES:EDI 84 inc fanIndex ;; update next index 85 and fanIndex, 3 86 pop bx 87 pop es 88ENDM 89 90;------------------------------------------------------------------------ 91; 92; This macro return ES:DI to tail of Rx queue 93 94ENQUEUE MACRO 95 LOCAL @noWrap 96 mov ax, _rxInOfs ;; DI = current in-offset 97 add ax, SIZE RX_ELEMENT ;; point to next _pktRxBuf buffer 98 cmp ax, LAST_OFS ;; pointing past last ? 99 jb @noWrap ;; no - jump 100 lea ax, _pktRxBuf ;; yes, point to 1st buffer 101 align 4 102@noWrap: cmp ax, _rxOutOfs ;; in-ofs = out-ofs ? 103 je @dump ;; yes, queue is full 104 mov di, _rxInOfs ;; ES:DI -> buffer at queue input 105 mov newInOffset, ax ;; remember new input offset 106 107 ;; NOTE. rxInOfs is updated after the packet has been copied 108 ;; to ES:DI (= DS:SI on 2nd call) by the packet driver 109 110ENDM 111 112;------------------------------------------------------------------------ 113; 114; This routine gets called by the packet driver twice: 115; 1st time (AX=0) it requests an address where to put the packet 116; 117; 2nd time (AX=1) the packet has been copied to this location (DS:SI) 118; BX has client handle (stored in RX_ELEMENT.handle). 119; CX has # of bytes in packet on both call. They should be equal. 120; 121; A test for equality is done by putting CX in _pktRxBuf [n].firstCount 122; and _pktRxBuf[n].secondCount, and CL on first call in 123; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive" 124; (PKTDRVR.C) 125; 126;--------------------------------------------------------------------- 127 128_PktReceiver: 129 pushf 130 cli ; no distraction wanted ! 131 push ds 132 push bx 133ifdef DOSX 134 mov bx, cs 135else 136 mov bx, SEG _DATA 137endif 138 mov ds, bx 139 mov es, bx ; ES = DS = CS or seg _DATA 140 pop bx ; restore handle 141 142 cmp ax, 0 ; first call? (AX=0) 143 jne @post ; AX=1: second call, do post process 144 145ifdef DEBUG 146 SHOW_RX ; show that a packet is received 147endif 148 cmp cx, RX_BUF_SIZE+14 ; size OK ? 149 ja @skip ; no, packet to large for us 150 151 ENQUEUE ; ES:DI -> _pktRxBuf[n] 152 153 mov [di].firstCount, cx ; remember the first count. 154 mov [di].handle, bx ; remember the handle. 155 add di, 6 ; ES:DI -> _pktRxBuf[n].destinAdr 156 pop ds 157 popf 158 retf ; far return to driver with ES:DI 159 160 align 4 161@dump: inc _pktDrop[0] ; discard the packet on 1st call 162 adc _pktDrop[2], 0 ; increment packets lost 163 164@skip: xor di, di ; return ES:DI = NIL pointer 165 xor ax, ax 166 mov es, ax 167 pop ds 168 popf 169 retf 170 171 align 4 172@post: or si, si ; DS:SI->_pktRxBuf[n][n].destinAdr 173 jz @discard ; make sure we don't use NULL-pointer 174 175 sub si, 6 ; DS:SI -> _pktRxBuf[n].destinAdr 176 ; 177 ; push si 178 ; push [si].firstCount 179 ; call bpf_filter_match ; run the filter here some day? 180 ; add sp, 4 181 ; cmp ax, 0 182 ; je @discard 183 184 mov [si].secondCount, cx 185 mov ax, newInOffset 186 mov _rxInOfs, ax ; update _pktRxBuf input offset 187 188 align 4 189@discard:pop ds 190 popf 191 retf 192 193_pktRxEnd db 0 ; marker for end of r-mode code/data 194 195_TEXT ENDS 196 197END 198