i8255x: cleanup + support for multiple TX descriptors.

git-svn-id: svn://kolibrios.org@5525 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2015-03-18 10:57:16 +00:00
parent 8502d3d6db
commit 6a6d3deaec

View File

@ -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