forked from KolibriOS/kolibrios
92f657f440
git-svn-id: svn://kolibrios.org@593 a494cfbc-eb01-0410-851d-a64ba20cac60
822 lines
21 KiB
PHP
822 lines
21 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
;; ;;
|
|
;; 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 ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
$Revision$
|
|
|
|
|
|
;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
|