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