Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4518 → Rev 4519

/drivers/ethernet/i8254x.asm
14,8 → 14,6
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; TODO: make better use of the available descriptors
 
format MS COFF
 
API_VERSION = 0x01000100
29,7 → 27,8
 
MAX_PKT_SIZE = 4096 ; Maximum packet size
 
RX_RING_SIZE = 8 ; Must be a multiple of 8
RX_RING_SIZE = 8 ; Must be a power of 2, and minimum 8
TX_RING_SIZE = 8 ; Must be a power of 2, and minimum 8
 
include '../struct.inc'
include '../macros.inc'
217,8 → 216,18
; Flow Control Type
FCT_TYPE_DEFAULT = 0x8808
 
; === TX Descriptor fields ===
 
 
; === TX Descriptor ===
 
struct TDESC
addr_l dd ?
addr_h dd ?
 
length_cso_cmd dd ? ; 16 bits length + 8 bits cso + 8 bits cmd
status dd ? ; status, checksum start field, special
ends
 
; TX Packet Length (word 2)
TXDESC_LEN_MASK = 0x0000ffff
 
238,8 → 247,17
TXDESC_EC = 0x00000002 ; Excess Collisions
TXDESC_DD = 0x00000001 ; Descriptor Done
 
; === RX Descriptor fields ===
 
 
; === RX Descriptor ===
 
struct RDESC
addr_l dd ?
addr_h dd ?
status_l dd ?
status_h dd ?
ends
 
; RX Packet Length (word 2)
RXDESC_LEN_MASK = 0x0000ffff
 
252,7 → 270,6
RXDESC_EOP = 0x00000002 ; End Of Packet
RXDESC_DD = 0x00000001 ; Descriptor Done
 
 
virtual at ebx
device:
ETH_DEVICE
266,11 → 283,11
.cur_tx dd ?
.last_tx dd ?
 
rb 0x100 - (($ - device) and 0xff)
.rx_desc rd RX_RING_SIZE*8
rb 0x100 - (($ - device) and 0xff) ; align 256
.rx_desc rb RX_RING_SIZE*sizeof.RDESC*2
 
rb 0x100 - (($ - device) and 0xff)
.tx_desc rd 256/8
rb 0x100 - (($ - device) and 0xff) ; align 256
.tx_desc rb TX_RING_SIZE*sizeof.TDESC*2
 
sizeof.device_struct = $ - device
 
498,8 → 515,8
test eax, eax
jnz @f
DEBUGF 2,"Could not attach int handler!\n"
; or eax, -1
; ret
or eax, -1
ret
@@:
 
 
558,15 → 575,15
stdcall KernelAlloc, MAX_PKT_SIZE
DEBUGF 1,"RX buffer: 0x%x\n", eax
pop edi
mov dword[edi + 16*RX_RING_SIZE], eax
mov dword[edi + RX_RING_SIZE*sizeof.RDESC], eax
push edi
GetRealAddr
pop edi
mov dword[edi], eax ; addres low
mov dword[edi + 4], 0 ; addres high
mov dword[edi + 8], 0
mov dword[edi + 12], 0
add edi, 16
mov [edi + RDESC.addr_l], eax
mov [edi + RDESC.addr_h], 0
mov [edi + RDESC.status_l], 0
mov [edi + RDESC.status_h], 0
add edi, sizeof.RDESC
pop ecx
dec ecx
jnz .loop
577,7 → 594,7
GetRealAddr
mov dword[esi + REG_RDBAL], eax ; Receive Descriptor Base Address Low
mov dword[esi + REG_RDBAH], 0 ; Receive Descriptor Base Address High
mov dword[esi + REG_RDLEN], 16*RX_RING_SIZE ; Receive Descriptor Length
mov dword[esi + REG_RDLEN], RX_RING_SIZE*sizeof.RDESC ; Receive Descriptor Length
mov dword[esi + REG_RDH], 0 ; Receive Descriptor Head
mov dword[esi + REG_RDT], RX_RING_SIZE-1 ; Receive Descriptor Tail
mov dword[esi + REG_RCTL], RCTL_SBP or RCTL_BAM or RCTL_SECRC or RCTL_UPE or RCTL_MPE
590,15 → 607,25
align 4
init_tx:
 
mov dword[device.tx_desc], 0
mov dword[device.tx_desc + 4], 0
mov dword[device.tx_desc + 16], 0
lea edi, [device.tx_desc]
mov ecx, TX_RING_SIZE
.loop:
mov [edi + TDESC.addr_l], eax
mov [edi + TDESC.addr_h], 0
mov [edi + TDESC.length_cso_cmd], 0
mov [edi + TDESC.status], 0
add edi, sizeof.TDESC
dec ecx
jnz .loop
 
mov [device.cur_tx], 0
mov [device.last_tx], 0
 
lea eax, [device.tx_desc]
GetRealAddr
mov dword[esi + REG_TDBAL], eax ; Transmit Descriptor Base Address Low
mov dword[esi + REG_TDBAH], 0 ; Transmit Descriptor Base Address High
mov dword[esi + REG_TDLEN], (1 * 128) ; Transmit Descriptor Length
mov dword[esi + REG_TDLEN], RX_RING_SIZE*sizeof.TDESC ; Transmit Descriptor Length
mov dword[esi + REG_TDH], 0 ; Transmit Descriptor Head
mov dword[esi + REG_TDT], 0 ; Transmit Descriptor Tail
mov dword[esi + REG_TCTL], 0x010400fa ; Enabled, Pad Short Packets, 15 retrys, 64-byte COLD, Re-transmit on Late Collision
614,7 → 641,7
start_i8254x:
 
