kolibrios-fun/kernel/branches/net/network/ethernet.inc
hidnplayr 602924a5b5 compile netcfg on unix
fixed bug in netcfg created in last revision
netcfg gives error msg when driver is not loaded
zeroconfig now works with latest version of libini
also fixed use of static and link-local ip in zeroconfig
initial IPv4 variables are now 0.0.0.0 instead of 255.255.255.255
created kernel function that shows number of active network devices 
fixed the use of temp mac variable in IPV4.inc (variable is now in stack)
rewrite of ARP code, needs full testing/debugging (new application needed: ARP manager)
port numbers are now in INET byte order, as is in posix standards

git-svn-id: svn://kolibrios.org@1196 a494cfbc-eb01-0410-851d-a64ba20cac60
2009-10-05 20:47:27 +00:00

515 lines
10 KiB
PHP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ETHERNET.INC ;;
;; ;;
;; Ethernet network layer for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision: 983 $
MAX_ETH_DEVICES equ MAX_NET_DEVICES
ETH_QUEUE_SIZE equ 16
struct ETH_FRAME
.DstMAC dp ? ; destination MAC-address [6 bytes]
.SrcMAC dp ? ; source MAC-address [6 bytes]
.Type dw ? ; type of the upper-layer protocol [2 bytes]
.Data: ; data [46-1500 bytes]
ends
struct ETH_DEVICE
.unload dd ?
.reset dd ?
.transmit dd ?
.set_MAC dd ?
.get_MAC dd ?
.set_mode dd ?
.get_mode dd ?
.bytes_tx dq ?
.bytes_rx dq ?
.packets_tx dd ?
.packets_rx dd ?
.mode dd ? ; This dword contains cable status (10mbit/100mbit, full/half duplex, auto negotiation or not,..)
.name dd ?
.mac dp ?
ends ; the rest of the device struct depends on the type of device
align 4
iglobal
ETH_BROADCAST dp 0xffffffffffff
endg
align 4
uglobal
ETH_RUNNING dd ?
ETH_DRV_LIST rd MAX_ETH_DEVICES
ETH_IN_QUEUE rd 3*ETH_QUEUE_SIZE+3
ETH_OUT_QUEUE rd 3*ETH_QUEUE_SIZE+3
endg
;-----------------------------------------------
;
; ETH_init
;
; This function resets all ethernet variables
;
; IN: /
; OUT: /
;
;-----------------------------------------------
align 4
ETH_init:
xor eax, eax
mov edi, ETH_RUNNING
mov ecx, (1+MAX_ETH_DEVICES)
rep stosd
mov dword [ETH_IN_QUEUE], ETH_QUEUE_SIZE
mov dword [ETH_IN_QUEUE+4], ETH_IN_QUEUE + queue.data
mov dword [ETH_IN_QUEUE+8], ETH_IN_QUEUE + queue.data
mov dword [ETH_OUT_QUEUE], ETH_QUEUE_SIZE
mov dword [ETH_OUT_QUEUE+4], ETH_OUT_QUEUE + queue.data
mov dword [ETH_OUT_QUEUE+8], ETH_OUT_QUEUE + queue.data
ret
;---------------------------------------------------------
;
; ETH_Add_Device:
;
; This function is called by ethernet drivers,
; to register each running ethernet device to the kernel
;
; IN: Pointer to device structure in ebx
; OUT: Device num in eax, -1 on error
;
;---------------------------------------------------------
align 4
ETH_Add_Device:
DEBUGF 1,"ETH_Add_Device: %x ", ebx
mov eax, [ETH_RUNNING]
cmp eax, MAX_ETH_DEVICES
jge .error
test eax, eax
jnz .notfirst
mov dword [ETH_IN_QUEUE], eax
mov dword [ETH_OUT_QUEUE], eax
.notfirst:
mov eax, ebx
mov ecx, MAX_ETH_DEVICES ; We need to check whole list because a device may be removed without re-organizing list
mov edi, ETH_DRV_LIST
cld
repne scasd ; See if device is already in the list
jz .error
xor eax, eax
mov ecx, MAX_ETH_DEVICES
mov edi, ETH_DRV_LIST
repne scasd ; Find empty spot in the list
jnz .error
sub edi, 4
mov [edi], ebx ; add device to list
sub edi, ETH_DRV_LIST ; edi = 4*device num Calculate device number in eax
mov eax, edi ; edx = 4*device num
shr eax, 2
inc [ETH_RUNNING] ; Indicate that one more ethernet device is up and running
DEBUGF 1,"- succes: %u\n",eax
ret
.error:
or eax, -1
DEBUGF 1,"- fail\n"
ret
;--------------------------------
;
; ETH_Remove_Device:
;
; This function is called by ethernet drivers,
; to unregister ethernet devices from the kernel
;
; IN: Pointer to device structure in ebx
; OUT: eax: -1 on error
;
;--------------------------------
align 4
ETH_Remove_Device:
cmp [ETH_RUNNING], 0
je .error
mov eax, ebx
mov ecx, MAX_ETH_DEVICES
mov edi, ETH_DRV_LIST
repne scasd
jnz .error
xor eax, eax
mov dword [edi-4], eax
dec [ETH_RUNNING]
jnz .notlast
mov dword [ETH_IN_QUEUE], ETH_QUEUE_SIZE
mov dword [ETH_OUT_QUEUE], ETH_QUEUE_SIZE
.notlast:
ret
.error:
or eax, -1
ret
;-------------------------------------------------------------
;
; ETH_Receiver:
;
; This function is called by ethernet drivers,
; It pushes the received ethernet packets onto the eth_in_queue
;
; IN: Pointer to buffer in [esp], size of buffer in [esp-4], pointer to eth_device in ebx
; OUT: /
;
;-------------------------------------------------------------
align 4
ETH_Receiver:
DEBUGF 1,"ETH_Receiver \n"
add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
.gohome:
ret
;-------------------------------------------------------------
;
; ETH_Handler:
;
; Handles all queued eth packets (called from kernel's main_loop)
;
; IN: /
; OUT: /
;
;-------------------------------------------------------------
align 4
ETH_handler:
get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
DEBUGF 1,"ETH_Handler - size: %u\n", ecx
cmp ecx, 60 ; check packet length
jl .dump
sub ecx, ETH_FRAME.Data
lea edx, [eax + ETH_FRAME.Data]
mov ax , [eax + ETH_FRAME.Type]
cmp ax, ETHER_IPv4
je IPv4_handler
cmp ax, ETHER_ARP
je ARP_handler
DEBUGF 1,"Unknown ethernet packet type %x\n", ax
.dump:
DEBUGF 1,"Dumping packet\n"
call kernel_free
add esp, 4
.gohome:
ret ; return 1. to get more from queue / 2. to caller
;-----------------------------------------------------------------
;
; ETH_Sender:
;
; This function sends an ethernet packet to the correct driver.
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; OUT: /
;
;-----------------------------------------------------------------
align 4
ETH_Sender:
DEBUGF 1,"ETH_Sender \n"
add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
.gohome:
ret
align 4
ETH_send_queued:
get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
call ETH_struc2dev ; convert struct ptr to device num (this way we know if driver is still mounted)
cmp edi, -1
je .fail
DEBUGF 1,"ETH_Sender - device: %u\n", edi
jmp [ebx+ETH_DEVICE.transmit]
.fail:
call kernel_free
add esp, 4 ; pop (balance stack)
DEBUGF 1,"ETH_Sender - fail\n"
.gohome:
ret
;---------------------------------------------------------------------------
;
; ETH_struc2dev
;
; IN: pointer to device struct in ebx
;
; OUT: edi is -1 on error, device number otherwise
;
;---------------------------------------------------------------------------
align 4
ETH_struc2dev:
push eax ecx
mov eax, ebx
mov ecx, MAX_ETH_DEVICES
mov edi, ETH_DRV_LIST
repne scasd
jnz .error
sub edi, ETH_DRV_LIST+4
shr edi, 2
pop ecx eax
ret
.error:
or edi, -1
pop ecx eax
ret
;---------------------------------------------------------------------------
;
; ETH_create_Packet
;
; IN: pointer to source mac in eax
; pointer to destination mac in ebx
; packet size in ecx
; device number in edx
; protocol in di
;
; OUT: edi is -1 on error, pointer to buffer otherwise ;; TODO: XCHG EDX AND EBX output parameters
; eax points to buffer start
; ebx is size of complete buffer
; ecx is unchanged (packet size of embedded data)
; edx is pointer to device structure
; esi points to procedure wich needs to be called to send packet
;
;---------------------------------------------------------------------------
align 4
ETH_create_Packet:
DEBUGF 1,"Creating Ethernet Packet:\n"
cmp ecx, 60-ETH_FRAME.Data
jl .exit
cmp ecx, 1514-ETH_FRAME.Data
jg .exit
push ecx di eax ebx edx
add ecx, ETH_FRAME.Data
push ecx
push ecx
call kernel_alloc
test eax, eax
jz .pop_exit
pop ecx
pop edx
mov edi, eax
pop esi
movsd
movsw
pop esi
movsd
movsw
pop ax
stosw
lea eax, [edi - ETH_FRAME.Data] ; Set eax to buffer start
mov ebx, ecx ; Set ebx to complete buffer size
pop ecx
mov esi, ETH_Sender
xor edx, edx ;;;; TODO: Fixme
mov edx, [ETH_DRV_LIST + edx]
DEBUGF 1,"done: %x size:%u device:%x\n", eax, ebx, edx
ret
.pop_exit:
add esp, 18
.exit:
or edi, -1
ret
;---------------------------------------------------------------------------
;
; ETH_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
ETH_API:
movzx eax, bh
shl eax, 2
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
dec bl
jz .bytes_tx ; 2
dec bl
jz .bytes_rx ; 3
dec bl
jz .read_mac ; 4
dec bl
jz .write_mac ; 5
dec bl
jz .in_queue ; 6
dec bl
jz .out_queue ; 7
.error:
mov eax, -1
ret
.packets_tx:
add eax, ETH_DRV_LIST
mov eax, dword [eax]
mov eax, dword [eax + ETH_DEVICE.packets_tx]
ret
.packets_rx:
add eax, ETH_DRV_LIST
mov eax, dword [eax]
mov eax, dword [eax + ETH_DEVICE.packets_rx]
ret
.bytes_tx:
add eax, ETH_DRV_LIST
mov eax, dword [eax]
mov eax, dword [eax + ETH_DEVICE.bytes_tx + 4]
mov eax, dword [eax + ETH_DEVICE.bytes_tx]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
.bytes_rx:
add eax, ETH_DRV_LIST
mov eax, dword [eax]
mov ebx, dword [eax + ETH_DEVICE.bytes_rx + 4]
mov eax, dword [eax + ETH_DEVICE.bytes_rx]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
.read_mac:
add eax, ETH_DRV_LIST
mov eax, [eax]
; push eax
; call dword [eax + ETH_DEVICE.get_MAC]
; pop eax
movzx ebx, word [eax + ETH_DEVICE.mac]
mov eax, dword [eax + ETH_DEVICE.mac + 2]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
.write_mac:
push ecx
push dx
add eax, ETH_DRV_LIST
mov eax, [eax]
mov eax, dword [eax + ETH_DEVICE.set_MAC]
call eax
ret
.in_queue:
add eax, ETH_IN_QUEUE
mov eax, [eax + queue.size]
ret
.out_queue:
add eax, ETH_OUT_QUEUE
mov eax, [eax + queue.size]
ret