-Refactoring of network drivers.

-Ommitted unnescessary copying of packets in some drivers.
-Some small updates in TCP (perhaps 50% done ?)

git-svn-id: svn://kolibrios.org@1519 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2010-07-15 18:54:19 +00:00
parent bec4526284
commit 084d99548d
16 changed files with 2245 additions and 3456 deletions

View File

@ -1,22 +1,18 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; 3Com network driver for KolibriOS ;;
;; ;;
;; Ported to KolibriOS net-branch by hidnplayr (28/05/10) ;;
;; ;;
;; Thanks to: scrap metal recyclers, whom provide me with ;;
;; loads of hardware ;;
;; diamond: who makes me understand KolibriOS ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Ethernet Driver for KolibriOS
;;
;; 3c59x.asm
;; Ported to KolibriOS net-branch by hidnplayr (28/05/10)
;;
;; Thanks to: scrap metal recyclers, whom provide me with loads of hardware
;; diamond: who makes me understand KolibriOS
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 3C59X.INC ;;
@ -84,13 +80,14 @@
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PROMISCIOUS equ 1
format MS COFF
API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
MAX_DEVICES equ 16
FORCE_FD equ 0 ; forcing full duplex mode makes sense at some cards and link types
PROMISCIOUS equ 0 ; enables promiscous mode
DEBUG equ 1
__DEBUG__ equ 1
@ -101,55 +98,18 @@ include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
public START
public service_proc
public version
virtual at ebx
device:
ETH_DEVICE
.rx_buffer dd ?
.tx_buffer dd ?
.dpd_buffer dd ?
.upd_buffer dd ?
.curr_upd dd ?
.prev_dpd dd ?
.io_addr dd ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
.prev_tx_frame dd ?
.ver_id db ?
.full_bus_master db ?
.has_hwcksm db ?
.preamble db ?
.dn_list_ptr_cleared db ?
.self_directed_packet rb 20
.size = $ - device
end virtual
struc DPD { ; Download Packet Descriptor
.next_ptr dd ?
.frame_start_hdr dd ?
.frag_addr dd ? ; for packet data
.frag_len dd ? ; for packet data
.realaddr dd ?
.size = 32
.next_ptr dd ?
.frame_start_hdr dd ?
.frag_addr dd ? ; for packet data
.frag_len dd ? ; for packet data
.realaddr dd ?
.size = 32
}
virtual at 0
@ -159,12 +119,12 @@ end virtual
struc UPD { ; Upload Packet Descriptor
.next_ptr dd ?
.pkt_status dd ?
.frag_addr dd ?
.frag_len dd ? ; for packet data
.realaddr dd ?
.size = 32
.next_ptr dd ?
.pkt_status dd ?
.frag_addr dd ?
.frag_len dd ? ; for packet data
.realaddr dd ?
.size = 32
}
@ -172,17 +132,11 @@ virtual at 0
upd UPD
end virtual
MAX_DEVICES equ 16
FORCE_FD equ 0 ; forcing full duplex mode makes sense at some cards and link types
; Ethernet frame symbols
ETH_ALEN equ 6
ETH_HLEN equ (2*ETH_ALEN+2)
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
; mininmum 64bytes frame length
; Registers
REG_POWER_MGMT_CTRL equ 0x7c
REG_UP_LIST_PTR equ 0x38
@ -193,9 +147,11 @@ end virtual
REG_TX_STATUS equ 0x1b
REG_RX_STATUS equ 0x18
REG_TX_DATA equ 0x10
; Common window registers
REG_INT_STATUS equ 0xe
REG_COMMAND equ 0xe
; Register window 7
REG_MASTER_STATUS equ 0xc
REG_POWER_MGMT_EVENT equ 0xc
@ -203,6 +159,7 @@ end virtual
REG_VLAN_ETHER_TYPE equ 0x4
REG_VLAN_MASK equ 0x0
REG_MASTER_ADDRESS equ 0x0
; Register window 6
REG_BYTES_XMITTED_OK equ 0xc
REG_BYTES_RCVD_OK equ 0xa
@ -216,6 +173,7 @@ end virtual
REG_MULTIPLE_COLLISIONS equ 0x2
REG_SQE_ERRORS equ 0x1
REG_CARRIER_LOST equ 0x0
; Register window 5
REG_INDICATION_ENABLE equ 0xc
REG_INTERRUPT_ENABLE equ 0xa
@ -223,6 +181,7 @@ end virtual
REG_RX_FILTER equ 0x8
REG_RX_EARLY_THRESH equ 0x6
REG_TX_START_THRESH equ 0x0
; Register window 4
REG_UPPER_BYTES_OK equ 0xe
REG_BAD_SSD equ 0xc
@ -231,8 +190,10 @@ end virtual
REG_NETWORK_DIAGNOSTIC equ 0x6
REG_FIFO_DIAGNOSTIC equ 0x4
REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported
; Bits in register window 4
BIT_AUTOSELECT equ 24
; Register window 3
REG_TX_FREE equ 0xc
REG_RX_FREE equ 0xa
@ -240,6 +201,7 @@ end virtual
REG_MAC_CONTROL equ 0x6
REG_MAX_PKT_SIZE equ 0x4
REG_INTERNAL_CONFIG equ 0x0
; Register window 2
REG_RESET_OPTIONS equ 0xc
REG_STATION_MASK_HI equ 0xa
@ -248,6 +210,7 @@ end virtual
REG_STATION_ADDRESS_HI equ 0x4
REG_STATION_ADDRESS_MID equ 0x2
REG_STATION_ADDRESS_LO equ 0x0
; Register window 1
REG_TRIGGER_BITS equ 0xc
REG_SOS_BITS equ 0xa
@ -258,34 +221,42 @@ end virtual
REG_SMB_STATUS equ 0x2
REG_SMB_ADDRESS equ 0x1
REG_SMB_FIFO_DATA equ 0x0
; Register window 0
REG_EEPROM_DATA equ 0xc
REG_EEPROM_COMMAND equ 0xa
REG_BIOS_ROM_DATA equ 0x8
REG_BIOS_ROM_ADDR equ 0x4
; Physical management bits
BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData
BIT_MGMT_DATA equ 1 ; MII management data bit
BIT_MGMT_CLK equ 0 ; MII management clock
; MII commands
MII_CMD_MASK equ (1111b shl 10)
MII_CMD_READ equ (0110b shl 10)
MII_CMD_WRITE equ (0101b shl 10)
; MII registers
REG_MII_BMCR equ 0 ; basic mode control register
REG_MII_BMSR equ 1 ; basic mode status register
REG_MII_ANAR equ 4 ; auto negotiation advertisement register
REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register
REG_MII_ANER equ 6 ; auto negotiation expansion register
; MII bits
BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete
BIT_MII_PREAMBLE_SUPPRESSION equ 6
; eeprom bits and commands
EEPROM_CMD_READ equ 0x80
EEPROM_BIT_BUSY equ 15
; eeprom registers
EEPROM_REG_OEM_NODE_ADDR equ 0xa
EEPROM_REG_CAPABILITIES equ 0x10
; Commands for command register
SELECT_REGISTER_WINDOW equ (1 shl 11)
@ -306,7 +277,6 @@ end virtual
EXTRA_PREAMBLE equ 0x4000
; Status
IntLatch equ 0x0001
HostError equ 0x0002
TxComplete equ 0x0004
@ -315,18 +285,15 @@ end virtual
RxEarly equ 0x0020
IntReq equ 0x0040
StatsFull equ 0x0080
DMADone equ 0x0100 ; 1 shl 8
DownComplete equ 0x0200 ; 1 shl 9
UpComplete equ 0x0400 ; 1 shl 10
DMADone equ 0x0100
DownComplete equ 0x0200
UpComplete equ 0x0400
DMAInProgress equ 0x0800 ; 1 shl 11 (DMA controller is still busy)
CmdInProgress equ 0x1000 ; 1 shl 12 (EL3_CMD is still busy)
S_5_INTS equ HostError + RxEarly + UpComplete + DownComplete ; + RxComplete + TxComplete + TxAvailable
S_5_INTS equ HostError + RxEarly + UpComplete + DownComplete ;+ TxComplete + RxComplete + TxAvailable
; Commands
TotalReset equ 0 shl 11
SelectWindow equ 1 shl 11
StartCoax equ 2 shl 11
@ -354,29 +321,47 @@ end virtual
StatsEnable equ 21 shl 11
StatsDisable equ 22 shl 11
StopCoax equ 23 shl 11
SetFilterBit equ 25 shl 11}
SetFilterBit equ 25 shl 11
; Rx mode bits
RxStation equ 1
RxMulticast equ 2
RxBroadcast equ 4
RxProm equ 8
; RX/TX buffers sizes
MAX_ETH_PKT_SIZE equ 1536 ; max packet size
NUM_RX_DESC equ 4 ; a power of 2 number
NUM_TX_DESC equ 4 ; a power of 2 number
RX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE*NUM_RX_DESC)
TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE*NUM_TX_DESC)
MAX_ETH_FRAME_SIZE equ 1520 ; size of ethernet frame + bytes alignment
virtual at ebx
device:
ETH_DEVICE
.dpd_buffer rd (dpd.size*NUM_TX_DESC)/4
.upd_buffer rd (upd.size*NUM_RX_DESC)/4
.curr_upd dd ?
.prev_dpd dd ?
.io_addr dd ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
.prev_tx_frame dd ?
.ver_id db ?
.full_bus_master db ?
.has_hwcksm db ?
.preamble db ?
.dn_list_ptr_cleared db ?
.self_directed_packet rb 20
.size = $ - device
end virtual
section '.flat' code readable align 16
@ -513,21 +498,14 @@ proc service_proc stdcall, ioctl:dword
mov [device.pci_dev], cl
; Now, it's time to find the base io addres of the PCI device
find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
; We've found the io address, find IRQ now
find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
allocate_and_clear [device.tx_buffer], (MAX_ETH_FRAME_SIZE*NUM_TX_DESC), .err
allocate_and_clear [device.rx_buffer], (MAX_ETH_FRAME_SIZE*NUM_RX_DESC), .err
allocate_and_clear [device.dpd_buffer], (dpd.size*NUM_TX_DESC), .err
allocate_and_clear [device.upd_buffer], (dpd.size*NUM_RX_DESC), .err
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
test eax, eax
@ -579,8 +557,6 @@ proc service_proc stdcall, ioctl:dword
; todo: reset device into virgin state
.err:
stdcall KernelFree, [device.rx_buffer]
stdcall KernelFree, [device.tx_buffer]
stdcall KernelFree, ebx
@ -613,7 +589,7 @@ endp
;***************************************************************************
align 4
probe: ; Tested - ok
probe:
DEBUGF 1,"Probing 3com card\n"
@ -671,6 +647,11 @@ probe: ; Tested - ok
jnz .boomerang_func
mov [device.transmit], vortex_transmit
DEBUGF 1,"Device is a vortex type\n"
DEBUGF 1,"I'm sorry but vortex code hasnt been tested yet\n"
DEBUGF 1,"Please contact me on hidnplayr@kolibrios.org\n"
DEBUGF 1,"If you can help me finish it!\n"
or eax, -1
ret
jmp @f
.boomerang_func: ; full bus master, so use boomerang functions
mov [device.transmit], boomerang_transmit
@ -812,6 +793,9 @@ reset:
mov ecx, 6
rep stosd
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
ret
@ -975,13 +959,9 @@ tx_reset:
jnz .tx_reset_loop
.tx_set_prev:
; init last_dpd
mov eax, [device.dpd_buffer]
add eax, (NUM_TX_DESC-1)*dpd.size
lea eax, [device.dpd_buffer + (NUM_TX_DESC-1)*dpd.size]
mov [device.prev_dpd], eax
mov eax, [device.tx_buffer]
add eax, (NUM_TX_DESC-1)*MAX_ETH_FRAME_SIZE
mov [device.prev_tx_frame], eax
.tx_enable:
ret
@ -1004,59 +984,54 @@ rx_reset:
set_io REG_COMMAND
mov ax, RxReset or 0x4
out dx, ax
; wait for RxReset to complete
mov ecx, 200000
.rx_reset_loop:
.loop:
in ax, dx
test ah, 10000b ; check CmdInProgress
dec ecx
jnz .rx_reset_loop
jnz .loop
; create upd ring
lea eax, [device.upd_buffer]
GetRealAddr
mov edi, eax ; real addr of first descr
mov eax, [device.upd_buffer]
mov [device.curr_upd], eax
call GetPgAddr
mov esi, eax
mov eax, [device.rx_buffer]
call GetPgAddr
mov edi, eax
mov edx, [device.upd_buffer]
add edx, (NUM_RX_DESC-1)*upd.size
mov eax, [device.upd_buffer]
push ebx
mov ebx, [device.rx_buffer]
lea esi, [device.upd_buffer] ; ptr to first descr
lea edx, [device.upd_buffer + (NUM_RX_DESC-1)*upd.size] ; ptr to last descr
mov ecx, NUM_RX_DESC
.upd_loop:
mov [edx + upd.next_ptr], esi ; edx = upd buff
and [eax + upd.pkt_status], 0 ; eax = next upd buff
mov [eax + upd.frag_addr], edi
mov [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
mov [eax + upd.realaddr], ebx
.upd_loop:
mov [edx + upd.next_ptr], edi
add edi, MAX_ETH_FRAME_SIZE
add ebx, MAX_ETH_FRAME_SIZE
push ecx edx
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
pop edx ecx
mov [esi + upd.realaddr], eax
call GetPgAddr
mov [esi + upd.frag_addr], eax
and [esi + upd.pkt_status], 0
mov [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
DEBUGF 1,"UPD: lin=%x phys=%x len=%x next ptr=%x\n", [esi+upd.realaddr]:8, [esi+upd.frag_addr]:8, [esi+upd.frag_len]:8, edi
DEBUGF 1,"UPD: cur=%x prev=%x\n", esi, edx
mov edx, esi
add esi, upd.size
mov edx, eax
add eax, upd.size
add edi, upd.size
dec ecx
jnz .upd_loop
pop ebx
mov eax, [device.upd_buffer]
call GetPgAddr
lea eax, [device.upd_buffer]
mov [device.curr_upd], eax
GetRealAddr
set_io 0
set_io REG_UP_LIST_PTR
out dx, eax
.rx_enable:
.rx_enable:
ret
@ -2228,6 +2203,8 @@ vortex_transmit:
mov ax, (10100b shl 11) + 1 ; StartDMADown
out dx, ax
.finish:
call KernelFree
add esp, 4
ret
@ -2245,26 +2222,32 @@ vortex_transmit:
align 4
boomerang_transmit:
DEBUGF 1,"Sending packet (boomerang)\n"
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
ja .finish ; packet is too long
jg .fail
call check_tx_status
test al, al
jnz tx_reset
; calculate descriptor address
mov eax, [device.prev_dpd]
DEBUGF 1,"Previous DPD: %x\n", eax
add eax, dpd.size
mov ecx, [device.dpd_buffer]
add ecx, NUM_TX_DESC*dpd.size
cmp eax, ecx
cmovae eax, [device.dpd_buffer] ; Wrap if needed
mov esi, [device.prev_dpd]
DEBUGF 1,"Previous DPD: %x\n", esi
add esi, dpd.size
lea ecx, [device.dpd_buffer + (NUM_TX_DESC)*dpd.size]
cmp esi, ecx
jl @f
lea esi, [device.dpd_buffer] ; Wrap if needed
@@:
DEBUGF 1,"Found a free DPD: %x\n", esi
DEBUGF 1,"Found a free DPD: %x\n", eax
push eax
; check DnListPtr
set_io 0
set_io REG_DN_LIST_PTR
@ -2272,91 +2255,56 @@ boomerang_transmit:
; mark if Dn_List_Ptr is cleared
test eax, eax
setz [device.dn_list_ptr_cleared]
; finish if no more free descriptor is available - FIXME!
cmp eax, [esp]
pop eax
jz .finish
push eax ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; calculate tx_buffer address
mov edi, [device.prev_tx_frame]
DEBUGF 1,"Previous TX frame:: %x\n", edi
add edi, MAX_ETH_FRAME_SIZE
mov ecx, [device.tx_buffer]
add ecx, NUM_TX_DESC*MAX_ETH_FRAME_SIZE
cmp edi, ecx
cmovae edi, [device.tx_buffer] ; Wrap if needed
DEBUGF 1,"Found place in TX buffer: %x\n", edi
push edi ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; cmp eax, esi
; jz .finish
; update statistics
inc [device.packets_tx]
mov ecx, [esp+8+8]
mov ecx, [esp+8] ; buffer size
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
; copy packet data
mov esi, [esp+4+8]
DEBUGF 1,"Copying %u bytes from %x to %x\n", ecx, esi, edi
shr cx , 1
jnc .nb
movsb
.nb:
shr cx , 1
jnc .nw
movsw
.nw:
rep movsd
; program DPD
mov eax, [esp] ; Tx buffer address
and [esi+dpd.next_ptr], 0
mov eax, [esp+4] ; Tx buffer address
mov [esi+dpd.realaddr], eax
call GetPgAddr
mov edi, [esp]
and edi, 4096 - 1
or edi, eax
mov eax, [esp+4] ; descriptor
DEBUGF 1,"Frag addr is: %x\n", edi
and [eax+dpd.next_ptr], 0
mov [eax+dpd.frag_addr], edi
mov ecx, [esp+8+8] ; packet size
mov [esi+dpd.frag_addr], eax
mov ecx, [esp+8] ; packet size
or ecx, 0x80000000 ; last fragment
DEBUGF 1,"Frag size + flag is: %x\n", ecx
mov [eax+dpd.frag_len], ecx
mov [esi+dpd.frag_len], ecx
mov ecx, [esp+8] ; packet size
; or ecx, 0x8000 ; transmission complete notification
or ecx, 1 shl 31
mov ecx, [esp+8+8] ; packet size
or ecx, 0x8000 ; transmission complete notification
; test byte [device.has_hwcksm], 0xff
; jz @f
; or ecx, (1 shl 26) ; set AddTcpChecksum
; or ecx, (1 shl 26) ; set AddTcpChecksum
;@@:
DEBUGF 1,"Frag start_hdr + flag is: %x\n", ecx
mov [eax+dpd.frame_start_hdr], ecx
mov [esi+dpd.frame_start_hdr], ecx
DEBUGF 1,"DPD: lin=%x phys=%x len=%x start hdr=%x\n", [esi+dpd.realaddr]:8, [esi+dpd.frag_addr]:8, [esi+dpd.frag_len]:8, [esi+dpd.frame_start_hdr]:8
; calculate physical address
mov edi, eax
call GetPgAddr
and edi, 4096 - 1
or eax, edi
; calculate physical address of dpd
mov eax, esi
GetRealAddr
cmp [device.dn_list_ptr_cleared], 0
jz .add_to_list
DEBUGF 1,"DN list ptr: %x\n", eax
; write Dn_List_Ptr
DEBUGF 1,"DPD phys addr=%x\n", eax
set_io 0
set_io REG_DN_LIST_PTR
out dx, eax
jmp .finish_pop
.add_to_list:
jmp .finish
.add_to_list:
DEBUGF 1,"Adding To list\n"
push eax
; DnStall
set_io 0
set_io REG_COMMAND
@ -2364,47 +2312,46 @@ boomerang_transmit:
out dx, ax
; wait for DnStall to complete
DEBUGF 1,"Waiting for DnStall\n"
mov ecx, 6000
.wait_for_stall:
.wait_for_stall:
in ax, dx ; read REG_INT_STATUS
test ah, 10000b
jz .dnstall_ok
dec ecx
jnz .wait_for_stall
.dnstall_ok:
.dnstall_ok:
DEBUGF 1,"DnStall ok!\n"
mov eax, [esp] ; prev_tx_frame
mov ecx, [device.prev_dpd]
mov [ecx+dpd.next_ptr], eax
set_io 0
set_io REG_DN_LIST_PTR
in eax, dx
test eax, eax
pop eax
jnz .dnunstall
; if Dn_List_Ptr has been cleared fill it up
DEBUGF 1,"DnList Ptr has been cleared\n"
mov eax, [esp]
out dx, eax
.dnunstall:
.dnunstall:
; DnUnStall
set_io 0
set_io REG_COMMAND
mov ax, ((110b shl 11)+3)
out dx, ax
.finish_pop:
pop [device.prev_tx_frame]
pop [device.prev_dpd]
.finish:
.finish:
mov [device.prev_dpd], esi
xor eax, eax
ret
ret 8
.fail:
stdcall KernelFree, [esp+4]
ret 8
;---------------------------------
@ -2581,7 +2528,9 @@ int_vortex:
.read_frame:
; program buffer address to read in
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
push ecx
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
pop ecx
test eax, eax
jz .finish
@ -2672,14 +2621,13 @@ int_vortex:
align 4
int_boomerang:
; DEBUGF 1,"\nIRQ %x Boomerang\n",eax:2
DEBUGF 1,"\nIRQ %x Boomerang\n",eax:2
; find pointer of device wich made IRQ occur
mov esi, BOOMERANG_LIST
mov ecx, [BOOMERANG_DEVICES]
; DEBUGF 1,"Devices: %u\n", ecx
test ecx, ecx
jz .fail
.nextdevice:
@ -2705,7 +2653,6 @@ int_boomerang:
.got_it:
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
push ax
; disable all INTS
@ -2713,13 +2660,6 @@ int_boomerang:
mov ax, SetIntrEnb
out dx, ax
;; acknowledge all int sources
;
; mov ax, word [esp]
; and ax, 0xff
; or ax, AckIntr
; out dx, ax
;--------------------------------------------------------------------------
test word[esp], UpComplete
jz .noRX
@ -2730,75 +2670,59 @@ int_boomerang:
DEBUGF 1,"UpComplete\n"
; check if packet is uploaded
mov eax, [device.curr_upd]
test byte [eax+upd.pkt_status+1], 0x80 ; upPktComplete
mov esi, [device.curr_upd]
test byte [esi+upd.pkt_status+1], 0x80 ; upPktComplete
jz .finish
DEBUGF 1, "Current upd: %x\n", esi
; packet is uploaded check for any error
.check_error:
test byte [eax+upd.pkt_status+1], 0x40 ; upError
test byte [esi+upd.pkt_status+1], 0x40 ; upError
jz .copy_packet_length
DEBUGF 1,"Error in packet\n"
and [eax+upd.pkt_status], 0 ; mark packet as read
and [esi+upd.pkt_status], 0 ; mark packet as read
jmp .finish
.copy_packet_length:
mov ecx, [eax+upd.pkt_status]
mov ecx, [esi+upd.pkt_status]
and ecx, 0x1fff
cmp ecx, MAX_ETH_PKT_SIZE
jbe .copy_packet
and [eax+upd.pkt_status], 0
jmp .finish
.copy_packet:
DEBUGF 1, " data hw addr:%x\n", [eax+upd.frag_addr]
; cmp ecx, MAX_ETH_PKT_SIZE
; jbe .copy_packet
; and [esi+upd.pkt_status], 0
; jmp .finish
; .copy_packet:
mov esi, [eax+upd.realaddr]
push esi ecx
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
pop ecx esi
test eax, eax
jz .finish
DEBUGF 1, "Received %u bytes in buffer %x\n", ecx, [esi+upd.realaddr]:8
push dword .loop ;.finish
push ecx eax
mov edi, eax
DEBUGF 1, " copying %u bytes from %x to %x\n", ecx, esi, edi
push ecx
push [esi+upd.realaddr]
; update statistics
inc [device.packets_rx]
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
; copy packet data
shr cx , 1
jnc .nb
movsb
.nb:
shr cx , 1
jnc .nw
movsw
.nw:
rep movsd
; update UPD (Alloc new buffer for next packet)
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
mov [esi + upd.realaddr], eax
GetRealAddr
mov [esi + upd.frag_addr], eax
and [esi + upd.pkt_status], 0
mov [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
mov eax, [device.curr_upd]
DEBUGF 1, "current upd: %x\n", eax
and [eax + upd.pkt_status], 0 ; clear the ring buffer entry for reuse
mov [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) ;;;
add eax, upd.size
mov ecx, [device.upd_buffer]
add ecx, (NUM_RX_DESC)*upd.size
cmp eax, ecx
cmovae eax, [device.upd_buffer]
mov [device.curr_upd], eax
DEBUGF 1, "next upd: %x\n", eax
; Update UPD pointer
add esi, upd.size
lea ecx, [device.upd_buffer+(NUM_RX_DESC)*upd.size]
cmp esi, ecx
jl @f
lea esi, [device.upd_buffer]
@@:
mov [device.curr_upd], esi
DEBUGF 1, "Next upd: %x\n", esi
jmp EthReceiver
.loop:
mov ebx, [esp]
jmp .receive
@ -2811,14 +2735,38 @@ int_boomerang:
in eax, dx
test ah, 0x20 ; UpStalled
jz .noUpUnStall
DEBUGF 1, "upUnStalling\n"
; issue upUnStall command
set_io REG_COMMAND
mov ax, ((11b shl 12)+1) ; upUnStall
out dx, ax
DEBUGF 1, "upUnStalling\n"
.noUpUnStall:
;;;; FIXME: make upunstall work
.noUpUnStall:
.noRX:
test word[esp], DownComplete
jz .noTX
DEBUGF 1, "Downcomplete!\n"
mov ecx, NUM_TX_DESC
lea esi, [device.dpd_buffer]
.txloop:
test [esi+dpd.frame_start_hdr], 1 shl 31
jz .maybenext
and [esi+dpd.frame_start_hdr], 0
push ecx
stdcall KernelFree, [esi+dpd.realaddr]
pop ecx
.maybenext:
add esi, dpd.size
dec ecx
jnz .txloop
.noTX:
pop ax
set_io 0
@ -2826,11 +2774,6 @@ int_boomerang:
or ax, AckIntr
out dx, ax
; set_io REG_COMMAND
; mov ax, AckIntr + IntLatch
; out dx, ax
set_io REG_INT_STATUS
in ax, dx
test ax, S_5_INTS
@ -2841,18 +2784,14 @@ int_boomerang:
mov ax, SetIntrEnb + S_5_INTS
out dx, ax
ret
; End of code
align 4 ; Place all initialised data here
macro strtbl name, [string]
{
common
@ -2866,7 +2805,7 @@ forward
VORTEX_DEVICES dd 0
BOOMERANG_DEVICES dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db '3C59X',0 ; max 16 chars include zero
@ -3001,7 +2940,6 @@ dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM
; 3c920B-EMB-WNM Tornado
HW_VERSIONS_SIZE = $ - hw_versions
include_debug_strings ; All data wich FDO uses will be included here
section '.data' data readable writable align 16 ; place all uninitialized data place here

View File

@ -1,9 +1,12 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; RTL8029/ne2000 driver for KolibriOS ;;
;; RTL8029/ne2000 driver for KolibriOS ;;
;; ;;
;; based on RTL8029.asm driver for menuetos ;;
;; and realtek8029.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; with help from CleverMouse ;;
@ -11,55 +14,46 @@
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; current status (september 2009) - UNSTABLE ;;
;; ;;
;; based on RTL8029.asm driver for menuetos ;;
;; and realtek8029.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;$Revision$
format MS COFF
API_VERSION equ 0x01000100
API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
DEBUG equ 1
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1
MAX_DEVICES equ 16
DEBUG equ 1
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
virtual at ebx
device:
device:
ETH_DEVICE
ETH_DEVICE
.io_addr dd ?
.irq_line db ?
.pci_bus db ?
.pci_dev db ?
.io_addr dd ?
.irq_line db ?
.pci_bus db ?
.pci_dev db ?
.flags db ?
.vendor db ?
.asic_base dw ?
.memsize db ?
.rx_start db ?
.tx_start db ?
.bmem dd ?
.rmem dd ?
.romdata rb 16
.flags db ?
.vendor db ?
.asic_base dw ?
.memsize db ?
.rx_start db ?
.tx_start db ?
.bmem dd ?
.rmem dd ?
.romdata rb 16
.size = $ - device
.size = $ - device
end virtual
@ -68,8 +62,6 @@ public START
public service_proc
public version
MAX_DEVICES equ 16 ; Max number of devices this driver may handle
P0_PSTART equ 0x01
P0_PSTOP equ 0x02
P0_BOUND equ 0x03
@ -234,8 +226,8 @@ proc service_proc stdcall, ioctl:dword
; check if the device is already listed
mov esi, DEVICE_LIST
mov ecx, [DEVICES]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice_pci
@ -269,8 +261,8 @@ proc service_proc stdcall, ioctl:dword
.isa:
mov esi, DEVICE_LIST
mov ecx, [DEVICES]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice_isa
mov al , [eax+3]
@ -305,9 +297,9 @@ proc service_proc stdcall, ioctl:dword
test eax, eax
jnz .err ; If an error occured, exit
mov eax, [DEVICES]
mov [DEVICE_LIST+4*eax], ebx
inc [DEVICES]
mov eax, [devices]
mov [device_list+4*eax], ebx
inc [devices]
mov [device.type], NET_TYPE_ETH
call NetRegDev
@ -346,7 +338,7 @@ endp
create_new_struct:
cmp [DEVICES], MAX_DEVICES
cmp [devices], MAX_DEVICES
jge .fail
push edx
@ -572,7 +564,7 @@ nsr_001:
nsr_002:
out dx, al
;clear remote bytes count
; clear remote bytes count
set_io 0
xor al, al
@ -584,7 +576,7 @@ nsr_002:
out dx, al
;initialize Receive configuration register
; initialize Receive configuration register
set_io P0_RCR
mov al, 0x20 ; monitor mode
out dx, al
@ -670,6 +662,9 @@ nsr_002:
mov ecx, 6
rep stosd
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
; Indicate that we have successfully reset the card
DEBUGF 2,"Done!\n"
@ -733,10 +728,14 @@ transmit:
adc dword [device.bytes_tx + 4], 0
.finish:
call Kernelfree
add esp, 4
xor eax, eax
ret
.err:
call Kernelfree
add esp, 4
or eax, -1
ret
@ -752,8 +751,8 @@ int_handler:
DEBUGF 2,"IRQ %x ",eax:2
; find pointer of device wich made INT occur
mov esi, DEVICE_LIST
mov ecx, [DEVICES]
mov esi, device_list
mov ecx, [devices]
.nextdevice:
mov ebx, [esi]
@ -1197,8 +1196,8 @@ epw_005: ; Wait for Remote DMA Complete
;all initialized data place here
align 4
DEVICES dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8029/ne2000',0 ;max 16 chars include zero
device_1 db 'Realtek 8029',0
@ -1213,7 +1212,7 @@ include_debug_strings
section '.data' data readable writable align 16 ;place all uninitialized data place here
DEVICE_LIST rd MAX_DEVICES
device_list rd MAX_DEVICES

View File

@ -3,22 +3,24 @@
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Realtek 8139 driver for KolibriOS ;;
;; Realtek 8139 driver for KolibriOS ;;
;; ;;
;; based on RTL8139.asm driver for menuetos ;;
;; and realtek8139.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; 0.1 - x march 2009 ;;
;; 0.2 - 8 november 2009 ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format MS COFF
API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
MAX_DEVICES equ 16
DEBUG equ 1
__DEBUG__ equ 1
@ -29,46 +31,10 @@ include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
public START
public service_proc
public version
virtual at ebx
device:
ETH_DEVICE
.rx_buffer dd ?
.tx_buffer dd ?
.rx_data_offset dd ?
.io_addr dd ?
.curr_tx_desc db ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
.hw_ver_id db ?
.size = $ - device
end virtual
; RTL8139 specific defines
MAX_RTL8139 equ 16 ; Max number of devices this driver may handle
TX_TIMEOUT equ 30 ; 300 milliseconds timeout
PCI_REG_CMD equ 0x04 ; command register
PCI_BIT_PIO equ 0 ; bit0: io space control
PCI_BIT_MMIO equ 1 ; bit1: memory space control
PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master
REG_IDR0 equ 0x00
REG_MAR0 equ 0x08 ; multicast filter register 0
REG_MAR4 equ 0x0c ; multicast filter register 4
@ -169,8 +135,8 @@ end virtual
RX_BUFFER_SIZE equ (8192 shl RBLEN);+16
MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC
NUM_TX_DESC equ 4
TX_BUF_SIZE equ 4096 ; size of one tx buffer (set to 4kb because of KolibriOS's page size)
EE_93C46_REG_ETH_ID equ 7 ; MAC offset
EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address
@ -228,6 +194,30 @@ end virtual
TSR_CRS equ 1 SHL 31
virtual at ebx
device:
ETH_DEVICE
.rx_buffer dd ?
.tx_buffer dd ?
.rx_data_offset dd ?
.io_addr dd ?
.curr_tx_desc db ?
.last_tx_desc db ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
.hw_ver_id db ?
.TX_DESC rd NUM_TX_DESC
.size = $ - device
end virtual
section '.flat' code readable align 16
@ -298,8 +288,8 @@ proc service_proc stdcall, ioctl:dword
; check if the device is already listed
mov esi, RTL8139_LIST
mov ecx, [RTL8139_DEV]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
@ -315,11 +305,11 @@ proc service_proc stdcall, ioctl:dword
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [RTL8139_DEV], MAX_RTL8139 ; First check if the driver can handle one more card
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jge .fail
push edx
stdcall KernelAlloc, device.size ; Allocate the buffer for eth_device structure
stdcall KernelAlloc, device.size ; Allocate the buffer for eth_device structure
pop edx
test eax, eax
jz .fail
@ -355,7 +345,7 @@ proc service_proc stdcall, ioctl:dword
allocate_and_clear [device.rx_buffer], (RX_BUFFER_SIZE+MAX_ETH_FRAME_SIZE), .err
allocate_and_clear [device.tx_buffer], (TX_BUF_SIZE*NUM_TX_DESC), .err
;; allocate_and_clear [device.tx_buffer], (TX_BUF_SIZE*NUM_TX_DESC), .err
; Ok, the eth_device structure is ready, let's probe the device
@ -363,10 +353,9 @@ proc service_proc stdcall, ioctl:dword
test eax, eax
jnz .err ; If an error occured, exit
mov eax, [RTL8139_DEV] ; Add the device structure to our device list
mov [RTL8139_LIST+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [RTL8139_DEV] ;
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
mov [device.type], NET_TYPE_ETH
call NetRegDev
@ -393,7 +382,7 @@ proc service_proc stdcall, ioctl:dword
.err:
stdcall KernelFree, dword [device.rx_buffer]
stdcall KernelFree, dword [device.tx_buffer]
;; stdcall KernelFree, dword [device.tx_buffer]
stdcall KernelFree, ebx
@ -537,7 +526,7 @@ reset:
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
@@:
; reset chip
@ -613,6 +602,7 @@ reset:
mov [device.rx_data_offset], eax
mov [device.curr_tx_desc], al
mov [device.last_tx_desc], al
; clear packet/byte counters
@ -625,21 +615,6 @@ reset:
set_io REG_MPC
out dx , eax
; Set up the 4 Txbuffer descriptors
set_io REG_TSAD0
mov eax, [device.tx_buffer]
mov ecx, 4
.loop:
push eax
call GetPgAddr
DEBUGF 1,"Desc: %x ", eax
out dx , eax
add dx , 4
pop eax
add eax, TX_BUF_SIZE
loop .loop
; set RxBuffer address, init RX buffer offset
mov eax, [device.rx_buffer]
@ -658,6 +633,9 @@ reset:
call read_mac
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
; Indicate that we have successfully reset the card
DEBUGF 2,"Done!\n"
@ -675,7 +653,6 @@ reset:
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4
transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
@ -686,71 +663,69 @@ transmit:
[eax+13]:2,[eax+12]:2
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
jg .finish ; packet is too long
jg .fail
cmp dword [esp+8], 60
jl .finish ; packet is too short
jl .fail
; check descriptor
DEBUGF 1,"Checking descriptor, "
; check if we own the discriptor
set_io 0
movzx ecx, [device.curr_tx_desc]
mov edx, [device.io_addr]
lea edx, [edx+ecx*4+REG_TSD0]
shl ecx, 2
lea edx, [edx+ecx+REG_TSD0]
in ax, dx
test ax, 0x1fff ; or no size given
jz .send_packet
and ax, (1 shl BIT_TOK) or (1 shl BIT_OWN)
cmp ax, (1 shl BIT_TOK) or (1 shl BIT_OWN)
jz .send_packet
; wait for timeout
DEBUGF 1,"Waiting for timeout, "
test ax, (1 shl BIT_OWN)
jz .wait_to_send
push edx ebx ; TODO : rtl8139 internal timer should be used instead
stdcall Sleep, TX_TIMEOUT ; ? What registers does this destroy ?
pop ebx edx
.send_packet:
; Set the buffer address
set_io 0
lea edx, [edx+ecx+REG_TSAD0]
mov eax, [esp+4]
mov [device.TX_DESC+ecx], eax
GetRealAddr
out dx, eax
in ax, dx
and ax, (1 shl BIT_TOK) or (1 shl BIT_OWN)
cmp ax, (1 shl BIT_TOK) or (1 shl BIT_OWN)
jz .send_packet ; if chip hung, reset it
push dx
call reset ; reset the card
pop dx
.send_packet:
DEBUGF 1,"Sending packet, "
push edx
movzx eax, [device.curr_tx_desc] ; calculate the current tx_buffer address
mov edx, TX_BUF_SIZE ;MAX_ETH_FRAME_SIZE ;
mul edx ;
mov edi, [device.tx_buffer] ;
add edi, eax ; Store it in edi
pop edx
mov esi, [esp+4] ; Copy data to that address
mov ecx, [esp+8] ;
shr ecx, 2 ;
rep movsd ;
mov ecx, [esp+8] ;
and ecx, 3 ;
rep movsb ;
inc [device.packets_tx] ;
mov eax, [esp+8] ; Get packet size in eax
; And the size of the buffer
set_io 0
lea edx, [edx+ecx+REG_TSD0]
mov eax, [esp+8]
; or eax, (ERTXTH shl BIT_ERTXTH) ; Early threshold
out dx , eax
; Update stats
inc [device.packets_tx]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
; or eax, (ERTXTH shl BIT_ERTXTH) ; Set descriptor size and the early tx treshold into the correct Transmission status register (TSD0, TSD1, TSD2 or TSD3)
out dx , eax ;
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
; get next descriptor
inc [device.curr_tx_desc]
and [device.curr_tx_desc], 3
DEBUGF 1," - Packet Sent! "
.finish:
DEBUGF 1," - Done!\n"
ret
DEBUGF 1,"Packet Sent! "
xor eax, eax
ret 8
.wait_to_send:
DEBUGF 1,"Waiting for timeout\n"
mov esi, 30
stdcall Sleep
in ax, dx
test ax, (1 shl BIT_OWN)
jnz .send_packet
pusha
call reset ; if chip hung, reset it
popa
jmp .send_packet
.fail:
DEBUGF 1,"failed!\n"
or eax, -1
ret 8
@ -761,16 +736,15 @@ transmit:
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
align 4
int_handler:
DEBUGF 1,"IRQ %x ",eax:2 ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
DEBUGF 1,"IRQ %x\n", eax:2 ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
; find pointer of device wich made IRQ occur
mov esi, RTL8139_LIST
mov ecx, [RTL8139_DEV]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .fail
.nextdevice:
@ -799,7 +773,6 @@ int_handler:
;----------------------------------------------------
; Received packet ok?
test ax, ISR_ROK
jz @f
push ax
@ -836,7 +809,6 @@ int_handler:
test eax, eax ; Test if we allocated succesfully
jz .abort
mov edi, eax ; Where we will copy too
mov esi, [esp] ; The buffer we will copy from
@ -914,60 +886,78 @@ int_handler:
;----------------------------------------------------
; Transmit error ?
@@:
test ax, ISR_TER
jz @f
push ax
cmp [device.curr_tx_desc], 4
jz .notxd
set_io 0
movzx ecx, [device.curr_tx_desc]
lea edx, [edx+ecx*4+REG_TSD0]
in eax, dx
.notxd:
test eax, TSR_TUN
jz .nobun
DEBUGF 2, "TX: FIFO Buffer underrun!\n"
.nobun:
test eax, TSR_OWC
jz .noowc
DEBUGF 2, "TX: OWC!\n"
.noowc:
test eax, TSR_TABT
jz .notabt
DEBUGF 2, "TX: TABT!\n"
.notabt:
test eax, TSR_CRS
jz .nocsl
DEBUGF 2, "TX: Carrier Sense Lost!\n"
.nocsl:
; test eax, TSR_OWN or TSR_TOK
; jz .nofd
; DEBUGF 1, "TX: Transmit OK (desc: %u)\n", ecx
; push ax
; cmp [device.curr_tx_desc], 4
; jz .notxd
;
; .nofd:
pop ax
; set_io 0
; movzx ecx, [device.curr_tx_desc]
; lea edx, [edx+ecx*4+REG_TSD0]
; in eax, dx
;
; .notxd:
; test eax, TSR_TUN
; jz .nobun
; DEBUGF 2, "TX: FIFO Buffer underrun!\n"
;
; .nobun:
; test eax, TSR_OWC
; jz .noowc
; DEBUGF 2, "TX: OWC!\n"
;
; .noowc:
; test eax, TSR_TABT
; jz .notabt
; DEBUGF 2, "TX: TABT!\n"
;
; .notabt:
; test eax, TSR_CRS
; jz .nocsl
; DEBUGF 2, "TX: Carrier Sense Lost!\n"
;
; .nocsl:
; pop ax
;----------------------------------------------------
; Transmit ok ?
@@:
test ax, ISR_TOK
jz @f
DEBUGF 1, "TX: Transmit OK (desc: %u)\n", [device.curr_tx_desc]:1
push ax
mov si, 4
.txdesloop:
movzx ecx, [device.last_tx_desc]
shl ecx, 2
set_io 0
set_io REG_TSD0
add edx, ecx
in eax, dx
test eax, TSR_TOK
jz .notthisone
mov eax, TSR_OWN
out dx , eax
DEBUGF 1,"TX OK: free buffer %x\n", [device.TX_DESC+ecx]:8
stdcall KernelFree, [device.TX_DESC+ecx]
.notthisone:
inc [device.last_tx_desc]
and [device.last_tx_desc], 3
dec si
jnz .txdesloop
.done:
pop ax
;----------------------------------------------------
; Rx buffer overflow ?
@@:
test ax, ISR_RXOVW
jz @f
@ -975,16 +965,14 @@ int_handler:
push ax
DEBUGF 2,"RX-buffer overflow!\n"
mov edx, [device.io_addr]
add edx, REG_ISR
set_io 0
set_io REG_ISR
mov ax , ISR_FIFOOVW or ISR_RXOVW
out dx , ax
pop ax
;----------------------------------------------------
; Packet underrun? ?
; Packet underrun?
@@:
test ax, ISR_PUN
jz @f
@ -993,23 +981,21 @@ int_handler:
;----------------------------------------------------
; Receive FIFO overflow ?
@@:
test ax, ISR_FIFOOVW
jz @f
push ax
DEBUGF 2,"RX fifo overflox!\n"
DEBUGF 2,"RX fifo overflow!\n"
mov edx, [device.io_addr]
add edx, REG_ISR
set_io 0
set_io REG_ISR
mov ax , ISR_FIFOOVW or ISR_RXOVW
out dx , ax
pop ax
;----------------------------------------------------
; Something about Cable changed ?
@@:
test ax, ISR_LENCHG
jz .fail
@ -1017,11 +1003,7 @@ int_handler:
DEBUGF 2,"Cable changed!\n"
call cable
; If none of the above events happened, just exit clearing int
.fail:
DEBUGF 1,"\n"
ret
@ -1213,47 +1195,48 @@ read_eeprom:
; End of code
section '.data' data readable writable align 16 ; place all uninitialized data place here
align 4 ; Place all initialised data here
RTL8139_DEV dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8139',0 ; max 16 chars include zero
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8139',0 ; max 16 chars include zero
device_1 db 'Realtek 8139',0
device_2 db 'Realtek 8139A',0
device_3 db 'Realtek 8139B',0
device_4 db 'Realtek 8139C',0
device_5 db 'Realtek 8100',0
device_6 db 'Realtek 8139D',0
device_7 db 'Realtek 8139CP',0
device_8 db 'Realtek 8101',0
device_unknown db 'Unknown RTL8139 clone', 0
device_1 db 'Realtek 8139',0
device_2 db 'Realtek 8139A',0
device_3 db 'Realtek 8139B',0
device_4 db 'Realtek 8139C',0
device_5 db 'Realtek 8100',0
device_6 db 'Realtek 8139D',0
device_7 db 'Realtek 8139CP',0
device_8 db 'Realtek 8101',0
device_unknown db 'Unknown RTL8139 clone', 0
crosslist dd device_1
dd device_2
dd device_3
dd device_4
dd device_5
dd device_6
dd device_7
dd device_8
dd device_unknown
crosslist:
dd device_1
dd device_2
dd device_3
dd device_4
dd device_5
dd device_6
dd device_7
dd device_8
dd device_unknown
hw_ver_array db VER_RTL8139 ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
db VER_RTL8139A
db VER_RTL8139B
db VER_RTL8139C
db VER_RTL8100
db VER_RTL8139D
db VER_RTL8139CP
db VER_RTL8101
db 0
hw_ver_array: ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
db VER_RTL8139
db VER_RTL8139A
db VER_RTL8139B
db VER_RTL8139C
db VER_RTL8100
db VER_RTL8139D
db VER_RTL8139CP
db VER_RTL8101
db 0
HW_VER_ARRAY_SIZE = $-hw_ver_array
include_debug_strings ; All data wich FDO uses will be included here
section '.data' data readable writable align 16 ; place all uninitialized data place here
RTL8139_LIST rd MAX_RTL8139 ; This list contains all pointers to device structures the driver is handling
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling

View File

@ -1,17 +1,15 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; DEC 21x4x driver for KolibriOS ;;
;; DEC 21x4x driver for KolibriOS ;;
;; ;;
;; Based on dec21140.Asm from Solar OS by ;;
;; Eugen Brasoveanu, ;;
;; Ontanu Bogdan Valentin ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; 0.1 - 5 june 2010 ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
@ -21,6 +19,9 @@
format MS COFF
API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
MAX_DEVICES equ 16
DEBUG equ 1
__DEBUG__ equ 1
@ -31,42 +32,32 @@ include 'imports.inc'
include 'fdo.inc'
include 'netdrv.inc'
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
public START
public service_proc
public version
virtual at ebx
device:
ETH_DEVICE
; device specific
.rx_p_des dd ? ; descriptors ring with received packets
.tx_p_des dd ? ; descriptors ring with 'to transmit' packets
.tx_free_des dd ? ; Tx descriptors available
.tx_wr_des dd ? ; Tx current descriptor to write data to
.tx_rd_des dd ? ; Tx current descriptor to read TX completion
.rx_crt_des dd ? ; Rx current descriptor
.rx_p_des dd ? ; descriptors ring with received packets
.tx_p_des dd ? ; descriptors ring with 'to transmit' packets
.tx_free_des dd ? ; Tx descriptors available
.tx_wr_des dd ? ; Tx current descriptor to write data to
.tx_rd_des dd ? ; Tx current descriptor to read TX completion
.rx_crt_des dd ? ; Rx current descriptor
.io_addr dd ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
.io_addr dd ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
.size = $ - device
.size = $ - device
end virtual
MAX_DEVICES equ 16
;-------------------------------------------
; configuration registers
;-------------------------------------------
@ -381,7 +372,7 @@ proc service_proc stdcall, ioctl:dword
; check if the device is already listed
mov esi, DEVICE_LIST
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
@ -442,7 +433,7 @@ proc service_proc stdcall, ioctl:dword
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
mov eax, [devices] ; Add the device structure to our device list
mov [DEVICE_LIST+4*eax], ebx ; (IRQ handler uses this list to find device)
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
call probe ; this function will output in eax
@ -771,6 +762,9 @@ reset:
mov ecx, 6
rep stosd
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
DEBUGF 1,"Reset done\n"
ret
@ -1000,15 +994,18 @@ transmit:
DEBUGF 1,"transmit ok\n"
xor eax, eax
call Kernelfree
add esp, 4
ret
.fail:
DEBUGF 1,"transmit failed\n"
or eax, -1
call Kernelfree
add esp, 4
ret
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
@ -1025,7 +1022,7 @@ int_handler:
mov ecx, [devices]
test ecx, ecx
jz .fail
mov esi, DEVICE_LIST
mov esi, device_list
.nextdevice:
mov ebx, dword [esi]
@ -1701,17 +1698,16 @@ mdio_write: ;int phy_id: edx, int location: edi, int value: ax)
; End of code
align 4 ; Place all initialised data here
devices dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'DEC21X4X',0 ; max 16 chars include zero
include_debug_strings ; All data wich FDO uses will be included here
section '.data' data readable writable align 16 ; place all uninitialized data place here
DEVICE_LIST rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling

File diff suppressed because it is too large Load Diff

View File

@ -187,47 +187,49 @@ macro virt_to_dma { ; input is eax
}
macro NET_DEVICE {
.type dd ?
.type dd ? ; Type field
.mtu dd ? ; Maximal Transmission Unit
.name dd ? ; Ptr to 0 terminated string
.unload dd ? ; Ptrs to driver functions
.reset dd ? ;
.transmit dd ? ;
.bytes_tx dq ? ; Statistics, updated by the driver
.bytes_rx dq ? ;
.packets_tx dd ? ;
.packets_rx dd ? ;
.end:
}
;struc ETH_DEVICE {
macro ETH_DEVICE {
NET_DEVICE
; pointers to procedures
.unload dd ?
.reset dd ?
.transmit dd ?
.set_MAC dd ?
.get_MAC dd ?
.set_mode dd ?
.get_mode dd ?
; status
.bytes_tx dq ?
.bytes_rx dq ?
.packets_tx dd ?
.packets_rx dd ?
.mode dd ?
.name dd ?
.mac dp ?
.set_mode dd ?
.get_mode dd ?
.set_MAC dd ?
.get_MAC dd ?
.mode dd ?
.mac dp ?
dp ? ; qword alignment
}
macro SLIP_DEVICE {
NET_DEVICE
; pointers to procedures
.unload dd ?
.reset dd ?
.transmit dd ?
.set_mode dd ?
.get_mode dd ?
; status
.bytes_tx dq ?
.bytes_rx dq ?
.packets_tx dd ?
.packets_rx dd ?
.mode dd ?
.name dd ?
}
macro GetRealAddr {
@ -235,7 +237,7 @@ macro GetRealAddr {
push eax
call GetPgAddr
and dword [esp], (PAGESIZE - 1)
add eax, dword [esp]
or eax, dword [esp]
add esp, 4
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -112,7 +112,7 @@ ARP_init:
;
; This function resets all ARP variables
;
; IN: eax = IPv4 address
; IN: eax = IPv4 address
; OUT: eax = -1 on error, else eax = first two bytes of mac
; ( high 16 bits are zero)
; ebx = last four bytes of mac ; TODO: special eax value for 'request send'
@ -130,18 +130,18 @@ ARP_IP_to_MAC:
; else
; destination is remote, so pass to gateway
xor edx, edx ; TODO: find device num in edx
xor edx, edx ;;; TODO: find device num in edx
mov ebx, [IP_LIST+edx]
and ebx, [SUBNET_LIST+edx]
mov ebx, [IP_LIST + edx]
and ebx, [SUBNET_LIST + edx]
mov ecx, eax
and ecx, [SUBNET_LIST+edx]
and ecx, [SUBNET_LIST + edx]
cmp ecx, ebx
je .local
mov eax, [GATEWAY_LIST+edx]
mov eax, [GATEWAY_LIST + edx]
DEBUGF 1,"requested IP is not on subnet, using gateway\n"
.local:
@ -274,7 +274,8 @@ ARP_create_request:
DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx
push edx ecx
jmp NET_send
call [ebx + NET_DEVICE.transmit]
ret
.exit:
add esp, 8
@ -572,7 +573,8 @@ ARP_handler:
DEBUGF 1,"ARP_Handler - Sending reply \n"
jmp NET_send ; And send it!
call [ebx + NET_DEVICE.transmit]
ret
.exit:
call kernel_free

View File

@ -172,10 +172,10 @@ IPv4_handler: ; TODO: implement handler for IP options
cmp [edx + IPv4_Packet.DestinationAddress], -1
je .ip_ok
; ; maybe it's a multicast then
;
; mov eax, [edx + IPv4_Packet.DestinationAddress]
; and eax, 0xff000000
; maybe it's a multicast then
mov eax, [edx + IPv4_Packet.DestinationAddress]
and eax, 0xff000000
; cmp eax, 224 shl 24
; je .ip_ok

View File

@ -16,8 +16,6 @@
$Revision$
ETH_QUEUE_SIZE equ 16
struct ETH_FRAME
.DstMAC dp ? ; destination MAC-address
.SrcMAC dp ? ; source MAC-address
@ -28,20 +26,14 @@ ends
virtual at NET_DEVICE.end
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 ?
.set_MAC dd ?
.get_MAC dd ?
.mode dd ?
.name dd ?
.mac dp ?
end virtual
@ -108,6 +100,9 @@ ETH_receiver:
cmp ax, ETHER_ARP
je ARP_handler
; cmp ax, ETHER_PPP_DISCOVERY
; je PPPOE_discovery
DEBUGF 2,"Unknown ethernet packet type %x\n", ax
.dump:
@ -138,7 +133,10 @@ ETH_create_packet:
DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx
cmp ecx, 1500 ;;;
push esi
mov esi, [NET_DRV_LIST] ;;; TODO: FIXME
cmp ecx, [esi + NET_DEVICE.mtu]
pop esi
jg .exit
push ecx di eax ebx edx
@ -171,7 +169,7 @@ ETH_create_packet:
mov ebx, [NET_DRV_LIST + ebx]
cmp edx, 46 + ETH_FRAME.Data ; If data size is less then 46, add padding bytes
jg .continue
jge .continue
mov edx, 46 + ETH_FRAME.Data
.continue:
@ -240,23 +238,23 @@ ETH_API:
ret
.packets_tx:
mov eax, dword [eax + ETH_DEVICE.packets_tx]
mov eax, dword [eax + NET_DEVICE.packets_tx]
ret
.packets_rx:
mov eax, dword [eax + ETH_DEVICE.packets_rx]
mov eax, dword [eax + NET_DEVICE.packets_rx]
ret
.bytes_tx:
mov ebx, dword [eax + ETH_DEVICE.bytes_tx + 4]
mov eax, dword [eax + ETH_DEVICE.bytes_tx]
mov ebx, dword [eax + NET_DEVICE.bytes_tx + 4]
mov eax, dword [eax + NET_DEVICE.bytes_tx]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
.bytes_rx:
mov ebx, dword [eax + ETH_DEVICE.bytes_rx + 4]
mov eax, dword [eax + ETH_DEVICE.bytes_rx]
mov ebx, dword [eax + NET_DEVICE.bytes_rx + 4]
mov eax, dword [eax + NET_DEVICE.bytes_rx]
mov [esp+20+4], ebx ; TODO: fix this ugly code
ret
@ -270,8 +268,7 @@ ETH_API:
.write_mac:
push ecx
push dx
mov eax, [eax + ETH_DEVICE.set_MAC]
call eax
call [eax + ETH_DEVICE.set_MAC]
ret
.in_queue:

View File

@ -209,8 +209,8 @@ ICMP_input:
pop ecx edx ebx
mov word [edx + ICMP_Packet.Checksum], ax
jmp NET_send ; Send the reply
; and return to caller of this proc
call [ebx + NET_DEVICE.transmit]
ret
@ -251,7 +251,7 @@ ICMP_input:
add esp, 4
sub edx, esi
mov edi, edx
;;; jmp SOCKET_input
jmp SOCKET_input
.dump:
DEBUGF 1,"ICMP_Handler - dumping\n"
@ -264,24 +264,22 @@ ICMP_input:
;-----------------------------------------------------------------
;
; Note: ICMP only works on top of IP protocol :)
; ICMP_output
;
; inputs:
;
; eax = dest ip
; ebx = source ip
; ecx = data length
; dh = type
; dl = code
; high 16 bits of edx = fragment id (for IP header)
; esi = data offset
; edi = identifier shl 16 + sequence number
; IN: eax = dest ip
; ebx = source ip
; ecx = data length
; dh = type
; dl = code
; high 16 bits of edx = fragment id (for IP header)
; esi = data offset
; edi = identifier shl 16 + sequence number
;
;-----------------------------------------------------------------
align 4
ICMP_output:
DEBUGF 1,"Create ICMP Packet\n"
DEBUGF 1,"Creating ICMP Packet\n"
push esi edi edx
@ -292,7 +290,7 @@ ICMP_output:
call IPv4_create_packet
jz .exit
DEBUGF 1,"full icmp packet size: %u\n", edx
DEBUGF 1,"full icmp packet size: %u\n", edx
pop eax
mov word [edi + ICMP_Packet.Type], ax ; Write both type and code bytes at once
@ -320,13 +318,12 @@ ICMP_output:
rep movsb
sub edi, edx ;;; TODO: find a better way to remember start of packet
mov ecx, [ebx + ETH_DEVICE.transmit]
push edx edi ecx
DEBUGF 1,"Sending ICMP Packet\n"
ret ; Send the packet (create_packet routine outputs pointer to routine to send packet in eax)
push edx edi
DEBUGF 1,"Sending ICMP Packet\n"
call [ebx + NET_DEVICE.transmit]
ret
.exit:
DEBUGF 1,"Creating ICMP Packet failed\n"
DEBUGF 1,"Creating ICMP Packet failed\n"
add esp, 3*4
ret

View File

@ -74,7 +74,6 @@ virtual at IP_SOCKET.end
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
.t_state dd ? ; TCB state
.t_timer dd ? ; TCB timer (seconds)
.t_rxtshift dd ?
.t_rxtcur dd ?
.t_dupacks dd ?
@ -144,6 +143,16 @@ virtual at IP_SOCKET.end
.ts_recent_age dd ?
.last_ack_sent dd ?
;-------
; Timers
.timer_retransmission dw ? ; rexmt
.timer_ack dw ?
.timer_persist dw ?
.timer_keepalive dw ? ; keepalive/syn timeout
.timer_timed_wait dw ? ; also used as 2msl timer
.end:
end virtual
@ -335,7 +344,7 @@ SOCKET_bind:
jz s_error
.got_port:
DEBUGF 1,"using local port: %u", bx
DEBUGF 1,"using local port: %u\n", bx
mov word [eax + UDP_SOCKET.LocalPort], bx
mov ebx, dword [edx + 4]
@ -391,7 +400,7 @@ SOCKET_connect:
mov bx , word [edx + 2]
mov word [eax + UDP_SOCKET.RemotePort], bx
mov [eax + UDP_SOCKET.firstpacket], 0
DEBUGF 1,"remote port: %u ",bx
DEBUGF 1,"remote port: %u\n",bx
mov ebx, dword [edx + 4]
mov dword [eax + IP_SOCKET.RemoteIP], ebx
@ -408,6 +417,8 @@ SOCKET_connect:
add [TCP_sequence_num], 6400
mov [eax + TCP_SOCKET.ISS], ebx
mov [eax + TCP_SOCKET.timer_keepalive], 120 ; 120*630ms => 75,6 seconds
lea ebx, [eax + SOCKET.lock]
call wait_mutex
@ -417,7 +428,7 @@ SOCKET_connect:
mov bx , word [edx + 2]
mov [eax + TCP_SOCKET.RemotePort], bx
DEBUGF 1,"remote port: %u ",bx
DEBUGF 1,"remote port: %u\n", bx
mov ebx, dword [edx + 4]
mov [eax + IP_SOCKET.RemoteIP], ebx
@ -435,6 +446,8 @@ SOCKET_connect:
call SOCKET_find_port
@@:
DEBUGF 1,"remote port: %u\n", [eax + TCP_SOCKET.LocalPort]:2
; mov [eax + TCP_SOCKET.t_state], TCB_SYN_SENT
call TCP_output

View File

@ -35,8 +35,10 @@ MIN_EPHEMERAL_PORT equ 49152
MAX_EPHEMERAL_PORT equ 61000
; Ethernet protocol numbers
ETHER_ARP equ 0x0608
ETHER_IPv4 equ 0x0008 ; Reversed from 0800 for intel
ETHER_ARP equ 0x0608
ETHER_IPv4 equ 0x0008 ; Reversed from 0800 for intel
ETHER_PPP_DISCOVERY equ 0x6388
ETHER_PPP_SESSION equ 0x6488
;Protocol family
AF_UNSPEC equ 0
@ -76,7 +78,20 @@ NET_TYPE_SLIP equ 2
virtual at 0
NET_DEVICE:
.type dd ?
.type dd ? ; Type field
.mtu dd ? ; Maximal Transmission Unit
.name dd ? ; Ptr to 0 terminated string
.unload dd ? ; Ptrs to driver functions
.reset dd ? ;
.transmit dd ? ;
.bytes_tx dq ? ; Statistics, updated by the driver
.bytes_rx dq ? ;
.packets_tx dd ? ;
.packets_rx dd ? ;
.end:
end virtual
@ -193,26 +208,17 @@ stack_handler:
je .exit
mov [net_10ms], eax
if ETH_QUEUE
call ETH_handler
call ETH_send_queued
end if
call TCP_10ms
test [net_10ms], 0x0f ; 160ms
jnz .exit
inc [net_tmr_count]
cmp [net_tmr_count], 50
je .500ms
cmp [net_tmr_count], 100
jne .exit
; call TCP_timer_160ms
test [net_10ms], 0x3f ; 640ms
jnz .exit
; call TCP_timer_640ms
call ARP_decrease_entry_ttls
call IPv4_decrease_fragment_ttls
call TCP_timer_1000ms
mov [net_tmr_count], 0
.500ms:
call TCP_500ms
.exit:
ret
@ -380,34 +386,6 @@ NET_ptr_to_num:
pop ecx
ret
;--------------------------
;
; NET_send
;
; IN: ebx = ptr to device struct
; [esp] = data ptr
; [esp + 4] = data size
;
; OUT: /
;
;--------------------------
align 4
NET_send:
call [ebx + ETH_DEVICE.transmit] ;;;;
;;; TODO:check if packet was sent ok
call kernel_free
add esp, 4
ret
;-----------------------------------------------------------------
;
; checksum_1
@ -563,7 +541,7 @@ sys_network:
jnz @f
mov esi, [esi + NET_DRV_LIST]
mov esi, [esi + ETH_DEVICE.name]
mov esi, [esi + NET_DEVICE.name]
mov edi, ecx
mov ecx, 64 ; max length
@ -578,7 +556,7 @@ sys_network:
jnz @f
mov esi, [esi + NET_DRV_LIST]
call [esi + ETH_DEVICE.reset]
call [esi + NET_DEVICE.reset]
jmp .return
@@:
@ -587,7 +565,7 @@ sys_network:
jnz @f
mov esi, [esi + NET_DRV_LIST]
call [esi + ETH_DEVICE.unload]
call [esi + NET_DEVICE.unload]
jmp .return
@@:
@ -645,13 +623,13 @@ sys_protocols:
cmp ax , ETHER_ARP
je ARP_API
cmp ax , 1337
cmp ax , 1337 ;;;;;
je ETH_API
add esp, 4 ; if we reached here, no function was called, so we need to balance stack
.doesnt_exist:
DEBUGF 1,"sys_protocols: protocol %u doesnt exist on device %u!\n",ax, bh
DEBUGF 1,"sys_protocols: protocol %u doesnt exist on device %u!\n", ax, bh
mov eax, -1
.return:

View File

@ -58,6 +58,22 @@ TCP_OPT_MAXSEG equ 2 ; Maximum Segment Size.
TCP_OPT_WINDOW equ 3 ; window scale
TCP_OPT_TIMESTAMP equ 8
; Fundamental timer values
TCP_time_MSL equ 47 ; max segment lifetime (30s)
TCP_time_re_min equ 2 ; min retransmission (1,28s)
TCP_time_re_max equ 100 ; max retransmission (64s)
TCP_time_pers_min equ 8 ; min persist (5,12s)
TCP_time_pers_max equ 94 ; max persist (60,16s)
TCP_time_keep_init equ 118 ; connectione stablishment (75,52s)
TCP_time_keep_idle equ 4608 ; idle time before 1st probe (2h)
TCP_time_keep_interval equ 118 ; between probes when no response (75,52s)
TCP_time_rtt_default equ 5 ; default Round Trip Time (3,2s)
; timer constants
TCP_max_rxtshift equ 12 ; max retransmissions waiting for ACK
TCP_max_keepcnt equ 8 ; max keepalive probes
struct TCP_segment
.SourcePort dw ?
.DestinationPort dw ?
@ -113,24 +129,56 @@ TCP_init:
mov ecx, (6*IP_MAX_INTERFACES)
rep stosd
mov [TCP_sequence_num],1
mov [TCP_sequence_num], 1
ret
;----------------------
;
;
;----------------------
align 4
TCP_timer_160ms:
mov eax, net_sockets
.loop:
mov eax, [eax + SOCKET.NextPtr]
or eax, eax
jz .exit
cmp [eax + SOCKET.Type], IP_PROTO_TCP
jne .loop
dec [eax + TCP_SOCKET.timer_ack]
jnz .loop
DEBUGF 1,"TCP ack for socket %x expired, time to piggyback!\n", eax
push eax
call TCP_respond
pop eax
jmp .loop
.exit:
ret
;-----------------------------------------------------------------
;
; decrease socket ttls
;
; IN: /
; OUT: /
;
; destroys: eax
;
;-----------------------------------------------------------------
align 4
TCP_timer_1000ms:
; scan through all the active TCP sockets, decrementing active timers
TCP_timer_640ms:
; Update TCP sequence number
add [TCP_sequence_num], 64000
; scan through all the active TCP sockets, decrementing ALL timers
; timers do not have the chance to wrap because of the keepalive timer will kill the socket when it expires
mov eax, net_sockets
.loop:
@ -142,62 +190,40 @@ TCP_timer_1000ms:
cmp [eax + SOCKET.Type], IP_PROTO_TCP
jne .loop
cmp [eax + TCP_SOCKET.t_timer], 0
jne .decrement_tcb
;;;;;; cmp [eax + TCP_SOCKET.wndsizeTimer], 0
jne .decrement_wnd
jmp .loop
dec [eax + TCP_SOCKET.timer_retransmission]
jnz .check_more2
.decrement_tcb:
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
dec [eax + TCP_SOCKET.t_timer]
DEBUGF 1,"socket %x: Retransmission timer expired\n", eax
push eax
call TCP_output
pop eax
.check_more2:
dec [eax + TCP_SOCKET.timer_keepalive]
jnz .check_more3
DEBUGF 1,"socket %x: Keepalive expired\n", eax
;;; TODO: check socket state and handle accordingly
.check_more3:
dec [eax + TCP_SOCKET.timer_timed_wait]
jnz .check_more5
DEBUGF 1,"socket %x: 2MSL timer expired\n", eax
.check_more5:
dec [eax + TCP_SOCKET.timer_persist]
jnz .loop
cmp [eax + TCP_SOCKET.t_state], TCB_TIMED_WAIT
jne .loop
push [eax + SOCKET.NextPtr]
call SOCKET_free
pop eax
jmp .check_only
.decrement_wnd:
;;;;;; dec [eax + TCP_SOCKET.wndsizeTimer]
DEBUGF 1,"socket %x: persist timer expired\n", eax
jmp .loop
.exit:
ret
;----------------------
;
; TCP_500ms
;
;----------------------
align 4
TCP_500ms:
add [TCP_sequence_num], 64000
ret
;----------------------
;
; TCP_10ms
;
;----------------------
align 4
TCP_10ms:
; todo: decrease timers
ret
;-----------------------------------------------------------------
;
; TCP_input:
@ -374,8 +400,9 @@ TCP_input:
;-------------------------------------
; Reset idle timer and keepalive timer
;;;; TODO: idle timer?
; TODO
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
;-----------------------------------------
; Process TCP options if not in LISTEN state
@ -475,13 +502,14 @@ TCP_input:
; Delete acknowledged bytes from send buffer
; Stop retransmit timer
mov [ebx + TCP_SOCKET.timer_ack], 0
; Awaken waiting processes
mov eax, ebx
call SOCKET_notify_owner
; Generate more output
call TCP_output
jmp .drop
@ -518,8 +546,9 @@ TCP_input:
add [ebx + TCP_SOCKET.RCV_NXT], ecx
; Add the data to the socket buffer
; The receiving process is awakened (by sorwakeup).
mov eax, ebx
;;; mov...
call SOCKET_input
; The delayed-ACK flag is set and the input processing is complete.
@ -679,8 +708,8 @@ align 4
jle @f
mov [ebx + TCP_SOCKET.SND_NXT], eax
; TODO: turn off retransmission timer
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
mov [ebx + TCP_SOCKET.timer_retransmission], 0
mov eax, [edx + TCP_segment.SequenceNumber]
mov [ebx + TCP_SOCKET.IRS], eax
@ -937,18 +966,6 @@ align 4
jg .ack_dup
jl .ack_nodup
; dd .ack_nodup ;TCB_CLOSED
; dd .ack_nodup ;TCB_LISTEN
; dd .ack_nodup ;TCB_SYN_SENT
; dd .ack_syn_rcvd ;TCB_SYN_RECEIVED
; dd .ack_dup ;TCB_ESTABLISHED
; dd .ack_dup ;TCB_CLOSE_WAIT
; dd .ack_dup ;TCB_FIN_WAIT_1
; dd .ack_dup ;TCB_CLOSING
; dd .ack_dup ;TCB_LAST_ACK
; dd .ack_dup ;TCB_FIN_WAIT_2
; dd .ack_dup ;TCB_TIMED_WAIT
;;;;;
.ack_dup:
@ -960,7 +977,7 @@ align 4
;;;; 887
;-------------------------------------------------
; If the congestion window was infalted to account
; If the congestion window was inflated to account
; for the other side's cached packets, retrace it
;;;; 888 - 902
@ -971,6 +988,14 @@ align 4
;;;;; 903 - 926
mov [ebx + TCP_SOCKET.timer_retransmission], 0
mov eax, [ebx + TCP_SOCKET.SND_MAX]
cmp eax, [edx + TCP_segment.AckNumber]
je .all_outstanding
mov [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value
.all_outstanding:
;-------------------------------------------
; Open congestion window in response to ACKs
@ -1428,7 +1453,7 @@ TCP_pull_out_of_band:
;
; TCP_output
;
; IN: eax = socket pointer
; IN: eax = socket pointer
;; esi = ptr to data
;; ecx = number of data bytes
;
@ -1614,7 +1639,7 @@ TCP_output:
.enter_persist:
DEBUGF 1,"Entering pesist state\n"
DEBUGF 1,"Entering persist state\n"
@ -1748,7 +1773,7 @@ TCP_output:
;;;; jz .fail
push edx eax
call NET_send
call [ebx + NET_DEVICE.transmit]
ret
;----------------
@ -1831,12 +1856,9 @@ TCP_output:
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov esi, [ebx + ETH_DEVICE.transmit]
call [ebx + NET_DEVICE.transmit]
ret
;-------------------------
;
; TCP_outflags
@ -1902,11 +1924,14 @@ TCP_drop:
;---------------------------------------
;
; TCP_respond
; TCP_ack
;
; The easy way to send a RST/ACK segment
; The easy way to send an ACK/RST/keepalive segment
;
; IN: eax = socket ptr
; -or-
; edx = packet ptr (eax must be 0)
; cl = flags
;
; OUT: /
;
@ -1916,6 +1941,113 @@ TCP_respond:
DEBUGF 1,"TCP_respond\n"
;---------------------
; Create the IP packet
push cx eax edx
mov ebx, [eax + IP_SOCKET.LocalIP]
mov eax, [eax + IP_SOCKET.RemoteIP]
mov ecx, TCP_segment.Data
mov di , IP_PROTO_TCP
call IPv4_create_packet
test edi, edi
jz .error
;---------------------------
; Now fill in the TCP header
pop ecx
pop esi
test esi, esi
; jz
push edx eax
push dword .checksum
je .use_segment
jmp .use_socket
;---------------------
; Fill in the checksum
.checksum:
push [esi + IP_SOCKET.LocalIP]
push [esi + IP_SOCKET.RemoteIP]
lea esi, [edi - 20]
xor ecx, ecx
call TCP_checksum
;--------------------
; And send the segment
call [ebx + NET_DEVICE.transmit]
ret
.error:
DEBUGF 1,"TCP_ack failed\n"
add esp, 4
ret
;---------------------------------------------------
; Fill in the TCP header by using a received segment
.use_segment:
mov ax, [esi + TCP_segment.DestinationPort]
rol ax, 8
stosw
mov ax, [esi + TCP_segment.SourcePort]
rol ax, 8
stosw
mov eax, [esi + TCP_segment.AckNumber]
bswap eax
stosd
xor eax, eax
stosd
mov al, 0x50 ; Dataoffset: 20 bytes
stosb
mov al, cl
stosb
mov ax, 1280
rol ax, 8
stosw ; window
xor eax, eax
stosd ; checksum + urgentpointer
ret
;-----------------------------------------------
; Fill in the TCP header by using the socket ptr
.use_socket:
mov ax, [esi + TCP_SOCKET.LocalPort]
rol ax, 8
stosw
mov ax, [esi + TCP_SOCKET.RemotePort]
rol ax, 8
stosw
mov eax, [esi + TCP_SOCKET.SND_NXT]
bswap eax
stosd
mov eax, [esi + TCP_SOCKET.RCV_NXT]
bswap eax
stosd
mov al, 0x50 ; Dataoffset: 20 bytes
stosb
mov al, cl
stosb
mov ax, [esi + TCP_SOCKET.RCV_WND]
rol ax, 8
stosw ; window
xor eax, eax
stosd ; checksum + urgentpointer
ret

View File

@ -252,8 +252,8 @@ UDP_output:
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx
jmp NET_send
call [ebx + NET_DEVICE.transmit]
ret
.fail:
add esp, 8+8
ret