1 PAGE 60,132 2 NAME PKT_RX 3 4 ifdef ??version ; using TASM 5 masm 6 jumps 7 endif 8 9 PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf, _pktTemp 10 PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd 11 12 ; 13 ; these sizes MUST be equal to the sizes in PKTDRVR.H 14 ; 15 16 RX_BUF_SIZE = 1500 ; max message size on Ethernet 17 TX_BUF_SIZE = 1500 18 19 ifdef 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 29 else 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 39 endif 40 41 ;------------------------------------------- 42 43 D_SEG 44 45 RX_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 53 ENDS 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 69 D_END 70 71 _TEXT SEGMENT 72 73 74 SHOW_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 88 ENDM 89 90 ;------------------------------------------------------------------------ 91 ; 92 ; This macro return ES:DI to tail of Rx queue 93 94 ENQUEUE 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 110 ENDM 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 133 ifdef DOSX 134 mov bx, cs 135 else 136 mov bx, SEG _DATA 137 endif 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 145 ifdef DEBUG 146 SHOW_RX ; show that a packet is received 147 endif 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 197 END 198