0,0 → 1,814 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; PCNET32.INC ;; |
;; ;; |
;; Ethernet driver for Menuet OS ;; |
;; ;; |
;; Version 1.0 31 July 2004 ;; |
;; ;; |
;; This driver is based on the PCNet32 driver from ;; |
;; the etherboot 5.0.6 project. The copyright statement is ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;; remaining parts Copyright 2004 Jarek Pelczar, ;; |
;; jpelczar@interia.pl ;; |
;; ;; |
;; See file COPYING for details ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;macro PutStr X |
;{ |
; local .__xyz1 |
; local .__xyz2 |
; push esi |
; mov esi,.__xyz1 |
; call sys_msg_board_str |
; push eax |
; mov eax,1 |
; call delay_hs |
; pop eax |
; jmp .__xyz2 |
;.__xyz1: |
; db X |
; db 13,10,0 |
;.__xyz2: |
; pop esi |
;} |
PCNET32_PORT_AUI equ 0x00 |
PCNET32_PORT_10BT equ 0x01 |
PCNET32_PORT_GPSI equ 0x02 |
PCNET32_PORT_MII equ 0x03 |
PCNET32_PORT_PORTSEL equ 0x03 |
PCNET32_PORT_ASEL equ 0x04 |
PCNET32_PORT_100 equ 0x40 |
PCNET32_PORT_FD equ 0x80 |
PCNET32_DMA_MASK equ 0xffffffff |
PCNET32_LOG_TX_BUFFERS equ 1 |
PCNET32_LOG_RX_BUFFERS equ 2 |
PCNET32_TX_RING_SIZE equ (1 shl PCNET32_LOG_TX_BUFFERS) |
PCNET32_TX_RING_MOD_MASK equ (PCNET32_TX_RING_SIZE-1) |
PCNET32_TX_RING_LEN_BITS equ 0 |
PCNET32_RX_RING_SIZE equ (1 shl PCNET32_LOG_RX_BUFFERS) |
PCNET32_RX_RING_MOD_MASK equ (PCNET32_RX_RING_SIZE-1) |
PCNET32_RX_RING_LEN_BITS equ (PCNET32_LOG_RX_BUFFERS shl 4) |
PCNET32_PKT_BUF_SZ equ 1544 |
PCNET32_PKT_BUF_SZ_NEG equ 0xf9f8 |
pcnet32_txb equ (eth_data_start) |
pcnet32_rxb equ ((pcnet32_txb+(PCNET32_PKT_BUF_SZ*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) |
pcnet32_tx_ring equ ((pcnet32_rxb+(PCNET32_PKT_BUF_SZ*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) |
pcnet32_rx_ring equ ((pcnet32_tx_ring+(16*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) |
virtual at ((pcnet32_rx_ring+(16*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) |
pcnet32_private: |
.mode dw ? |
.tlen_rlen dw ? |
.phys_addr db ?,?,?,?,?,? |
.reserved dw ? |
.filter dd ?,? |
.rx_ring dd ? |
.tx_ring dd ? |
.cur_rx dd ? |
.cur_tx dd ? |
.dirty_rx dd ? |
.dirty_tx dd ? |
.tx_full db ? |
.options dd ? |
.full_duplex db ? |
.chip_version dd ? |
.mii db ? |
.ltint db ? |
.dxsuflo db ? |
.fset db ? |
.fdx db ? |
end virtual |
virtual at 0 |
pcnet32_rx_head: |
.base dd ? |
.buf_length dw ? |
.status dw ? |
.msg_length dd ? |
.reserved dd ? |
end virtual |
virtual at 0 |
pcnet32_tx_head: |
.base dd ? |
.length dw ? |
.status dw ? |
.misc dd ? |
.reserved dd ? |
end virtual |
|
uglobal |
pcnet32_access: |
.read_csr dd ? |
.write_csr dd ? |
.read_bcr dd ? |
.write_bcr dd ? |
.read_rap dd ? |
.write_rap dd ? |
.reset dd ? |
endg |
|
iglobal |
pcnet32_options_mapping: |
dd PCNET32_PORT_ASEL ; 0 Auto-select |
dd PCNET32_PORT_AUI ; 1 BNC/AUI |
dd PCNET32_PORT_AUI ; 2 AUI/BNC |
dd PCNET32_PORT_ASEL ; 3 not supported |
dd PCNET32_PORT_10BT or PCNET32_PORT_FD ; 4 10baseT-FD |
dd PCNET32_PORT_ASEL ; 5 not supported |
dd PCNET32_PORT_ASEL ; 6 not supported |
dd PCNET32_PORT_ASEL ; 7 not supported |
dd PCNET32_PORT_ASEL ; 8 not supported |
dd PCNET32_PORT_MII ; 9 MII 10baseT |
dd PCNET32_PORT_MII or PCNET32_PORT_FD ; 10 MII 10baseT-FD |
dd PCNET32_PORT_MII ; 11 MII (autosel) |
dd PCNET32_PORT_10BT ; 12 10BaseT |
dd PCNET32_PORT_MII or PCNET32_PORT_100 ; 13 MII 100BaseTx |
dd PCNET32_PORT_MII or PCNET32_PORT_100 or PCNET32_PORT_FD ; 14 MII 100BaseTx-FD |
dd PCNET32_PORT_ASEL ; 15 not supported |
endg |
|
PCNET32_WIO_RDP equ 0x10 |
PCNET32_WIO_RAP equ 0x12 |
PCNET32_WIO_RESET equ 0x14 |
PCNET32_WIO_BDP equ 0x16 |
PCNET32_DWIO_RDP equ 0x10 |
PCNET32_DWIO_RAP equ 0x14 |
PCNET32_DWIO_RESET equ 0x18 |
PCNET32_DWIO_BDP equ 0x1C |
PCNET32_TOTAL_SIZE equ 0x20 |
; ebx - index |
; return: |
; eax - data |
pcnet32_wio_read_csr: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
mov ax,bx |
out dx,ax |
lea edx,[ebp+PCNET32_WIO_RDP] |
in ax,dx |
and eax,0xffff |
pop edx |
ret |
; eax - data |
; ebx - index |
pcnet32_wio_write_csr: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
xchg eax,ebx |
out dx,ax |
xchg eax,ebx |
lea edx,[ebp+PCNET32_WIO_RDP] |
out dx,ax |
pop edx |
ret |
; ebx - index |
; return: |
; eax - data |
pcnet32_wio_read_bcr: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
mov ax,bx |
out dx,ax |
lea edx,[ebp+PCNET32_WIO_BDP] |
in ax,dx |
and eax,0xffff |
pop edx |
ret |
; eax - data |
; ebx - index |
pcnet32_wio_write_bcr: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
xchg eax,ebx |
out dx,ax |
xchg eax,ebx |
lea edx,[ebp+PCNET32_WIO_BDP] |
out dx,ax |
pop edx |
ret |
pcnet32_wio_read_rap: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
in ax,dx |
and eax,0xffff |
pop edx |
ret |
; eax - val |
pcnet32_wio_write_rap: |
push edx |
lea edx,[ebp+PCNET32_WIO_RAP] |
out dx,ax |
pop edx |
ret |
pcnet32_wio_reset: |
push edx |
push eax |
lea edx,[ebp+PCNET32_WIO_RESET] |
in ax,dx |
pop eax |
pop edx |
ret |
pcnet32_wio_check: |
push edx |
mov ax,88 |
lea edx,[ebp+PCNET32_WIO_RAP] |
out dx,ax |
nop |
nop |
in ax,dx |
cmp ax,88 |
sete al |
pop edx |
ret |
|
iglobal |
pcnet32_wio: |
dd pcnet32_wio_read_csr |
dd pcnet32_wio_write_csr |
dd pcnet32_wio_read_bcr |
dd pcnet32_wio_write_bcr |
dd pcnet32_wio_read_rap |
dd pcnet32_wio_write_rap |
dd pcnet32_wio_reset |
endg |
|
; ebx - index |
; return: |
; eax - data |
pcnet32_dwio_read_csr: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
mov ebx,eax |
out dx,eax |
lea edx,[ebp+PCNET32_DWIO_RDP] |
in eax,dx |
and eax,0xffff |
pop edx |
ret |
; ebx - index |
; eax - data |
pcnet32_dwio_write_csr: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
xchg eax,ebx |
out dx,eax |
lea edx,[ebp+PCNET32_DWIO_RDP] |
xchg eax,ebx |
out dx,eax |
pop edx |
ret |
; ebx - index |
; return: |
; eax - data |
pcnet32_dwio_read_bcr: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
mov ebx,eax |
out dx,eax |
lea edx,[ebp+PCNET32_DWIO_BDP] |
in eax,dx |
and eax,0xffff |
pop edx |
ret |
; ebx - index |
; eax - data |
pcnet32_dwio_write_bcr: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
xchg eax,ebx |
out dx,eax |
lea edx,[ebp+PCNET32_DWIO_BDP] |
xchg eax,ebx |
out dx,eax |
pop edx |
ret |
pcnet32_dwio_read_rap: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
in eax,dx |
and eax,0xffff |
pop edx |
ret |
; eax - val |
pcnet32_dwio_write_rap: |
push edx |
lea edx,[ebp+PCNET32_DWIO_RAP] |
out dx,eax |
pop edx |
ret |
pcnet32_dwio_reset: |
push edx |
push eax |
lea edx,[ebp+PCNET32_DWIO_RESET] |
in eax,dx |
pop eax |
pop edx |
ret |
pcnet32_dwio_check: |
push edx |
lea edx,[PCNET32_DWIO_RAP] |
mov eax,88 |
out dx,eax |
nop |
nop |
in eax,dx |
and eax,0xffff |
cmp eax,88 |
sete al |
pop edx |
ret |
|
iglobal |
pcnet32_dwio: |
dd pcnet32_dwio_read_csr |
dd pcnet32_dwio_write_csr |
dd pcnet32_dwio_read_bcr |
dd pcnet32_dwio_write_bcr |
dd pcnet32_dwio_read_rap |
dd pcnet32_dwio_write_rap |
dd pcnet32_dwio_reset |
endg |
|
pcnet32_init_ring: |
mov [pcnet32_private.tx_full],0 |
mov [pcnet32_private.cur_rx],0 |
mov [pcnet32_private.cur_tx],0 |
mov [pcnet32_private.dirty_rx],0 |
mov [pcnet32_private.dirty_tx],0 |
mov edi,pcnet32_rx_ring |
mov ecx,PCNET32_RX_RING_SIZE |
mov ebx,pcnet32_rxb |
.rx_init: |
mov [edi+pcnet32_rx_head.base],ebx |
mov [edi+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG |
mov [edi+pcnet32_rx_head.status],word 0x8000 |
add ebx,PCNET32_PKT_BUF_SZ |
; inc ebx |
add edi,16 |
loop .rx_init |
mov edi,pcnet32_tx_ring |
mov ecx,PCNET32_TX_RING_SIZE |
.tx_init: |
mov [edi+pcnet32_tx_head.base],dword 0 |
mov [edi+pcnet32_tx_head.status],word 0 |
add edi,16 |
loop .tx_init |
mov [pcnet32_private.tlen_rlen],(PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) |
mov esi,node_addr |
mov edi,pcnet32_private.phys_addr |
cld |
movsd |
movsw |
mov dword [pcnet32_private.rx_ring],pcnet32_rx_ring |
mov dword [pcnet32_private.tx_ring],pcnet32_tx_ring |
ret |
pcnet32_reset: |
; Reset PCNET32 |
mov ebp,[io_addr] |
call dword [pcnet32_access.reset] |
; set 32bit mode |
mov ebx,20 |
mov eax,2 |
call dword [pcnet32_access.write_bcr] |
; set/reset autoselect bit |
mov ebx,2 |
call dword [pcnet32_access.read_bcr] |
and eax,not 2 |
test [pcnet32_private.options],PCNET32_PORT_ASEL |
jz .L1 |
or eax,2 |
.L1: |
call dword [pcnet32_access.write_bcr] |
; Handle full duplex setting |
cmp byte [pcnet32_private.full_duplex],0 |
je .L2 |
mov ebx,9 |
call dword [pcnet32_access.read_bcr] |
and eax,not 3 |
test [pcnet32_private.options],PCNET32_PORT_FD |
jz .L3 |
or eax,1 |
cmp [pcnet32_private.options],PCNET32_PORT_FD or PCNET32_PORT_AUI |
jne .L4 |
or eax,2 |
jmp .L4 |
.L3: |
test [pcnet32_private.options],PCNET32_PORT_ASEL |
jz .L4 |
cmp [pcnet32_private.chip_version],0x2627 |
jne .L4 |
or eax,3 |
.L4: |
mov ebx,9 |
call dword [pcnet32_access.write_bcr] |
.L2: |
; set/reset GPSI bit |
mov ebx,124 |
call dword [pcnet32_access.read_csr] |
mov ecx,[pcnet32_private.options] |
and ecx,PCNET32_PORT_PORTSEL |
cmp ecx,PCNET32_PORT_GPSI |
jne .L5 |
or eax,0x10 |
.L5: |
call dword [pcnet32_access.write_csr] |
cmp [pcnet32_private.mii],0 |
je .L6 |
test [pcnet32_private.options],PCNET32_PORT_ASEL |
jnz .L6 |
mov ebx,32 |
call dword [pcnet32_access.read_bcr] |
and eax,not 0x38 |
test [pcnet32_private.options],PCNET32_PORT_FD |
jz .L7 |
or eax,0x10 |
.L7: |
test [pcnet32_private.options],PCNET32_PORT_100 |
jz .L8 |
or eax,0x08 |
.L8: |
call dword [pcnet32_access.write_bcr] |
jmp .L9 |
.L6: |
test [pcnet32_private.options],PCNET32_PORT_ASEL |
jz .L9 |
mov ebx,32 |
; PutStr "ASEL, enable auto-negotiation" |
call dword [pcnet32_access.read_bcr] |
and eax,not 0x98 |
or eax,0x20 |
call dword [pcnet32_access.write_bcr] |
.L9: |
cmp [pcnet32_private.ltint],0 |
je .L10 |
mov ebx,5 |
call dword [pcnet32_access.read_csr] |
or eax,(1 shl 14) |
call dword [pcnet32_access.write_csr] |
.L10: |
mov eax,[pcnet32_private.options] |
and eax,PCNET32_PORT_PORTSEL |
shl eax,7 |
mov [pcnet32_private.mode],ax |
mov [pcnet32_private.filter],dword 0xffffffff |
mov [pcnet32_private.filter+4],dword 0xffffffff |
call pcnet32_init_ring |
mov ebx,1 |
mov eax,pcnet32_private |
and eax,0xffff |
call dword [pcnet32_access.write_csr] |
mov eax,pcnet32_private |
mov ebx,2 |
shr eax,16 |
call dword [pcnet32_access.write_csr] |
mov ebx,4 |
mov eax,0x0915 |
call dword [pcnet32_access.write_csr] |
mov ebx,0 |
mov eax,1 |
call dword [pcnet32_access.write_csr] |
mov ecx,100 |
.L11: |
xor ebx,ebx |
call dword [pcnet32_access.read_csr] |
test ax,0x100 |
jnz .L12 |
loop .L11 |
.L12: |
; PutStr "hardware reset" |
xor ebx,ebx |
mov eax,0x0002 |
call dword [pcnet32_access.write_csr] |
xor ebx,ebx |
call dword [pcnet32_access.read_csr] |
; PutStr "PCNET reset complete" |
ret |
pcnet32_adjust_pci_device: |
;*******Get current setting************************ |
mov al, 2 ;read a word |
mov bh, [pci_dev] |
mov ah, [pci_bus] |
mov bl, 0x04 ;from command Register |
call pci_read_reg |
;******see if its already set as bus master******** |
mov bx, ax |
and bx,5 |
cmp bx,5 |
je pcnet32_adjust_pci_device_Latency |
;******Make card a bus master******* |
mov cx, ax ;value to write |
mov bh, [pci_dev] |
mov al, 2 ;write a word |
or cx,5 |
mov ah, [pci_bus] |
mov bl, 0x04 ;to command register |
call pci_write_reg |
;******Check latency setting*********** |
pcnet32_adjust_pci_device_Latency: |
;*******Get current latency setting************************ |
; mov al, 1 ;read a byte |
; mov bh, [pci_dev] |
; mov ah, [pci_bus] |
; mov bl, 0x0D ;from Lantency Timer Register |
; call pci_read_reg |
;******see if its aat least 64 clocks******** |
; cmp ax,64 |
; jge pcnet32_adjust_pci_device_Done |
;******Set latency to 32 clocks******* |
; mov cx, 64 ;value to write |
; mov bh, [pci_dev] |
; mov al, 1 ;write a byte |
; mov ah, [pci_bus] |
; mov bl, 0x0D ;to Lantency Timer Register |
; call pci_write_reg |
;******Check latency setting*********** |
pcnet32_adjust_pci_device_Done: |
ret |
pcnet32_probe: |
mov ebp,[io_addr] |
call pcnet32_wio_reset |
xor ebx,ebx |
call pcnet32_wio_read_csr |
cmp eax,4 |
jne .try_dwio |
call pcnet32_wio_check |
and al,al |
jz .try_dwio |
; PutStr "Using WIO" |
mov esi,pcnet32_wio |
jmp .L1 |
.try_dwio: |
call pcnet32_dwio_reset |
xor ebx,ebx |
call pcnet32_dwio_read_csr |
cmp eax,4 |
jne .no_dev |
call pcnet32_dwio_check |
and al,al |
jz .no_dev |
; PutStr "Using DWIO" |
mov esi,pcnet32_dwio |
jmp .L1 |
.no_dev: |
; PutStr "PCNET32 not found" |
ret |
.L1: |
mov edi,pcnet32_access |
mov ecx,7 |
cld |
rep movsd |
mov ebx,88 |
call dword [pcnet32_access.read_csr] |
mov ecx,eax |
mov ebx,89 |
call dword [pcnet32_access.read_csr] |
shl eax,16 |
or eax,ecx |
mov ecx,eax |
and ecx,0xfff |
cmp ecx,3 |
jne .no_dev |
shr eax,12 |
and eax,0xffff |
mov [pcnet32_private.chip_version],eax |
; PutStr "PCNET32 chip version OK" |
mov [pcnet32_private.fdx],0 |
mov [pcnet32_private.mii],0 |
mov [pcnet32_private.fset],0 |
mov [pcnet32_private.dxsuflo],0 |
mov [pcnet32_private.ltint],0 |
mov eax,[pcnet32_private.chip_version] |
cmp eax,0x2420 |
je .L2 |
cmp eax,0x2430 |
je .L3 |
cmp eax,0x2621 |
je .L4 |
cmp eax,0x2623 |
je .L5 |
cmp eax,0x2624 |
je .L6 |
cmp eax,0x2625 |
je .L7 |
cmp eax,0x2626 |
je .L8 |
cmp eax,0x2627 |
je .L9 |
; PutStr "Invalid chip rev" |
jmp .no_dev |
.L2: |
; PutStr "PCnet/PCI 79C970" |
jmp .L10 |
.L3: |
; PutStr "PCnet/PCI 79C970" |
jmp .L10 |
.L4: |
; PutStr "PCnet/PCI II 79C970A" |
mov [pcnet32_private.fdx],1 |
jmp .L10 |
.L5: |
; PutStr "PCnet/FAST 79C971" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
mov [pcnet32_private.fset],1 |
mov [pcnet32_private.ltint],1 |
jmp .L10 |
.L6: |
; PutStr "PCnet/FAST+ 79C972" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
mov [pcnet32_private.fset],1 |
jmp .L10 |
.L7: |
; PutStr "PCnet/FAST III 79C973" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
jmp .L10 |
.L8: |
; PutStr "PCnet/Home 79C978" |
mov [pcnet32_private.fdx],1 |
mov ebx,49 |
call dword [pcnet32_access.read_bcr] |
call dword [pcnet32_access.write_bcr] |
jmp .L10 |
.L9: |
; PutStr "PCnet/FAST III 79C975" |
mov [pcnet32_private.fdx],1 |
mov [pcnet32_private.mii],1 |
.L10: |
cmp [pcnet32_private.fset],1 |
jne .L11 |
mov ebx,18 |
call dword [pcnet32_access.read_bcr] |
or eax,0x800 |
call dword [pcnet32_access.write_bcr] |
mov ebx,80 |
call dword [pcnet32_access.read_csr] |
and eax,0xc00 |
or eax,0xc00 |
call dword [pcnet32_access.write_csr] |
mov [pcnet32_private.dxsuflo],1 |
mov [pcnet32_private.ltint],1 |
.L11: |
; read MAC |
mov edi,node_addr |
mov edx,ebp |
mov ecx,6 |
.Lmac: |
in al,dx |
stosb |
inc edx |
loop .Lmac |
; PutStr "MAC read" |
call pcnet32_adjust_pci_device |
; PutStr "PCI done" |
mov eax,PCNET32_PORT_ASEL |
mov [pcnet32_private.options],eax |
mov [pcnet32_private.mode],word 0x0003 |
mov [pcnet32_private.tlen_rlen],word (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) |
mov esi,node_addr |
mov edi,pcnet32_private.phys_addr |
cld |
movsd |
movsw |
mov [pcnet32_private.filter],dword 0 |
mov [pcnet32_private.filter+4],dword 0 |
mov dword [pcnet32_private.rx_ring],pcnet32_rx_ring |
mov dword [pcnet32_private.tx_ring],pcnet32_tx_ring |
; PutStr "Switching to 32" |
mov ebx,20 |
mov eax,2 |
call dword [pcnet32_access.write_bcr] |
mov ebx,1 |
mov eax,(pcnet32_private and 0xffff) |
call dword [pcnet32_access.write_csr] |
mov ebx,2 |
mov eax,(pcnet32_private shr 16) and 0xffff |
call dword [pcnet32_access.write_csr] |
mov ebx,0 |
mov eax,1 |
call dword [pcnet32_access.write_csr] |
mov esi,1 |
call delay_ms |
call pcnet32_reset |
mov eax, [pci_data] |
mov [eth_status], eax |
ret |
pcnet32_poll: |
xor eax,eax |
mov [eth_rx_data_len],ax |
mov eax,[pcnet32_private.cur_rx] |
and eax,PCNET32_RX_RING_MOD_MASK |
mov ebx,eax |
imul esi,eax,PCNET32_PKT_BUF_SZ |
add esi,pcnet32_rxb |
shl ebx,4 |
add ebx,pcnet32_rx_ring |
mov cx,[ebx+pcnet32_rx_head.status] |
test cx,0x8000 |
jnz .L1 |
cmp ch,3 |
jne .L1 |
; PutStr "PCNETRX" |
mov ecx,[ebx+pcnet32_rx_head.msg_length] |
and ecx,0xfff |
sub ecx,4 |
mov [eth_rx_data_len],cx |
push ecx |
shr ecx,2 |
mov edi,Ether_buffer |
cld |
rep movsd |
pop ecx |
and ecx,3 |
rep movsb |
mov [ebx+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG |
or [ebx+pcnet32_rx_head.status],word 0x8000 |
inc [pcnet32_private.cur_rx] |
.L1: |
ret |
; Pointer to 48 bit destination address in edi |
; Type of packet in bx |
; size of packet in ecx |
; pointer to packet data in esi |
pcnet32_xmit: |
push edi |
push esi |
push ebx |
push ecx |
; PutStr "PCNETTX" |
mov esi,edi |
mov edi,[pcnet32_private.cur_tx] |
imul edi,PCNET32_PKT_BUF_SZ |
add edi,pcnet32_txb ; edi=ptxb |
mov eax,edi |
cld ; copy MAC |
movsd |
movsw |
mov esi,node_addr |
cld |
movsd |
movsw |
mov [edi],bx |
add edi,2 |
mov esi,[esp+8] |
mov ecx,[esp] |
push ecx |
shr ecx,2 |
cld |
rep movsd |
pop ecx |
and ecx,3 |
rep movsb |
; mov ecx,[esp] |
; add ecx,14 ; ETH_HLEN |
; xor eax,eax |
; pad to min length (60=ETH_ZLEN) |
; cmp ecx,60 |
; jae .L1 |
; sub ecx,60 |
; cld |
; rep stosb |
;.L1: |
mov edi,pcnet32_tx_ring+0 ; entry=0 |
mov ecx,[esp] |
add ecx,14 |
cmp cx,60 |
jae .L1 |
mov cx,60 |
.L1: |
neg cx |
mov [edi+pcnet32_tx_head.length],cx |
mov [edi+pcnet32_tx_head.misc],dword 0 |
mov [edi+pcnet32_tx_head.base],eax |
mov [edi+pcnet32_tx_head.status],word 0x8300 |
; trigger an immediate send poll |
mov ebx,0 |
mov eax,0x0008 ; 0x0048 |
mov ebp,[io_addr] |
call dword [pcnet32_access.write_csr] |
mov dword [pcnet32_private.cur_tx],0 |
; wait for TX to complete |
mov ecx,[timer_ticks];[0xfdf0] |
add ecx,100 |
.L2: |
mov ax,[edi+pcnet32_tx_head.status] |
test ax,0x8000 |
jz .L3 |
cmp ecx,[timer_ticks];[0xfdf0] |
jb .L4 |
mov esi,10 |
call delay_ms |
jnz .L2 |
.L4: |
; PutStr "PCNET: Send timeout" |
.L3: |
mov dword [edi+pcnet32_tx_head.base],0 |
pop ecx |
pop ebx |
pop esi |
pop edi |
ret |