Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved.    ;;
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
 
17
$Revision: 983 $
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
49
uglobal
50
 
51
	ETH_RUNNING	dd  ?
52
	ETH_DRV_LIST	rd  MAX_ETH_DEVICES
53
	ETH_IN_QUEUE	rd  3*ETH_QUEUE_SIZE+3
54
	ETH_OUT_QUEUE	rd  3*ETH_QUEUE_SIZE+3
55
endg
56
 
57
 
58
;-----------------------------------------------
59
;
60
; ETH_init
61
;
62
;  This function resets all ethernet variables
63
;
64
;  IN:  /
65
;  OUT: /
66
;
67
;-----------------------------------------------
68
 
69
align 4
70
ETH_init:
71
 
72
	xor	eax, eax
73
	mov	edi, ETH_RUNNING
74
	mov	ecx, (1+MAX_ETH_DEVICES)
75
	rep	stosd
76
 
1174 hidnplayr 77
	mov	dword [ETH_IN_QUEUE], ETH_QUEUE_SIZE
1159 hidnplayr 78
	mov	dword [ETH_IN_QUEUE+4], ETH_IN_QUEUE + queue.data
79
	mov	dword [ETH_IN_QUEUE+8], ETH_IN_QUEUE + queue.data
80
 
1174 hidnplayr 81
	mov	dword [ETH_OUT_QUEUE], ETH_QUEUE_SIZE
1159 hidnplayr 82
	mov	dword [ETH_OUT_QUEUE+4], ETH_OUT_QUEUE + queue.data
83
	mov	dword [ETH_OUT_QUEUE+8], ETH_OUT_QUEUE + queue.data
84
 
85
	ret
86
 
87
 
88
;---------------------------------------------------------
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
;
98
;---------------------------------------------------------
99
 
100
align 4
101
ETH_Add_Device:
102
 
1185 hidnplayr 103
	DEBUGF	1,"ETH_Add_Device: %x ", ebx
1174 hidnplayr 104
 
105
	mov	eax, [ETH_RUNNING]
106
	cmp	eax, MAX_ETH_DEVICES
1159 hidnplayr 107
	jge	.error
108
 
1174 hidnplayr 109
	test	eax, eax
110
	jnz	.notfirst
111
	mov	dword [ETH_IN_QUEUE], eax
112
	mov	dword [ETH_OUT_QUEUE], eax
113
      .notfirst:
114
 
1159 hidnplayr 115
	mov	eax, ebx
116
	mov	ecx, MAX_ETH_DEVICES	  ; We need to check whole list because a device may be removed without re-organizing list
117
	mov	edi, ETH_DRV_LIST
118
 
119
	cld
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
164
ETH_Remove_Device:
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
209
ETH_Receiver:
210
	DEBUGF	1,"ETH_Receiver \n"
211
 
212
	add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
213
 
214
  .gohome:
215
	ret
216
 
217
 
218
 
219
 
220
 
