Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
1196 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
1159 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
 
1206 hidnplayr 17
$Revision: 1473 $
1159 hidnplayr 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
 
1274 hidnplayr 47
struct	eth_queue_entry
48
	.owner		dd ?
49
	.data_ptr	dd ?
50
	.data_size	dd ?
51
	.size:
52
ends
1159 hidnplayr 53
 
1274 hidnplayr 54
 
1159 hidnplayr 55
align 4
1196 hidnplayr 56
iglobal
57
 
58
	ETH_BROADCAST	dp  0xffffffffffff
59
endg
60
 
61
align 4
1159 hidnplayr 62
uglobal
63
 
64
	ETH_RUNNING	dd  ?
65
	ETH_DRV_LIST	rd  MAX_ETH_DEVICES
66
	ETH_IN_QUEUE	rd  3*ETH_QUEUE_SIZE+3
1259 hidnplayr 67
if QUEUE_BEFORE_SENDING
1159 hidnplayr 68
	ETH_OUT_QUEUE	rd  3*ETH_QUEUE_SIZE+3
1259 hidnplayr 69
end if
1159 hidnplayr 70
endg
71
 
72
 
1257 hidnplayr 73
;-----------------------------------------------------------------
1159 hidnplayr 74
;
75
; ETH_init
76
;
77
;  This function resets all ethernet variables
78
;
79
;  IN:  /
80
;  OUT: /
81
;
1257 hidnplayr 82
;-----------------------------------------------------------------
1159 hidnplayr 83
align 4
84
ETH_init:
85
 
86
	xor	eax, eax
87
	mov	edi, ETH_RUNNING
88
	mov	ecx, (1+MAX_ETH_DEVICES)
89
	rep	stosd
90
 
1249 hidnplayr 91
	init_queue ETH_IN_QUEUE
1259 hidnplayr 92
 
93
if QUEUE_BEFORE_SENDING
1249 hidnplayr 94
	init_queue ETH_OUT_QUEUE
1259 hidnplayr 95
end if
1159 hidnplayr 96
 
97
	ret
98
 
99
 
1257 hidnplayr 100
;-----------------------------------------------------------------
1159 hidnplayr 101
;
102
; ETH_Add_Device:
103
;
104
;  This function is called by ethernet drivers,
105
;  to register each running ethernet device to the kernel
106
;
107
;  IN:  Pointer to device structure in ebx
108
;  OUT: Device num in eax, -1 on error
109
;
1257 hidnplayr 110
;-----------------------------------------------------------------
1159 hidnplayr 111
align 4
1249 hidnplayr 112
ETH_add_device:
1159 hidnplayr 113
 
1185 hidnplayr 114
	DEBUGF	1,"ETH_Add_Device: %x ", ebx
1174 hidnplayr 115
 
116
	mov	eax, [ETH_RUNNING]
117
	cmp	eax, MAX_ETH_DEVICES
1159 hidnplayr 118
	jge	.error
119
 
1174 hidnplayr 120
	test	eax, eax
121
	jnz	.notfirst
122
	mov	dword [ETH_IN_QUEUE], eax
1259 hidnplayr 123
if QUEUE_BEFORE_SENDING
1174 hidnplayr 124
	mov	dword [ETH_OUT_QUEUE], eax
1259 hidnplayr 125
end if
1174 hidnplayr 126
      .notfirst:
127
 
1159 hidnplayr 128
	mov	eax, ebx
129
	mov	ecx, MAX_ETH_DEVICES	  ; We need to check whole list because a device may be removed without re-organizing list
130
	mov	edi, ETH_DRV_LIST
131
 
132
	repne	scasd			  ; See if device is already in the list
133
	jz	.error
134
 
135
	xor	eax, eax
136
	mov	ecx, MAX_ETH_DEVICES
137
	mov	edi, ETH_DRV_LIST
138
 
139
	repne	scasd			  ; Find empty spot in the list
140
	jnz	.error
141
 
142
	sub	edi, 4
143
	mov	[edi], ebx		  ; add device to list
144
 
145
	sub	edi, ETH_DRV_LIST	  ; edi = 4*device num       Calculate device number in eax
146
	mov	eax, edi		  ; edx = 4*device num
147
	shr	eax, 2
148
 
