pkt_rx0.asm
5.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
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