Subversion Repositories Kolibri OS

Rev

Details | 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: 1274 $
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
156
	DEBUGF	1,"- fail\n"
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
 
1249 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
1257 hidnplayr 228
 
1249 hidnplayr 229
	ret
1159 hidnplayr 230
 
1249 hidnplayr 231
  .fail:
232
	DEBUGF	1,"ETH_IN_QUEUE is full!\n"
233
	add	esp, 4
234
	call	kernel_free
235
	add	esp, 4
1257 hidnplayr 236
 
1159 hidnplayr 237
	ret
238
 
239
 
240
 
1257 hidnplayr 241
;-----------------------------------------------------------------
1159 hidnplayr 242
;
243
; ETH_Handler:
244
;
245
;  Handles all queued eth packets (called from kernel's main_loop)
246
;
247
;  IN:  /
248
;  OUT: /
249
;
1257 hidnplayr 250
;-----------------------------------------------------------------
1159 hidnplayr 251
align 4
1196 hidnplayr 252
ETH_handler:
1159 hidnplayr 253
 
1249 hidnplayr 254
	get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
1159 hidnplayr 255
 
1249 hidnplayr 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
266
 
1159 hidnplayr 267
	DEBUGF	1,"ETH_Handler - size: %u\n", ecx
268
	cmp	ecx, 60    ; check packet length
269
	jl	.dump
270
	sub	ecx, ETH_FRAME.Data
271
 
272
	lea	edx, [eax + ETH_FRAME.Data]
273
	mov	ax , [eax + ETH_FRAME.Type]
274
 
275
	cmp	ax, ETHER_IPv4
1196 hidnplayr 276
	je	IPv4_handler
1159 hidnplayr 277
 
278
	cmp	ax, ETHER_ARP
1196 hidnplayr 279
	je	ARP_handler
1159 hidnplayr 280
 
281
	DEBUGF	1,"Unknown ethernet packet type %x\n", ax
282
 
283
  .dump:
284
	DEBUGF	1,"Dumping packet\n"
285
	call	kernel_free
286
	add	esp, 4
287
 
288
  .gohome:
1249 hidnplayr 289
	ret				; return to get more from queue / to caller
1159 hidnplayr 290
 
291
 
292
 
293
;-----------------------------------------------------------------
294
;
1249 hidnplayr 295
; ETH_sender:
1159 hidnplayr 296
;
297
;  This function sends an ethernet packet to the correct driver.
298
;
299
;  IN:  Pointer to buffer in [esp]
300
;       size of buffer in [esp+4]
301
;       pointer to device struct in ebx
302
;  OUT: /
303
;
304
;-----------------------------------------------------------------
305
align 4
1249 hidnplayr 306
ETH_sender:
1259 hidnplayr 307
if QUEUE_BEFORE_SENDING
1249 hidnplayr 308
	DEBUGF	1,"ETH_Sender: queuing for device: %x, %u bytes\n", [esp], [esp + 4]
1159 hidnplayr 309
 
1249 hidnplayr 310
	push	ebx
311
	mov	esi, esp
312
	add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
313
	DEBUGF	1,"Queued packet successfully\n"
314
	add	esp, 3*4
1257 hidnplayr 315
 
1249 hidnplayr 316
	ret
1159 hidnplayr 317
 
1249 hidnplayr 318
  .fail:
319
	DEBUGF	1,"ETH_OUT_QUEUE is full!\n"
320
	add	esp, 4
321
	call	kernel_free
322
	add	esp, 4
1257 hidnplayr 323
 
1159 hidnplayr 324
	ret
325
 
326
 
1249 hidnplayr 327
 
328
;-----------------------------------------------------------------
329
;
330
; ETH_send_queued:
331
;
332
;  IN:  /
333
;  OUT: /
334
;
335
;-----------------------------------------------------------------
1159 hidnplayr 336
align 4
337
ETH_send_queued:
338
 
1249 hidnplayr 339
	get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
1159 hidnplayr 340
 
1254 hidnplayr 341
	push	ETH_send_queued 		; this will cause the procedure to check for more packets
342
						; when a single packet is handled
1249 hidnplayr 343
 
1254 hidnplayr 344
	mov	ebx, [esi]
345
	pushd	[esi + 8]
346
	pushd	[esi + 4]
1249 hidnplayr 347
 
348
	DEBUGF	1,"dequeued packet for device %x\n", ebx
1259 hidnplayr 349
end if
1254 hidnplayr 350
	call	[ebx+ETH_DEVICE.transmit]	; we will return to get_from_queue macro after transmitting packet
1159 hidnplayr 351
	call	kernel_free
352
	add	esp, 4 ; pop (balance stack)
1249 hidnplayr 353
 
1257 hidnplayr 354
  .gohome:
1159 hidnplayr 355
	ret
356
 
1249 hidnplayr 357
 
1257 hidnplayr 358
;-----------------------------------------------------------------
1159 hidnplayr 359
;
360
; ETH_struc2dev
361
;
362
; IN: pointer to device struct in ebx
363
;
364
; OUT: edi is -1 on error, device number otherwise
365
;
1257 hidnplayr 366
;-----------------------------------------------------------------
1159 hidnplayr 367
align 4
368
ETH_struc2dev:
369
	push	eax ecx
370
 
371
	mov	eax, ebx
372
	mov	ecx, MAX_ETH_DEVICES
373
	mov	edi, ETH_DRV_LIST
374
 
375
	repne	scasd
376
	jnz	.error
377
 
378
	sub	edi, ETH_DRV_LIST+4
379
	shr	edi, 2
380
 
381
	pop	ecx eax
382
	ret
383
  .error:
384
	or	edi, -1
385
	pop	ecx eax
386
 
387
	ret
388
 
389
 
1257 hidnplayr 390
;-----------------------------------------------------------------
1159 hidnplayr 391
;
1257 hidnplayr 392
; ETH_create_packet
1159 hidnplayr 393
;
394
; IN: pointer to source mac in eax
395
;     pointer to destination mac in ebx
396
;     packet size in ecx
397
;     device number in edx
398
;     protocol in di
399
;
1206 hidnplayr 400
; OUT: edi is -1 on error, pointer to buffer otherwise
1159 hidnplayr 401
;      eax points to buffer start
1206 hidnplayr 402
;      ebx is pointer to device structure
1159 hidnplayr 403
;      ecx is unchanged (packet size of embedded data)
1206 hidnplayr 404
;      edx is size of complete buffer
1159 hidnplayr 405
;      esi points to procedure wich needs to be called to send packet
406
;
1257 hidnplayr 407
;-----------------------------------------------------------------
1159 hidnplayr 408
align 4
1249 hidnplayr 409
ETH_create_packet:
1159 hidnplayr 410
 
1206 hidnplayr 411
	DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx
1159 hidnplayr 412
 
1206 hidnplayr 413
	cmp	ecx, 1500
1159 hidnplayr 414
	jg	.exit
415
 
416
	push	ecx di eax ebx edx
417
 
418
	add	ecx, ETH_FRAME.Data
419
	push	ecx
420
	push	ecx
421
	call	kernel_alloc
422
	test	eax, eax
423
	jz	.pop_exit
424
 
425
	pop	ecx
426
	pop	edx
427
 
428
	mov	edi, eax
429
	pop	esi
430
	movsd
431
	movsw
432
	pop	esi
433
	movsd
434
	movsw
435
	pop	ax
436
	stosw
437
 
438
	lea	eax, [edi - ETH_FRAME.Data]  ; Set eax to buffer start
1206 hidnplayr 439
	mov	edx, ecx		     ; Set ebx to complete buffer size
1159 hidnplayr 440
	pop	ecx
1249 hidnplayr 441
	mov	esi, ETH_sender
1159 hidnplayr 442
 
1206 hidnplayr 443
	xor	ebx, ebx			;;;; TODO: Fixme
444
	mov	ebx, [ETH_DRV_LIST + ebx]
1159 hidnplayr 445
 
1206 hidnplayr 446
	cmp	edx, 46 + ETH_FRAME.Data    ; If data size is less then 46, add padding bytes
447
	jg	.continue
448
	mov	edx, 46 + ETH_FRAME.Data
449
       .continue:
450
 
451
	DEBUGF 1,"done: %x size:%u device:%x\n", eax, edx, ebx
1159 hidnplayr 452
	ret
453
 
454
  .pop_exit:
1206 hidnplayr 455
	DEBUGF 1,"Out of ram space!!\n"
1159 hidnplayr 456
	add	esp, 18
1206 hidnplayr 457
	or	edi,-1
458
	ret
459
 
1159 hidnplayr 460
  .exit:
1206 hidnplayr 461
	DEBUGF 1,"Packet too large!\n"
1159 hidnplayr 462
	or	edi, -1
463
	ret
464
 
465
 
466
 
1257 hidnplayr 467
;-----------------------------------------------------------------
1159 hidnplayr 468
;
469
; ETH_API
470
;
471
; This function is called by system function 75
472
;
473
; IN:  subfunction number in bl
474
;      device number in bh
475
;      ecx, edx, .. depends on subfunction
476
;
477
; OUT:
478
;
1257 hidnplayr 479
;-----------------------------------------------------------------
1159 hidnplayr 480
align 4
481
ETH_API:
482
 
483
	movzx	eax, bh
484
	shl	eax, 2
485
 
486
	test	bl, bl
487
	jz	.packets_tx	; 0
488
	dec	bl
489
	jz	.packets_rx	; 1
490
	dec	bl
491
	jz	.bytes_tx	; 2
492
	dec	bl
493
	jz	.bytes_rx	; 3
494
	dec	bl
495
	jz	.read_mac	; 4
496
	dec	bl
497
	jz	.write_mac	; 5
498
	dec	bl
499
	jz	.in_queue	; 6
500
	dec	bl
501
	jz	.out_queue	; 7
502
 
503
.error:
504
	mov	eax, -1
505
	ret
506
 
507
.packets_tx:
508
	add	eax, ETH_DRV_LIST
1171 hidnplayr 509
	mov	eax, dword [eax]
510
	mov	eax, dword [eax + ETH_DEVICE.packets_tx]
511
 
1159 hidnplayr 512
	ret
513
 
514
.packets_rx:
515
	add	eax, ETH_DRV_LIST
1171 hidnplayr 516
	mov	eax, dword [eax]
517
	mov	eax, dword [eax + ETH_DEVICE.packets_rx]
1159 hidnplayr 518
	ret
519
 
520
.bytes_tx:
521
	add	eax, ETH_DRV_LIST
1171 hidnplayr 522
	mov	eax, dword [eax]
1241 clevermous 523
	mov	ebx, dword [eax + ETH_DEVICE.bytes_tx + 4]
1174 hidnplayr 524
	mov	eax, dword [eax + ETH_DEVICE.bytes_tx]
525
	mov	[esp+20+4], ebx 			; TODO: fix this ugly code
1159 hidnplayr 526
	ret
527
 
528
.bytes_rx:
529
	add	eax, ETH_DRV_LIST
1171 hidnplayr 530
	mov	eax, dword [eax]
1174 hidnplayr 531
	mov	ebx, dword [eax + ETH_DEVICE.bytes_rx + 4]
532
	mov	eax, dword [eax + ETH_DEVICE.bytes_rx]
533
	mov	[esp+20+4], ebx 			; TODO: fix this ugly code
1159 hidnplayr 534
	ret
535
 
1174 hidnplayr 536
 
1159 hidnplayr 537
.read_mac:
538
	add	eax, ETH_DRV_LIST
539
	mov	eax, [eax]
540
;        push    eax
541
;        call    dword [eax + ETH_DEVICE.get_MAC]
542
;        pop     eax
543
	movzx	ebx, word [eax + ETH_DEVICE.mac]
544
	mov	eax, dword [eax + ETH_DEVICE.mac + 2]
1171 hidnplayr 545
	mov	[esp+20+4], ebx 			; TODO: fix this ugly code
1159 hidnplayr 546
	ret
547
 
548
.write_mac:
549
	push	ecx
550
	push	dx
551
	add	eax, ETH_DRV_LIST
552
	mov	eax, [eax]
553
	mov	eax, dword [eax + ETH_DEVICE.set_MAC]
554
	call	eax
555
	ret
556
 
557
.in_queue:
558
	add	eax, ETH_IN_QUEUE
559
	mov	eax, [eax + queue.size]
560
	ret
561
 
562
.out_queue:
1259 hidnplayr 563
if QUEUE_BEFORE_SENDING
1159 hidnplayr 564
	add	eax, ETH_OUT_QUEUE
565
	mov	eax, [eax + queue.size]
1259 hidnplayr 566
else
567
	mov	eax, -1
568
end if
1159 hidnplayr 569
	ret