149
	inc	[ETH_RUNNING]		  ; Indicate that one more ethernet device is up and running
1174 hidnplayr 150
 
1159 hidnplayr 151
	DEBUGF	1,"- succes: %u\n",eax
152
	ret
153
 
154
       .error:
155
	or	eax, -1
1473 hidnplayr 156
	DEBUGF	2,"Adding ETH device failed\n"
1159 hidnplayr 157
	ret
158
 
159
 
160
 
161
 
1257 hidnplayr 162
;-----------------------------------------------------------------
1159 hidnplayr 163
;
164
; ETH_Remove_Device:
165
;
166
;  This function is called by ethernet drivers,
167
;  to unregister ethernet devices from the kernel
168
;
169
;  IN:  Pointer to device structure in ebx
170
;  OUT: eax: -1 on error
171
;
1257 hidnplayr 172
;-----------------------------------------------------------------
1159 hidnplayr 173
align 4
1249 hidnplayr 174
ETH_remove_device:
1159 hidnplayr 175
 
176
	cmp	[ETH_RUNNING], 0
177
	je	.error
178
 
179
	mov	eax, ebx
180
	mov	ecx, MAX_ETH_DEVICES
181
	mov	edi, ETH_DRV_LIST
182
 
183
	repne	scasd
184
	jnz	.error
185
 
186
	xor	eax, eax
187
	mov	dword [edi-4], eax
188
 
189
	dec	[ETH_RUNNING]
1174 hidnplayr 190
	jnz	.notlast
1159 hidnplayr 191
 
1174 hidnplayr 192
	mov	dword [ETH_IN_QUEUE], ETH_QUEUE_SIZE
1259 hidnplayr 193
if QUEUE_BEFORE_SENDING
1174 hidnplayr 194
	mov	dword [ETH_OUT_QUEUE], ETH_QUEUE_SIZE
1259 hidnplayr 195
end if
1174 hidnplayr 196
 
1257 hidnplayr 197
  .notlast:
1159 hidnplayr 198
	ret
199
 
1257 hidnplayr 200
  .error:
1159 hidnplayr 201
	or	eax, -1
202
	ret
203
 
204
 
205
 
1257 hidnplayr 206
;-----------------------------------------------------------------
1159 hidnplayr 207
;
208
; ETH_Receiver:
209
;
210
;  This function is called by ethernet drivers,
211
;  It pushes the received ethernet packets onto the eth_in_queue
212
;
1257 hidnplayr 213
;  IN:  [esp]   = Pointer to buffer
214
;       [esp-4] = size of buffer
215
;       ebx     = pointer to eth_device
1159 hidnplayr 216
;  OUT: /
217
;
1257 hidnplayr 218
;-----------------------------------------------------------------
1159 hidnplayr 219
align 4
1249 hidnplayr 220
ETH_receiver:
1257 hidnplayr 221
 
