Subversion Repositories Kolibri OS

Rev

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