Rev 5201 | Rev 5596 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3555 | Serge | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
||
5565 | serge | 3 | ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; |
3555 | Serge | 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 | |||
17 | $Revision: 3346 $ |
||
18 | |||
19 | ETH_FRAME_MINIMUM = 60 |
||
4265 | Serge | 20 | ETH_QUEUE_SIZE = 255 |
3555 | Serge | 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 | |||
5565 | serge | 36 | iglobal |
37 | align 4 |
||
4265 | Serge | 38 | |
5565 | serge | 39 | ETH_BROADCAST dp 0xffffffffffff |
4265 | Serge | 40 | |
5565 | serge | 41 | ETH_frame_queued dd 0 ; Number of queued frames |
4265 | Serge | 42 | |
5565 | serge | 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 |
||
3555 | Serge | 45 | |
46 | endg |
||
47 | |||
4265 | Serge | 48 | uglobal |
49 | align 4 |
||
50 | ETH_input_event dd ? |
||
51 | endg |
||
52 | |||
53 | macro ETH_init { |
||
54 | |||
55 | movi ebx, 1 |
||
56 | mov ecx, ETH_process_input |
||
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 | |||
3555 | Serge | 65 | ;----------------------------------------------------------------- |
66 | ; |
||
67 | ; ETH_input |
||
68 | ; |
||
69 | ; This function is called by ethernet drivers, |
||
5565 | serge | 70 | ; It pushes the received ethernet packets onto the ethernet input queue |
3555 | Serge | 71 | ; |
72 | ; IN: [esp] = Pointer to buffer |
||
5565 | serge | 73 | ; |
3555 | Serge | 74 | ; OUT: / |
75 | ; |
||
76 | ;----------------------------------------------------------------- |
||
77 | align 4 |
||
78 | ETH_input: |
||
79 | |||
5565 | serge | 80 | pop eax |
81 | pushf |
||
82 | cli |
||
4265 | Serge | 83 | |
5565 | serge | 84 | cmp [ETH_frame_queued], ETH_QUEUE_SIZE |
85 | jae .full |
||
86 | inc [ETH_frame_queued] |
||
4265 | Serge | 87 | |
5565 | serge | 88 | ; Add frame to the end of the linked list |
89 | mov [eax + NET_BUFF.NextPtr], ETH_frame_head |
||
90 | |||
91 | mov ebx, [ETH_frame_tail] |
||
92 | mov [eax + NET_BUFF.PrevPtr], ebx |
||
93 | |||
94 | mov [ETH_frame_tail], eax |
||
95 | mov [ebx + NET_BUFF.NextPtr], eax |
||
96 | |||
97 | popf |
||
98 | |||
99 | ; Now queue an event to process it |
||
4265 | Serge | 100 | xor edx, edx |
101 | mov eax, [ETH_input_event] |
||
102 | mov ebx, [eax + EVENT.id] |
||
103 | xor esi, esi |
||
104 | call raise_event |
||
105 | |||
106 | ret |
||
107 | |||
5565 | serge | 108 | .full: |
5201 | serge | 109 | DEBUGF DEBUG_NETWORK_ERROR, "ETH incoming queue is full, discarding packet!\n" |
5565 | serge | 110 | popf |
111 | push eax |
||
112 | call NET_BUFF_free |
||
4265 | Serge | 113 | ret |
114 | |||
115 | |||
116 | |||
117 | |||
118 | align 4 |
||
119 | ETH_process_input: |
||
120 | |||
121 | xor esi, esi |
||
122 | mov ecx, MANUAL_DESTROY |
||
123 | call create_event |
||
124 | mov [ETH_input_event], eax |
||
5565 | serge | 125 | pushf |
4265 | Serge | 126 | .wait: |
5565 | serge | 127 | popf |
4265 | Serge | 128 | mov eax, [ETH_input_event] |
129 | mov ebx, [eax + EVENT.id] |
||
130 | call wait_event |
||
131 | |||
132 | .loop: |
||
5565 | serge | 133 | pushf |
134 | cli |
||
135 | cmp [ETH_frame_queued], 0 |
||
136 | je .wait |
||
4265 | Serge | 137 | |
5565 | serge | 138 | dec [ETH_frame_queued] |
4265 | Serge | 139 | |
5565 | serge | 140 | mov esi, [ETH_frame_head] |
141 | mov ebx, [esi + NET_BUFF.NextPtr] |
||
4265 | Serge | 142 | |
5565 | serge | 143 | mov [ETH_frame_head], ebx |
144 | mov [ebx + NET_BUFF.PrevPtr], ETH_frame_head |
||
145 | |||
146 | popf |
||
147 | |||
148 | mov eax, [esi + NET_BUFF.offset] |
||
149 | add eax, esi |
||
150 | mov ecx, [esi + NET_BUFF.length] |
||
151 | mov ebx, [esi + NET_BUFF.device] |
||
152 | |||
153 | pushd .loop ; return address for protocol handler |
||
154 | push esi ; keep pointer to NET_BUFF on stack |
||
155 | |||
4265 | Serge | 156 | DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_input: size=%u\n", ecx |
3725 | Serge | 157 | sub ecx, sizeof.ETH_header |
3555 | Serge | 158 | jb .dump |
159 | |||
5565 | serge | 160 | ; Set registers for protocol handlers |
3555 | Serge | 161 | lea edx, [eax + sizeof.ETH_header] |
162 | mov ax, [eax + ETH_header.Type] |
||
163 | |||
5565 | serge | 164 | ; Place protocol handlers here |
3626 | Serge | 165 | cmp ax, ETHER_PROTO_IPv4 |
3555 | Serge | 166 | je IPv4_input |
167 | |||
3626 | Serge | 168 | cmp ax, ETHER_PROTO_ARP |
3555 | Serge | 169 | je ARP_input |
170 | |||
5201 | serge | 171 | ; cmp ax, ETHER_PROTO_IPv6 |
172 | ; je IPv6_input |
||
3555 | Serge | 173 | |
5201 | serge | 174 | ; cmp ax, ETHER_PROTO_PPP_DISCOVERY |
175 | ; je PPPoE_discovery_input |
||
3555 | Serge | 176 | |
5201 | serge | 177 | ; cmp ax, ETHER_PROTO_PPP_SESSION |
178 | ; je PPPoE_session_input |
||
3555 | Serge | 179 | |
4265 | Serge | 180 | DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_input: Unknown packet type=%x\n", ax |
3555 | Serge | 181 | |
182 | .dump: |
||
4265 | Serge | 183 | DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_input: dumping\n" |
5565 | serge | 184 | call NET_BUFF_free |
3555 | Serge | 185 | ret |
186 | |||
187 | ;----------------------------------------------------------------- |
||
188 | ; |
||
189 | ; ETH_output |
||
190 | ; |
||
5201 | serge | 191 | ; IN: ax = protocol |
3555 | Serge | 192 | ; ebx = device ptr |
5201 | serge | 193 | ; ecx = payload size |
3555 | Serge | 194 | ; edx = pointer to destination mac |
195 | ; |
||
5565 | serge | 196 | ; OUT: eax = start of net frame / 0 on error |
5201 | serge | 197 | ; ebx = device ptr |
198 | ; ecx = payload size |
||
5565 | serge | 199 | ; edi = start of payload |
3555 | Serge | 200 | ; |
201 | ;----------------------------------------------------------------- |
||
202 | align 4 |
||
203 | ETH_output: |
||
204 | |||
3589 | Serge | 205 | DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: size=%u device=%x\n", ecx, ebx |
3555 | Serge | 206 | |
5201 | serge | 207 | cmp ecx, [ebx + ETH_DEVICE.mtu] |
3555 | Serge | 208 | ja .exit |
209 | |||
210 | push ecx |
||
5201 | serge | 211 | push ax edx |
3555 | Serge | 212 | |
5565 | serge | 213 | add ecx, sizeof.ETH_header + NET_BUFF.data |
214 | stdcall NET_BUFF_alloc, ecx |
||
3555 | Serge | 215 | test eax, eax |
216 | jz .out_of_ram |
||
5565 | serge | 217 | mov [eax + NET_BUFF.type], NET_BUFF_ETH |
218 | mov [eax + NET_BUFF.device], ebx |
||
219 | mov [eax + NET_BUFF.offset], NET_BUFF.data |
||
220 | lea edi, [eax + NET_BUFF.data] |
||
3555 | Serge | 221 | |
222 | pop esi |
||
223 | movsd |
||
224 | movsw |
||
5201 | serge | 225 | lea esi, [ebx + ETH_DEVICE.mac] |
3555 | Serge | 226 | movsd |
227 | movsw |
||
228 | pop ax |
||
229 | stosw |
||
230 | |||
5565 | serge | 231 | lea eax, [edi - sizeof.ETH_header - NET_BUFF.data] ; Set eax to buffer start |
3555 | Serge | 232 | pop ecx |
5565 | serge | 233 | |
3555 | Serge | 234 | lea edx, [ecx + sizeof.ETH_header] ; Set edx to complete buffer size |
235 | cmp edx, ETH_FRAME_MINIMUM |
||
236 | jbe .adjust_size |
||
237 | .done: |
||
5565 | serge | 238 | mov [eax + NET_BUFF.length], edx |
3589 | Serge | 239 | DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: ptr=%x size=%u\n", eax, edx |
3555 | Serge | 240 | ret |
241 | |||
242 | .adjust_size: |
||
243 | mov edx, ETH_FRAME_MINIMUM |
||
244 | test edx, edx ; clear zero flag |
||
245 | jmp .done |
||
246 | |||
247 | .out_of_ram: |
||
3589 | Serge | 248 | DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Out of ram!\n" |
5201 | serge | 249 | add esp, 4+2+4 |
250 | xor eax, eax |
||
3555 | Serge | 251 | ret |
252 | |||
253 | .exit: |
||
3589 | Serge | 254 | DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Packet too large!\n" |
5201 | serge | 255 | xor eax, eax |
3555 | Serge | 256 | ret |
257 | |||
258 | |||
259 | |||
260 | ;----------------------------------------------------------------- |
||
261 | ; |
||
262 | ; ETH_API |
||
263 | ; |
||
3626 | Serge | 264 | ; This function is called by system function 76 |
3555 | Serge | 265 | ; |
266 | ; IN: subfunction number in bl |
||
267 | ; device number in bh |
||
268 | ; ecx, edx, .. depends on subfunction |
||
269 | ; |
||
270 | ; OUT: |
||
271 | ; |
||
272 | ;----------------------------------------------------------------- |
||
273 | align 4 |
||
274 | ETH_api: |
||
275 | |||
3626 | Serge | 276 | cmp bh, NET_DEVICES_MAX |
3555 | Serge | 277 | ja .error |
278 | movzx eax, bh |
||
279 | mov eax, dword [NET_DRV_LIST + 4*eax] |
||
3626 | Serge | 280 | cmp [eax + NET_DEVICE.device_type], NET_DEVICE_ETH |
3555 | Serge | 281 | jne .error |
282 | |||
283 | and ebx, 0xff |
||
284 | cmp ebx, .number |
||
285 | ja .error |
||
286 | jmp dword [.table + 4*ebx] |
||
287 | |||
288 | .table: |
||
3626 | Serge | 289 | dd .read_mac ; 0 |
3555 | Serge | 290 | .number = ($ - .table) / 4 - 1 |
291 | |||
292 | .error: |
||
293 | or eax, -1 |
||
294 | ret |
||
295 | |||
296 | |||
297 | .read_mac: |
||
298 | movzx ebx, word [eax + ETH_DEVICE.mac] |
||
299 | mov eax, dword [eax + ETH_DEVICE.mac + 2] |
||
5565 | serge | 300 | mov [esp+20+4], ebx ; FIXME |
3555 | Serge | 301 | ret |
302 |