27,8 → 27,10 |
__DEBUG__ = 1 |
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only |
|
MAX_PKT_SIZE = 16384 ; Maximum packet size |
MAX_PKT_SIZE = 4096 ; Maximum packet size |
|
RX_RING_SIZE = 8 ; Must be a multiple of 8 |
|
include '../struct.inc' |
include '../macros.inc' |
include '../proc32.inc' |
260,11 → 262,12 |
.pci_dev dd ? |
.irq_line db ? |
|
.cur_rx dd ? |
.cur_tx dd ? |
.last_tx dd ? |
|
rb 0x100 - (($ - device) and 0xff) |
.rx_desc rd 256/8 |
.rx_desc rd RX_RING_SIZE*8 |
|
rb 0x100 - (($ - device) and 0xff) |
.tx_desc rd 256/8 |
273,6 → 276,7 |
|
end virtual |
|
|
section '.flat' code readable align 16 |
|
|
518,7 → 522,7 |
mov eax, dword [esi + REG_ICR] ; Clear any pending interrupts |
mov dword [esi + REG_ITR], 0 ; Disable interrupt throttling logic |
|
mov dword [esi + REG_PBA], 0x00000030 ; PBA: set the RX buffer size to 48KB (TX buffer is calculated as 64-RX buffer) |
mov dword [esi + REG_PBA], 0x00000004 ; PBA: set the RX buffer size to 4KB (TX buffer is calculated as 64-RX buffer) |
mov dword [esi + REG_RDTR], 0 ; RDTR: set no delay |
|
mov dword [esi + REG_TXCW], 0x08008060 ; TXCW: set ANE, TxConfigWord (Half/Full duplex, Next Page Reqest) |
535,22 → 539,57 |
stosd |
stosd |
|
stdcall KernelAlloc, 48*1024 |
mov dword [device.rx_desc + 16], eax |
call init_rx |
call init_tx |
|
xor eax, eax |
ret |
|
|
|
align 4 |
init_rx: |
|
lea edi, [device.rx_desc] |
mov ecx, RX_RING_SIZE |
.loop: |
push ecx |
push edi |
stdcall KernelAlloc, MAX_PKT_SIZE |
DEBUGF 1,"RX buffer: 0x%x\n", eax |
pop edi |
mov dword[edi + 16*RX_RING_SIZE], eax |
push edi |
GetRealAddr |
mov dword [device.rx_desc], eax |
mov dword [device.rx_desc + 4], 0 |
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 |
pop ecx |
dec ecx |
jnz .loop |
|
mov [device.cur_rx], 0 |
|
lea eax, [device.rx_desc] |
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], (1 * 128) ; Receive Descriptor Length |
mov dword[esi + REG_RDLEN], 16*RX_RING_SIZE ; Receive Descriptor Length |
mov dword [esi + REG_RDH], 0 ; Receive Descriptor Head |
mov dword [esi + REG_RDT], 1 ; Receive Descriptor Tail |
mov dword [esi + REG_RCTL], RCTL_EN or RCTL_SBP or RCTL_BAM or RCTL_SECRC or RCTL_UPE or RCTL_MPE |
; Receiver Enable, Store Bad Packets, Broadcast Accept Mode, Strip Ethernet CRC from incoming packet, Promiscuous mode |
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 |
; Store Bad Packets, Broadcast Accept Mode, Strip Ethernet CRC from incoming packet, Promiscuous mode |
|
ret |
|
|
|
align 4 |
init_tx: |
|
mov dword [device.tx_desc], 0 |
mov dword [device.tx_desc + 4], 0 |
mov dword [device.tx_desc + 16], 0 |
565,9 → 604,9 |
mov dword [esi + REG_TCTL], 0x010400fa ; Enabled, Pad Short Packets, 15 retrys, 64-byte COLD, Re-transmit on Late Collision |
mov dword [esi + REG_TIPG], 0x0060200A ; IPGT 10, IPGR1 8, IPGR2 6 |
|
xor eax, eax |
ret |
|
|
align 4 |
reset: |
call reset_dontstart |
574,14 → 613,17 |
|
start_i8254x: |
|
mov esi, [device.mmio_addr] |
or dword[esi + REG_RCTL], RCTL_EN |
|
xor eax, eax |
mov [esi + REG_RDTR], eax ; Clear the Receive Delay Timer Register |
mov [esi + REG_RADV], eax ; Clear the Receive Interrupt Absolute Delay Timer |
mov [esi + REG_RSRPD], eax ; Clear the Receive Small Packet Detect Interrupt |
; or eax, 1 shl 0 + 1 shl 7 ; TXDW + RXT0 |
mov eax, 1+4+16 ;;;; hack! |
mov [esi + REG_IMS], eax ; Enable interrupt types |
|
mov dword[esi + REG_IMS], 0x1F6DC ; Enable interrupt types |
mov eax, [esi + REG_ICR] ; Clear pending interrupts |
|
mov [device.mtu], 1514 |
|
; Set link state to unknown |
637,23 → 679,22 |
;; ;; |
;; Transmit ;; |
;; ;; |
;; In: buffer pointer in [esp+4] ;; |
;; size of buffer in [esp+8] ;; |
;; pointer to device structure in ebx ;; |
;; In: pointer to device structure in ebx ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
transmit: |
DEBUGF 1,"\nTransmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8] |
mov eax, [esp+4] |
|
proc transmit stdcall bufferptr, buffersize |
|
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",\ |
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ |
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
[eax+13]:2,[eax+12]:2 |
|
cmp dword [esp + 8], 1514 |
cmp [buffersize], 1514 |
ja .fail |
cmp dword [esp + 8], 60 |
cmp [buffersize], 60 |
jb .fail |
|
; Program the descriptor (use legacy mode) |
663,7 → 704,7 |
mov dword [edi], eax ; Real addr (for i8254x) |
mov dword [edi + 4], 0x00000000 ; |
|
mov ecx, [esp + 8] |
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 |
675,20 → 716,22 |
|
; Update stats |
inc [device.packets_tx] |
mov eax, [esp + 8] |
mov eax, [buffersize] |
add dword [device.bytes_tx], eax |
adc dword [device.bytes_tx + 4], 0 |
|
xor eax, eax |
ret 8 |
ret |
|
.fail: |
DEBUGF 2,"Send failed\n" |
stdcall KernelFree, [esp+4] |
stdcall KernelFree, [bufferptr] |
or eax, -1 |
ret 8 |
ret |
|
endp |
|
|
;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Interrupt handler ;; |
727,27 → 770,30 |
|
.got_it: |
|
DEBUGF 1,"Device: %x Status: %x ", ebx, eax |
DEBUGF 1,"Device: %x Status: %x\n", ebx, eax |
|
;--------- |
; RX done? |
|
test eax, ICR_RXDMT0 |
test eax, ICR_RXDMT0 + ICR_RXT0 |
jz .no_rx |
|
push eax ebx |
push .retaddr |
|
.retaddr: |
pop ebx eax |
; Get last descriptor addr |
lea esi, [device.rx_desc] |
|
mov esi, [device.cur_rx] |
shl esi, 4 |
lea esi, [device.rx_desc + esi] |
cmp byte [esi + 12], 0 ; Check status field |
je .retaddr |
je .no_rx |
|
push eax ebx |
push .retaddr |
movzx ecx, word [esi + 8] ; Get the packet length |
DEBUGF 1,"got %u bytes\n", ecx |
push ecx |
push dword [esi + 16] ; Get packet pointer |
push dword[esi + 16*RX_RING_SIZE] ; Get packet pointer |
|
; Update stats |
add dword [device.bytes_rx], ecx |
754,21 → 800,26 |
adc dword [device.bytes_rx + 4], 0 |
inc dword [device.packets_rx] |
|
; allocate new descriptor |
stdcall KernelAlloc, 48*1024 |
mov dword [esi + 16], eax |
; Allocate new descriptor |
push esi |
stdcall KernelAlloc, MAX_PKT_SIZE |
pop esi |
mov dword[esi + 16*RX_RING_SIZE], eax |
GetRealAddr |
mov dword [esi], eax |
mov dword[esi + 8], 0 |
mov dword[esi + 12], 0 |
|
; reset descriptor status |
; Move the receive descriptor tail |
mov esi, [device.mmio_addr] |
mov dword [esi + REG_RDH], 0x00000000 ; Receive Descriptor Head |
mov dword [esi + REG_RDT], 0x00000001 ; Receive Descriptor Tail |
mov eax, [device.cur_rx] |
mov [esi + REG_RDT], eax |
|
; Move to next rx desc |
inc [device.cur_rx] |
and [device.cur_rx], RX_RING_SIZE-1 |
|
jmp Eth_input |
.retaddr: |
pop ebx eax |
|
.no_rx: |
|
;-------------- |
777,7 → 828,7 |
test eax, ICR_LSC |
jz .no_link |
|
DEBUGF 1,"Link Changed\n" |
DEBUGF 2,"Link Changed\n" |
|
.no_link: |
|
790,7 → 841,7 |
DEBUGF 1,"Transmit done\n" |
|
lea edi, [device.tx_desc] ; Transmit Descriptor Base Address |
push dword [edi + 16] ; Store the data location (for driver) |
push dword[edi + 16] |
call KernelFree |
|
.no_tx: |