221
;-------------------------------------------------------------
222
;
223
; ETH_Handler:
224
;
225
;  Handles all queued eth packets (called from kernel's main_loop)
226
;
227
;  IN:  /
228
;  OUT: /
229
;
230
;-------------------------------------------------------------
231
 
232
align 4
233
ETH_Handler:
234
 
235
	get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
236
 
237
	DEBUGF	1,"ETH_Handler - size: %u\n", ecx
238
	cmp	ecx, 60    ; check packet length
239
	jl	.dump
240
	sub	ecx, ETH_FRAME.Data
241
 
242
	lea	edx, [eax + ETH_FRAME.Data]
243
	mov	ax , [eax + ETH_FRAME.Type]
244
 
245
	cmp	ax, ETHER_IPv4
246
	je	IPv4_Handler
247
 
248
	cmp	ax, ETHER_ARP
249
	je	ARP_Handler
250
 
251
	DEBUGF	1,"Unknown ethernet packet type %x\n", ax
252
 
253
  .dump:
254
	DEBUGF	1,"Dumping packet\n"
255
	call	kernel_free
256
	add	esp, 4
257
 
258
  .gohome:
259
	ret				; return 1. to get more from queue / 2. to caller
260
 
261
 
262
 
263
;-----------------------------------------------------------------
264
;
265
; ETH_Sender:
266
;
267
;  This function sends an ethernet packet to the correct driver.
268
;
269
;  IN:  Pointer to buffer in [esp]
270
;       size of buffer in [esp+4]
271
;       pointer to device struct in ebx
272
;  OUT: /
273
;
274
;-----------------------------------------------------------------
275
 
276
align 4
277
ETH_Sender:
278
	DEBUGF	1,"ETH_Sender \n"
279
 
280
	add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
281
 
282
  .gohome:
283
	ret
284
 
285
 
286
align 4
287
ETH_send_queued:
288
 
289
	get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
290
 
291
	call	ETH_struc2dev		 ; convert struct ptr to device num (this way we know if driver is still mounted)
292
	cmp	edi, -1
293
	je	.fail
294
 
295
	DEBUGF 1,"ETH_Sender - device: %u\n", edi
296
 
297
	jmp	[ebx+ETH_DEVICE.transmit]
298
 
299
     .fail:
300
	call	kernel_free
301
	add	esp, 4 ; pop (balance stack)
302
	DEBUGF 1,"ETH_Sender - fail\n"
303
     .gohome:
304
	ret
305
 
306
;---------------------------------------------------------------------------
307
;
308
; ETH_struc2dev
309
;
310
; IN: pointer to device struct in ebx
311
;
312
; OUT: edi is -1 on error, device number otherwise
313
;
314
;---------------------------------------------------------------------------
315
 
316
align 4
317
ETH_struc2dev:
318
	push	eax ecx
319
 
320
	mov	eax, ebx
321
	mov	ecx, MAX_ETH_DEVICES
322
	mov	edi, ETH_DRV_LIST
323
 
324
	repne	scasd
325
	jnz	.error
326
 
327
	sub	edi, ETH_DRV_LIST+4
328
	shr	edi, 2
329
 
330
	pop	ecx eax
331
	ret
332
  .error:
333
	or	edi, -1
334
	pop	ecx eax
335
 
336
	ret
337
 
338
 
339
;---------------------------------------------------------------------------
340
;
341
; ETH_create_Packet
342
;
343
; IN: pointer to source mac in eax
344
;     pointer to destination mac in ebx
345
;     packet size in ecx
346
;     device number in edx
347
;     protocol in di
348
;
349
; OUT: edi is -1 on error, pointer to buffer otherwise                    ;; TODO: XCHG EDX AND EBX output parameters
350
;      eax points to buffer start
351
;      ebx is size of complete buffer
352
;      ecx is unchanged (packet size of embedded data)
353
;      edx is pointer to device structure
354
;      esi points to procedure wich needs to be called to send packet
355
;
356
;---------------------------------------------------------------------------
357
 
358
align 4
359
ETH_create_Packet:
360
 
361
	DEBUGF 1,"Creating Ethernet Packet:\n"
362
 
363
	cmp	ecx, 60-ETH_FRAME.Data
364
	jl	.exit
365
	cmp	ecx, 1514-ETH_FRAME.Data
366
	jg	.exit
367
 
368
	push	ecx di eax ebx edx
369
 
370
	add	ecx, ETH_FRAME.Data
371
	push	ecx
372
	push	ecx
373
	call	kernel_alloc
374
	test	eax, eax
375
	jz	.pop_exit
376
 
377
	pop	ecx
378
	pop	edx
379
 
380
	DEBUGF 1,"1"
381
	mov	edi, eax
382
	pop	esi
383
	movsd
384
	movsw
385
	DEBUGF 1,"2"
386
	pop	esi
387
	movsd
388
	movsw
389
	DEBUGF 1,"3"
390
	pop	ax
391
	stosw
392
	DEBUGF 1,"4"
393
 
394
	lea	eax, [edi - ETH_FRAME.Data]  ; Set eax to buffer start
395
	mov	ebx, ecx		     ; Set ebx to complete buffer size
396
	pop	ecx
397
	mov	esi, ETH_Sender
398
 
399
	xor	edx, edx ;;;; TODO: Fixme
400
	mov	edx, [ETH_DRV_LIST + edx]
401
 
402
	DEBUGF 1,"done: %x size:%u device:%x\n", eax, ebx, edx
403
	ret
404
 
405
  .pop_exit:
406
	add	esp, 18
407
  .exit:
408
	or	edi, -1
409
	ret
410
 
411
 
412
 
413
 
414
;---------------------------------------------------------------------------
415
;
416
; ETH_API
417
;
418
; This function is called by system function 75
419
;
420
; IN:  subfunction number in bl
421
;      device number in bh
422
;      ecx, edx, .. depends on subfunction
423
;
424
; OUT:
425
;
426
;---------------------------------------------------------------------------
427
 
428
align 4
429
ETH_API:
430
 
431
	movzx	eax, bh
432
	shl	eax, 2
433
 
434
	test	bl, bl
435
	jz	.packets_tx	; 0
436
	dec	bl
437
	jz	.packets_rx	; 1
438
	dec	bl
439
	jz	.bytes_tx	; 2
440
	dec	bl
441
	jz	.bytes_rx	; 3
442
	dec	bl
443
	jz	.read_mac	; 4
444
	dec	bl
445
	jz	.write_mac	; 5
446
	dec	bl
447
	jz	.in_queue	; 6
448
	dec	bl
449
	jz	.out_queue	; 7
450
 
451
.error:
452
	mov	eax, -1
453
	ret
454
 
455
.packets_tx:
456
	add	eax, ETH_DRV_LIST
1171 hidnplayr 457
	mov	eax, dword [eax]
458
	mov	eax, dword [eax + ETH_DEVICE.packets_tx]
459
 
1159 hidnplayr 460
	ret
461
 
462
.packets_rx:
463
	add	eax, ETH_DRV_LIST
1171 hidnplayr 464
	mov	eax, dword [eax]
465
	mov	eax, dword [eax + ETH_DEVICE.packets_rx]
1159 hidnplayr 466
	ret
467
 
468
.bytes_tx:
469
	add	eax, ETH_DRV_LIST
1171 hidnplayr 470
	mov	eax, dword [eax]
1159 hidnplayr 471
	mov	eax, dword [eax + ETH_DEVICE.bytes_tx + 4]
1174 hidnplayr 472
	mov	eax, dword [eax + ETH_DEVICE.bytes_tx]
473
	mov	[esp+20+4], ebx 			; TODO: fix this ugly code
1159 hidnplayr 474
	ret
475
 
476
.bytes_rx:
477
	add	eax, ETH_DRV_LIST
1171 hidnplayr 478
	mov	eax, dword [eax]
1174 hidnplayr 479
	mov	ebx, dword [eax + ETH_DEVICE.bytes_rx + 4]
480
	mov	eax, dword [eax + ETH_DEVICE.bytes_rx]
481
	mov	[esp+20+4], ebx 			; TODO: fix this ugly code
1159 hidnplayr 482
	ret
483
 
1174 hidnplayr 484
 
1159 hidnplayr 485
.read_mac:
486
	add	eax, ETH_DRV_LIST
487
	mov	eax, [eax]
488
;        push    eax
489
;        call    dword [eax + ETH_DEVICE.get_MAC]
490
;        pop     eax
491
	movzx	ebx, word [eax + ETH_DEVICE.mac]
492
	mov	eax, dword [eax + ETH_DEVICE.mac + 2]
1171 hidnplayr 493
	mov	[esp+20+4], ebx 			; TODO: fix this ugly code
1159 hidnplayr 494
	ret
495
 
496
.write_mac:
497
	push	ecx
498
	push	dx
499
	add	eax, ETH_DRV_LIST
500
	mov	eax, [eax]
501
	mov	eax, dword [eax + ETH_DEVICE.set_MAC]
502
	call	eax
503
	ret
504
 
505
.in_queue:
506
	add	eax, ETH_IN_QUEUE
507
	mov	eax, [eax + queue.size]
508
	ret
509
 
510
.out_queue:
511
	add	eax, ETH_OUT_QUEUE
512
	mov	eax, [eax + queue.size]
513
	ret