mov esi, [device.mmio_addr]
or dword[esi + REG_RCTL], RCTL_EN
or dword[esi + REG_RCTL], RCTL_EN ; Enable the receiver
 
xor eax, eax
mov [esi + REG_RDTR], eax ; Clear the Receive Delay Timer Register
625,10 → 652,8
mov eax, [esi + REG_ICR] ; Clear pending interrupts
 
mov [device.mtu], 1514
mov [device.state], ETH_LINK_UNKOWN ; Set link state to unknown
 
; Set link state to unknown
mov [device.state], ETH_LINK_UNKOWN
 
xor eax, eax
ret
 
685,6 → 710,9
 
proc transmit stdcall bufferptr, buffersize
 
pushf
cli
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
mov eax, [bufferptr]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
698,21 → 726,27
jb .fail
 
; Program the descriptor (use legacy mode)
lea edi, [device.tx_desc] ; Transmit Descriptor Base Address
mov dword[edi + 16], eax ; Store the data location (for driver)
GetRealAddr ;
mov dword[edi], eax ; Real addr (for i8254x)
mov dword[edi + 4], 0x00000000 ;
mov edi, [device.cur_tx]
DEBUGF 1, "Using TX desc: %u\n", edi
shl edi, 4 ; edi = edi * sizeof.TDESC
lea edi, [device.tx_desc + edi]
mov dword[edi + TX_RING_SIZE*sizeof.TDESC], eax ; Store the data location (for driver)
GetRealAddr
mov [edi + TDESC.addr_l], eax ; Data location (for hardware)
mov [edi + TDESC.addr_h], 0
 
mov ecx, [buffersize]
or ecx, 1 shl 24 + 1 shl 25 + 1 shl 27 ; EOP + IFCS + RS
mov dword[edi + 8], ecx ; Packet size
mov dword[edi + 12], 0x00000000
or ecx, TXDESC_EOP + TXDESC_IFCS + TXDESC_RS
mov [edi + TDESC.length_cso_cmd], ecx
mov [edi + TDESC.status], 0
 
; Tell i8254x wich descriptor(s) we programmed
mov edi, [device.mmio_addr]
mov dword[edi + REG_TDH], 0 ; TDH - Transmit Descriptor Head
mov dword[edi + REG_TDT], 1 ; TDT - Transmit Descriptor Tail
mov eax, [device.cur_tx]
inc eax
and eax, TX_RING_SIZE-1
mov [device.cur_tx], eax
mov dword[edi + REG_TDT], eax ; TDT - Transmit Descriptor Tail
 
; Update stats
inc [device.packets_tx]
721,6 → 755,7
adc dword[device.bytes_tx + 4], 0
 
xor eax, eax
popf
ret
 
.fail:
727,6 → 762,7
DEBUGF 2,"Send failed\n"
stdcall KernelFree, [bufferptr]
or eax, -1
popf
ret
 
endp
783,9 → 819,9
pop ebx eax
; Get last descriptor addr
mov esi, [device.cur_rx]
shl esi, 4
shl esi, 4 ; esi = esi * sizeof.RDESC
lea esi, [device.rx_desc + esi]
cmp byte[esi + 12], 0 ; Check status field
cmp byte[esi + RDESC.status_h], 0 ; Check status field
je .no_rx
 
push eax ebx
793,22 → 829,22
movzx ecx, word[esi + 8] ; Get the packet length
DEBUGF 1,"got %u bytes\n", ecx
push ecx
push dword[esi + 16*RX_RING_SIZE] ; Get packet pointer
push dword[esi + RX_RING_SIZE*sizeof.RDESC] ; Get packet pointer
 
; Update stats
add dword[device.bytes_rx], ecx
adc dword[device.bytes_rx + 4], 0
inc dword[device.packets_rx]
inc [device.packets_rx]
 
; Allocate new descriptor
push esi
stdcall KernelAlloc, MAX_PKT_SIZE
pop esi
mov dword[esi + 16*RX_RING_SIZE], eax
mov dword[esi + RX_RING_SIZE*sizeof.RDESC], eax
GetRealAddr
mov dword[esi], eax
mov dword[esi + 8], 0
mov dword[esi + 12], 0
mov [esi + RDESC.addr_l], eax
mov [esi + RDESC.status_l], 0
mov [esi + RDESC.status_h], 0
 
; Move the receive descriptor tail
mov esi, [device.mmio_addr]
840,12 → 876,28
 
DEBUGF 1,"Transmit done\n"
 
lea edi, [device.tx_desc] ; Transmit Descriptor Base Address
push dword[edi + 16]
.txdesc_loop:
mov edi, [device.last_tx]
shl edi, 4 ; edi = edi * sizeof.TDESC
lea edi, [device.tx_desc + edi]
test [edi + TDESC.status], TXDESC_DD ; Descriptor done?
jz .no_tx
cmp dword[edi + TX_RING_SIZE*sizeof.TDESC], 0
je .no_tx
 
DEBUGF 1,"Cleaning up TX desc: 0x%x\n", edi
 
push ebx
push dword[edi + TX_RING_SIZE*sizeof.TDESC]
mov dword[edi + TX_RING_SIZE*sizeof.TDESC], 0
call KernelFree
pop ebx
 
inc [device.last_tx]
and [device.last_tx], TX_RING_SIZE-1
jmp .txdesc_loop
 
.no_tx:
.fail:
pop edi esi ebx
xor eax, eax
inc eax