forked from KolibriOS/kolibrios
3C59X: Improved interrupt handeling. Small fixes (magic numbers, delays)
git-svn-id: svn://kolibrios.org@9188 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
9c0be1dd39
commit
329531cd24
@ -1,6 +1,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; 3Com network driver for KolibriOS ;;
|
||||
@ -90,15 +90,20 @@ entry START
|
||||
COMPATIBLE_API = 0x0100
|
||||
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
|
||||
|
||||
MAX_DEVICES = 16
|
||||
; configureable area
|
||||
|
||||
MAX_DEVICES = 16 ; Maximum number of devices this driver may handle
|
||||
|
||||
FORCE_FD = 0 ; forcing full duplex mode makes sense at some cards and link types
|
||||
|
||||
NUM_RX_DESC = 4 ; a power of 2 number
|
||||
NUM_TX_DESC = 4 ; a power of 2 number
|
||||
NUM_RX_DESC = 32 ; Number of receive descriptors (must be power of 2)
|
||||
NUM_TX_DESC = 16 ; Number of transmit descriptors (must be power of 2)
|
||||
|
||||
__DEBUG__ = 1
|
||||
__DEBUG__ = 1 ; 1 = on, 0 = off
|
||||
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only
|
||||
|
||||
; end configureable area
|
||||
|
||||
section '.flat' readable writable executable
|
||||
|
||||
include '../proc32.inc'
|
||||
@ -107,6 +112,17 @@ include '../macros.inc'
|
||||
include '../fdo.inc'
|
||||
include '../netdrv.inc'
|
||||
|
||||
|
||||
if (bsr NUM_RX_DESC)>(bsf NUM_RX_DESC)
|
||||
display 'NUM_RX_DESC must be a power of two'
|
||||
err
|
||||
end if
|
||||
|
||||
if (bsr NUM_TX_DESC)>(bsf NUM_TX_DESC)
|
||||
display 'NUM_TX_DESC must be a power of two'
|
||||
err
|
||||
end if
|
||||
|
||||
; Registers
|
||||
REG_POWER_MGMT_CTRL = 0x7c
|
||||
REG_UP_LIST_PTR = 0x38
|
||||
@ -402,11 +418,11 @@ proc service_proc stdcall, ioctl:dword
|
||||
|
||||
; check if the device is already listed
|
||||
|
||||
mov ecx, [vortex_devices]
|
||||
mov ecx, [devices]
|
||||
test ecx, ecx
|
||||
jz .maybeboomerang
|
||||
jz .firstdevice
|
||||
|
||||
mov esi, vortex_list
|
||||
mov esi, device_list
|
||||
mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers
|
||||
mov ax , [eax+1] ;
|
||||
.nextdevice:
|
||||
@ -419,31 +435,9 @@ proc service_proc stdcall, ioctl:dword
|
||||
add esi, 4
|
||||
loop .nextdevice
|
||||
|
||||
|
||||
.maybeboomerang:
|
||||
mov ecx, [boomerang_devices]
|
||||
test ecx, ecx
|
||||
jz .firstdevice
|
||||
|
||||
mov esi, boomerang_list
|
||||
mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers
|
||||
mov ax, [eax+1] ;
|
||||
.nextdevice2:
|
||||
mov ebx, [esi]
|
||||
cmp al, byte[ebx + device.pci_bus]
|
||||
jne @f
|
||||
cmp ah, byte[ebx + device.pci_dev]
|
||||
je .find_devicenum ; Device is already loaded, let's find it's device number
|
||||
@@:
|
||||
add esi, 4
|
||||
loop .nextdevice2
|
||||
|
||||
|
||||
; This device doesnt have its own eth_device structure yet, lets create one
|
||||
.firstdevice:
|
||||
mov ecx, [boomerang_devices]
|
||||
add ecx, [vortex_devices]
|
||||
cmp ecx, MAX_DEVICES ; First check if the driver can handle one more card
|
||||
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
|
||||
jae .fail
|
||||
|
||||
allocate_and_clear ebx, sizeof.device, .fail ; Allocate the buffer for device structure
|
||||
@ -481,14 +475,9 @@ proc service_proc stdcall, ioctl:dword
|
||||
test eax, eax
|
||||
jnz .err ; If an error occured, exit
|
||||
|
||||
|
||||
movzx ecx, [ebx + device.ver_id]
|
||||
test word [hw_versions+2+ecx*4], IS_VORTEX
|
||||
jz .not_vortex
|
||||
|
||||
mov eax, [vortex_devices] ; Add the device structure to our device list
|
||||
mov [vortex_list+4*eax], ebx ; (IRQ handler uses this list to find device)
|
||||
inc [vortex_devices] ;
|
||||
mov eax, [devices] ; Add the device structure to our device list
|
||||
mov [device_list+4*eax], ebx ;
|
||||
inc [devices] ;
|
||||
|
||||
.register:
|
||||
mov [ebx + device.type], NET_TYPE_ETH
|
||||
@ -500,13 +489,6 @@ proc service_proc stdcall, ioctl:dword
|
||||
call start_device
|
||||
ret
|
||||
|
||||
.not_vortex:
|
||||
mov eax, [boomerang_devices] ; Add the device structure to our device list
|
||||
mov [boomerang_list+4*eax], ebx ; (IRQ handler uses this list to find device)
|
||||
inc [boomerang_devices]
|
||||
|
||||
jmp .register
|
||||
|
||||
; If the device was already loaded, find the device number and return it in eax
|
||||
|
||||
.find_devicenum:
|
||||
@ -697,13 +679,19 @@ probe:
|
||||
; or al, 0x14
|
||||
out dx, ax
|
||||
; wait for GlobalReset to complete
|
||||
mov ecx, 64000
|
||||
mov ecx, 2000
|
||||
.rsloop:
|
||||
in ax, dx
|
||||
test ah, 10000b ; CmdInProgress
|
||||
|
||||
pusha
|
||||
mov esi, 1
|
||||
invoke Sleep
|
||||
popa
|
||||
|
||||
loopz .rsloop
|
||||
|
||||
DEBUGF 1,"Waiting for nic to boot..\n"
|
||||
DEBUGF 1,"Waiting for NIC to boot..\n"
|
||||
; wait for 2 seconds for NIC to boot
|
||||
mov esi, 2000 ; WTF? FIXME
|
||||
invoke Sleep ; 2 seconds
|
||||
@ -1140,38 +1128,36 @@ try_phy:
|
||||
|
||||
mov al, MII_BMCR
|
||||
push eax
|
||||
call mdio_read ; returns with window #4
|
||||
or ah, 0x80 ; software reset
|
||||
call mdio_read
|
||||
or ax, BMCR_RESET
|
||||
mov esi, eax
|
||||
mov eax, [esp]
|
||||
call mdio_write ; returns with window #4
|
||||
call mdio_write
|
||||
|
||||
; wait for reset to complete
|
||||
mov esi, 2000
|
||||
invoke Sleep ; 2s FIXME
|
||||
|
||||
mov eax, [esp]
|
||||
call mdio_read ; returns with window #4
|
||||
test ah, 0x80
|
||||
mov al, MII_BMCR
|
||||
call mdio_read
|
||||
test ax, BMCR_RESET
|
||||
jnz .fail1
|
||||
mov eax, [esp]
|
||||
|
||||
; wait for a while after reset
|
||||
mov esi, 20
|
||||
invoke Sleep ; 20ms
|
||||
|
||||
mov eax, [esp]
|
||||
mov al, MII_BMSR
|
||||
call mdio_read ; returns with window #4
|
||||
test al, 1 ; extended capability supported?
|
||||
call mdio_read
|
||||
test al, BMSR_ERCAP
|
||||
jz .fail2
|
||||
DEBUGF 1,"Extended capability supported\n"
|
||||
|
||||
; auto-neg capable?
|
||||
test al , 1000b
|
||||
jz .fail2 ; not auto-negotiation capable
|
||||
test al, BMSR_ANEGCAPABLE
|
||||
jz .fail2
|
||||
DEBUGF 1,"Auto-negotiation capable\n"
|
||||
|
||||
; auto-neg complete?
|
||||
test al , 100000b
|
||||
test al, BMSR_ANEGCOMPLETE
|
||||
jnz .auto_neg_ok
|
||||
DEBUGF 1,"Restarting auto-negotiation\n"
|
||||
|
||||
@ -1180,23 +1166,25 @@ try_phy:
|
||||
mov al, MII_ADVERTISE
|
||||
push eax
|
||||
call mdio_read ; returns with window #4
|
||||
or ax , 1111b shl 5; advertise only 10base-T and 100base-TX
|
||||
or ax, ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL
|
||||
mov esi, eax
|
||||
pop eax
|
||||
call mdio_write ; returns with window #4
|
||||
mov eax, [esp]
|
||||
call mdio_read ; returns with window #4
|
||||
mov esi, eax
|
||||
or bh , 10010b ; restart auto-negotiation
|
||||
or bx, BMCR_ANENABLE or BMCR_ANRESTART
|
||||
mov eax, [esp]
|
||||
call mdio_write ; returns with window #4
|
||||
mov esi, 4000
|
||||
invoke Sleep ; 4 seconds
|
||||
mov eax, [esp]
|
||||
|
||||
mov al, MII_BMSR
|
||||
call mdio_read ; returns with window #4
|
||||
test al , 100000b ; auto-neg complete?
|
||||
test al, BMSR_ANEGCOMPLETE
|
||||
jnz .auto_neg_ok
|
||||
|
||||
jmp .fail3
|
||||
.auto_neg_ok:
|
||||
DEBUGF 1,"Auto-negotiation complete\n"
|
||||
@ -2137,15 +2125,14 @@ check_tx_status:
|
||||
;; ;;
|
||||
;; Transmit (vortex) ;;
|
||||
;; ;;
|
||||
;; In: buffer pointer in [esp+4] ;;
|
||||
;; pointer to device structure in ebx ;;
|
||||
;; In: pointer to device structure in ebx ;;
|
||||
;; Out: eax = 0 on success ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 16
|
||||
proc vortex_transmit stdcall bufferptr
|
||||
|
||||
pushf
|
||||
cli
|
||||
spin_lock_irqsave
|
||||
|
||||
mov esi, [bufferptr]
|
||||
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
|
||||
@ -2156,9 +2143,9 @@ proc vortex_transmit stdcall bufferptr
|
||||
[eax+13]:2,[eax+12]:2
|
||||
|
||||
cmp [esi + NET_BUFF.length], 1514
|
||||
ja .fail
|
||||
ja .error
|
||||
cmp [esi + NET_BUFF.length], 60
|
||||
jb .fail
|
||||
jb .error
|
||||
|
||||
call check_tx_status
|
||||
|
||||
@ -2172,7 +2159,7 @@ proc vortex_transmit stdcall bufferptr
|
||||
set_io [ebx + device.io_addr], REG_MASTER_STATUS
|
||||
in ax, dx
|
||||
test ah, 0x80
|
||||
jnz .fail ; no DMA for sending
|
||||
jnz .overrun ; no DMA for sending
|
||||
|
||||
; program frame address to be sent
|
||||
set_io [ebx + device.io_addr], REG_MASTER_ADDRESS
|
||||
@ -2190,15 +2177,32 @@ proc vortex_transmit stdcall bufferptr
|
||||
set_io [ebx + device.io_addr], REG_COMMAND
|
||||
mov ax, (10100b shl 11) + 1 ; StartDMADown
|
||||
out dx, ax
|
||||
.finish:
|
||||
popf
|
||||
|
||||
; Update stats
|
||||
inc [ebx + device.packets_tx]
|
||||
mov eax, [esi + NET_BUFF.length]
|
||||
add dword[ebx + device.bytes_tx], eax
|
||||
adc dword[ebx + device.bytes_tx + 4], 0
|
||||
|
||||
spin_unlock_irqrestore
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.fail:
|
||||
DEBUGF 2,"Send failed\n"
|
||||
.error:
|
||||
DEBUGF 2, "TX packet error\n"
|
||||
inc [ebx + device.packets_tx_err]
|
||||
invoke NetFree, [bufferptr]
|
||||
popf
|
||||
|
||||
spin_unlock_irqrestore
|
||||
or eax, -1
|
||||
ret
|
||||
|
||||
.overrun:
|
||||
DEBUGF 2, "TX overrun\n"
|
||||
inc [ebx + device.packets_tx_ovr]
|
||||
invoke NetFree, [bufferptr]
|
||||
|
||||
spin_unlock_irqrestore
|
||||
or eax, -1
|
||||
ret
|
||||
|
||||
@ -2208,15 +2212,14 @@ endp
|
||||
;; ;;
|
||||
;; Transmit (boomerang) ;;
|
||||
;; ;;
|
||||
;; In: buffer pointer in [esp+4] ;;
|
||||
;; pointer to device structure in ebx ;;
|
||||
;; In: pointer to device structure in ebx ;;
|
||||
;; Out: eax = 0 on success ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 16
|
||||
proc boomerang_transmit stdcall bufferptr
|
||||
|
||||
pushf
|
||||
cli
|
||||
spin_lock_irqsave
|
||||
|
||||
mov esi, [bufferptr]
|
||||
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [esi + NET_BUFF.length]
|
||||
@ -2227,9 +2230,9 @@ proc boomerang_transmit stdcall bufferptr
|
||||
[eax+13]:2,[eax+12]:2
|
||||
|
||||
cmp [esi + NET_BUFF.length], 1514
|
||||
ja .fail
|
||||
ja .error
|
||||
cmp [esi + NET_BUFF.length], 60
|
||||
jb .fail
|
||||
jb .error
|
||||
|
||||
call check_tx_status ; Reset TX engine if needed
|
||||
|
||||
@ -2339,14 +2342,32 @@ proc boomerang_transmit stdcall bufferptr
|
||||
|
||||
.finish:
|
||||
mov [ebx + device.curr_tx], edi
|
||||
popf
|
||||
|
||||
; Update stats
|
||||
inc [ebx + device.packets_tx]
|
||||
mov eax, [esi + NET_BUFF.length]
|
||||
add dword[ebx + device.bytes_tx], eax
|
||||
adc dword[ebx + device.bytes_tx + 4], 0
|
||||
|
||||
spin_unlock_irqrestore
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.fail:
|
||||
DEBUGF 2,"Send failed\n"
|
||||
.error:
|
||||
DEBUGF 2, "TX packet error\n"
|
||||
inc [ebx + device.packets_tx_err]
|
||||
invoke NetFree, [bufferptr]
|
||||
popf
|
||||
|
||||
spin_unlock_irqrestore
|
||||
or eax, -1
|
||||
ret
|
||||
|
||||
.overrun:
|
||||
DEBUGF 2, "TX overrun\n"
|
||||
inc [ebx + device.packets_tx_ovr]
|
||||
invoke NetFree, [bufferptr]
|
||||
|
||||
spin_unlock_irqrestore
|
||||
or eax, -1
|
||||
ret
|
||||
|
||||
@ -2448,23 +2469,15 @@ read_mac_eeprom:
|
||||
;; Vortex Interrupt handler ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 4
|
||||
align 16
|
||||
int_vortex:
|
||||
|
||||
push ebx esi edi
|
||||
|
||||
DEBUGF 1,"INT\n"
|
||||
|
||||
; find pointer of device wich made IRQ occur
|
||||
|
||||
mov ecx, [vortex_devices]
|
||||
test ecx, ecx
|
||||
jz .nothing
|
||||
mov esi, vortex_list
|
||||
.nextdevice:
|
||||
mov ebx, [esi]
|
||||
mov ebx, [esp+4*4]
|
||||
DEBUGF 1,"INT for 0x%x\n", ebx
|
||||
|
||||
; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
|
||||
|
||||
set_io [ebx + device.io_addr], 0
|
||||
set_io [ebx + device.io_addr], REG_INT_STATUS
|
||||
@ -2472,21 +2485,7 @@ int_vortex:
|
||||
and ax, S_5_INTS
|
||||
jnz .nothing
|
||||
|
||||
add esi, 4
|
||||
|
||||
test ax , ax
|
||||
jnz .got_it
|
||||
loop .nextdevice
|
||||
|
||||
.nothing:
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
|
||||
ret
|
||||
|
||||
.got_it:
|
||||
|
||||
DEBUGF 1,"Device: %x Status: %x\n", ebx, eax:4
|
||||
DEBUGF 1,"Status: %x\n", eax:4
|
||||
|
||||
test ax, RxComplete
|
||||
jz .noRX
|
||||
@ -2576,10 +2575,7 @@ int_vortex:
|
||||
out dx, ax
|
||||
|
||||
.finish:
|
||||
|
||||
|
||||
.noRX:
|
||||
|
||||
test ax, DMADone
|
||||
jz .noDMA
|
||||
|
||||
@ -2595,17 +2591,11 @@ int_vortex:
|
||||
out dx, ax
|
||||
|
||||
.nodmaclear:
|
||||
|
||||
pop ax
|
||||
|
||||
DEBUGF 1, "DMA Done!\n", cx
|
||||
|
||||
|
||||
|
||||
.noDMA:
|
||||
|
||||
|
||||
|
||||
.ACK:
|
||||
set_io [ebx + device.io_addr], 0
|
||||
set_io [ebx + device.io_addr], REG_COMMAND
|
||||
@ -2613,6 +2603,14 @@ int_vortex:
|
||||
out dx, ax
|
||||
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
inc eax
|
||||
|
||||
ret
|
||||
|
||||
.nothing:
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
|
||||
ret
|
||||
|
||||
@ -2624,41 +2622,24 @@ int_vortex:
|
||||
;; Boomerang Interrupt handler ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
align 4
|
||||
align 16
|
||||
int_boomerang:
|
||||
|
||||
push ebx esi edi
|
||||
|
||||
DEBUGF 1,"INT\n"
|
||||
mov ebx, [esp+4*4]
|
||||
DEBUGF 1,"INT for 0x%x\n", ebx
|
||||
|
||||
; find pointer of device wich made IRQ occur
|
||||
|
||||
mov ecx, [boomerang_devices]
|
||||
test ecx, ecx
|
||||
jz .nothing
|
||||
mov esi, boomerang_list
|
||||
.nextdevice:
|
||||
mov ebx, [esi]
|
||||
; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
|
||||
|
||||
set_io [ebx + device.io_addr], 0
|
||||
set_io [ebx + device.io_addr], REG_INT_STATUS
|
||||
in ax, dx
|
||||
test ax, S_5_INTS
|
||||
jnz .got_it
|
||||
.continue:
|
||||
add esi, 4
|
||||
dec ecx
|
||||
jnz .nextdevice
|
||||
.nothing:
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
|
||||
ret
|
||||
|
||||
jz .nothing
|
||||
.got_it:
|
||||
DEBUGF 1,"Status: %x\n", ax
|
||||
|
||||
DEBUGF 1,"Device: %x Status: %x\n", ebx, ax
|
||||
push ax
|
||||
|
||||
; disable all INTS
|
||||
@ -2796,6 +2777,14 @@ int_boomerang:
|
||||
out dx, ax
|
||||
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
inc eax
|
||||
|
||||
ret
|
||||
|
||||
.nothing:
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
|
||||
ret
|
||||
|
||||
@ -2919,10 +2908,8 @@ HW_VERSIONS_SIZE = $ - hw_versions
|
||||
include_debug_strings ; All data wich FDO uses will be included here
|
||||
|
||||
align 4
|
||||
vortex_devices dd 0
|
||||
boomerang_devices dd 0
|
||||
vortex_list rd MAX_DEVICES
|
||||
boomerang_list rd MAX_DEVICES
|
||||
devices dd 0
|
||||
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user