Subversion Repositories Kolibri OS

Rev

Rev 1159 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved.    ;;
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: 983 $
18
 
19
MAX_ETH_DEVICES 	equ MAX_NET_DEVICES
20
ETH_QUEUE_SIZE		equ 16
21
 
22
struct	ETH_FRAME
23
	.DstMAC 	dp  ?  ; destination MAC-address [6 bytes]
24
	.SrcMAC 	dp  ?  ; source MAC-address [6 bytes]
25
	.Type		dw  ?  ; type of the upper-layer protocol [2 bytes]
26
	.Data:		       ; data [46-1500 bytes]
27
ends
28
 
29
struct	ETH_DEVICE
30
	.unload 	dd ?
31
	.reset		dd ?
32
	.transmit	dd ?
33
	.set_MAC	dd ?
34
	.get_MAC	dd ?
35
	.set_mode	dd ?
36
	.get_mode	dd ?
37
 
38
	.bytes_tx	dq ?
39
	.bytes_rx	dq ?
40
	.packets_tx	dd ?
41
	.packets_rx	dd ?
42
	.mode		dd ?  ; This dword contains cable status (10mbit/100mbit, full/half duplex, auto negotiation or not,..)
43
	.name		dd ?
44
	.mac		dp ?
45
ends			      ; the rest of the device struct depends on the type of device
46
 
47
 
48
align 4
49
uglobal
50
 
51
	ETH_RUNNING	dd  ?
52
	ETH_DRV_LIST	rd  MAX_ETH_DEVICES
53
	ETH_IN_QUEUE	rd  3*ETH_QUEUE_SIZE+3
54
	ETH_OUT_QUEUE	rd  3*ETH_QUEUE_SIZE+3
55
endg
56
 
57
 
58
;-----------------------------------------------
59
;
60
; ETH_init
61
;
62
;  This function resets all ethernet variables
63
;
64
;  IN:  /
65
;  OUT: /
66
;
67
;-----------------------------------------------
68
 
69
align 4
70
ETH_init:
71
 
72
	xor	eax, eax
73
	mov	edi, ETH_RUNNING
74
	mov	ecx, (1+MAX_ETH_DEVICES)
75
	rep	stosd
76
 
77
	mov	dword [ETH_IN_QUEUE], eax
78
	mov	dword [ETH_IN_QUEUE+4], ETH_IN_QUEUE + queue.data
79
	mov	dword [ETH_IN_QUEUE+8], ETH_IN_QUEUE + queue.data
80
 
81
	mov	dword [ETH_OUT_QUEUE], eax
82
	mov	dword [ETH_OUT_QUEUE+4], ETH_OUT_QUEUE + queue.data
83
	mov	dword [ETH_OUT_QUEUE+8], ETH_OUT_QUEUE + queue.data
84
 
85
	ret
86
 
87
 
88
 
89
;---------------------------------------------------------
90
;
91
; ETH_Add_Device:
92
;
93
;  This function is called by ethernet drivers,
94
;  to register each running ethernet device to the kernel
95
;
96
;  IN:  Pointer to device structure in ebx
97
;  OUT: Device num in eax, -1 on error
98
;
99
;---------------------------------------------------------
100
 
101
align 4
102
ETH_Add_Device:
103
 
104
	DEBUGF	1,"ETH_Add_Device: %x\n", ebx
105
	cmp	[ETH_RUNNING], MAX_ETH_DEVICES
106
	jge	.error
107
 
108
	mov	eax, ebx
109
	mov	ecx, MAX_ETH_DEVICES	  ; We need to check whole list because a device may be removed without re-organizing list
110
	mov	edi, ETH_DRV_LIST
111
 
112
	cld
113
	repne	scasd			  ; See if device is already in the list
114
	jz	.error
115
 
116
	xor	eax, eax
117
	mov	ecx, MAX_ETH_DEVICES
118
	mov	edi, ETH_DRV_LIST
