-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 ;; ;; 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 ;; ;; 3C59X.INC ;;
@ -84,13 +80,14 @@
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PROMISCIOUS equ 1
format MS COFF format MS COFF
API_VERSION equ 0x01000100 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
__DEBUG__ equ 1 __DEBUG__ equ 1
@ -101,55 +98,18 @@ include 'imports.inc'
include 'fdo.inc' include 'fdo.inc'
include 'netdrv.inc' include 'netdrv.inc'
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
public START public START
public service_proc public service_proc
public version 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 struc DPD { ; Download Packet Descriptor
.next_ptr dd ? .next_ptr dd ?
.frame_start_hdr dd ? .frame_start_hdr dd ?
.frag_addr dd ? ; for packet data .frag_addr dd ? ; for packet data
.frag_len dd ? ; for packet data .frag_len dd ? ; for packet data
.realaddr dd ? .realaddr dd ?
.size = 32 .size = 32
} }
virtual at 0 virtual at 0
@ -159,12 +119,12 @@ end virtual
struc UPD { ; Upload Packet Descriptor struc UPD { ; Upload Packet Descriptor
.next_ptr dd ? .next_ptr dd ?
.pkt_status dd ? .pkt_status dd ?
.frag_addr dd ? .frag_addr dd ?
.frag_len dd ? ; for packet data .frag_len dd ? ; for packet data
.realaddr dd ? .realaddr dd ?
.size = 32 .size = 32
} }
@ -172,17 +132,11 @@ virtual at 0
upd UPD upd UPD
end virtual 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 ; Ethernet frame symbols
ETH_ALEN equ 6 ETH_ALEN equ 6
ETH_HLEN equ (2*ETH_ALEN+2) ETH_HLEN equ (2*ETH_ALEN+2)
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
; mininmum 64bytes frame length ; mininmum 64bytes frame length
; Registers ; Registers
REG_POWER_MGMT_CTRL equ 0x7c REG_POWER_MGMT_CTRL equ 0x7c
REG_UP_LIST_PTR equ 0x38 REG_UP_LIST_PTR equ 0x38
@ -193,9 +147,11 @@ end virtual
REG_TX_STATUS equ 0x1b REG_TX_STATUS equ 0x1b
REG_RX_STATUS equ 0x18 REG_RX_STATUS equ 0x18
REG_TX_DATA equ 0x10 REG_TX_DATA equ 0x10
; Common window registers ; Common window registers
REG_INT_STATUS equ 0xe REG_INT_STATUS equ 0xe
REG_COMMAND equ 0xe REG_COMMAND equ 0xe
; Register window 7 ; Register window 7
REG_MASTER_STATUS equ 0xc REG_MASTER_STATUS equ 0xc
REG_POWER_MGMT_EVENT equ 0xc REG_POWER_MGMT_EVENT equ 0xc
@ -203,6 +159,7 @@ end virtual
REG_VLAN_ETHER_TYPE equ 0x4 REG_VLAN_ETHER_TYPE equ 0x4
REG_VLAN_MASK equ 0x0 REG_VLAN_MASK equ 0x0
REG_MASTER_ADDRESS equ 0x0 REG_MASTER_ADDRESS equ 0x0
; Register window 6 ; Register window 6
REG_BYTES_XMITTED_OK equ 0xc REG_BYTES_XMITTED_OK equ 0xc
REG_BYTES_RCVD_OK equ 0xa REG_BYTES_RCVD_OK equ 0xa
@ -216,6 +173,7 @@ end virtual
REG_MULTIPLE_COLLISIONS equ 0x2 REG_MULTIPLE_COLLISIONS equ 0x2
REG_SQE_ERRORS equ 0x1 REG_SQE_ERRORS equ 0x1
REG_CARRIER_LOST equ 0x0 REG_CARRIER_LOST equ 0x0
; Register window 5 ; Register window 5
REG_INDICATION_ENABLE equ 0xc REG_INDICATION_ENABLE equ 0xc
REG_INTERRUPT_ENABLE equ 0xa REG_INTERRUPT_ENABLE equ 0xa
@ -223,6 +181,7 @@ end virtual
REG_RX_FILTER equ 0x8 REG_RX_FILTER equ 0x8
REG_RX_EARLY_THRESH equ 0x6 REG_RX_EARLY_THRESH equ 0x6
REG_TX_START_THRESH equ 0x0 REG_TX_START_THRESH equ 0x0
; Register window 4 ; Register window 4
REG_UPPER_BYTES_OK equ 0xe REG_UPPER_BYTES_OK equ 0xe
REG_BAD_SSD equ 0xc REG_BAD_SSD equ 0xc
@ -231,8 +190,10 @@ end virtual
REG_NETWORK_DIAGNOSTIC equ 0x6 REG_NETWORK_DIAGNOSTIC equ 0x6
REG_FIFO_DIAGNOSTIC equ 0x4 REG_FIFO_DIAGNOSTIC equ 0x4
REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported
; Bits in register window 4 ; Bits in register window 4
BIT_AUTOSELECT equ 24 BIT_AUTOSELECT equ 24
; Register window 3 ; Register window 3
REG_TX_FREE equ 0xc REG_TX_FREE equ 0xc
REG_RX_FREE equ 0xa REG_RX_FREE equ 0xa
@ -240,6 +201,7 @@ end virtual
REG_MAC_CONTROL equ 0x6 REG_MAC_CONTROL equ 0x6
REG_MAX_PKT_SIZE equ 0x4 REG_MAX_PKT_SIZE equ 0x4
REG_INTERNAL_CONFIG equ 0x0 REG_INTERNAL_CONFIG equ 0x0
; Register window 2 ; Register window 2
REG_RESET_OPTIONS equ 0xc REG_RESET_OPTIONS equ 0xc
REG_STATION_MASK_HI equ 0xa REG_STATION_MASK_HI equ 0xa
@ -248,6 +210,7 @@ end virtual
REG_STATION_ADDRESS_HI equ 0x4 REG_STATION_ADDRESS_HI equ 0x4
REG_STATION_ADDRESS_MID equ 0x2 REG_STATION_ADDRESS_MID equ 0x2
REG_STATION_ADDRESS_LO equ 0x0 REG_STATION_ADDRESS_LO equ 0x0
; Register window 1 ; Register window 1
REG_TRIGGER_BITS equ 0xc REG_TRIGGER_BITS equ 0xc
REG_SOS_BITS equ 0xa REG_SOS_BITS equ 0xa
@ -258,34 +221,42 @@ end virtual
REG_SMB_STATUS equ 0x2 REG_SMB_STATUS equ 0x2
REG_SMB_ADDRESS equ 0x1 REG_SMB_ADDRESS equ 0x1
REG_SMB_FIFO_DATA equ 0x0 REG_SMB_FIFO_DATA equ 0x0
; Register window 0 ; Register window 0
REG_EEPROM_DATA equ 0xc REG_EEPROM_DATA equ 0xc
REG_EEPROM_COMMAND equ 0xa REG_EEPROM_COMMAND equ 0xa
REG_BIOS_ROM_DATA equ 0x8 REG_BIOS_ROM_DATA equ 0x8
REG_BIOS_ROM_ADDR equ 0x4 REG_BIOS_ROM_ADDR equ 0x4
; Physical management bits ; Physical management bits
BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData
BIT_MGMT_DATA equ 1 ; MII management data bit BIT_MGMT_DATA equ 1 ; MII management data bit
BIT_MGMT_CLK equ 0 ; MII management clock BIT_MGMT_CLK equ 0 ; MII management clock
; MII commands ; MII commands
MII_CMD_MASK equ (1111b shl 10) MII_CMD_MASK equ (1111b shl 10)
MII_CMD_READ equ (0110b shl 10) MII_CMD_READ equ (0110b shl 10)
MII_CMD_WRITE equ (0101b shl 10) MII_CMD_WRITE equ (0101b shl 10)
; MII registers ; MII registers
REG_MII_BMCR equ 0 ; basic mode control register REG_MII_BMCR equ 0 ; basic mode control register
REG_MII_BMSR equ 1 ; basic mode status register REG_MII_BMSR equ 1 ; basic mode status register
REG_MII_ANAR equ 4 ; auto negotiation advertisement register REG_MII_ANAR equ 4 ; auto negotiation advertisement register
REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register
REG_MII_ANER equ 6 ; auto negotiation expansion register REG_MII_ANER equ 6 ; auto negotiation expansion register
; MII bits ; MII bits
BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete
BIT_MII_PREAMBLE_SUPPRESSION equ 6 BIT_MII_PREAMBLE_SUPPRESSION equ 6
; eeprom bits and commands ; eeprom bits and commands
EEPROM_CMD_READ equ 0x80 EEPROM_CMD_READ equ 0x80
EEPROM_BIT_BUSY equ 15 EEPROM_BIT_BUSY equ 15
; eeprom registers ; eeprom registers
EEPROM_REG_OEM_NODE_ADDR equ 0xa EEPROM_REG_OEM_NODE_ADDR equ 0xa
EEPROM_REG_CAPABILITIES equ 0x10 EEPROM_REG_CAPABILITIES equ 0x10
; Commands for command register ; Commands for command register
SELECT_REGISTER_WINDOW equ (1 shl 11) SELECT_REGISTER_WINDOW equ (1 shl 11)
@ -306,7 +277,6 @@ end virtual
EXTRA_PREAMBLE equ 0x4000 EXTRA_PREAMBLE equ 0x4000
; Status ; Status
IntLatch equ 0x0001 IntLatch equ 0x0001
HostError equ 0x0002 HostError equ 0x0002
TxComplete equ 0x0004 TxComplete equ 0x0004
@ -315,18 +285,15 @@ end virtual
RxEarly equ 0x0020 RxEarly equ 0x0020
IntReq equ 0x0040 IntReq equ 0x0040
StatsFull equ 0x0080 StatsFull equ 0x0080
DMADone equ 0x0100 ; 1 shl 8 DMADone equ 0x0100
DownComplete equ 0x0200 ; 1 shl 9 DownComplete equ 0x0200
UpComplete equ 0x0400 ; 1 shl 10 UpComplete equ 0x0400
DMAInProgress equ 0x0800 ; 1 shl 11 (DMA controller is still busy) DMAInProgress equ 0x0800 ; 1 shl 11 (DMA controller is still busy)
CmdInProgress equ 0x1000 ; 1 shl 12 (EL3_CMD 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 ; Commands
TotalReset equ 0 shl 11 TotalReset equ 0 shl 11
SelectWindow equ 1 shl 11 SelectWindow equ 1 shl 11
StartCoax equ 2 shl 11 StartCoax equ 2 shl 11
@ -354,29 +321,47 @@ end virtual
StatsEnable equ 21 shl 11 StatsEnable equ 21 shl 11
StatsDisable equ 22 shl 11 StatsDisable equ 22 shl 11
StopCoax equ 23 shl 11 StopCoax equ 23 shl 11
SetFilterBit equ 25 shl 11} SetFilterBit equ 25 shl 11
; Rx mode bits ; Rx mode bits
RxStation equ 1 RxStation equ 1
RxMulticast equ 2 RxMulticast equ 2
RxBroadcast equ 4 RxBroadcast equ 4
RxProm equ 8 RxProm equ 8
; RX/TX buffers sizes ; RX/TX buffers sizes
MAX_ETH_PKT_SIZE equ 1536 ; max packet size MAX_ETH_PKT_SIZE equ 1536 ; max packet size
NUM_RX_DESC equ 4 ; a power of 2 number NUM_RX_DESC equ 4 ; a power of 2 number
NUM_TX_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 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 section '.flat' code readable align 16
@ -513,21 +498,14 @@ proc service_proc stdcall, ioctl:dword
mov [device.pci_dev], cl mov [device.pci_dev], cl
; Now, it's time to find the base io addres of the PCI device ; 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] find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
; We've found the io address, find IRQ now ; We've found the io address, find IRQ now
find_irq [device.pci_bus], [device.pci_dev], [device.irq_line] 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",\ 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 [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 ; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax call probe ; this function will output in eax
test eax, eax test eax, eax
@ -579,8 +557,6 @@ proc service_proc stdcall, ioctl:dword
; todo: reset device into virgin state ; todo: reset device into virgin state
.err: .err:
stdcall KernelFree, [device.rx_buffer]
stdcall KernelFree, [device.tx_buffer]
stdcall KernelFree, ebx stdcall KernelFree, ebx
@ -613,7 +589,7 @@ endp
;*************************************************************************** ;***************************************************************************
align 4 align 4
probe: ; Tested - ok probe:
DEBUGF 1,"Probing 3com card\n" DEBUGF 1,"Probing 3com card\n"
@ -671,6 +647,11 @@ probe: ; Tested - ok
jnz .boomerang_func jnz .boomerang_func
mov [device.transmit], vortex_transmit mov [device.transmit], vortex_transmit
DEBUGF 1,"Device is a vortex type\n" 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 jmp @f
.boomerang_func: ; full bus master, so use boomerang functions .boomerang_func: ; full bus master, so use boomerang functions
mov [device.transmit], boomerang_transmit mov [device.transmit], boomerang_transmit
@ -812,6 +793,9 @@ reset:
mov ecx, 6 mov ecx, 6
rep stosd rep stosd
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
ret ret
@ -975,13 +959,9 @@ tx_reset:
jnz .tx_reset_loop jnz .tx_reset_loop
.tx_set_prev: .tx_set_prev:
; init last_dpd ; init last_dpd
mov eax, [device.dpd_buffer] lea eax, [device.dpd_buffer + (NUM_TX_DESC-1)*dpd.size]
add eax, (NUM_TX_DESC-1)*dpd.size
mov [device.prev_dpd], eax 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: .tx_enable:
ret ret
@ -1004,59 +984,54 @@ rx_reset:
set_io REG_COMMAND set_io REG_COMMAND
mov ax, RxReset or 0x4 mov ax, RxReset or 0x4
out dx, ax out dx, ax
; wait for RxReset to complete ; wait for RxReset to complete
mov ecx, 200000 mov ecx, 200000
.rx_reset_loop: .loop:
in ax, dx in ax, dx
test ah, 10000b ; check CmdInProgress test ah, 10000b ; check CmdInProgress
dec ecx dec ecx
jnz .rx_reset_loop jnz .loop
; create upd ring ; create upd ring
lea eax, [device.upd_buffer]
GetRealAddr
mov edi, eax ; real addr of first descr
mov eax, [device.upd_buffer] lea esi, [device.upd_buffer] ; ptr to first descr
mov [device.curr_upd], eax lea edx, [device.upd_buffer + (NUM_RX_DESC-1)*upd.size] ; ptr to last descr
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]
mov ecx, NUM_RX_DESC 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 .upd_loop:
mov [eax + upd.frag_addr], edi mov [edx + upd.next_ptr], edi
mov [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
mov [eax + upd.realaddr], ebx
add edi, MAX_ETH_FRAME_SIZE push ecx edx
add ebx, MAX_ETH_FRAME_SIZE 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 add esi, upd.size
mov edx, eax add edi, upd.size
add eax, upd.size
dec ecx dec ecx
jnz .upd_loop jnz .upd_loop
pop ebx lea eax, [device.upd_buffer]
mov [device.curr_upd], eax
mov eax, [device.upd_buffer] GetRealAddr
call GetPgAddr
set_io 0 set_io 0
set_io REG_UP_LIST_PTR set_io REG_UP_LIST_PTR
out dx, eax out dx, eax
.rx_enable: .rx_enable:
ret ret
@ -2228,6 +2203,8 @@ vortex_transmit:
mov ax, (10100b shl 11) + 1 ; StartDMADown mov ax, (10100b shl 11) + 1 ; StartDMADown
out dx, ax out dx, ax
.finish: .finish:
call KernelFree
add esp, 4
ret ret
@ -2245,26 +2222,32 @@ vortex_transmit:
align 4 align 4
boomerang_transmit: 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 cmp dword [esp+8], MAX_ETH_FRAME_SIZE
ja .finish ; packet is too long jg .fail
call check_tx_status call check_tx_status
test al, al test al, al
jnz tx_reset jnz tx_reset
; calculate descriptor address ; calculate descriptor address
mov eax, [device.prev_dpd] mov esi, [device.prev_dpd]
DEBUGF 1,"Previous DPD: %x\n", eax DEBUGF 1,"Previous DPD: %x\n", esi
add eax, dpd.size add esi, dpd.size
mov ecx, [device.dpd_buffer] lea ecx, [device.dpd_buffer + (NUM_TX_DESC)*dpd.size]
add ecx, NUM_TX_DESC*dpd.size cmp esi, ecx
cmp eax, ecx jl @f
cmovae eax, [device.dpd_buffer] ; Wrap if needed 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 ; check DnListPtr
set_io 0 set_io 0
set_io REG_DN_LIST_PTR set_io REG_DN_LIST_PTR
@ -2272,91 +2255,56 @@ boomerang_transmit:
; mark if Dn_List_Ptr is cleared ; mark if Dn_List_Ptr is cleared
test eax, eax test eax, eax
setz [device.dn_list_ptr_cleared] setz [device.dn_list_ptr_cleared]
; finish if no more free descriptor is available - FIXME! ; finish if no more free descriptor is available - FIXME!
cmp eax, [esp] ; cmp eax, esi
pop eax ; jz .finish
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 ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; update statistics ; update statistics
inc [device.packets_tx] inc [device.packets_tx]
mov ecx, [esp+8] ; buffer size
mov ecx, [esp+8+8]
add dword [device.bytes_tx], ecx add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0 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 ; 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 call GetPgAddr
mov edi, [esp] mov [esi+dpd.frag_addr], eax
and edi, 4096 - 1 mov ecx, [esp+8] ; packet size
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
or ecx, 0x80000000 ; last fragment or ecx, 0x80000000 ; last fragment
DEBUGF 1,"Frag size + flag is: %x\n", ecx mov [esi+dpd.frag_len], ecx
mov [eax+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 ; test byte [device.has_hwcksm], 0xff
; jz @f ; 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 [esi+dpd.frame_start_hdr], ecx
mov [eax+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 ; calculate physical address of dpd
mov edi, eax mov eax, esi
call GetPgAddr GetRealAddr
and edi, 4096 - 1
or eax, edi
cmp [device.dn_list_ptr_cleared], 0 cmp [device.dn_list_ptr_cleared], 0
jz .add_to_list jz .add_to_list
DEBUGF 1,"DN list ptr: %x\n", eax
; write Dn_List_Ptr ; write Dn_List_Ptr
DEBUGF 1,"DPD phys addr=%x\n", eax
set_io 0 set_io 0
set_io REG_DN_LIST_PTR set_io REG_DN_LIST_PTR
out dx, eax out dx, eax
jmp .finish_pop jmp .finish
.add_to_list:
.add_to_list:
DEBUGF 1,"Adding To list\n" DEBUGF 1,"Adding To list\n"
push eax
; DnStall ; DnStall
set_io 0 set_io 0
set_io REG_COMMAND set_io REG_COMMAND
@ -2364,47 +2312,46 @@ boomerang_transmit:
out dx, ax out dx, ax
; wait for DnStall to complete ; wait for DnStall to complete
DEBUGF 1,"Waiting for DnStall\n" DEBUGF 1,"Waiting for DnStall\n"
mov ecx, 6000 mov ecx, 6000
.wait_for_stall: .wait_for_stall:
in ax, dx ; read REG_INT_STATUS in ax, dx ; read REG_INT_STATUS
test ah, 10000b test ah, 10000b
jz .dnstall_ok jz .dnstall_ok
dec ecx dec ecx
jnz .wait_for_stall jnz .wait_for_stall
.dnstall_ok: .dnstall_ok:
DEBUGF 1,"DnStall ok!\n" DEBUGF 1,"DnStall ok!\n"
mov eax, [esp] ; prev_tx_frame
mov ecx, [device.prev_dpd] mov ecx, [device.prev_dpd]
mov [ecx+dpd.next_ptr], eax mov [ecx+dpd.next_ptr], eax
set_io 0 set_io 0
set_io REG_DN_LIST_PTR set_io REG_DN_LIST_PTR
in eax, dx in eax, dx
test eax, eax test eax, eax
pop eax
jnz .dnunstall jnz .dnunstall
; if Dn_List_Ptr has been cleared fill it up ; if Dn_List_Ptr has been cleared fill it up
DEBUGF 1,"DnList Ptr has been cleared\n" DEBUGF 1,"DnList Ptr has been cleared\n"
mov eax, [esp]
out dx, eax out dx, eax
.dnunstall: .dnunstall:
; DnUnStall ; DnUnStall
set_io 0 set_io 0
set_io REG_COMMAND set_io REG_COMMAND
mov ax, ((110b shl 11)+3) mov ax, ((110b shl 11)+3)
out dx, ax out dx, ax
.finish_pop: .finish:
pop [device.prev_tx_frame] mov [device.prev_dpd], esi
pop [device.prev_dpd]
.finish:
xor eax, eax xor eax, eax
ret ret 8
.fail:
stdcall KernelFree, [esp+4]
ret 8
;--------------------------------- ;---------------------------------
@ -2581,7 +2528,9 @@ int_vortex:
.read_frame: .read_frame:
; program buffer address to read in ; 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 test eax, eax
jz .finish jz .finish
@ -2672,14 +2621,13 @@ int_vortex:
align 4 align 4
int_boomerang: 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 ; find pointer of device wich made IRQ occur
mov esi, BOOMERANG_LIST mov esi, BOOMERANG_LIST
mov ecx, [BOOMERANG_DEVICES] mov ecx, [BOOMERANG_DEVICES]
; DEBUGF 1,"Devices: %u\n", ecx
test ecx, ecx test ecx, ecx
jz .fail jz .fail
.nextdevice: .nextdevice:
@ -2705,7 +2653,6 @@ int_boomerang:
.got_it: .got_it:
DEBUGF 1,"Device: %x Status: %x ", ebx, eax DEBUGF 1,"Device: %x Status: %x ", ebx, eax
push ax push ax
; disable all INTS ; disable all INTS
@ -2713,13 +2660,6 @@ int_boomerang:
mov ax, SetIntrEnb mov ax, SetIntrEnb
out dx, ax out dx, ax
;; acknowledge all int sources
;
; mov ax, word [esp]
; and ax, 0xff
; or ax, AckIntr
; out dx, ax
;-------------------------------------------------------------------------- ;--------------------------------------------------------------------------
test word[esp], UpComplete test word[esp], UpComplete
jz .noRX jz .noRX
@ -2730,75 +2670,59 @@ int_boomerang:
DEBUGF 1,"UpComplete\n" DEBUGF 1,"UpComplete\n"
; check if packet is uploaded ; check if packet is uploaded
mov eax, [device.curr_upd] mov esi, [device.curr_upd]
test byte [eax+upd.pkt_status+1], 0x80 ; upPktComplete test byte [esi+upd.pkt_status+1], 0x80 ; upPktComplete
jz .finish jz .finish
DEBUGF 1, "Current upd: %x\n", esi
; packet is uploaded check for any error ; packet is uploaded check for any error
.check_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 jz .copy_packet_length
DEBUGF 1,"Error in packet\n" 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 jmp .finish
.copy_packet_length: .copy_packet_length:
mov ecx, [eax+upd.pkt_status] mov ecx, [esi+upd.pkt_status]
and ecx, 0x1fff and ecx, 0x1fff
cmp ecx, MAX_ETH_PKT_SIZE
jbe .copy_packet
and [eax+upd.pkt_status], 0
jmp .finish
.copy_packet: ; cmp ecx, MAX_ETH_PKT_SIZE
DEBUGF 1, " data hw addr:%x\n", [eax+upd.frag_addr] ; jbe .copy_packet
; and [esi+upd.pkt_status], 0
; jmp .finish
; .copy_packet:
mov esi, [eax+upd.realaddr] DEBUGF 1, "Received %u bytes in buffer %x\n", ecx, [esi+upd.realaddr]:8
push esi ecx
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
pop ecx esi
test eax, eax
jz .finish
push dword .loop ;.finish push dword .loop ;.finish
push ecx eax push ecx
mov edi, eax push [esi+upd.realaddr]
DEBUGF 1, " copying %u bytes from %x to %x\n", ecx, esi, edi
; update statistics ; update statistics
inc [device.packets_rx] inc [device.packets_rx]
add dword [device.bytes_rx], ecx add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0 adc dword [device.bytes_rx + 4], 0
; copy packet data ; update UPD (Alloc new buffer for next packet)
shr cx , 1 stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
jnc .nb mov [esi + upd.realaddr], eax
movsb GetRealAddr
.nb: mov [esi + upd.frag_addr], eax
shr cx , 1 and [esi + upd.pkt_status], 0
jnc .nw mov [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
movsw
.nw:
rep movsd
mov eax, [device.curr_upd] ; Update UPD pointer
DEBUGF 1, "current upd: %x\n", eax add esi, upd.size
and [eax + upd.pkt_status], 0 ; clear the ring buffer entry for reuse lea ecx, [device.upd_buffer+(NUM_RX_DESC)*upd.size]
mov [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) ;;; cmp esi, ecx
add eax, upd.size jl @f
lea esi, [device.upd_buffer]
mov ecx, [device.upd_buffer] @@:
add ecx, (NUM_RX_DESC)*upd.size mov [device.curr_upd], esi
DEBUGF 1, "Next upd: %x\n", esi
cmp eax, ecx
cmovae eax, [device.upd_buffer]
mov [device.curr_upd], eax
DEBUGF 1, "next upd: %x\n", eax
jmp EthReceiver jmp EthReceiver
.loop: .loop:
mov ebx, [esp] mov ebx, [esp]
jmp .receive jmp .receive
@ -2811,14 +2735,38 @@ int_boomerang:
in eax, dx in eax, dx
test ah, 0x20 ; UpStalled test ah, 0x20 ; UpStalled
jz .noUpUnStall jz .noUpUnStall
DEBUGF 1, "upUnStalling\n"
; issue upUnStall command ; issue upUnStall command
set_io REG_COMMAND set_io REG_COMMAND
mov ax, ((11b shl 12)+1) ; upUnStall mov ax, ((11b shl 12)+1) ; upUnStall
out dx, ax out dx, ax
DEBUGF 1, "upUnStalling\n"
.noUpUnStall:
;;;; FIXME: make upunstall work
.noUpUnStall:
.noRX: .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 pop ax
set_io 0 set_io 0
@ -2826,11 +2774,6 @@ int_boomerang:
or ax, AckIntr or ax, AckIntr
out dx, ax out dx, ax
; set_io REG_COMMAND
; mov ax, AckIntr + IntLatch
; out dx, ax
set_io REG_INT_STATUS set_io REG_INT_STATUS
in ax, dx in ax, dx
test ax, S_5_INTS test ax, S_5_INTS
@ -2841,18 +2784,14 @@ int_boomerang:
mov ax, SetIntrEnb + S_5_INTS mov ax, SetIntrEnb + S_5_INTS
out dx, ax out dx, ax
ret ret
; End of code ; End of code
align 4 ; Place all initialised data here align 4 ; Place all initialised data here
macro strtbl name, [string] macro strtbl name, [string]
{ {
common common
@ -2866,7 +2805,7 @@ forward
VORTEX_DEVICES dd 0 VORTEX_DEVICES dd 0
BOOMERANG_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 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 ; 3c920B-EMB-WNM Tornado
HW_VERSIONS_SIZE = $ - hw_versions HW_VERSIONS_SIZE = $ - hw_versions
include_debug_strings ; All data wich FDO uses will be included here 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 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 ;; ;; 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 ;; ;; Written by hidnplayr@kolibrios.org ;;
;; with help from CleverMouse ;; ;; with help from CleverMouse ;;
@ -11,55 +14,46 @@
;; GNU GENERAL PUBLIC LICENSE ;; ;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;; ;; 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 format MS COFF
API_VERSION equ 0x01000100 API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
DEBUG equ 1 MAX_DEVICES equ 16
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1 DEBUG equ 1
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1
include 'proc32.inc' include 'proc32.inc'
include 'imports.inc' include 'imports.inc'
include 'fdo.inc' include 'fdo.inc'
include 'netdrv.inc' include 'netdrv.inc'
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
virtual at ebx virtual at ebx
device: device:
ETH_DEVICE ETH_DEVICE
.io_addr dd ? .io_addr dd ?
.irq_line db ? .irq_line db ?
.pci_bus db ? .pci_bus db ?
.pci_dev db ? .pci_dev db ?
.flags db ? .flags db ?
.vendor db ? .vendor db ?
.asic_base dw ? .asic_base dw ?
.memsize db ? .memsize db ?
.rx_start db ? .rx_start db ?
.tx_start db ? .tx_start db ?
.bmem dd ? .bmem dd ?
.rmem dd ? .rmem dd ?
.romdata rb 16 .romdata rb 16
.size = $ - device .size = $ - device
end virtual end virtual
@ -68,8 +62,6 @@ public START
public service_proc public service_proc
public version public version
MAX_DEVICES equ 16 ; Max number of devices this driver may handle
P0_PSTART equ 0x01 P0_PSTART equ 0x01
P0_PSTOP equ 0x02 P0_PSTOP equ 0x02
P0_BOUND equ 0x03 P0_BOUND equ 0x03
@ -234,8 +226,8 @@ proc service_proc stdcall, ioctl:dword
; check if the device is already listed ; check if the device is already listed
mov esi, DEVICE_LIST mov esi, device_list
mov ecx, [DEVICES] mov ecx, [devices]
test ecx, ecx test ecx, ecx
jz .firstdevice_pci jz .firstdevice_pci
@ -269,8 +261,8 @@ proc service_proc stdcall, ioctl:dword
.isa: .isa:
mov esi, DEVICE_LIST mov esi, device_list
mov ecx, [DEVICES] mov ecx, [devices]
test ecx, ecx test ecx, ecx
jz .firstdevice_isa jz .firstdevice_isa
mov al , [eax+3] mov al , [eax+3]
@ -305,9 +297,9 @@ proc service_proc stdcall, ioctl:dword
test eax, eax test eax, eax
jnz .err ; If an error occured, exit jnz .err ; If an error occured, exit
mov eax, [DEVICES] mov eax, [devices]
mov [DEVICE_LIST+4*eax], ebx mov [device_list+4*eax], ebx
inc [DEVICES] inc [devices]
mov [device.type], NET_TYPE_ETH mov [device.type], NET_TYPE_ETH
call NetRegDev call NetRegDev
@ -346,7 +338,7 @@ endp
create_new_struct: create_new_struct:
cmp [DEVICES], MAX_DEVICES cmp [devices], MAX_DEVICES
jge .fail jge .fail
push edx push edx
@ -572,7 +564,7 @@ nsr_001:
nsr_002: nsr_002:
out dx, al out dx, al
;clear remote bytes count ; clear remote bytes count
set_io 0 set_io 0
xor al, al xor al, al
@ -584,7 +576,7 @@ nsr_002:
out dx, al out dx, al
;initialize Receive configuration register ; initialize Receive configuration register
set_io P0_RCR set_io P0_RCR
mov al, 0x20 ; monitor mode mov al, 0x20 ; monitor mode
out dx, al out dx, al
@ -670,6 +662,9 @@ nsr_002:
mov ecx, 6 mov ecx, 6
rep stosd rep stosd
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
; Indicate that we have successfully reset the card ; Indicate that we have successfully reset the card
DEBUGF 2,"Done!\n" DEBUGF 2,"Done!\n"
@ -733,10 +728,14 @@ transmit:
adc dword [device.bytes_tx + 4], 0 adc dword [device.bytes_tx + 4], 0
.finish: .finish:
call Kernelfree
add esp, 4
xor eax, eax xor eax, eax
ret ret
.err: .err:
call Kernelfree
add esp, 4
or eax, -1 or eax, -1
ret ret
@ -752,8 +751,8 @@ int_handler:
DEBUGF 2,"IRQ %x ",eax:2 DEBUGF 2,"IRQ %x ",eax:2
; find pointer of device wich made INT occur ; find pointer of device wich made INT occur
mov esi, DEVICE_LIST mov esi, device_list
mov ecx, [DEVICES] mov ecx, [devices]
.nextdevice: .nextdevice:
mov ebx, [esi] mov ebx, [esi]
@ -1197,8 +1196,8 @@ epw_005: ; Wait for Remote DMA Complete
;all initialized data place here ;all initialized data place here
align 4 align 4
DEVICES dd 0 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 'RTL8029/ne2000',0 ;max 16 chars include zero my_service db 'RTL8029/ne2000',0 ;max 16 chars include zero
device_1 db 'Realtek 8029',0 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 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. ;; ;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;; ;; 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 ;; ;; Written by hidnplayr@kolibrios.org ;;
;; ;; ;; ;;
;; 0.1 - x march 2009 ;;
;; 0.2 - 8 november 2009 ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;; ;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;; ;; Version 2, June 1991 ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format MS COFF format MS COFF
API_VERSION equ 0x01000100 API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
MAX_DEVICES equ 16
DEBUG equ 1 DEBUG equ 1
__DEBUG__ equ 1 __DEBUG__ equ 1
@ -29,46 +31,10 @@ include 'imports.inc'
include 'fdo.inc' include 'fdo.inc'
include 'netdrv.inc' include 'netdrv.inc'
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
public START public START
public service_proc public service_proc
public version 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_IDR0 equ 0x00
REG_MAR0 equ 0x08 ; multicast filter register 0 REG_MAR0 equ 0x08 ; multicast filter register 0
REG_MAR4 equ 0x0c ; multicast filter register 4 REG_MAR4 equ 0x0c ; multicast filter register 4
@ -169,8 +135,8 @@ end virtual
RX_BUFFER_SIZE equ (8192 shl RBLEN);+16 RX_BUFFER_SIZE equ (8192 shl RBLEN);+16
MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC
NUM_TX_DESC equ 4 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_REG_ETH_ID equ 7 ; MAC offset
EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address
@ -228,6 +194,30 @@ end virtual
TSR_CRS equ 1 SHL 31 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 section '.flat' code readable align 16
@ -298,8 +288,8 @@ proc service_proc stdcall, ioctl:dword
; check if the device is already listed ; check if the device is already listed
mov esi, RTL8139_LIST mov esi, device_list
mov ecx, [RTL8139_DEV] mov ecx, [devices]
test ecx, ecx test ecx, ecx
jz .firstdevice 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 ; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice: .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 jge .fail
push edx 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 pop edx
test eax, eax test eax, eax
jz .fail 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.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 ; 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 test eax, eax
jnz .err ; If an error occured, exit jnz .err ; If an error occured, exit
mov eax, [RTL8139_DEV] ; Add the device structure to our device list mov eax, [devices] ; Add the device structure to our device list
mov [RTL8139_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 [RTL8139_DEV] ; inc [devices] ;
mov [device.type], NET_TYPE_ETH mov [device.type], NET_TYPE_ETH
call NetRegDev call NetRegDev
@ -393,7 +382,7 @@ proc service_proc stdcall, ioctl:dword
.err: .err:
stdcall KernelFree, dword [device.rx_buffer] stdcall KernelFree, dword [device.rx_buffer]
stdcall KernelFree, dword [device.tx_buffer] ;; stdcall KernelFree, dword [device.tx_buffer]
stdcall KernelFree, ebx stdcall KernelFree, ebx
@ -537,7 +526,7 @@ reset:
DEBUGF 1,"\nCould not attach int handler!\n" DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1 ; or eax, -1
; ret ; ret
@@: @@:
; reset chip ; reset chip
@ -613,6 +602,7 @@ reset:
mov [device.rx_data_offset], eax mov [device.rx_data_offset], eax
mov [device.curr_tx_desc], al mov [device.curr_tx_desc], al
mov [device.last_tx_desc], al
; clear packet/byte counters ; clear packet/byte counters
@ -625,21 +615,6 @@ reset:
set_io REG_MPC set_io REG_MPC
out dx , eax 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 ; set RxBuffer address, init RX buffer offset
mov eax, [device.rx_buffer] mov eax, [device.rx_buffer]
@ -658,6 +633,9 @@ reset:
call read_mac 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 ; Indicate that we have successfully reset the card
DEBUGF 2,"Done!\n" DEBUGF 2,"Done!\n"
@ -675,7 +653,6 @@ reset:
;; pointer to device structure in ebx ;; ;; pointer to device structure in ebx ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4 align 4
transmit: transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8] DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
@ -686,71 +663,69 @@ transmit:
[eax+13]:2,[eax+12]:2 [eax+13]:2,[eax+12]:2
cmp dword [esp+8], MAX_ETH_FRAME_SIZE cmp dword [esp+8], MAX_ETH_FRAME_SIZE
jg .finish ; packet is too long jg .fail
cmp dword [esp+8], 60 cmp dword [esp+8], 60
jl .finish ; packet is too short jl .fail
; check descriptor ; check if we own the discriptor
DEBUGF 1,"Checking descriptor, " set_io 0
movzx ecx, [device.curr_tx_desc] movzx ecx, [device.curr_tx_desc]
mov edx, [device.io_addr] shl ecx, 2
lea edx, [edx+ecx*4+REG_TSD0] lea edx, [edx+ecx+REG_TSD0]
in ax, dx in ax, dx
test ax, 0x1fff ; or no size given test ax, (1 shl BIT_OWN)
jz .send_packet jz .wait_to_send
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, "
push edx ebx ; TODO : rtl8139 internal timer should be used instead .send_packet:
stdcall Sleep, TX_TIMEOUT ; ? What registers does this destroy ? ; Set the buffer address
pop ebx edx 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 the size of the buffer
and ax, (1 shl BIT_TOK) or (1 shl BIT_OWN) set_io 0
cmp ax, (1 shl BIT_TOK) or (1 shl BIT_OWN) lea edx, [edx+ecx+REG_TSD0]
jz .send_packet ; if chip hung, reset it mov eax, [esp+8]
push dx ; or eax, (ERTXTH shl BIT_ERTXTH) ; Early threshold
call reset ; reset the card out dx , eax
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
; Update stats
inc [device.packets_tx]
add dword [device.bytes_tx], eax add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0 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) ; get next descriptor
out dx , eax ;
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
inc [device.curr_tx_desc] inc [device.curr_tx_desc]
and [device.curr_tx_desc], 3 and [device.curr_tx_desc], 3
DEBUGF 1," - Packet Sent! " DEBUGF 1,"Packet Sent! "
.finish: xor eax, eax
DEBUGF 1," - Done!\n" ret 8
ret
.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 ;; ;; Interrupt handler ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;
align 4 align 4
int_handler: 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 ; find pointer of device wich made IRQ occur
mov esi, RTL8139_LIST mov esi, device_list
mov ecx, [RTL8139_DEV] mov ecx, [devices]
test ecx, ecx test ecx, ecx
jz .fail jz .fail
.nextdevice: .nextdevice:
@ -799,7 +773,6 @@ int_handler:
;---------------------------------------------------- ;----------------------------------------------------
; Received packet ok? ; Received packet ok?
test ax, ISR_ROK test ax, ISR_ROK
jz @f jz @f
push ax push ax
@ -836,7 +809,6 @@ int_handler:
test eax, eax ; Test if we allocated succesfully test eax, eax ; Test if we allocated succesfully
jz .abort jz .abort
mov edi, eax ; Where we will copy too mov edi, eax ; Where we will copy too
mov esi, [esp] ; The buffer we will copy from mov esi, [esp] ; The buffer we will copy from
@ -914,60 +886,78 @@ int_handler:
;---------------------------------------------------- ;----------------------------------------------------
; Transmit error ? ; Transmit error ?
@@: @@:
test ax, ISR_TER test ax, ISR_TER
jz @f jz @f
push ax ; push ax
cmp [device.curr_tx_desc], 4 ; cmp [device.curr_tx_desc], 4
jz .notxd ; 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
; ;
; .nofd: ; set_io 0
pop ax ; 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 ? ; Transmit ok ?
@@: @@:
test ax, ISR_TOK test ax, ISR_TOK
jz @f 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 ? ; Rx buffer overflow ?
@@: @@:
test ax, ISR_RXOVW test ax, ISR_RXOVW
jz @f jz @f
@ -975,16 +965,14 @@ int_handler:
push ax push ax
DEBUGF 2,"RX-buffer overflow!\n" DEBUGF 2,"RX-buffer overflow!\n"
mov edx, [device.io_addr] set_io 0
add edx, REG_ISR set_io REG_ISR
mov ax , ISR_FIFOOVW or ISR_RXOVW mov ax , ISR_FIFOOVW or ISR_RXOVW
out dx , ax out dx , ax
pop ax pop ax
;---------------------------------------------------- ;----------------------------------------------------
; Packet underrun? ? ; Packet underrun?
@@: @@:
test ax, ISR_PUN test ax, ISR_PUN
jz @f jz @f
@ -993,23 +981,21 @@ int_handler:
;---------------------------------------------------- ;----------------------------------------------------
; Receive FIFO overflow ? ; Receive FIFO overflow ?
@@: @@:
test ax, ISR_FIFOOVW test ax, ISR_FIFOOVW
jz @f jz @f
push ax push ax
DEBUGF 2,"RX fifo overflox!\n" DEBUGF 2,"RX fifo overflow!\n"
mov edx, [device.io_addr] set_io 0
add edx, REG_ISR set_io REG_ISR
mov ax , ISR_FIFOOVW or ISR_RXOVW mov ax , ISR_FIFOOVW or ISR_RXOVW
out dx , ax out dx , ax
pop ax pop ax
;---------------------------------------------------- ;----------------------------------------------------
; Something about Cable changed ? ; Something about Cable changed ?
@@: @@:
test ax, ISR_LENCHG test ax, ISR_LENCHG
jz .fail jz .fail
@ -1017,11 +1003,7 @@ int_handler:
DEBUGF 2,"Cable changed!\n" DEBUGF 2,"Cable changed!\n"
call cable call cable
; If none of the above events happened, just exit clearing int
.fail: .fail:
DEBUGF 1,"\n"
ret ret
@ -1213,47 +1195,48 @@ read_eeprom:
; End of code ; End of code
section '.data' data readable writable align 16 ; place all uninitialized data place here
align 4 ; Place all initialised data here align 4 ; Place all initialised data here
RTL8139_DEV dd 0 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 'RTL8139',0 ; max 16 chars include zero my_service db 'RTL8139',0 ; max 16 chars include zero
device_1 db 'Realtek 8139',0 device_1 db 'Realtek 8139',0
device_2 db 'Realtek 8139A',0 device_2 db 'Realtek 8139A',0
device_3 db 'Realtek 8139B',0 device_3 db 'Realtek 8139B',0
device_4 db 'Realtek 8139C',0 device_4 db 'Realtek 8139C',0
device_5 db 'Realtek 8100',0 device_5 db 'Realtek 8100',0
device_6 db 'Realtek 8139D',0 device_6 db 'Realtek 8139D',0
device_7 db 'Realtek 8139CP',0 device_7 db 'Realtek 8139CP',0
device_8 db 'Realtek 8101',0 device_8 db 'Realtek 8101',0
device_unknown db 'Unknown RTL8139 clone', 0 device_unknown db 'Unknown RTL8139 clone', 0
crosslist dd device_1 crosslist:
dd device_2 dd device_1
dd device_3 dd device_2
dd device_4 dd device_3
dd device_5 dd device_4
dd device_6 dd device_5
dd device_7 dd device_6
dd device_8 dd device_7
dd device_unknown 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 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_RTL8139A db VER_RTL8139
db VER_RTL8139B db VER_RTL8139A
db VER_RTL8139C db VER_RTL8139B
db VER_RTL8100 db VER_RTL8139C
db VER_RTL8139D db VER_RTL8100
db VER_RTL8139CP db VER_RTL8139D
db VER_RTL8101 db VER_RTL8139CP
db 0 db VER_RTL8101
db 0
HW_VER_ARRAY_SIZE = $-hw_ver_array HW_VER_ARRAY_SIZE = $-hw_ver_array
include_debug_strings ; All data wich FDO uses will be included here 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
RTL8139_LIST rd MAX_RTL8139 ; 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 ;; ;; 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 ;; ;; Based on dec21140.Asm from Solar OS by ;;
;; Eugen Brasoveanu, ;; ;; Eugen Brasoveanu, ;;
;; Ontanu Bogdan Valentin ;; ;; Ontanu Bogdan Valentin ;;
;; ;; ;; ;;
;; Written by hidnplayr@kolibrios.org ;; ;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; 0.1 - 5 june 2010 ;;
;; ;; ;; ;;
;; GNU GENERAL PUBLIC LICENSE ;; ;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;; ;; Version 2, June 1991 ;;
@ -21,6 +19,9 @@
format MS COFF format MS COFF
API_VERSION equ 0x01000100 API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
MAX_DEVICES equ 16
DEBUG equ 1 DEBUG equ 1
__DEBUG__ equ 1 __DEBUG__ equ 1
@ -31,42 +32,32 @@ include 'imports.inc'
include 'fdo.inc' include 'fdo.inc'
include 'netdrv.inc' include 'netdrv.inc'
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
public START public START
public service_proc public service_proc
public version public version
virtual at ebx virtual at ebx
device: device:
ETH_DEVICE ETH_DEVICE
; device specific .rx_p_des dd ? ; descriptors ring with received packets
.rx_p_des dd ? ; descriptors ring with received packets .tx_p_des dd ? ; descriptors ring with 'to transmit' packets
.tx_p_des dd ? ; descriptors ring with 'to transmit' packets .tx_free_des dd ? ; Tx descriptors available
.tx_free_des dd ? ; Tx descriptors available .tx_wr_des dd ? ; Tx current descriptor to write data to
.tx_wr_des dd ? ; Tx current descriptor to write data to .tx_rd_des dd ? ; Tx current descriptor to read TX completion
.tx_rd_des dd ? ; Tx current descriptor to read TX completion .rx_crt_des dd ? ; Rx current descriptor
.rx_crt_des dd ? ; Rx current descriptor
.io_addr dd ? .io_addr dd ?
.pci_bus db ? .pci_bus db ?
.pci_dev db ? .pci_dev db ?
.irq_line db ? .irq_line db ?
.size = $ - device .size = $ - device
end virtual end virtual
MAX_DEVICES equ 16
;------------------------------------------- ;-------------------------------------------
; configuration registers ; configuration registers
;------------------------------------------- ;-------------------------------------------
@ -381,7 +372,7 @@ proc service_proc stdcall, ioctl:dword
; check if the device is already listed ; check if the device is already listed
mov esi, DEVICE_LIST mov esi, device_list
mov ecx, [devices] mov ecx, [devices]
test ecx, ecx test ecx, ecx
jz .firstdevice jz .firstdevice
@ -442,7 +433,7 @@ proc service_proc stdcall, ioctl:dword
; Ok, the eth_device structure is ready, let's probe the device ; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this 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 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] ; inc [devices] ;
call probe ; this function will output in eax call probe ; this function will output in eax
@ -771,6 +762,9 @@ reset:
mov ecx, 6 mov ecx, 6
rep stosd rep stosd
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
DEBUGF 1,"Reset done\n" DEBUGF 1,"Reset done\n"
ret ret
@ -1000,15 +994,18 @@ transmit:
DEBUGF 1,"transmit ok\n" DEBUGF 1,"transmit ok\n"
xor eax, eax xor eax, eax
call Kernelfree
add esp, 4
ret ret
.fail: .fail:
DEBUGF 1,"transmit failed\n" DEBUGF 1,"transmit failed\n"
or eax, -1 or eax, -1
call Kernelfree
add esp, 4
ret ret
;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;
;; ;; ;; ;;
;; Interrupt handler ;; ;; Interrupt handler ;;
@ -1025,7 +1022,7 @@ int_handler:
mov ecx, [devices] mov ecx, [devices]
test ecx, ecx test ecx, ecx
jz .fail jz .fail
mov esi, DEVICE_LIST mov esi, device_list
.nextdevice: .nextdevice:
mov ebx, dword [esi] mov ebx, dword [esi]
@ -1701,17 +1698,16 @@ mdio_write: ;int phy_id: edx, int location: edi, int value: ax)
; End of code ; End of code
align 4 ; Place all initialised data here align 4 ; Place all initialised data here
devices dd 0 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 my_service db 'DEC21X4X',0 ; max 16 chars include zero
include_debug_strings ; All data wich FDO uses will be included here 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 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 { 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 { ;struc ETH_DEVICE {
macro ETH_DEVICE { macro ETH_DEVICE {
NET_DEVICE NET_DEVICE
; pointers to procedures
.unload dd ? .set_mode dd ?
.reset dd ? .get_mode dd ?
.transmit dd ?
.set_MAC dd ? .set_MAC dd ?
.get_MAC dd ? .get_MAC dd ?
.set_mode dd ?
.get_mode dd ? .mode dd ?
; status .mac dp ?
.bytes_tx dq ? dp ? ; qword alignment
.bytes_rx dq ?
.packets_tx dd ?
.packets_rx dd ?
.mode dd ?
.name dd ?
.mac dp ?
} }
macro SLIP_DEVICE { macro SLIP_DEVICE {
NET_DEVICE NET_DEVICE
; pointers to procedures
.unload dd ?
.reset dd ?
.transmit dd ?
.set_mode dd ? .set_mode dd ?
.get_mode dd ? .get_mode dd ?
; status
.bytes_tx dq ?
.bytes_rx dq ?
.packets_tx dd ?
.packets_rx dd ?
.mode dd ? .mode dd ?
.name dd ?
} }
macro GetRealAddr { macro GetRealAddr {
@ -235,7 +237,7 @@ macro GetRealAddr {
push eax push eax
call GetPgAddr call GetPgAddr
and dword [esp], (PAGESIZE - 1) and dword [esp], (PAGESIZE - 1)
add eax, dword [esp] or eax, dword [esp]
add esp, 4 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 ; 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 ; OUT: eax = -1 on error, else eax = first two bytes of mac
; ( high 16 bits are zero) ; ( high 16 bits are zero)
; ebx = last four bytes of mac ; TODO: special eax value for 'request send' ; ebx = last four bytes of mac ; TODO: special eax value for 'request send'
@ -130,18 +130,18 @@ ARP_IP_to_MAC:
; else ; else
; destination is remote, so pass to gateway ; 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] mov ebx, [IP_LIST + edx]
and ebx, [SUBNET_LIST+edx] and ebx, [SUBNET_LIST + edx]
mov ecx, eax mov ecx, eax
and ecx, [SUBNET_LIST+edx] and ecx, [SUBNET_LIST + edx]
cmp ecx, ebx cmp ecx, ebx
je .local je .local
mov eax, [GATEWAY_LIST+edx] mov eax, [GATEWAY_LIST + edx]
DEBUGF 1,"requested IP is not on subnet, using gateway\n" DEBUGF 1,"requested IP is not on subnet, using gateway\n"
.local: .local:
@ -274,7 +274,8 @@ ARP_create_request:
DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx
push edx ecx push edx ecx
jmp NET_send call [ebx + NET_DEVICE.transmit]
ret
.exit: .exit:
add esp, 8 add esp, 8
@ -572,7 +573,8 @@ ARP_handler:
DEBUGF 1,"ARP_Handler - Sending reply \n" DEBUGF 1,"ARP_Handler - Sending reply \n"
jmp NET_send ; And send it! call [ebx + NET_DEVICE.transmit]
ret
.exit: .exit:
call kernel_free call kernel_free

View File

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

View File

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

View File

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

View File

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

View File

@ -35,8 +35,10 @@ MIN_EPHEMERAL_PORT equ 49152
MAX_EPHEMERAL_PORT equ 61000 MAX_EPHEMERAL_PORT equ 61000
; Ethernet protocol numbers ; Ethernet protocol numbers
ETHER_ARP equ 0x0608 ETHER_ARP equ 0x0608
ETHER_IPv4 equ 0x0008 ; Reversed from 0800 for intel ETHER_IPv4 equ 0x0008 ; Reversed from 0800 for intel
ETHER_PPP_DISCOVERY equ 0x6388
ETHER_PPP_SESSION equ 0x6488
;Protocol family ;Protocol family
AF_UNSPEC equ 0 AF_UNSPEC equ 0
@ -76,7 +78,20 @@ NET_TYPE_SLIP equ 2
virtual at 0 virtual at 0
NET_DEVICE: 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:
end virtual end virtual
@ -193,26 +208,17 @@ stack_handler:
je .exit je .exit
mov [net_10ms], eax mov [net_10ms], eax
if ETH_QUEUE test [net_10ms], 0x0f ; 160ms
call ETH_handler jnz .exit
call ETH_send_queued
end if
call TCP_10ms
inc [net_tmr_count] ; call TCP_timer_160ms
cmp [net_tmr_count], 50
je .500ms
cmp [net_tmr_count], 100
jne .exit
test [net_10ms], 0x3f ; 640ms
jnz .exit
; call TCP_timer_640ms
call ARP_decrease_entry_ttls call ARP_decrease_entry_ttls
call IPv4_decrease_fragment_ttls call IPv4_decrease_fragment_ttls
call TCP_timer_1000ms
mov [net_tmr_count], 0
.500ms:
call TCP_500ms
.exit: .exit:
ret ret
@ -380,34 +386,6 @@ NET_ptr_to_num:
pop ecx pop ecx
ret 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 ; checksum_1
@ -563,7 +541,7 @@ sys_network:
jnz @f jnz @f
mov esi, [esi + NET_DRV_LIST] mov esi, [esi + NET_DRV_LIST]
mov esi, [esi + ETH_DEVICE.name] mov esi, [esi + NET_DEVICE.name]
mov edi, ecx mov edi, ecx
mov ecx, 64 ; max length mov ecx, 64 ; max length
@ -578,7 +556,7 @@ sys_network:
jnz @f jnz @f
mov esi, [esi + NET_DRV_LIST] mov esi, [esi + NET_DRV_LIST]
call [esi + ETH_DEVICE.reset] call [esi + NET_DEVICE.reset]
jmp .return jmp .return
@@: @@:
@ -587,7 +565,7 @@ sys_network:
jnz @f jnz @f
mov esi, [esi + NET_DRV_LIST] mov esi, [esi + NET_DRV_LIST]
call [esi + ETH_DEVICE.unload] call [esi + NET_DEVICE.unload]
jmp .return jmp .return
@@: @@:
@ -645,13 +623,13 @@ sys_protocols:
cmp ax , ETHER_ARP cmp ax , ETHER_ARP
je ARP_API je ARP_API
cmp ax , 1337 cmp ax , 1337 ;;;;;
je ETH_API je ETH_API
add esp, 4 ; if we reached here, no function was called, so we need to balance stack add esp, 4 ; if we reached here, no function was called, so we need to balance stack
.doesnt_exist: .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 mov eax, -1
.return: .return:

View File

@ -58,6 +58,22 @@ TCP_OPT_MAXSEG equ 2 ; Maximum Segment Size.
TCP_OPT_WINDOW equ 3 ; window scale TCP_OPT_WINDOW equ 3 ; window scale
TCP_OPT_TIMESTAMP equ 8 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 struct TCP_segment
.SourcePort dw ? .SourcePort dw ?
.DestinationPort dw ? .DestinationPort dw ?
@ -113,24 +129,56 @@ TCP_init:
mov ecx, (6*IP_MAX_INTERFACES) mov ecx, (6*IP_MAX_INTERFACES)
rep stosd 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 ret
;----------------------------------------------------------------- ;-----------------------------------------------------------------
; ;
; decrease socket ttls
;
; IN: /
; OUT: /
;
; destroys: eax
; ;
;----------------------------------------------------------------- ;-----------------------------------------------------------------
align 4 align 4
TCP_timer_1000ms: TCP_timer_640ms:
; scan through all the active TCP sockets, decrementing active timers
; 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 mov eax, net_sockets
.loop: .loop:
@ -142,62 +190,40 @@ TCP_timer_1000ms:
cmp [eax + SOCKET.Type], IP_PROTO_TCP cmp [eax + SOCKET.Type], IP_PROTO_TCP
jne .loop jne .loop
cmp [eax + TCP_SOCKET.t_timer], 0 dec [eax + TCP_SOCKET.timer_retransmission]
jne .decrement_tcb jnz .check_more2
;;;;;; cmp [eax + TCP_SOCKET.wndsizeTimer], 0
jne .decrement_wnd
jmp .loop
.decrement_tcb: DEBUGF 1,"socket %x: Retransmission timer expired\n", eax
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
dec [eax + TCP_SOCKET.t_timer] 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 jnz .loop
cmp [eax + TCP_SOCKET.t_state], TCB_TIMED_WAIT DEBUGF 1,"socket %x: persist timer expired\n", eax
jne .loop
push [eax + SOCKET.NextPtr]
call SOCKET_free
pop eax
jmp .check_only
.decrement_wnd:
;;;;;; dec [eax + TCP_SOCKET.wndsizeTimer]
jmp .loop
.exit: .exit:
ret 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: ; TCP_input:
@ -374,8 +400,9 @@ TCP_input:
;------------------------------------- ;-------------------------------------
; Reset idle timer and keepalive timer ; 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 ; Process TCP options if not in LISTEN state
@ -475,13 +502,14 @@ TCP_input:
; Delete acknowledged bytes from send buffer ; Delete acknowledged bytes from send buffer
; Stop retransmit timer ; Stop retransmit timer
mov [ebx + TCP_SOCKET.timer_ack], 0
; Awaken waiting processes ; Awaken waiting processes
mov eax, ebx
call SOCKET_notify_owner
; Generate more output ; Generate more output
call TCP_output
jmp .drop jmp .drop
@ -518,8 +546,9 @@ TCP_input:
add [ebx + TCP_SOCKET.RCV_NXT], ecx add [ebx + TCP_SOCKET.RCV_NXT], ecx
; Add the data to the socket buffer ; Add the data to the socket buffer
mov eax, ebx
; The receiving process is awakened (by sorwakeup). ;;; mov...
call SOCKET_input
; The delayed-ACK flag is set and the input processing is complete. ; The delayed-ACK flag is set and the input processing is complete.
@ -679,8 +708,8 @@ align 4
jle @f jle @f
mov [ebx + TCP_SOCKET.SND_NXT], eax mov [ebx + TCP_SOCKET.SND_NXT], eax
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
; TODO: turn off retransmission timer mov [ebx + TCP_SOCKET.timer_retransmission], 0
mov eax, [edx + TCP_segment.SequenceNumber] mov eax, [edx + TCP_segment.SequenceNumber]
mov [ebx + TCP_SOCKET.IRS], eax mov [ebx + TCP_SOCKET.IRS], eax
@ -937,18 +966,6 @@ align 4
jg .ack_dup jg .ack_dup
jl .ack_nodup 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: .ack_dup:
@ -960,7 +977,7 @@ align 4
;;;; 887 ;;;; 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 ; for the other side's cached packets, retrace it
;;;; 888 - 902 ;;;; 888 - 902
@ -971,6 +988,14 @@ align 4
;;;;; 903 - 926 ;;;;; 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 ; Open congestion window in response to ACKs
@ -1428,7 +1453,7 @@ TCP_pull_out_of_band:
; ;
; TCP_output ; TCP_output
; ;
; IN: eax = socket pointer ; IN: eax = socket pointer
;; esi = ptr to data ;; esi = ptr to data
;; ecx = number of data bytes ;; ecx = number of data bytes
; ;
@ -1614,7 +1639,7 @@ TCP_output:
.enter_persist: .enter_persist:
DEBUGF 1,"Entering pesist state\n" DEBUGF 1,"Entering persist state\n"
@ -1748,7 +1773,7 @@ TCP_output:
;;;; jz .fail ;;;; jz .fail
push edx eax push edx eax
call NET_send call [ebx + NET_DEVICE.transmit]
ret ret
;---------------- ;----------------
@ -1831,12 +1856,9 @@ TCP_output:
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov esi, [ebx + ETH_DEVICE.transmit] call [ebx + NET_DEVICE.transmit]
ret ret
;------------------------- ;-------------------------
; ;
; TCP_outflags ; 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 ; IN: eax = socket ptr
; -or-
; edx = packet ptr (eax must be 0)
; cl = flags
; ;
; OUT: / ; OUT: /
; ;
@ -1916,6 +1941,113 @@ TCP_respond:
DEBUGF 1,"TCP_respond\n" 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 ret

View File

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