i8255x: Cleanup, Better handeling of received frames.

git-svn-id: svn://kolibrios.org@5562 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2015-05-29 19:12:25 +00:00
parent c9d8d9f37b
commit b754cb2eae

View File

@ -45,10 +45,10 @@ include '../netdrv.inc'
; Serial EEPROM
EE_SK = 1 shl 0 ; serial clock
EE_CS = 1 shl 1 ; chip select
EE_DI = 1 shl 2 ; data in
EE_DO = 1 shl 3 ; data out
EE_SK = 1 shl 0 ; serial clock
EE_CS = 1 shl 1 ; chip select
EE_DI = 1 shl 2 ; data in
EE_DO = 1 shl 3 ; data out
EE_MASK = EE_SK + EE_CS + EE_DI + EE_DO
; opcodes, first bit is start bit and must be 1
@ -73,45 +73,50 @@ RX_RESUMENR = 0x0007
INT_MASK = 0x0100
DRVR_INT = 0x0200 ; Driver generated interrupt
CmdIASetup = 0x0001
CmdConfigure = 0x0002
CmdTx = 0x0004
CmdTxFlex = 0x0008
Cmdsuspend = 0x4000
REG_SCB_STATUS = 0
REG_SCB_CMD = 2
REG_SCB_PTR = 4
REG_PORT = 8
REG_EEPROM = 14
REG_MDI_CTRL = 16
CmdRxFlex = 0x0008
PHY_100a = 0x000003E0
PHY_100c = 0x035002A8
PHY_82555_tx = 0x015002A8
PHY_nsc_tx = 0x5C002000
PHY_82562_et = 0x033002A8
PHY_82562_em = 0x032002A8
PHY_82562_ek = 0x031002A8
PHY_82562_eh = 0x017002A8
PHY_82552_v = 0xd061004d
PHY_unknown = 0xFFFFFFFF
reg_scb_status = 0
reg_scb_cmd = 2
reg_scb_ptr = 4
reg_port = 8
reg_eeprom = 14
reg_mdi_ctrl = 16
MAC_82557_D100_A = 0
MAC_82557_D100_B = 1
MAC_82557_D100_C = 2
MAC_82558_D101_A4 = 4
MAC_82558_D101_B0 = 5
MAC_82559_D101M = 8
MAC_82559_D101S = 9
MAC_82550_D102 = 12
MAC_82550_D102_C = 13
MAC_82551_E = 14
MAC_82551_F = 15
MAC_82551_10 = 16
MAC_unknown = 0xFF
phy_100a = 0x000003E0
phy_100c = 0x035002A8
phy_82555_tx = 0x015002A8
phy_nsc_tx = 0x5C002000
phy_82562_et = 0x033002A8
phy_82562_em = 0x032002A8
phy_82562_ek = 0x031002A8
phy_82562_eh = 0x017002A8
phy_82552_v = 0xd061004d
phy_unknown = 0xFFFFFFFF
mac_82557_D100_A = 0
mac_82557_D100_B = 1
mac_82557_D100_C = 2
mac_82558_D101_A4 = 4
mac_82558_D101_B0 = 5
mac_82559_D101M = 8
mac_82559_D101S = 9
mac_82550_D102 = 12
mac_82550_D102_C = 13
mac_82551_E = 14
mac_82551_F = 15
mac_82551_10 = 16
mac_unknown = 0xFF
SCB_STATUS_RUS = 111100b ; RU Status
RU_STATUS_IDLE = 0000b shl 2
RU_STATUS_SUSPENDED = 0001b shl 2
RU_STATUS_NO_RESOURCES = 0010b shl 2
RU_STATUS_READY = 0100b shl 2
SCB_STATUS_FCP = 1 shl 8 ; Flow Control Pause
SCB_STATUS_SWI = 1 shl 10 ; Software Interrupt
SCB_STATUS_MDI = 1 shl 11 ; MDI read/write complete
SCB_STATUS_RNR = 1 shl 12 ; Receiver Not Ready
SCB_STATUS_CNA = 1 shl 13 ; Command unit Not Active
SCB_STATUS_FR = 1 shl 14 ; Frame received
SCB_STATUS_CX_TNO = 1 shl 15 ; Command finished / Transmit Not Okay
struct rxfd
@ -125,6 +130,24 @@ struct rxfd
ends
RXFD_STATUS_RC = 1 shl 0 ; Receive collision
RXFD_STATUS_IA = 1 shl 1 ; IA mismatch
RXFD_STATUS_NA = 1 shl 2 ; No address match
RXFD_STATUS_RE = 1 shl 4 ; Receive Error
RXFD_STATUS_TL = 1 shl 5 ; Type/length
RXFD_STATUS_FS = 1 shl 7 ; Frame too short
RXFD_STATUS_DMA_FAIL = 1 shl 8 ; DMA overrun failure
RXFD_STATUS_NR = 1 shl 9 ; Out of buffer space; no resources
RXFD_STATUS_MISA = 1 shl 10 ; Alignment error
RXFD_STATUS_CRC_ERR = 1 shl 11 ; CRC error in aligned frame
RXFD_STATUS_OK = 1 shl 13 ; Frame received and stored
RXFD_STATUS_C = 1 shl 15 ; Completion of frame reception
RXFD_CMD_SF = 1 shl 3
RXFD_CMD_H = 1 shl 4 ; Header RFD
RXFD_CMD_SUSPEND = 1 shl 14 ; Suspends RU after receiving the frame
RXFD_CMD_EL = 1 shl 15 ; Last RFD in RFA
struct txfd
status dw ?
@ -140,6 +163,12 @@ struct txfd
ends
TXFD_CMD_IA = 1 shl 0
TXFD_CMD_CFG = 1 shl 1
TXFD_CMD_TX = 1 shl 2
TXFD_CMD_TX_FLEX = 1 shl 3
TXFD_CMD_SUSPEND = 1 shl 14
struc confcmd {
.status dw ?
@ -455,7 +484,7 @@ reset:
; reset the card
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], reg_port
set_io [ebx + device.io_addr], REG_PORT
xor eax, eax ; Software Reset
out dx, eax
@ -468,10 +497,10 @@ reset:
lea eax, [ebx + device.lstats.tx_good_frames] ; lstats
invoke GetPhysAddr
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
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
call cmd_wait
@ -479,11 +508,11 @@ reset:
;------------------------
; 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
out dx, eax
set_io [ebx + device.io_addr], reg_scb_cmd
set_io [ebx + device.io_addr], REG_SCB_CMD
mov ax, RX_ADDR_LOAD or INT_MASK
out dx, ax
call cmd_wait
@ -504,13 +533,13 @@ reset:
DEBUGF 1, "Starting RX"
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
mov eax, [ebx + device.rx_desc]
invoke GetPhysAddr
add eax, NET_BUFF.data
out dx, eax
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
call cmd_wait
@ -518,11 +547,11 @@ reset:
;----------
; Set-up TX
set_io [ebx + device.io_addr], reg_scb_ptr
set_io [ebx + device.io_addr], REG_SCB_PTR
xor eax, eax
out dx, eax
set_io [ebx + device.io_addr], reg_scb_cmd
set_io [ebx + device.io_addr], REG_SCB_CMD
mov ax, CU_CMD_BASE or INT_MASK
out dx, ax
call cmd_wait
@ -530,7 +559,7 @@ reset:
;-------------------------
; Individual address setup
mov [ebx + device.confcmd.command], CmdIASetup + Cmdsuspend
mov [ebx + device.confcmd.command], TXFD_CMD_IA + TXFD_CMD_SUSPEND
mov [ebx + device.confcmd.status], 0
lea eax, [ebx + device.tx_ring]
invoke GetPhysAddr
@ -540,12 +569,12 @@ reset:
movsd
movsw
set_io [ebx + device.io_addr], reg_scb_ptr
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
set_io [ebx + device.io_addr], REG_SCB_CMD
mov ax, CU_START or INT_MASK
out dx, ax
call cmd_wait
@ -553,7 +582,7 @@ reset:
;-------------
; Configure CU
mov [ebx + device.confcmd.command], CmdConfigure + Cmdsuspend
mov [ebx + device.confcmd.command], TXFD_CMD_CFG + TXFD_CMD_SUSPEND
mov [ebx + device.confcmd.status], 0
lea eax, [ebx + device.confcmd.status]
invoke GetPhysAddr
@ -571,12 +600,12 @@ reset:
mov byte[ebx + device.confcmd.data + 19], 0x80
mov byte[ebx + device.confcmd.data + 21], 0x05
set_io [ebx + device.io_addr], reg_scb_ptr
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
set_io [ebx + device.io_addr], REG_SCB_CMD
mov ax, CU_START ; expect Interrupts from now on
out dx, ax
call cmd_wait
@ -610,8 +639,8 @@ init_rx_ring:
mov esi, eax
invoke GetPhysAddr
add eax, NET_BUFF.data
mov [esi + sizeof.NET_BUFF + rxfd.status], 0x0000
mov [esi + sizeof.NET_BUFF + rxfd.command], 0xc000 ; End of list + Suspend
mov [esi + sizeof.NET_BUFF + rxfd.status], 0
mov [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
mov [esi + sizeof.NET_BUFF + rxfd.link], eax
mov [esi + sizeof.NET_BUFF + rxfd.count], 0
mov [esi + sizeof.NET_BUFF + rxfd.size], 1528
@ -693,7 +722,7 @@ proc transmit stdcall bufferptr
; 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.command], TXFD_CMD_SUSPEND + TXFD_CMD_TX + TXFD_CMD_TX_FLEX
mov [edi + txfd.count], 0x01208000
; Fill in buffer address and size
@ -711,11 +740,11 @@ proc transmit stdcall bufferptr
mov eax, edi
invoke GetPhysAddr
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
; Start the transmit
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
@ -767,10 +796,10 @@ int_handler:
.nextdevice:
mov ebx, [esi]
; set_io [ebx + device.io_addr], 0 ; reg_scb_status = 0
set_io [ebx + device.io_addr], reg_scb_status
; set_io [ebx + device.io_addr], 0 ; REG_SCB_STATUS = 0
set_io [ebx + device.io_addr], REG_SCB_STATUS
in ax, dx
out dx, ax ; send it back to ACK
out dx, ax ; send it back to ACK
test ax, ax
jnz .got_it
.continue:
@ -781,13 +810,13 @@ int_handler:
pop edi esi ebx
xor eax, eax
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
ret ; If no device was found, abort (The irq was probably for a device, not registered to this driver)
.got_it:
DEBUGF 1,"Device: %x Status: %x\n", ebx, ax
test ax, 1 shl 14 ; did we receive a frame?
test ax, SCB_STATUS_FR ; did we receive a frame?
jz .no_rx
push ax
@ -799,8 +828,10 @@ int_handler:
pop ebx
mov esi, [ebx + device.rx_desc]
cmp [esi + sizeof.NET_BUFF + rxfd.status], 0 ; we could also check bits C and OK (bit 15 and 13)
je .nodata
test [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_C ; Completed?
jz .no_rx_
test [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_OK ; OK?
jz .not_ok
DEBUGF 1,"rxfd status=0x%x\n", [esi + sizeof.NET_BUFF + rxfd.status]:4
@ -828,8 +859,8 @@ int_handler:
mov esi, eax
invoke GetPhysAddr
add eax, NET_BUFF.data
mov [esi + sizeof.NET_BUFF + rxfd.status], 0x0000
mov [esi + sizeof.NET_BUFF + rxfd.command], 0xc000 ; End of list + Suspend
mov [esi + sizeof.NET_BUFF + rxfd.status], 0
mov [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
mov [esi + sizeof.NET_BUFF + rxfd.link], eax
mov [esi + sizeof.NET_BUFF + rxfd.count], 0
mov [esi + sizeof.NET_BUFF + rxfd.size], 1528
@ -837,28 +868,50 @@ int_handler:
; restart RX
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
; mov eax, [ebx + device.rx_desc]
; invoke GetPhysAddr
; add eax, NET_BUFF.data
out dx, eax
set_io [ebx + device.io_addr], reg_scb_cmd
set_io [ebx + device.io_addr], REG_SCB_CMD
mov ax, RX_START
out dx, ax
call cmd_wait
.out_of_mem:
; And give packet to kernel
; Hand the frame over to the kernel
jmp [EthInput]
.nodata:
.not_ok:
; Reset the FD
mov [esi + sizeof.NET_BUFF + rxfd.status], 0
mov [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
mov [esi + sizeof.NET_BUFF + rxfd.count], 0
; Restart RX
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], REG_SCB_PTR
mov eax, esi
invoke GetPhysAddr
add eax, NET_BUFF.data
out dx, eax
set_io [ebx + device.io_addr], REG_SCB_CMD
mov ax, RX_START
out dx, ax
call cmd_wait
push ebx
jmp .rx_loop
.no_rx_:
DEBUGF 1, "no more data\n"
pop ax
.no_rx:
test ax, 1 shl 13
test ax, SCB_STATUS_CNA
jz .no_tx
DEBUGF 1, "Command completed\n"
@ -889,29 +942,11 @@ int_handler:
pop eax
.no_tx:
and ax, 00111100b
cmp ax, 00001000b
test ax, RU_STATUS_NO_RESOURCES
jne .fail
DEBUGF 2, "Out of resources!\n"
; call init_rx_ring
; test eax, eax
; jz .fail
; restart RX
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], reg_scb_ptr
mov eax, [ebx + device.rx_desc]
invoke GetPhysAddr
add eax, NET_BUFF.data
out dx, eax
set_io [ebx + device.io_addr], reg_scb_cmd
mov ax, RX_START
out dx, ax
call cmd_wait
.fail:
pop edi esi ebx
xor eax, eax
@ -942,7 +977,7 @@ ee_read: ; esi = address to read
DEBUGF 1,"Eeprom read from 0x%x\n", esi
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], reg_eeprom
set_io [ebx + device.io_addr], REG_EEPROM
;-----------------------------------------------------
; Prepend start bit + read opcode to the address field
@ -1020,7 +1055,7 @@ ee_write: ; esi = address to write to, di = data
DEBUGF 1,"Eeprom write 0x%x to 0x%x\n", di, esi
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], reg_eeprom
set_io [ebx + device.io_addr], REG_EEPROM
;-----------------------------------------------------
; Prepend start bit + write opcode to the address field
@ -1090,7 +1125,7 @@ align 4
ee_get_width:
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], reg_eeprom
set_io [ebx + device.io_addr], REG_EEPROM
mov al, EE_CS ; activate eeprom
out dx, al
@ -1167,7 +1202,7 @@ mdio_read:
or eax, 10b shl 26 ; read opcode
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], reg_mdi_ctrl
set_io [ebx + device.io_addr], REG_MDI_CTRL
out dx, eax
.wait:
@ -1199,7 +1234,7 @@ mdio_write:
or eax, 01b shl 26 ; write opcode
set_io [ebx + device.io_addr], 0
set_io [ebx + device.io_addr], reg_mdi_ctrl
set_io [ebx + device.io_addr], REG_MDI_CTRL
out dx, eax
.wait: