1;
2; This file requires NASM 0.97+ to assemble
3;
4; Currently used only for djgpp + DOS4GW targets
5;
6; these sizes MUST be equal to the sizes in PKTDRVR.H
7;
8%define  ETH_MTU     1500                  ; max data size on Ethernet
9%define  ETH_MIN     60                    ; min/max total frame size
10%define  ETH_MAX     (ETH_MTU+2*6+2)       ; =1514
11%define  NUM_RX_BUF  32                    ; # of RX element buffers
12%define  RX_SIZE     (ETH_MAX+6)           ; sizeof(RX_ELEMENT) = 1514+6
13%idefine offset
14
15struc RX_ELEMENT
16      .firstCount  resw 1                  ; # of bytes on 1st call
17      .secondCount resw 1                  ; # of bytes on 2nd call
18      .handle      resw 1                  ; handle for upcall
19    ; .timeStamp   resw 4                  ; 64-bit RDTSC value
20      .destinAdr   resb 6                  ; packet destination address
21      .sourceAdr   resb 6                  ; packet source address
22      .protocol    resw 1                  ; packet protocol number
23      .rxBuffer    resb ETH_MTU            ; RX buffer
24endstruc
25
26;-------------------------------------------
27
28[org 0]  ; assemble to .bin file
29
30_rxOutOfs   dw   offset _pktRxBuf          ; ring buffer offsets
31_rxInOfs    dw   offset _pktRxBuf          ; into _pktRxBuf
32_pktDrop    dw   0,0                       ; packet drop counter
33_pktTemp    resb 20                        ; temp work area
34_pktTxBuf   resb (ETH_MAX)                 ; TX buffer
35_pktRxBuf   resb (RX_SIZE*NUM_RX_BUF)      ; RX structures
36 LAST_OFS   equ  $
37
38screenSeg   dw  0B800h
39newInOffset dw  0
40
41fanChars    db  '-\|/'
42fanIndex    dw  0
43
44%macro SHOW_RX 0
45       push es
46       push bx
47       mov bx, [screenSeg]
48       mov es, bx                    ;; r-mode segment of colour screen
49       mov di, 158                   ;; upper right corner - 1
50       mov bx, [fanIndex]
51       mov al, [fanChars+bx]         ;; get write char
52       mov ah, 15                    ;;  and white colour
53       cld                           ;; Needed?
54       stosw                         ;; write to screen at ES:EDI
55       inc word [fanIndex]           ;; update next index
56       and word [fanIndex], 3
57       pop bx
58       pop es
59%endmacro
60
61;PutTimeStamp
62;       rdtsc
63;       mov [si].timeStamp, eax
64;       mov [si+4].timeStamp, edx
65;       ret
66
67
68;------------------------------------------------------------------------
69;
70; This routine gets called by the packet driver twice:
71;   1st time (AX=0) it requests an address where to put the packet
72;
73;   2nd time (AX=1) the packet has been copied to this location (DS:SI)
74;   BX has client handle (stored in RX_ELEMENT.handle).
75;   CX has # of bytes in packet on both call. They should be equal.
76; A test for equality is done by putting CX in _pktRxBuf [n].firstCount
77; and _pktRxBuf[n].secondCount, and CL on first call in
78; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"
79; (PKTDRVR.C)
80;
81;---------------------------------------------------------------------
82
83_PktReceiver:
84         pushf
85         cli                         ; no distraction wanted !
86         push ds
87         push bx
88         mov bx, cs
89         mov ds, bx
90         mov es, bx                  ; ES = DS = CS or seg _DATA
91         pop bx                      ; restore handle
92
93         cmp ax, 0                   ; first call? (AX=0)
94         jne @post                   ; AX=1: second call, do post process
95
96%ifdef DEBUG
97         SHOW_RX                     ; show that a packet is received
98%endif
99
100         cmp cx, ETH_MAX             ; size OK ?
101         ja  @skip                   ; no, too big
102
103         mov ax, [_rxInOfs]
104         add ax, RX_SIZE
105         cmp ax, LAST_OFS
106         jb  @noWrap
107         mov ax, offset _pktRxBuf
108@noWrap:
109         cmp ax, [_rxOutOfs]
110         je  @dump
111         mov di, [_rxInOfs]          ; ES:DI -> _pktRxBuf[n]
112         mov [newInOffset], ax
113
114         mov [di], cx                ; remember firstCount.
115         mov [di+4], bx              ; remember handle.
116         add di, 6                   ; ES:DI -> _pktRxBuf[n].destinAdr
117         pop ds
118         popf
119         retf                        ; far return to driver with ES:DI
120
121@dump:   add word [_pktDrop+0], 1    ; discard the packet on 1st call
122         adc word [_pktDrop+2], 0    ; increment packets lost
123
124@skip:   xor di, di                  ; return ES:DI = NIL pointer
125         xor ax, ax
126         mov es, ax
127         pop ds
128         popf
129         retf
130
131@post:   or si, si                   ; DS:SI->_pktRxBuf[n][n].destinAdr
132         jz @discard                 ; make sure we don't use NULL-pointer
133
134       ;
135       ; push si
136       ; call bpf_filter_match       ; run the filter here some day
137       ; pop si
138       ; cmp ax, 0
139       ; je  @discard
140
141         mov [si-6+2], cx            ; store _pktRxBuf[n].secondCount
142         mov ax, [newInOffset]
143         mov [_rxInOfs], ax          ; update _pktRxBuf input offset
144
145       ; call PutTimeStamp
146
147@discard:
148         pop ds
149         popf
150         retf
151
152_pktRxEnd  db 0                      ; marker for end of r-mode code/data
153
154END
155
156