28,6 → 28,8 |
|
MAX_DEVICES = 16 |
|
TX_RING_SIZE = 16 |
|
DEBUG = 1 |
__DEBUG__ = 1 |
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only |
122,18 → 124,20 |
|
ends |
|
struc txfd { |
struct txfd |
|
.status dw ? |
.command dw ? |
.link dd ? |
.desc_addr dd ? |
.count dd ? |
status dw ? |
command dw ? |
link dd ? |
desc_addr dd ? |
count dd ? |
|
.buf_addr0 dd ? |
.buf_size0 dd ? |
buf_addr dd ? |
buf_size dd ? |
virt_addr dd ? |
dd ? ; alignment |
|
} |
ends |
|
struc confcmd { |
|
172,12 → 176,13 |
pci_bus dd ? |
pci_dev dd ? |
rx_desc dd ? |
last_tx_buffer dd ? |
cur_tx dd ? |
last_tx dd ? |
ee_bus_width db ? |
irq_line db ? |
|
rb 0x100 - ($ and 0xff) ; align 256 |
txfd txfd |
tx_ring rb TX_RING_SIZE*sizeof.txfd |
|
rb 0x100 - ($ and 0xff) ; align 256 |
confcmd confcmd |
466,13 → 471,13 |
set_io [ebx + device.io_addr], reg_scb_ptr |
out dx, eax |
|
mov ax, INT_MASK + CU_STATSADDR |
set_io [ebx + device.io_addr], reg_scb_cmd |
mov ax, CU_STATSADDR or INT_MASK |
out dx, ax |
call cmd_wait |
|
;----------------- |
; setup RX |
;------------------------ |
; setup RX base addr to 0 |
|
set_io [ebx + device.io_addr], reg_scb_ptr |
xor eax, eax |
479,7 → 484,7 |
out dx, eax |
|
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 |
call cmd_wait |
|
486,12 → 491,18 |
;----------------------------- |
; Create RX and TX descriptors |
|
call create_ring |
call init_rx_ring |
test eax, eax |
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], reg_scb_ptr |
mov eax, [ebx + device.rx_desc] |
499,11 → 510,12 |
add eax, NET_BUFF.data |
out dx, eax |
|
mov ax, INT_MASK + RX_START |
set_io [ebx + device.io_addr], reg_scb_cmd |
mov ax, RX_START or INT_MASK |
out dx, ax |
call cmd_wait |
|
;---------- |
; Set-up TX |
|
set_io [ebx + device.io_addr], reg_scb_ptr |
511,15 → 523,39 |
out dx, eax |
|
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 |
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.status], 0 |
lea eax, [ebx + device.txfd.status] |
lea eax, [ebx + device.confcmd.status] |
invoke GetPhysAddr |
mov [ebx + device.confcmd.link], eax |
|
535,46 → 571,17 |
mov byte[ebx + device.confcmd.data + 19], 0x80 |
mov byte[ebx + device.confcmd.data + 21], 0x05 |
|
mov [ebx + device.txfd.command], CmdIASetup |
mov [ebx + device.txfd.status], 0 |
set_io [ebx + device.io_addr], reg_scb_ptr |
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 |
lea eax, [ebx + device.txfd.status] |
invoke GetPhysAddr |
out dx, eax |
|
; Start CU & enable ints |
|
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 |
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" |
|
mov [ebx + device.mtu], 1514 |
|
; Set link state to unknown |
589,7 → 596,7 |
|
|
align 4 |
create_ring: |
init_rx_ring: |
|
DEBUGF 1,"Creating ring\n" |
|
609,23 → 616,46 |
mov [esi + sizeof.NET_BUFF + rxfd.count], 0 |
mov [esi + sizeof.NET_BUFF + rxfd.size], 1528 |
|
;----------------------- |
; build txfd structure |
ret |
|
lea eax, [ebx + device.txfd.status] |
.out_of_mem: |
|
ret |
|
|
|
|
align 4 |
init_tx_ring: |
|
DEBUGF 1,"Creating TX ring\n" |
|
lea esi, [ebx + device.tx_ring] |
mov eax, esi |
invoke GetPhysAddr |
mov [ebx + device.txfd.link], eax |
mov [ebx + device.txfd.count], 0x01208000 |
lea eax, [ebx + device.txfd.buf_addr0] |
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 [ebx + device.txfd.desc_addr], eax |
mov dword[ebx + device.tx_ring + sizeof.txfd*(TX_RING_SIZE-1) + txfd.link], eax |
|
.out_of_mem: |
mov [ebx + device.cur_tx], 0 |
mov [ebx + device.last_tx], 0 |
|
ret |
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Transmit ;; |
652,23 → 682,34 |
cmp [esi + NET_BUFF.length], 60 |
jb .fail |
|
;;; TODO: check if current descriptor is in use |
; fill in buffer address and size |
mov eax, [bufferptr] |
mov [ebx + device.last_tx_buffer], eax |
add eax, [eax + NET_BUFF.offset] |
; Get current TX descriptor |
mov edi, [ebx + device.cur_tx] |
mov eax, sizeof.txfd |
mul edi |
lea edi, [ebx + device.tx_ring + eax] |
|
; Check if current descriptor is free or still in use |
cmp [edi + txfd.status], 0 |
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 |
mov [ebx + device.txfd.buf_addr0], eax |
mov ecx, [bufferptr] |
mov ecx, [ecx + NET_BUFF.length] |
mov [ebx + device.txfd.buf_size0], ecx |
pop edi |
mov [edi + txfd.buf_addr], eax |
mov ecx, [esi + NET_BUFF.length] |
mov [edi + txfd.buf_size], ecx |
|
mov [ebx + device.txfd.status], 0 |
mov [ebx + device.txfd.command], Cmdsuspend + CmdTx + CmdTxFlex ;+ 1 shl 15 ;;; EL bit |
; mov [txfd.count], 0x02208000 ;;;;;;;;;;; |
|
; Inform device of the new/updated transmit descriptor |
lea eax, [ebx + device.txfd.status] |
mov eax, edi |
invoke GetPhysAddr |
set_io [ebx + device.io_addr], 0 |
set_io [ebx + device.io_addr], reg_scb_ptr |
675,10 → 716,9 |
out dx, eax |
|
; Start the transmit |
set_io [ebx + device.io_addr], reg_scb_cmd |
mov ax, CU_START |
set_io [ebx + device.io_addr], reg_scb_cmd |
out dx, ax |
call cmd_wait |
|
; Update stats |
inc [ebx + device.packets_tx] |
685,6 → 725,12 |
add dword[ebx + device.bytes_tx], ecx |
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" |
popf |
xor eax, eax |
691,6 → 737,7 |
ret |
|
.fail: |
DEBUGF 2,"Transmit failed!\n" |
invoke NetFree, [bufferptr] |
popf |
or eax, -1 |
808,18 → 855,37 |
|
.no_rx: |
|
; Cleanup after TX |
cmp [ebx + device.txfd.status], 0 |
je .done |
cmp [ebx + device.last_tx_buffer], 0 |
je .done |
push ax |
DEBUGF 1, "Removing packet 0x%x from RAM!\n", [ebx + device.last_tx_buffer] |
invoke KernelFree, [ebx + device.last_tx_buffer] |
mov [ebx + device.last_tx_buffer], 0 |
pop ax |
test ax, 1 shl 13 |
jz .no_tx |
DEBUGF 1, "Command completed\n" |
|
.done: |
push eax |
.loop_tx: |
mov edi, [ebx + device.last_tx] |
mov eax, sizeof.txfd |
mul eax |
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: |
|
and ax, 00111100b |
cmp ax, 00001000b |
jne .fail |