Subversion Repositories Kolibri OS

Rev

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