119
 
120
	repne	scasd			  ; Find empty spot in the list
121
	jnz	.error
122
 
123
	sub	edi, 4
124
	mov	[edi], ebx		  ; add device to list
125
 
126
	sub	edi, ETH_DRV_LIST	  ; edi = 4*device num       Calculate device number in eax
127
	mov	eax, edi		  ; edx = 4*device num
128
	shr	eax, 2
129
 
130
;        shr     eax, 1                    ; edx = 2*device num
131
;        add     edi, eax                  ; edi = 6*device_num                   Meanwhile, calculate MAC offset in edi
132
;        shr     eax, 1                    ; edx = device num
133
;        add     edi, MAC_LIST             ; edi = MAC_LIST+6*device_num
134
;        push    eax
135
 
136
;        push    edi
137
;        call    [ebx+ETH_DEVICE.get_MAC]  ; Get MAC address from driver
138
;        pop     edi
139
;
140
;        stosd                             ; Write MAC address to the MAC list
141
;        mov     ax, bx                    ;
142
;        stosw                             ;
143
 
144
	inc	[ETH_RUNNING]		  ; Indicate that one more ethernet device is up and running
145
;        pop     eax                       ; Output device num in eax
146
	DEBUGF	1,"- succes: %u\n",eax
147
	ret
148
 
149
       .error:
150
	or	eax, -1
151
	DEBUGF	1,"- fail\n"
152
 
153
	ret
154
 
155
 
156
 
157
 
158
;--------------------------------
159
;
160
; ETH_Remove_Device:
161
;
162
;  This function is called by ethernet drivers,
163
;  to unregister ethernet devices from the kernel
164
;
165
;  IN:  Pointer to device structure in ebx
166
;  OUT: eax: -1 on error
167
;
168
;--------------------------------
169
 
170
align 4
171
ETH_Remove_Device:
172
 
173
	cmp	[ETH_RUNNING], 0
174
	je	.error
175
 
176
	mov	eax, ebx
177
	mov	ecx, MAX_ETH_DEVICES
178
	mov	edi, ETH_DRV_LIST
179
 
180
	repne	scasd
181
	jnz	.error
182
 
183
	xor	eax, eax
184
	mov	dword [edi-4], eax
185
 
186
	dec	[ETH_RUNNING]
187
 
188
	ret
189
 
190
       .error:
191
	or	eax, -1
192
 
193
	ret
194
 
195
 
196
 
197
;-------------------------------------------------------------
198
;
199
; ETH_Receiver:
200
;
201
;  This function is called by ethernet drivers,
202
;  It pushes the received ethernet packets onto the eth_in_queue
203
;
204
;  IN:  Pointer to buffer in [esp], size of buffer in [esp-4], pointer to eth_device in ebx
205
;  OUT: /
206
;
207
;-------------------------------------------------------------
208
 
209
align 4
210
ETH_Receiver:
211
	DEBUGF	1,"ETH_Receiver \n"
212
 
213
	add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
214
 
215
  .gohome:
216
	ret
217
 
218
 
219
 
220
 
221
 
