Subversion Repositories Kolibri OS

Rev

Rev 9394 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
9017 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  ETHERNET.INC                                                   ;;
7
;;                                                                 ;;
8
;;  Ethernet network layer for KolibriOS                           ;;
9
;;                                                                 ;;
10
;;    Written by hidnplayr@kolibrios.org                           ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
4850 mario79 17
$Revision: 9395 $
3545 hidnplayr 18
 
19
ETH_FRAME_MINIMUM       = 60
3982 hidnplayr 20
ETH_QUEUE_SIZE          = 255
3545 hidnplayr 21
 
22
struct  ETH_header
23
 
24
        DstMAC          dp  ?  ; destination MAC-address
25
        SrcMAC          dp  ?  ; source MAC-address
26
        Type            dw  ?  ; type of the upper-layer protocol
27
 
28
ends
29
 
30
struct  ETH_DEVICE      NET_DEVICE
31
 
32
        mac             dp ?
33
 
34
ends
35
 
5522 hidnplayr 36
iglobal
37
align 4
3982 hidnplayr 38
 
5522 hidnplayr 39
        ETH_BROADCAST   dp 0xffffffffffff
3982 hidnplayr 40
 
5522 hidnplayr 41
        ETH_frame_queued        dd 0    ; Number of queued frames
3982 hidnplayr 42
 
5522 hidnplayr 43
        ETH_frame_head          dd ETH_frame_head       ; Pointer to next frame in the linked list
44
        ETH_frame_tail          dd ETH_frame_head       ; Pointer to last frame in the linked list
3545 hidnplayr 45
 
46
endg
47
 
3982 hidnplayr 48
uglobal
49
align 4
50
        ETH_input_event dd ?
51
endg
52
 
6011 hidnplayr 53
macro   eth_init {
3982 hidnplayr 54
 
55
        movi    ebx, 1
6011 hidnplayr 56
        mov     ecx, eth_process_input
3982 hidnplayr 57
        call    new_sys_threads
58
        test    eax, eax
59
        jns     @f
60
        DEBUGF  DEBUG_NETWORK_ERROR,'K : cannot create kernel thread for ethernet, error %d\n', eax
61
  @@:
62
 
63
}
64
 
3545 hidnplayr 65
align 4
9394 Boppan 66
; This function is called by ethernet drivers.
67
; Push the received ethernet packet onto the ethernet input queue.
68
;
69
;  Input:
9395 Boppan 70
;    [esp] = Pointer to buffer
71
;    [esp + 4] = Return address (yes, really)
9394 Boppan 72
;
73
;  Example:
74
;    push .retaddr
75
;    push buf_addr
76
;    jmp eth_input
6011 hidnplayr 77
eth_input:
3545 hidnplayr 78
 
5522 hidnplayr 79
        pop     eax
3982 hidnplayr 80
 
9017 hidnplayr 81
if defined NETWORK_SANITY_CHECKS
82
        cmp     eax, [net_buffs_low]
83
        jb      .assert_mbuff
84
        cmp     eax, [net_buffs_high]
85
        ja      .assert_mbuff
86
        test    eax, 0x7ff
87
        jnz     .assert_mbuff
88
end if
89
 
90
        spin_lock_irqsave
91
 
5522 hidnplayr 92
        cmp     [ETH_frame_queued], ETH_QUEUE_SIZE
93
        jae     .full
94
        inc     [ETH_frame_queued]
3982 hidnplayr 95
 
5522 hidnplayr 96
; Add frame to the end of the linked list
97
        mov     [eax + NET_BUFF.NextPtr], ETH_frame_head
98
 
99
        mov     ebx, [ETH_frame_tail]
100
        mov     [eax + NET_BUFF.PrevPtr], ebx
101
 
102
        mov     [ETH_frame_tail], eax
103
        mov     [ebx + NET_BUFF.NextPtr], eax
104
 
9017 hidnplayr 105
        spin_unlock_irqrestore
5522 hidnplayr 106
 
7536 hidnplayr 107
; Mark it as being an Ethernet Frame
108
        mov     [eax + NET_BUFF.type], NET_BUFF_ETH
109
 
5522 hidnplayr 110
; Now queue an event to process it
3982 hidnplayr 111
        xor     edx, edx
112
        mov     eax, [ETH_input_event]
113
        mov     ebx, [eax + EVENT.id]
114
        xor     esi, esi
115
        call    raise_event
116
 
117
        ret
118
 
5522 hidnplayr 119
  .full:
9017 hidnplayr 120
        mov     ebx, [eax + NET_BUFF.device]
121
        inc     [ebx + NET_DEVICE.packets_rx_ovr]
122
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ETH incoming queue is full, discarding packet!\n"
123
        spin_unlock_irqrestore
124
        stdcall net_buff_free, eax
3982 hidnplayr 125
        ret
126
 
9017 hidnplayr 127
if defined NETWORK_SANITY_CHECKS
128
  .assert_mbuff:
129
        DEBUGF  DEBUG_NETWORK_ERROR, "eth_input: invalid buffer 0x%x\n", eax