1473 hidnplayr 222
;        DEBUGF  1,"ETH_Receiver: "
223
;        push    ebx
224
;        mov     esi, esp
225
;        add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
226
;        DEBUGF  1,"Queued packet successfully\n"
227
;        add     esp, 4*3
1159 hidnplayr 228
;
1473 hidnplayr 229
;        ret
1159 hidnplayr 230
;
1473 hidnplayr 231
;  .fail:
232
;        DEBUGF  1,"ETH_IN_QUEUE is full!\n"
233
;        add     esp, 4
234
;        call    kernel_free
235
;        add     esp, 4
1159 hidnplayr 236
;
1473 hidnplayr 237
;        ret
1159 hidnplayr 238
;
1473 hidnplayr 239
;
240
;
241
;;-----------------------------------------------------------------
242
;;
243
;; ETH_Handler:
244
;;
245
;;  Handles all queued eth packets (called from kernel's main_loop)
246
;;
247
;;  IN:  /
248
;;  OUT: /
249
;;
250
;;-----------------------------------------------------------------
251
;align 4
252
;ETH_handler:
253
;
254
;        get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
255
;
256
;        push    ETH_handler
257
;
258
;        lodsd
259
;        mov     ebx, eax
260
;        lodsd
261
;        mov     ecx, eax
262
;        lodsd
263
;        xchg    eax, ecx
264
;        push    ecx
265
;        push    eax
1159 hidnplayr 266
 
267
 
1473 hidnplayr 268
;-----------------------------
269
	mov	eax, [esp]
270
	mov	ecx, [esp+4]
271
;-----------------------------
1249 hidnplayr 272
 
1159 hidnplayr 273
	DEBUGF	1,"ETH_Handler - size: %u\n", ecx
274
	cmp	ecx, 60    ; check packet length
275
	jl	.dump
276
	sub	ecx, ETH_FRAME.Data
277
 
278
	lea	edx, [eax + ETH_FRAME.Data]
279
	mov	ax , [eax + ETH_FRAME.Type]
280
 
281
	cmp	ax, ETHER_IPv4
1196 hidnplayr 282
	je	IPv4_handler
1159 hidnplayr 283
 
284
	cmp	ax, ETHER_ARP
1196 hidnplayr 285
	je	ARP_handler
1159 hidnplayr 286
 
1473 hidnplayr 287
	DEBUGF	2,"Unknown ethernet packet type %x\n", ax
1159 hidnplayr 288
 
289
  .dump:
1473 hidnplayr 290
	DEBUGF	2,"ETH_Handler - dumping\n"
1159 hidnplayr 291
	call	kernel_free
292
	add	esp, 4
293
 
294
  .gohome:
1249 hidnplayr 295
	ret				; return to get more from queue / to caller
1159 hidnplayr 296
 
297
 
298
 
1473 hidnplayr 299
 
300
align 4
301
ETH_handler:
302
ret
303
 
304
 
1159 hidnplayr 305
;-----------------------------------------------------------------
306
;
1249 hidnplayr 307
; ETH_sender:
1159 hidnplayr 308
;
309
;  This function sends an ethernet packet to the correct driver.
310
;
311
;  IN:  Pointer to buffer in [esp]
312
;       size of buffer in [esp+4]
313
;       pointer to device struct in ebx
314
;  OUT: /
315
;
316
;-----------------------------------------------------------------
317
align 4
1249 hidnplayr 318
ETH_sender:
1259 hidnplayr 319
if QUEUE_BEFORE_SENDING
1249 hidnplayr 320
	DEBUGF	1,"ETH_Sender: queuing for device: %x, %u bytes\n", [esp], [esp + 4]
1159 hidnplayr 321
 
1249 hidnplayr 322
	push	ebx
323
	mov	esi, esp
324
	add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
325
	DEBUGF	1,"Queued packet successfully\n"
326
	add	esp, 3*4
1257 hidnplayr 327
 
1249 hidnplayr 328
	ret
1159 hidnplayr 329
 
1249 hidnplayr 330
  .fail:
331
	DEBUGF	1,"ETH_OUT_QUEUE is full!\n"
332
	add	esp, 4
333
	call	kernel_free
334
	add	esp, 4
1257 hidnplayr 335
 
1159 hidnplayr 336
	ret
337
 
338
 
1249 hidnplayr 339
 
340
;-----------------------------------------------------------------
341
;
342
; ETH_send_queued:
343
;
344
;  IN:  /
345
;  OUT: /
346
;
347
;-----------------------------------------------------------------
1159 hidnplayr 348
align 4
349
ETH_send_queued:
350
 
1249 hidnplayr 351
	get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
1159 hidnplayr 352
 
1254 hidnplayr 353
	push	ETH_send_queued 		; this will cause the procedure to check for more packets
354
						; when a single packet is handled
1249 hidnplayr 355
 
1254 hidnplayr 356
	mov	ebx, [esi]
357
	pushd	[esi + 8]
358
	pushd	[esi + 4]
1249 hidnplayr 359
 
360
	DEBUGF	1,"dequeued packet for device %x\n", ebx
1259 hidnplayr 361
end if
1254 hidnplayr 362
	call	[ebx+ETH_DEVICE.transmit]	; we will return to get_from_queue macro after transmitting packet
1159 hidnplayr 363
	call	kernel_free
364
	add	esp, 4 ; pop (balance stack)
1249 hidnplayr 365
 
1257 hidnplayr 366
  .gohome:
1159 hidnplayr 367
	ret
368
 
1249 hidnplayr 369
 
1257 hidnplayr 370
;-----------------------------------------------------------------
1159 hidnplayr 371
;
372
; ETH_struc2dev
373
;
374
; IN: pointer to device struct in ebx
375
;
376
; OUT: edi is -1 on error, device number otherwise
377
;
1257 hidnplayr 378
;-----------------------------------------------------------------
1159 hidnplayr 379
align 4
380
ETH_struc2dev:
1473 hidnplayr 381
	push	ecx
1159 hidnplayr 382
 
383
	mov	ecx, MAX_ETH_DEVICES
384
	mov	edi, ETH_DRV_LIST
385
 
386
 
1473 hidnplayr 387
  .loop:
388
	cmp	ebx, [edi]
389
	jz	.found
390
	add	edi, 4
391
	dec	ecx
392
	jnz	.loop
1159 hidnplayr 393
 
394
	or	edi, -1
395
 
1473 hidnplayr 396
	pop	ecx
1159 hidnplayr 397
	ret
398
 
1473 hidnplayr 399
  .found:
400
	sub	edi, ETH_DRV_LIST
401
	shr	edi, 2
1159 hidnplayr 402
 
1473 hidnplayr 403
	pop	ecx
404
	ret
405
 
406
 
1257 hidnplayr 407
;-----------------------------------------------------------------
1159 hidnplayr 408
;
1257 hidnplayr 409
; ETH_create_packet
1159 hidnplayr 410
;
411
; IN: pointer to source mac in eax
412
;     pointer to destination mac in ebx
413
;     packet size in ecx
414
;     device number in edx
415
;     protocol in di
416
;
1206 hidnplayr 417
; OUT: edi is -1 on error, pointer to buffer otherwise
1159 hidnplayr 418
;      eax points to buffer start
1206 hidnplayr 419
;      ebx is pointer to device structure
1159 hidnplayr 420
;      ecx is unchanged (packet size of embedded data)
1206 hidnplayr 421
;      edx is size of complete buffer
1159 hidnplayr 422
;      esi points to procedure wich needs to be called to send packet
423
;
1257 hidnplayr 424
;-----------------------------------------------------------------
1159 hidnplayr 425
align 4
1249 hidnplayr 426
ETH_create_packet:
1159 hidnplayr 427
 
1473 hidnplayr 428
	DEBUGF	1,"Creating Ethernet Packet (size=%u): \n", ecx
1159 hidnplayr 429
 
1206 hidnplayr 430
	cmp	ecx, 1500
1159 hidnplayr 431
	jg	.exit
432
 
433
	push	ecx di eax ebx edx
434
 
435
	add	ecx, ETH_FRAME.Data
436
	push	ecx
437
	push	ecx
438
	call	kernel_alloc
439
	test	eax, eax
440
	jz	.pop_exit
441
 
442
	pop	ecx
443
	pop	edx
444
 
445
	mov	edi, eax
446
	pop	esi
447
	movsd
448
	movsw
449
	pop	esi
450
	movsd
451
	movsw
452
	pop	ax
453
	stosw
454
 
455
	lea	eax, [edi - ETH_FRAME.Data]  ; Set eax to buffer start
1206 hidnplayr 456
	mov	edx, ecx		     ; Set ebx to complete buffer size
1159 hidnplayr 457
	pop	ecx
1249 hidnplayr 458
	mov	esi, ETH_sender
1159 hidnplayr 459
 
1206 hidnplayr 460
	xor	ebx, ebx			;;;; TODO: Fixme
461
	mov	ebx, [ETH_DRV_LIST + ebx]
1159 hidnplayr 462
 
1206 hidnplayr 463
	cmp	edx, 46 + ETH_FRAME.Data    ; If data size is less then 46, add padding bytes
464
	jg	.continue
465
	mov	edx, 46 + ETH_FRAME.Data
466
       .continue:
467
 
1473 hidnplayr 468
	DEBUGF	1,"done: %x size:%u device:%x\n", eax, edx, ebx
1159 hidnplayr 469
	ret
470
 
471
  .pop_exit:
1473 hidnplayr 472
	DEBUGF	2,"Out of ram space!!\n"
1159 hidnplayr 473
	add	esp, 18
1206 hidnplayr 474
	or	edi,-1
475
	ret
476
 
1159 hidnplayr 477
  .exit:
1473 hidnplayr 478
	DEBUGF	2,"Packet too large!\n"
1159 hidnplayr 479
	or	edi, -1
480
	ret
481
 
482
 
483
 
1257 hidnplayr 484
;-----------------------------------------------------------------
1159 hidnplayr 485
;
486
; ETH_API
487
;
488
; This function is called by system function 75
489
;
490
; IN:  subfunction number in bl
491
;      device number in bh
492
;      ecx, edx, .. depends on subfunction
493
;
494
; OUT:
495
;
1257 hidnplayr 496
;-----------------------------------------------------------------
1159 hidnplayr 497
align 4
498
ETH_API:
499
 
500
	movzx	eax, bh
501
	shl	eax, 2
502
 
503
	test	bl, bl
504
	jz	.packets_tx	; 0
505
	dec	bl
506
	jz	.packets_rx	; 1
507
	dec	bl
508
	jz	.bytes_tx	; 2
509
	dec	bl
510
	jz	.bytes_rx	; 3
511
	dec	bl
512
	jz	.read_mac	; 4
513
	dec	bl
514
	jz	.write_mac	; 5
515
	dec	bl
516
	jz	.in_queue	; 6
517
	dec	bl
518
	jz	.out_queue	; 7
519
 
520
.error:
521
	mov	eax, -1
522
	ret
523
 
524
.packets_tx:
525
	add	eax, ETH_DRV_LIST
1171 hidnplayr 526
	mov	eax, dword [eax]
527
	mov	eax, dword [eax + ETH_DEVICE.packets_tx]
528
 
1159 hidnplayr 529
	ret
530
 
531
.packets_rx:
532
	add	eax, ETH_DRV_LIST
1171 hidnplayr 533
	mov	eax, dword [eax]
534
	mov	eax, dword [eax + ETH_DEVICE.packets_rx]
1159 hidnplayr 535
	ret
536
 
537
.bytes_tx:
538
	add	eax, ETH_DRV_LIST
1171 hidnplayr 539
	mov	eax, dword [eax]
1241 clevermous 540
	mov	ebx, dword [eax + ETH_DEVICE.bytes_tx + 4]
1174 hidnplayr 541
	mov	eax, dword [eax + ETH_DEVICE.bytes_tx]
542
	mov	[esp+20+4], ebx 			; TODO: fix this ugly code
1159 hidnplayr 543
	ret
544
 
545
.bytes_rx:
546
	add	eax, ETH_DRV_LIST
1171 hidnplayr 547
	mov	eax, dword [eax]
1174 hidnplayr 548
	mov	ebx, dword [eax + ETH_DEVICE.bytes_rx + 4]
549
	mov	eax, dword [eax + ETH_DEVICE.bytes_rx]
550
	mov	[esp+20+4], ebx 			; TODO: fix this ugly code
1159 hidnplayr 551
	ret
552
 
1174 hidnplayr 553
 
1159 hidnplayr 554
.read_mac:
555
	add	eax, ETH_DRV_LIST
556
	mov	eax, [eax]
557
;        push    eax
558
;        call    dword [eax + ETH_DEVICE.get_MAC]
559
;        pop     eax
560
	movzx	ebx, word [eax + ETH_DEVICE.mac]
561
	mov	eax, dword [eax + ETH_DEVICE.mac + 2]
1171 hidnplayr 562
	mov	[esp+20+4], ebx 			; TODO: fix this ugly code
1159 hidnplayr 563
	ret
564
 
565
.write_mac:
566
	push	ecx
567
	push	dx
568
	add	eax, ETH_DRV_LIST
569
	mov	eax, [eax]
570
	mov	eax, dword [eax + ETH_DEVICE.set_MAC]
571
	call	eax
572
	ret
573
 
574
.in_queue:
575
	add	eax, ETH_IN_QUEUE
576
	mov	eax, [eax + queue.size]
577
	ret
578
 
579
.out_queue:
1259 hidnplayr 580
if QUEUE_BEFORE_SENDING
1159 hidnplayr 581
	add	eax, ETH_OUT_QUEUE
582
	mov	eax, [eax + queue.size]
1259 hidnplayr 583
else
584
	mov	eax, -1
585
end if
1159 hidnplayr 586
	ret