Subversion Repositories Kolibri OS

Rev

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