Subversion Repositories Kolibri OS

Rev

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