Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1518 → Rev 1519

/kernel/branches/net/drivers/3c59x.asm
1,23 → 1,19
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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,14 → 80,15
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
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
__DEBUG_LEVEL__ equ 1
101,47 → 98,10
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 ?
172,17 → 132,11
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
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
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
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
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
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
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
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,19 → 221,23
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
277,15 → 244,19
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
EXTRA_PREAMBLE equ 0x4000
 
; Status
 
IntLatch equ 0x0001
HostError equ 0x0002
TxComplete equ 0x0004
315,18 → 285,15
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,30 → 321,48
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
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
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, [device.rx_buffer]
stdcall KernelFree, [device.tx_buffer]
stdcall KernelFree, ebx
 
 
613,7 → 589,7
;***************************************************************************
 
align 4
probe: ; Tested - ok
probe:
 
DEBUGF 1,"Probing 3com card\n"
 
671,6 → 647,11
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
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
ret
 
 
975,13 → 959,9
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,54 → 984,49
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
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 eax, [device.rx_buffer]
call GetPgAddr
mov edi, eax
mov ecx, NUM_RX_DESC
 
mov edx, [device.upd_buffer]
add edx, (NUM_RX_DESC-1)*upd.size
.upd_loop:
mov [edx + upd.next_ptr], edi
 
mov eax, [device.upd_buffer]
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)
 
push ebx
mov ebx, [device.rx_buffer]
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 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
 
add edi, MAX_ETH_FRAME_SIZE
add ebx, MAX_ETH_FRAME_SIZE
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
2228,6 → 2203,8
mov ax, (10100b shl 11) + 1 ; StartDMADown
out dx, ax
.finish:
call KernelFree
add esp, 4
ret
 
 
2245,26 → 2222,32
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
; 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
; cmp eax, esi
; 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
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 [esi+dpd.frag_addr], eax
mov ecx, [esp+8] ; packet size
or ecx, 0x80000000 ; last fragment
mov [esi+dpd.frag_len], ecx
 
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] ; packet size
; or ecx, 0x8000 ; transmission complete notification
 
mov ecx, [esp+8+8] ; packet size
or ecx, 0x80000000 ; last fragment
DEBUGF 1,"Frag size + flag is: %x\n", ecx
mov [eax+dpd.frag_len], ecx
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
;@@:
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
jmp .finish
 
.add_to_list:
 
DEBUGF 1,"Adding To list\n"
 
push eax
; DnStall
set_io 0
set_io REG_COMMAND
2364,7 → 2312,6
out dx, ax
 
; wait for DnStall to complete
 
DEBUGF 1,"Waiting for DnStall\n"
mov ecx, 6000
.wait_for_stall:
2376,7 → 2323,6
 
.dnstall_ok:
DEBUGF 1,"DnStall ok!\n"
mov eax, [esp] ; prev_tx_frame
mov ecx, [device.prev_dpd]
mov [ecx+dpd.next_ptr], eax
 
2383,12 → 2329,12
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:
2398,15 → 2344,16
mov ax, ((110b shl 11)+3)
out dx, ax
 
.finish_pop:
pop [device.prev_tx_frame]
pop [device.prev_dpd]
 
.finish:
mov [device.prev_dpd], esi
xor eax, eax
ret
ret 8
 
.fail:
stdcall KernelFree, [esp+4]
ret 8
 
 
;---------------------------------
; Write MAC
 
2581,7 → 2528,9
 
.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,7 → 2621,7
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
 
2679,7 → 2628,6
mov esi, BOOMERANG_LIST
mov ecx, [BOOMERANG_DEVICES]
 
; DEBUGF 1,"Devices: %u\n", ecx
test ecx, ecx
jz .fail
.nextdevice:
2705,7 → 2653,6
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
 
push ax
; disable all INTS
 
2713,13 → 2660,6
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
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]
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 ecx eax
mov edi, eax
push ecx
push [esi+upd.realaddr]
 
DEBUGF 1, " copying %u bytes from %x to %x\n", ecx, esi, edi
 
; 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
; 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
 
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
 
jmp EthReceiver
.loop:
 
.loop:
mov ebx, [esp]
jmp .receive
 
2811,14 → 2735,38
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"
 
;;;; FIXME: make upunstall work
 
.noUpUnStall:
.noRX:
test word[esp], DownComplete
jz .noTX
DEBUGF 1, "Downcomplete!\n"
 
.noRX:
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
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,7 → 2784,6
mov ax, SetIntrEnb + S_5_INTS
out dx, ax
 
 
ret
 
 
2848,11 → 2790,8
 
 
; End of code
 
align 4 ; Place all initialised data here
 
 
 
macro strtbl name, [string]
{
common
2866,7 → 2805,7
 
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
; 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