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 |