forked from KolibriOS/kolibrios
i8255x: cleanup + support for multiple TX descriptors.
git-svn-id: svn://kolibrios.org@5525 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
8502d3d6db
commit
6a6d3deaec
@ -28,6 +28,8 @@ entry START
|
|||||||
|
|
||||||
MAX_DEVICES = 16
|
MAX_DEVICES = 16
|
||||||
|
|
||||||
|
TX_RING_SIZE = 16
|
||||||
|
|
||||||
DEBUG = 1
|
DEBUG = 1
|
||||||
__DEBUG__ = 1
|
__DEBUG__ = 1
|
||||||
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only
|
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only
|
||||||
@ -122,18 +124,20 @@ struct rxfd
|
|||||||
|
|
||||||
ends
|
ends
|
||||||
|
|
||||||
struc txfd {
|
struct txfd
|
||||||
|
|
||||||
.status dw ?
|
status dw ?
|
||||||
.command dw ?
|
command dw ?
|
||||||
.link dd ?
|
link dd ?
|
||||||
.desc_addr dd ?
|
desc_addr dd ?
|
||||||
.count dd ?
|
count dd ?
|
||||||
|
|
||||||
.buf_addr0 dd ?
|
buf_addr dd ?
|
||||||
.buf_size0 dd ?
|
buf_size dd ?
|
||||||
|
virt_addr dd ?
|
||||||
|
dd ? ; alignment
|
||||||
|
|
||||||
}
|
ends
|
||||||
|
|
||||||
struc confcmd {
|
struc confcmd {
|
||||||
|
|
||||||
@ -172,12 +176,13 @@ struct device ETH_DEVICE
|
|||||||
pci_bus dd ?
|
pci_bus dd ?
|
||||||
pci_dev dd ?
|
pci_dev dd ?
|
||||||
rx_desc dd ?
|
rx_desc dd ?
|
||||||
last_tx_buffer dd ?
|
cur_tx dd ?
|
||||||
|
last_tx dd ?
|
||||||
ee_bus_width db ?
|
ee_bus_width db ?
|
||||||
irq_line db ?
|
irq_line db ?
|
||||||
|
|
||||||
rb 0x100 - ($ and 0xff) ; align 256
|
rb 0x100 - ($ and 0xff) ; align 256
|
||||||
txfd txfd
|
tx_ring rb TX_RING_SIZE*sizeof.txfd
|
||||||
|
|
||||||
rb 0x100 - ($ and 0xff) ; align 256
|
rb 0x100 - ($ and 0xff) ; align 256
|
||||||
confcmd confcmd
|
confcmd confcmd
|
||||||
@ -466,31 +471,37 @@ reset:
|
|||||||
set_io [ebx + device.io_addr], reg_scb_ptr
|
set_io [ebx + device.io_addr], reg_scb_ptr
|
||||||
out dx, eax
|
out dx, eax
|
||||||
|
|
||||||
mov ax, INT_MASK + CU_STATSADDR
|
|
||||||
set_io [ebx + device.io_addr], reg_scb_cmd
|
set_io [ebx + device.io_addr], reg_scb_cmd
|
||||||
|
mov ax, CU_STATSADDR or INT_MASK
|
||||||
out dx, ax
|
out dx, ax
|
||||||
call cmd_wait
|
call cmd_wait
|
||||||
|
|
||||||
;-----------------
|
;------------------------
|
||||||
; setup RX
|
; setup RX base addr to 0
|
||||||
|
|
||||||
set_io [ebx + device.io_addr], reg_scb_ptr
|
set_io [ebx + device.io_addr], reg_scb_ptr
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
out dx, eax
|
out dx, eax
|
||||||
|
|
||||||
set_io [ebx + device.io_addr], reg_scb_cmd
|
set_io [ebx + device.io_addr], reg_scb_cmd
|
||||||
mov ax, INT_MASK + RX_ADDR_LOAD
|
mov ax, RX_ADDR_LOAD or INT_MASK
|
||||||
out dx, ax
|
out dx, ax
|
||||||
call cmd_wait
|
call cmd_wait
|
||||||
|
|
||||||
;-----------------------------
|
;-----------------------------
|
||||||
; Create RX and TX descriptors
|
; Create RX and TX descriptors
|
||||||
|
|
||||||
call create_ring
|
call init_rx_ring
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .error
|
jz .error
|
||||||
|
|
||||||
; RX start
|
call init_tx_ring
|
||||||
|
|
||||||
|
|
||||||
|
;---------
|
||||||
|
; Start RX
|
||||||
|
|
||||||
|
DEBUGF 1, "Starting RX"
|
||||||
|
|
||||||
set_io [ebx + device.io_addr], 0
|
set_io [ebx + device.io_addr], 0
|
||||||
set_io [ebx + device.io_addr], reg_scb_ptr
|
set_io [ebx + device.io_addr], reg_scb_ptr
|
||||||
@ -499,11 +510,12 @@ reset:
|
|||||||
add eax, NET_BUFF.data
|
add eax, NET_BUFF.data
|
||||||
out dx, eax
|
out dx, eax
|
||||||
|
|
||||||
mov ax, INT_MASK + RX_START
|
|
||||||
set_io [ebx + device.io_addr], reg_scb_cmd
|
set_io [ebx + device.io_addr], reg_scb_cmd
|
||||||
|
mov ax, RX_START or INT_MASK
|
||||||
out dx, ax
|
out dx, ax
|
||||||
call cmd_wait
|
call cmd_wait
|
||||||
|
|
||||||
|
;----------
|
||||||
; Set-up TX
|
; Set-up TX
|
||||||
|
|
||||||
set_io [ebx + device.io_addr], reg_scb_ptr
|
set_io [ebx + device.io_addr], reg_scb_ptr
|
||||||
@ -511,15 +523,39 @@ reset:
|
|||||||
out dx, eax
|
out dx, eax
|
||||||
|
|
||||||
set_io [ebx + device.io_addr], reg_scb_cmd
|
set_io [ebx + device.io_addr], reg_scb_cmd
|
||||||
mov ax, INT_MASK + CU_CMD_BASE
|
mov ax, CU_CMD_BASE or INT_MASK
|
||||||
out dx, ax
|
out dx, ax
|
||||||
call cmd_wait
|
call cmd_wait
|
||||||
|
|
||||||
; --------------------
|
;-------------------------
|
||||||
|
; Individual address setup
|
||||||
|
|
||||||
|
mov [ebx + device.confcmd.command], CmdIASetup + Cmdsuspend
|
||||||
|
mov [ebx + device.confcmd.status], 0
|
||||||
|
lea eax, [ebx + device.tx_ring]
|
||||||
|
invoke GetPhysAddr
|
||||||
|
mov [ebx + device.confcmd.link], eax
|
||||||
|
lea edi, [ebx + device.confcmd.data]
|
||||||
|
lea esi, [ebx + device.mac]
|
||||||
|
movsd
|
||||||
|
movsw
|
||||||
|
|
||||||
|
set_io [ebx + device.io_addr], reg_scb_ptr
|
||||||
|
lea eax, [ebx + device.confcmd.status]
|
||||||
|
invoke GetPhysAddr
|
||||||
|
out dx, eax
|
||||||
|
|
||||||
|
set_io [ebx + device.io_addr], reg_scb_cmd
|
||||||
|
mov ax, CU_START or INT_MASK
|
||||||
|
out dx, ax
|
||||||
|
call cmd_wait
|
||||||
|
|
||||||
|
;-------------
|
||||||
|
; Configure CU
|
||||||
|
|
||||||
mov [ebx + device.confcmd.command], CmdConfigure + Cmdsuspend
|
mov [ebx + device.confcmd.command], CmdConfigure + Cmdsuspend
|
||||||
mov [ebx + device.confcmd.status], 0
|
mov [ebx + device.confcmd.status], 0
|
||||||
lea eax, [ebx + device.txfd.status]
|
lea eax, [ebx + device.confcmd.status]
|
||||||
invoke GetPhysAddr
|
invoke GetPhysAddr
|
||||||
mov [ebx + device.confcmd.link], eax
|
mov [ebx + device.confcmd.link], eax
|
||||||
|
|
||||||
@ -535,46 +571,17 @@ reset:
|
|||||||
mov byte[ebx + device.confcmd.data + 19], 0x80
|
mov byte[ebx + device.confcmd.data + 19], 0x80
|
||||||
mov byte[ebx + device.confcmd.data + 21], 0x05
|
mov byte[ebx + device.confcmd.data + 21], 0x05
|
||||||
|
|
||||||
mov [ebx + device.txfd.command], CmdIASetup
|
|
||||||
mov [ebx + device.txfd.status], 0
|
|
||||||
lea eax, [ebx + device.confcmd.status]
|
|
||||||
invoke GetPhysAddr
|
|
||||||
mov [ebx + device.txfd.link], eax
|
|
||||||
|
|
||||||
;;; copy in our MAC
|
|
||||||
|
|
||||||
lea edi, [ebx + device.txfd.desc_addr]
|
|
||||||
lea esi, [ebx + device.mac]
|
|
||||||
movsd
|
|
||||||
movsw
|
|
||||||
|
|
||||||
set_io [ebx + device.io_addr], reg_scb_ptr
|
set_io [ebx + device.io_addr], reg_scb_ptr
|
||||||
lea eax, [ebx + device.txfd.status]
|
lea eax, [ebx + device.confcmd.status]
|
||||||
invoke GetPhysAddr
|
invoke GetPhysAddr
|
||||||
out dx, eax
|
out dx, eax
|
||||||
|
|
||||||
; Start CU & enable ints
|
|
||||||
|
|
||||||
set_io [ebx + device.io_addr], reg_scb_cmd
|
set_io [ebx + device.io_addr], reg_scb_cmd
|
||||||
mov ax, CU_START
|
mov ax, CU_START ; expect Interrupts from now on
|
||||||
out dx, ax
|
out dx, ax
|
||||||
call cmd_wait
|
call cmd_wait
|
||||||
|
|
||||||
;-----------------------
|
|
||||||
; build txfd structure (again!)
|
|
||||||
|
|
||||||
lea eax, [ebx + device.txfd.status]
|
|
||||||
invoke GetPhysAddr
|
|
||||||
mov [ebx + device.txfd.link], eax
|
|
||||||
mov [ebx + device.txfd.count], 0x02208000
|
|
||||||
lea eax, [ebx + device.txfd.buf_addr0]
|
|
||||||
invoke GetPhysAddr
|
|
||||||
mov [ebx + device.txfd.desc_addr], eax
|
|
||||||
|
|
||||||
; Indicate that we have successfully reset the card
|
|
||||||
|
|
||||||
DEBUGF 1,"Reset complete\n"
|
DEBUGF 1,"Reset complete\n"
|
||||||
|
|
||||||
mov [ebx + device.mtu], 1514
|
mov [ebx + device.mtu], 1514
|
||||||
|
|
||||||
; Set link state to unknown
|
; Set link state to unknown
|
||||||
@ -589,7 +596,7 @@ reset:
|
|||||||
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
create_ring:
|
init_rx_ring:
|
||||||
|
|
||||||
DEBUGF 1,"Creating ring\n"
|
DEBUGF 1,"Creating ring\n"
|
||||||
|
|
||||||
@ -609,16 +616,7 @@ create_ring:
|
|||||||
mov [esi + sizeof.NET_BUFF + rxfd.count], 0
|
mov [esi + sizeof.NET_BUFF + rxfd.count], 0
|
||||||
mov [esi + sizeof.NET_BUFF + rxfd.size], 1528
|
mov [esi + sizeof.NET_BUFF + rxfd.size], 1528
|
||||||
|
|
||||||
;-----------------------
|
ret
|
||||||
; build txfd structure
|
|
||||||
|
|
||||||
lea eax, [ebx + device.txfd.status]
|
|
||||||
invoke GetPhysAddr
|
|
||||||
mov [ebx + device.txfd.link], eax
|
|
||||||
mov [ebx + device.txfd.count], 0x01208000
|
|
||||||
lea eax, [ebx + device.txfd.buf_addr0]
|
|
||||||
invoke GetPhysAddr
|
|
||||||
mov [ebx + device.txfd.desc_addr], eax
|
|
||||||
|
|
||||||
.out_of_mem:
|
.out_of_mem:
|
||||||
|
|
||||||
@ -626,6 +624,38 @@ create_ring:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
align 4
|
||||||
|
init_tx_ring:
|
||||||
|
|
||||||
|
DEBUGF 1,"Creating TX ring\n"
|
||||||
|
|
||||||
|
lea esi, [ebx + device.tx_ring]
|
||||||
|
mov eax, esi
|
||||||
|
invoke GetPhysAddr
|
||||||
|
mov ecx, TX_RING_SIZE
|
||||||
|
.next_desc:
|
||||||
|
mov [esi + txfd.status], 0
|
||||||
|
mov [esi + txfd.command], 0
|
||||||
|
lea edx, [eax + txfd.buf_addr]
|
||||||
|
mov [esi + txfd.desc_addr], edx
|
||||||
|
add eax, sizeof.txfd
|
||||||
|
mov [esi + txfd.link], eax
|
||||||
|
mov [esi + txfd.count], 0x01208000 ; One buffer, 0x20 bytes of transmit threshold, end of frame
|
||||||
|
add esi, sizeof.txfd
|
||||||
|
dec ecx
|
||||||
|
jnz .next_desc
|
||||||
|
|
||||||
|
lea eax, [ebx + device.tx_ring]
|
||||||
|
invoke GetPhysAddr
|
||||||
|
mov dword[ebx + device.tx_ring + sizeof.txfd*(TX_RING_SIZE-1) + txfd.link], eax
|
||||||
|
|
||||||
|
mov [ebx + device.cur_tx], 0
|
||||||
|
mov [ebx + device.last_tx], 0
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; Transmit ;;
|
;; Transmit ;;
|
||||||
@ -652,45 +682,62 @@ proc transmit stdcall bufferptr
|
|||||||
cmp [esi + NET_BUFF.length], 60
|
cmp [esi + NET_BUFF.length], 60
|
||||||
jb .fail
|
jb .fail
|
||||||
|
|
||||||
;;; TODO: check if current descriptor is in use
|
; Get current TX descriptor
|
||||||
; fill in buffer address and size
|
mov edi, [ebx + device.cur_tx]
|
||||||
mov eax, [bufferptr]
|
mov eax, sizeof.txfd
|
||||||
mov [ebx + device.last_tx_buffer], eax
|
mul edi
|
||||||
add eax, [eax + NET_BUFF.offset]
|
lea edi, [ebx + device.tx_ring + eax]
|
||||||
invoke GetPhysAddr
|
|
||||||
mov [ebx + device.txfd.buf_addr0], eax
|
|
||||||
mov ecx, [bufferptr]
|
|
||||||
mov ecx, [ecx + NET_BUFF.length]
|
|
||||||
mov [ebx + device.txfd.buf_size0], ecx
|
|
||||||
|
|
||||||
mov [ebx + device.txfd.status], 0
|
; Check if current descriptor is free or still in use
|
||||||
mov [ebx + device.txfd.command], Cmdsuspend + CmdTx + CmdTxFlex ;+ 1 shl 15 ;;; EL bit
|
cmp [edi + txfd.status], 0
|
||||||
; mov [txfd.count], 0x02208000 ;;;;;;;;;;;
|
jne .fail
|
||||||
|
|
||||||
|
; Fill in status and command values
|
||||||
|
mov [edi + txfd.status], 0
|
||||||
|
mov [edi + txfd.command], Cmdsuspend + CmdTx + CmdTxFlex ;;;+ 1 shl 15 ;;; EL bit
|
||||||
|
mov [edi + txfd.count], 0x01208000
|
||||||
|
|
||||||
|
; Fill in buffer address and size
|
||||||
|
mov [edi + txfd.virt_addr], esi
|
||||||
|
mov eax, esi
|
||||||
|
add eax, [esi + NET_BUFF.offset]
|
||||||
|
push edi
|
||||||
|
invoke GetPhysAddr
|
||||||
|
pop edi
|
||||||
|
mov [edi + txfd.buf_addr], eax
|
||||||
|
mov ecx, [esi + NET_BUFF.length]
|
||||||
|
mov [edi + txfd.buf_size], ecx
|
||||||
|
|
||||||
; Inform device of the new/updated transmit descriptor
|
; Inform device of the new/updated transmit descriptor
|
||||||
lea eax, [ebx + device.txfd.status]
|
mov eax, edi
|
||||||
invoke GetPhysAddr
|
invoke GetPhysAddr
|
||||||
set_io [ebx + device.io_addr], 0
|
set_io [ebx + device.io_addr], 0
|
||||||
set_io [ebx + device.io_addr], reg_scb_ptr
|
set_io [ebx + device.io_addr], reg_scb_ptr
|
||||||
out dx, eax
|
out dx, eax
|
||||||
|
|
||||||
; Start the transmit
|
; Start the transmit
|
||||||
mov ax, CU_START
|
|
||||||
set_io [ebx + device.io_addr], reg_scb_cmd
|
set_io [ebx + device.io_addr], reg_scb_cmd
|
||||||
|
mov ax, CU_START
|
||||||
out dx, ax
|
out dx, ax
|
||||||
call cmd_wait
|
|
||||||
|
|
||||||
; Update stats
|
; Update stats
|
||||||
inc [ebx + device.packets_tx]
|
inc [ebx + device.packets_tx]
|
||||||
add dword[ebx + device.bytes_tx], ecx
|
add dword[ebx + device.bytes_tx], ecx
|
||||||
adc dword[ebx + device.bytes_tx + 4], 0
|
adc dword[ebx + device.bytes_tx + 4], 0
|
||||||
|
|
||||||
|
; Wait for command to complete
|
||||||
|
call cmd_wait
|
||||||
|
|
||||||
|
inc [ebx + device.cur_tx]
|
||||||
|
and [ebx + device.cur_tx], TX_RING_SIZE - 1
|
||||||
|
|
||||||
DEBUGF 1,"Transmit OK\n"
|
DEBUGF 1,"Transmit OK\n"
|
||||||
popf
|
popf
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.fail:
|
.fail:
|
||||||
|
DEBUGF 2,"Transmit failed!\n"
|
||||||
invoke NetFree, [bufferptr]
|
invoke NetFree, [bufferptr]
|
||||||
popf
|
popf
|
||||||
or eax, -1
|
or eax, -1
|
||||||
@ -808,18 +855,37 @@ int_handler:
|
|||||||
|
|
||||||
.no_rx:
|
.no_rx:
|
||||||
|
|
||||||
; Cleanup after TX
|
test ax, 1 shl 13
|
||||||
cmp [ebx + device.txfd.status], 0
|
jz .no_tx
|
||||||
je .done
|
DEBUGF 1, "Command completed\n"
|
||||||
cmp [ebx + device.last_tx_buffer], 0
|
|
||||||
je .done
|
push eax
|
||||||
push ax
|
.loop_tx:
|
||||||
DEBUGF 1, "Removing packet 0x%x from RAM!\n", [ebx + device.last_tx_buffer]
|
mov edi, [ebx + device.last_tx]
|
||||||
invoke KernelFree, [ebx + device.last_tx_buffer]
|
mov eax, sizeof.txfd
|
||||||
mov [ebx + device.last_tx_buffer], 0
|
mul eax
|
||||||
pop ax
|
lea edi, [ebx + device.tx_ring + eax]
|
||||||
|
|
||||||
|
cmp [edi + txfd.status], 0
|
||||||
|
je .tx_done
|
||||||
|
|
||||||
|
cmp [edi + txfd.virt_addr], 0
|
||||||
|
je .tx_done
|
||||||
|
|
||||||
|
DEBUGF 1,"Freeing buffer 0x%x\n", [edi + txfd.virt_addr]
|
||||||
|
|
||||||
|
push [edi + txfd.virt_addr]
|
||||||
|
mov [edi + txfd.virt_addr], 0
|
||||||
|
invoke NetFree
|
||||||
|
|
||||||
|
inc [ebx + device.last_tx]
|
||||||
|
and [ebx + device.last_tx], TX_RING_SIZE - 1
|
||||||
|
|
||||||
|
jmp .loop_tx
|
||||||
|
.tx_done:
|
||||||
|
pop eax
|
||||||
|
.no_tx:
|
||||||
|
|
||||||
.done:
|
|
||||||
and ax, 00111100b
|
and ax, 00111100b
|
||||||
cmp ax, 00001000b
|
cmp ax, 00001000b
|
||||||
jne .fail
|
jne .fail
|
||||||
|
Loading…
Reference in New Issue
Block a user