130
        DEBUGF  DEBUG_NETWORK_ERROR, "eth_input: caller=0x%x\n", [esp+4]
131
        xor     eax, eax
132
        ret
133
end if
3982 hidnplayr 134
 
135
 
9017 hidnplayr 136
 
6011 hidnplayr 137
;-----------------------------------------------------------------;
138
;                                                                 ;
139
; eth_process_input: Process packets from ethernet input queue.   ;
140
;                                                                 ;
141
;  IN:  /                                                         ;
142
;                                                                 ;
143
;  OUT: /                                                         ;
144
;                                                                 ;
145
;-----------------------------------------------------------------;
3982 hidnplayr 146
align 4
6011 hidnplayr 147
eth_process_input:
3982 hidnplayr 148
 
149
        xor     esi, esi
150
        mov     ecx, MANUAL_DESTROY
151
        call    create_event
152
        mov     [ETH_input_event], eax
5522 hidnplayr 153
        pushf
3982 hidnplayr 154
  .wait:
5522 hidnplayr 155
        popf
3982 hidnplayr 156
        mov     eax, [ETH_input_event]
157
        mov     ebx, [eax + EVENT.id]
158
        call    wait_event
159
 
160
  .loop:
5522 hidnplayr 161
        pushf
162
        cli
163
        cmp     [ETH_frame_queued], 0
164
        je      .wait
3982 hidnplayr 165
 
5522 hidnplayr 166
        dec     [ETH_frame_queued]
3982 hidnplayr 167
 
5522 hidnplayr 168
        mov     esi, [ETH_frame_head]
169
        mov     ebx, [esi + NET_BUFF.NextPtr]
3982 hidnplayr 170
 
5522 hidnplayr 171
        mov     [ETH_frame_head], ebx
172
        mov     [ebx + NET_BUFF.PrevPtr], ETH_frame_head
173
 
174
        popf
175
 
176
        mov     eax, [esi + NET_BUFF.offset]
177
        add     eax, esi
178
        mov     ecx, [esi + NET_BUFF.length]
179
        mov     ebx, [esi + NET_BUFF.device]
180
 
181
        pushd   .loop           ; return address for protocol handler
182
        push    esi             ; keep pointer to NET_BUFF on stack
183
 
3982 hidnplayr 184
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ETH_input: size=%u\n", ecx
3643 hidnplayr 185
        sub     ecx, sizeof.ETH_header
9017 hidnplayr 186
        jb      .err
3545 hidnplayr 187
 
5522 hidnplayr 188
; Set registers for protocol handlers
3545 hidnplayr 189
        lea     edx, [eax + sizeof.ETH_header]
190
        mov     ax, [eax + ETH_header.Type]
191
 
5522 hidnplayr 192
; Place protocol handlers here
3600 hidnplayr 193
        cmp     ax, ETHER_PROTO_IPv4
6011 hidnplayr 194
        je      ipv4_input
3545 hidnplayr 195
 
3601 hidnplayr 196
        cmp     ax, ETHER_PROTO_ARP
6011 hidnplayr 197
        je      arp_input
3545 hidnplayr 198
 
5001 hidnplayr 199
;        cmp     ax, ETHER_PROTO_IPv6
6011 hidnplayr 200
;        je      ipv6_input
3545 hidnplayr 201
 
5001 hidnplayr 202
;        cmp     ax, ETHER_PROTO_PPP_DISCOVERY
6011 hidnplayr 203
;        je      pppoe_discovery_input
3545 hidnplayr 204
 
5001 hidnplayr 205
;        cmp     ax, ETHER_PROTO_PPP_SESSION
6011 hidnplayr 206
;        je      pppoe_session_input
3545 hidnplayr 207
 
4256 hidnplayr 208
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ETH_input: Unknown packet type=%x\n", ax
3545 hidnplayr 209
 
9017 hidnplayr 210
  .drop:
211
        mov     eax, [esp]
212
        mov     eax, [eax + NET_BUFF.device]
213
        inc     [eax + NET_DEVICE.packets_rx_drop]
214
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ETH_input: dropping\n"
6011 hidnplayr 215
        call    net_buff_free
3545 hidnplayr 216
        ret
217
 
9017 hidnplayr 218
  .err:
219
        mov     eax, [esp]
220
        mov     eax, [eax + NET_BUFF.device]
221
        inc     [eax + NET_DEVICE.packets_rx_err]
222
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ETH_input: invalid frame received\n"
223
        call    net_buff_free
224
        ret
6011 hidnplayr 225
 
226
 
9017 hidnplayr 227
 
228
 
6011 hidnplayr 229
;-----------------------------------------------------------------;
230
;                                                                 ;
231
; eth_output                                                      ;
232
;                                                                 ;
233
;  IN:  ax = protocol                                             ;
234
;       ebx = device ptr                                          ;
235
;       ecx = payload size                                        ;
236
;       edx = pointer to destination mac                          ;
237
;                                                                 ;
238
;  OUT: eax = start of net frame / 0 on error                     ;
239
;       ebx = device ptr                                          ;
240
;       ecx = payload size                                        ;
241
;       edi = start of payload                                    ;
242
;                                                                 ;
243
;-----------------------------------------------------------------;
3545 hidnplayr 244
align 4
6011 hidnplayr 245
eth_output:
3545 hidnplayr 246
 
