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