summaryrefslogtreecommitdiffstats
path: root/lib/libpcap/libpcap/msdos/pkt_rx0.asm
blob: d604fa14be67f9e1e873e1e8afc53daf5de3c38a (plain) (blame)
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