3556 hidnplayr 247
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ETH_output: size=%u device=%x\n", ecx, ebx
3545 hidnplayr 248
 
5015 hidnplayr 249
        cmp     ecx, [ebx + ETH_DEVICE.mtu]
9017 hidnplayr 250
        ja      .too_large
3545 hidnplayr 251
 
252
        push    ecx
5015 hidnplayr 253
        push    ax edx
3545 hidnplayr 254
 
5522 hidnplayr 255
        add     ecx, sizeof.ETH_header + NET_BUFF.data
6011 hidnplayr 256
        stdcall net_buff_alloc, ecx
3545 hidnplayr 257
        test    eax, eax
258
        jz      .out_of_ram
9017 hidnplayr 259
 
5522 hidnplayr 260
        mov     [eax + NET_BUFF.type], NET_BUFF_ETH
261
        mov     [eax + NET_BUFF.device], ebx
262
        mov     [eax + NET_BUFF.offset], NET_BUFF.data
263
        lea     edi, [eax + NET_BUFF.data]
3545 hidnplayr 264
 
265
        pop     esi
266
        movsd
267
        movsw
5015 hidnplayr 268
        lea     esi, [ebx + ETH_DEVICE.mac]
3545 hidnplayr 269
        movsd
270
        movsw
271
        pop     ax
272
        stosw
273
 
5522 hidnplayr 274
        lea     eax, [edi - sizeof.ETH_header - NET_BUFF.data]  ; Set eax to buffer start
3545 hidnplayr 275
        pop     ecx
5522 hidnplayr 276
 
3545 hidnplayr 277
        lea     edx, [ecx + sizeof.ETH_header]  ; Set edx to complete buffer size
278
        cmp     edx, ETH_FRAME_MINIMUM
279
        jbe     .adjust_size
280
  .done:
5522 hidnplayr 281
        mov     [eax + NET_BUFF.length], edx
3556 hidnplayr 282
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ETH_output: ptr=%x size=%u\n", eax, edx
3545 hidnplayr 283
        ret
284
 
285
  .adjust_size:
286
        mov     edx, ETH_FRAME_MINIMUM
5015 hidnplayr 287
        test    edx, edx                        ; clear zero flag
3545 hidnplayr 288
        jmp     .done
289
 
290
  .out_of_ram:
9017 hidnplayr 291
        inc     [ebx + NET_DEVICE.packets_tx_drop]
292
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ETH_output: Out of ram!\n"
293
        add     esp, 4+2
294
        pop     ecx
5015 hidnplayr 295
        xor     eax, eax
3545 hidnplayr 296
        ret
297
 
9017 hidnplayr 298
  .too_large:
299
        inc     [eax + NET_DEVICE.packets_tx_err]
300
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ETH_output: Packet too large!\n"
5015 hidnplayr 301
        xor     eax, eax
3545 hidnplayr 302
        ret
303
 
304
 
305
 
6011 hidnplayr 306
;-----------------------------------------------------------------;
307
;                                                                 ;
308
; eth_api: Part of system function 76.                            ;
309
;                                                                 ;
310
;  IN:  bl = subfunction number                                   ;
311
;       bh = device number                                        ;
312
;       ecx, edx, .. depends on subfunction                       ;
313
;                                                                 ;
314
; OUT:  depends on subfunction                                    ;
315
;                                                                 ;
316
;-----------------------------------------------------------------;
3545 hidnplayr 317
align 4
6011 hidnplayr 318
eth_api:
3545 hidnplayr 319
 
3600 hidnplayr 320
        cmp     bh, NET_DEVICES_MAX
3545 hidnplayr 321
        ja      .error
322
        movzx   eax, bh
7679 hidnplayr 323
        mov     eax, dword [net_device_list + 4*eax]
3600 hidnplayr 324
        cmp     [eax + NET_DEVICE.device_type], NET_DEVICE_ETH
3545 hidnplayr 325
        jne     .error
326
 
327
        and     ebx, 0xff
328
        cmp     ebx, .number
329
        ja      .error
330
        jmp     dword [.table + 4*ebx]
331
 
332
  .table:
3601 hidnplayr 333
        dd      .read_mac       ; 0
3545 hidnplayr 334
  .number = ($ - .table) / 4 - 1
335
 
336
  .error:
337
        or      eax, -1
338
        ret
339
 
340
 
341
  .read_mac:
342
        movzx   ebx, word [eax + ETH_DEVICE.mac]
343
        mov     eax, dword [eax + ETH_DEVICE.mac + 2]
5522 hidnplayr 344
        mov     [esp+20+4], ebx                         ; FIXME
3545 hidnplayr 345
        ret
346