222
;-------------------------------------------------------------
223
;
224
; ETH_Handler:
225
;
226
;  Handles all queued eth packets (called from kernel's main_loop)
227
;
228
;  IN:  /
229
;  OUT: /
230
;
231
;-------------------------------------------------------------
232
 
233
align 4
234
ETH_Handler:
235
 
236
	get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
237
 
238
	DEBUGF	1,"ETH_Handler - size: %u\n", ecx
239
	cmp	ecx, 60    ; check packet length
240
	jl	.dump
241
	sub	ecx, ETH_FRAME.Data
242
 
243
	lea	edx, [eax + ETH_FRAME.Data]
244
	mov	ax , [eax + ETH_FRAME.Type]
245
 
246
	cmp	ax, ETHER_IPv4
247
	je	IPv4_Handler
248
 
249
	cmp	ax, ETHER_ARP
250
	je	ARP_Handler
251
 
252
	DEBUGF	1,"Unknown ethernet packet type %x\n", ax
253
 
254
  .dump:
255
	DEBUGF	1,"Dumping packet\n"
256
	call	kernel_free
257
	add	esp, 4
258
 
259
  .gohome:
260
	ret				; return 1. to get more from queue / 2. to caller
261
 
262
 
263
 
264
;-----------------------------------------------------------------
265
;
266
; ETH_Sender:
267
;
268
;  This function sends an ethernet packet to the correct driver.
269
;
270
;  IN:  Pointer to buffer in [esp]
271
;       size of buffer in [esp+4]
272
;       pointer to device struct in ebx
273
;  OUT: /
274
;
275
;-----------------------------------------------------------------
276
 
277
align 4
278
ETH_Sender:
279
	DEBUGF	1,"ETH_Sender \n"
280
 
281
	add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
282
 
283
  .gohome:
284
	ret
285
 
286
 
287
align 4
288
ETH_send_queued:
289
 
290
	get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
291
 
292
	call	ETH_struc2dev		 ; convert struct ptr to device num (this way we know if driver is still mounted)
293
	cmp	edi, -1
294
	je	.fail
295
 
296
	DEBUGF 1,"ETH_Sender - device: %u\n", edi
297
 
298
	jmp	[ebx+ETH_DEVICE.transmit]
299
 
300
     .fail:
301
	call	kernel_free
302
	add	esp, 4 ; pop (balance stack)
303
	DEBUGF 1,"ETH_Sender - fail\n"
304
     .gohome:
305
	ret
306
 
307
;---------------------------------------------------------------------------
308
;
309
; ETH_struc2dev
310
;
311
; IN: pointer to device struct in ebx
312
;
313
; OUT: edi is -1 on error, device number otherwise
314
;
315
;---------------------------------------------------------------------------
316
 
317
align 4
318
ETH_struc2dev:
319
	push	eax ecx
320
 
321
	mov	eax, ebx
322
	mov	ecx, MAX_ETH_DEVICES
323
	mov	edi, ETH_DRV_LIST
324
 
325
	repne	scasd
326
	jnz	.error
327
 
328
	sub	edi, ETH_DRV_LIST+4
329
	shr	edi, 2
330
 
331
	pop	ecx eax
332
	ret
333
  .error:
334
	or	edi, -1
335
	pop	ecx eax
336
 
337
	ret
338
 
339
 
340
;---------------------------------------------------------------------------
341
;
342
; ETH_create_Packet
343
;
344
; IN: pointer to source mac in eax
345
;     pointer to destination mac in ebx
346
;     packet size in ecx
347
;     device number in edx
348
;     protocol in di
349
;
350
; OUT: edi is -1 on error, pointer to buffer otherwise                    ;; TODO: XCHG EDX AND EBX output parameters
351
;      eax points to buffer start
352
;      ebx is size of complete buffer
353
;      ecx is unchanged (packet size of embedded data)
354
;      edx is pointer to device structure
355
;      esi points to procedure wich needs to be called to send packet
356
;
357
;---------------------------------------------------------------------------
358
 
359
align 4
360
ETH_create_Packet:
361
 
362
	DEBUGF 1,"Creating Ethernet Packet:\n"
363
 
364
	cmp	ecx, 60-ETH_FRAME.Data
365
	jl	.exit
366
	cmp	ecx, 1514-ETH_FRAME.Data
367
	jg	.exit
368
 
369
	push	ecx di eax ebx edx
370
 
371
	add	ecx, ETH_FRAME.Data
372
	push	ecx
373
	push	ecx
374
	call	kernel_alloc
375
	test	eax, eax
376
	jz	.pop_exit
377
 
378
	pop	ecx
379
	pop	edx
380
 
381
	DEBUGF 1,"1"
382
	mov	edi, eax
383
	pop	esi
384
	movsd
385
	movsw
386
	DEBUGF 1,"2"
387
	pop	esi
388
	movsd
389
	movsw
390
	DEBUGF 1,"3"
391
	pop	ax
392
	stosw
393
	DEBUGF 1,"4"
394
 
395
	lea	eax, [edi - ETH_FRAME.Data]  ; Set eax to buffer start
396
	mov	ebx, ecx		     ; Set ebx to complete buffer size
397
	pop	ecx
398
	mov	esi, ETH_Sender
399
 
400
	xor	edx, edx ;;;; TODO: Fixme
401
	mov	edx, [ETH_DRV_LIST + edx]
402
 
403
	DEBUGF 1,"done: %x size:%u device:%x\n", eax, ebx, edx
404
	ret
405
 
406
  .pop_exit:
407
	add	esp, 18
408
  .exit:
409
	or	edi, -1
410
	ret
411
 
412
 
413
 
414
 
415
;---------------------------------------------------------------------------
416
;
417
; ETH_API
418
;
419
; This function is called by system function 75
420
;
421
; IN:  subfunction number in bl
422
;      device number in bh
423
;      ecx, edx, .. depends on subfunction
424
;
425
; OUT:
426
;
427
;---------------------------------------------------------------------------
428
 
429
align 4
430
ETH_API:
431
 
432
	movzx	eax, bh
433
	shl	eax, 2
434
 
435
	test	bl, bl
436
	jz	.packets_tx	; 0
437
	dec	bl
438
	jz	.packets_rx	; 1
439
	dec	bl
440
	jz	.bytes_tx	; 2
441
	dec	bl
442
	jz	.bytes_rx	; 3
443
	dec	bl
444
	jz	.read_mac	; 4
445
	dec	bl
446
	jz	.write_mac	; 5
447
	dec	bl
448
	jz	.in_queue	; 6
449
	dec	bl
450
	jz	.out_queue	; 7
451
 
452
 
453
.error:
454
	mov	eax, -1
455
	ret
456
 
457
.packets_tx:
458
	add	eax, ETH_DRV_LIST
459
	mov	eax, [eax]
460
	mov	eax, [eax + ETH_DEVICE.packets_tx]
461
	ret
462
 
463
.packets_rx:
464
	add	eax, ETH_DRV_LIST
465
	mov	eax, [eax]
466
	mov	eax, [eax + ETH_DEVICE.packets_rx]
467
	ret
468
 
469
.bytes_tx:
470
	add	eax, ETH_DRV_LIST
471
	mov	eax, [eax]
472
	mov	eax, dword [eax + ETH_DEVICE.bytes_tx + 4]
473
	ret
474
 
475
.bytes_rx:
476
	add	eax, ETH_DRV_LIST
477
	mov	eax, [eax]
478
	mov	eax, dword [eax + ETH_DEVICE.bytes_rx + 4]
479
	ret
480
 
481
.read_mac:
482
	add	eax, ETH_DRV_LIST
483
	mov	eax, [eax]
484
;        push    eax
485
;        call    dword [eax + ETH_DEVICE.get_MAC]
486
;        pop     eax
487
	movzx	ebx, word [eax + ETH_DEVICE.mac]
488
	mov	eax, dword [eax + ETH_DEVICE.mac + 2]
489
	mov	[esp+20+4], ebx 	; TODO: fix this ugly code
490
	ret
491
 
492
.write_mac:
493
	push	ecx
494
	push	dx
495
	add	eax, ETH_DRV_LIST
496
	mov	eax, [eax]
497
	mov	eax, dword [eax + ETH_DEVICE.set_MAC]
498
	call	eax
499
	ret
500
 
501
.in_queue:
502
	add	eax, ETH_IN_QUEUE
503
	mov	eax, [eax + queue.size]
504
	ret
505
 
506
.out_queue:
507
	add	eax, ETH_OUT_QUEUE
508
	mov	eax, [eax + queue.size]
509
	ret