Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 260 → Rev 261

/kernel/trunk/network/eth_drv/drivers/rtl8029.inc
0,0 → 1,955
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; RTL8029.INC ;;
;; ;;
;; Ethernet driver for Menuet OS ;;
;; ;;
;; Version 0.2 31 July 2002 ;;
;; ;;
;; This driver is based on the ns8390 driver from ;;
;; the etherboot 5.0.6 project. The copyright statement is ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; remaining parts Copyright 2002 Mike Hibbett, ;;
;; mikeh@oceanfree.net ;;
;; ;;
;; See file COPYING for details ;;
;; ;;
;; While this implementation handles only PCI bus RTL8029 ;;
;; hardware, it can be easily adapted to other NE2000 clone ;;
;; products. I just dont have any to try! ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
 
;********************************************************************
; Interface
; rtl8029_reset
; rtl8029_probe
; rtl8029_poll
; rtl8029_transmit
;
;********************************************************************
 
 
 
 
;**************************************************************************
; 8390 Register Definitions
;**************************************************************************
D8390_P0_COMMAND equ 0x00
D8390_P0_PSTART equ 0x01
D8390_P0_PSTOP equ 0x02
D8390_P0_BOUND equ 0x03
D8390_P0_TSR equ 0x04
D8390_P0_TPSR equ 0x04
D8390_P0_TBCR0 equ 0x05
D8390_P0_TBCR1 equ 0x06
D8390_P0_ISR equ 0x07
D8390_P0_RSAR0 equ 0x08
D8390_P0_RSAR1 equ 0x09
D8390_P0_RBCR0 equ 0x0A
D8390_P0_RBCR1 equ 0x0B
D8390_P0_RSR equ 0x0C
D8390_P0_RCR equ 0x0C
D8390_P0_TCR equ 0x0D
D8390_P0_DCR equ 0x0E
D8390_P0_IMR equ 0x0F
D8390_P1_COMMAND equ 0x00
D8390_P1_PAR0 equ 0x01
D8390_P1_PAR1 equ 0x02
D8390_P1_PAR2 equ 0x03
D8390_P1_PAR3 equ 0x04
D8390_P1_PAR4 equ 0x05
D8390_P1_PAR5 equ 0x06
D8390_P1_CURR equ 0x07
D8390_P1_MAR0 equ 0x08
 
D8390_COMMAND_PS0 equ 0x0 ; Page 0 select
D8390_COMMAND_PS1 equ 0x40 ; Page 1 select
D8390_COMMAND_PS2 equ 0x80 ; Page 2 select
D8390_COMMAND_RD2 equ 0x20 ; Remote DMA control
D8390_COMMAND_RD1 equ 0x10
D8390_COMMAND_RD0 equ 0x08
D8390_COMMAND_TXP equ 0x04 ; transmit packet
D8390_COMMAND_STA equ 0x02 ; start
D8390_COMMAND_STP equ 0x01 ; stop
 
D8390_COMMAND_RD2_STA equ 0x22
D8390_COMMAND_RD2_STP equ 0x21
D8390_COMMAND_RD1_STA equ 0x12
D8390_COMMAND_RD0_STA equ 0x0A
D8390_COMMAND_PS0_RD2_STP equ 0x21
D8390_COMMAND_PS1_RD2_STP equ 0x61
D8390_COMMAND_PS0_RD2_STA equ 0x22
D8390_COMMAND_PS0_TXP_RD2_STA equ 0x26
 
D8390_RCR_MON equ 0x20 ; monitor mode
 
D8390_DCR_FT1 equ 0x40
D8390_DCR_LS equ 0x08 ; Loopback select
D8390_DCR_WTS equ 0x01 ; Word transfer select
 
D8390_DCR_FT1_LS equ 0x48
D8390_DCR_WTS_FT1_LS equ 0x49
 
D8390_ISR_PRX equ 0x01 ; successful recv
D8390_ISR_PTX equ 0x02 ; successful xmit
D8390_ISR_RXE equ 0x04 ; receive error
D8390_ISR_TXE equ 0x08 ; transmit error
D8390_ISR_OVW equ 0x10 ; Overflow
D8390_ISR_CNT equ 0x20 ; Counter overflow
D8390_ISR_RDC equ 0x40 ; Remote DMA complete
D8390_ISR_RST equ 0x80 ; reset
 
D8390_RSTAT_PRX equ 0x01 ; successful recv
D8390_RSTAT_CRC equ 0x02 ; CRC error
D8390_RSTAT_FAE equ 0x04 ; Frame alignment error
D8390_RSTAT_OVER equ 0x08 ; FIFO overrun
 
D8390_TXBUF_SIZE equ 6
D8390_RXBUF_END equ 32
D8390_PAGE_SIZE equ 256
 
ETH_ALEN equ 6
ETH_HLEN equ 14
ETH_ZLEN equ 60
ETH_FRAME_LEN equ 1514
 
FLAG_PIO equ 0x01
FLAG_16BIT equ 0x02
ASIC_PIO equ 0
 
VENDOR_NONE equ 0
VENDOR_WD equ 1
VENDOR_NOVELL equ 2
VENDOR_3COM equ 3
 
NE_ASIC_OFFSET equ 0x10
NE_RESET equ 0x0F ; Used to reset card
NE_DATA equ 0x00 ; Used to read/write NIC mem
 
MEM_8192 equ 32
MEM_16384 equ 64
MEM_32768 equ 128
 
ISA_MAX_ADDR equ 0x400
 
uglobal
eth_flags: db 0
eth_vendor: db 0
eth_nic_base: dw 0
eth_asic_base: dw 0
eth_memsize: db 0
eth_rx_start: db 0
eth_tx_start: db 0
eth_bmem: dd 0
eth_rmem: dd 0
romdata: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
endg
 
iglobal
test_data: db 'NE*000 memory',0
test_buffer: db ' ',0
endg
 
uglobal
eth_type: dw 0
pkthdr: db 0,0,0,0 ; status, next, (short) len
pktoff: dw 0
eth_rx_data_ptr: dd 0
eth_tmp_len: dw 0
endg
 
 
 
;***************************************************************************
; Function
; eth_pio_read
;
; Description
; Read a frame from the ethernet card via Programmed I/O
; src in ebx
; cnt in ecx
; dst in edi
;***************************************************************************
eth_pio_read:
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, 0
je epr_001
 
inc ecx
and ecx, 0xFFFFFFFE
 
epr_001:
mov al, D8390_COMMAND_RD2_STA
mov dx, [eth_nic_base]
add dx, D8390_P0_COMMAND
out dx, al
 
mov al, cl
mov dx, [eth_nic_base]
add dx, D8390_P0_RBCR0
out dx, al
 
mov al, ch
mov dx, [eth_nic_base]
add dx, D8390_P0_RBCR1
out dx, al
 
mov al, bl
mov dx, [eth_nic_base]
add dx, D8390_P0_RSAR0
out dx, al
 
mov al, bh
mov dx, [eth_nic_base]
add dx, D8390_P0_RSAR1
out dx, al
 
mov al, D8390_COMMAND_RD0_STA
mov dx, [eth_nic_base]
add dx, D8390_P0_COMMAND
out dx, al
 
mov dx, [eth_asic_base]
add dx, ASIC_PIO
 
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, 0
je epr_003
 
shr ecx, 1
 
epr_002:
; 2 bytes at a time
in ax, dx
mov [edi], ax
add edi, 2
loop epr_002
ret
 
epr_003:
; 1 byte at a time
in al, dx
mov [edi], al
inc edi
loop epr_003
ret
 
 
 
 
;***************************************************************************
; Function
; eth_pio_write
;
; Description
; writes a frame to the ethernet card via Programmed I/O
; dst in ebx
; cnt in ecx
; src in esi
;***************************************************************************
eth_pio_write:
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, 0
je epw_001
 
inc ecx
and ecx, 0xFFFFFFFE
 
epw_001:
mov al, D8390_COMMAND_RD2_STA
mov dx, [eth_nic_base]
add dx, D8390_P0_COMMAND
out dx, al
 
mov al, D8390_ISR_RDC
mov dx, [eth_nic_base]
add dx, D8390_P0_ISR
out dx, al
 
 
mov al, cl
mov dx, [eth_nic_base]
add dx, D8390_P0_RBCR0
out dx, al
 
mov al, ch
mov dx, [eth_nic_base]
add dx, D8390_P0_RBCR1
out dx, al
 
mov al, bl
mov dx, [eth_nic_base]
add dx, D8390_P0_RSAR0
out dx, al
 
mov al, bh
mov dx, [eth_nic_base]
add dx, D8390_P0_RSAR1
out dx, al
 
mov al, D8390_COMMAND_RD1_STA
mov dx, [eth_nic_base]
add dx, D8390_P0_COMMAND
out dx, al
 
mov dx, [eth_asic_base]
add dx, ASIC_PIO
 
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, 0
je epw_003
 
shr ecx, 1
 
epw_002:
; 2 bytes at a time
mov ax, [esi]
add esi, 2
out dx, ax
 
loop epw_002
jmp epw_004
 
epw_003:
; 1 byte at a time
mov al, [esi]
inc esi
out dx, al
loop epw_003
 
epw_004:
mov dx, [eth_nic_base]
add dx, D8390_P0_ISR
 
epw_005:
in al, dx
and al, D8390_ISR_RDC
cmp al, D8390_ISR_RDC
jne epw_005
 
ret
 
 
 
;***************************************************************************
; Function
; rtl8029_reset
; Description
; Place the chip (ie, the ethernet card) into a virgin state
; No inputs
; All registers destroyed
;
;***************************************************************************
rtl8029_reset:
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0_RD2_STP
out dx, al
 
mov dx, bx
add dx, D8390_P0_DCR
mov al, [eth_flags]
and al, FLAG_16BIT
cmp al, FLAG_16BIT
jne nsr_001
 
mov al, 0x49
jmp nsr_002
 
nsr_001:
mov al, 0x48
 
nsr_002:
out dx, al
 
xor al, al
 
mov dx, bx
add dx, D8390_P0_RBCR0
out dx, al
 
mov dx, bx
add dx, D8390_P0_RBCR1
out dx, al
 
mov dx, bx
add dx, D8390_P0_RCR
mov al, 0x20
out dx, al
 
mov dx, bx
add dx, D8390_P0_TCR
mov al, 2
out dx, al
 
mov dx, bx
add dx, D8390_P0_TPSR
mov al, [eth_tx_start]
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTART
mov al, [eth_rx_start]
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTOP
mov al, [eth_memsize]
out dx, al
 
mov dx, bx
add dx, D8390_P0_BOUND
mov al, [eth_memsize]
dec al
out dx, al
 
mov dx, bx
add dx, D8390_P0_ISR
mov al, 0xff
out dx, al
 
mov dx, bx
add dx, D8390_P0_IMR
xor al, al
out dx, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS1_RD2_STP
out dx, al
 
mov dx, bx
add dx, D8390_P1_PAR0
mov esi, node_addr
mov ecx, ETH_ALEN
 
nsr_003:
mov al, [esi]
out dx, al
 
inc esi
inc dx
loop nsr_003
 
mov dx, bx
add dx, D8390_P1_MAR0
mov ecx, ETH_ALEN
 
mov al, 0xff
 
nsr_004:
out dx, al
inc dx
loop nsr_004
 
mov dx, bx
add dx, D8390_P1_CURR
mov al, [eth_rx_start]
out dx, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0_RD2_STA
out dx, al
 
mov dx, bx
add dx, D8390_P0_ISR
mov al, 0xff
out dx, al
 
mov dx, bx
add dx, D8390_P0_TCR
mov al, 0
out dx, al
 
mov dx, bx
add dx, D8390_P0_RCR
mov al, 4
out dx, al
 
ret
 
 
 
;***************************************************************************
; Function
; rtl8029_probe
; Description
; Searches for an ethernet card, enables it and clears the rx buffer
; If a card was found, it enables the ethernet -> TCPIP link
;
;***************************************************************************
rtl8029_probe:
mov eax, [io_addr]
mov [eth_nic_base], ax ; The IO address space is 16 bit only
 
mov al, VENDOR_NONE
mov [eth_vendor], al
 
mov al, [eth_vendor]
cmp al, VENDOR_NONE
 
jne ep_check_have_vendor
xor eax, eax
mov [eth_bmem], eax
 
mov al, FLAG_PIO
mov [eth_flags], al
 
mov ax, [eth_nic_base]
add ax, NE_ASIC_OFFSET
mov [eth_asic_base], ax
 
mov al, MEM_16384
mov [eth_memsize], al
 
mov al, 32
mov [eth_tx_start], al
 
add al, D8390_TXBUF_SIZE
mov [eth_rx_start], al
 
mov dx, [eth_asic_base]
add dx, NE_RESET
 
in al, dx
out dx, al
 
in al, 0x84
 
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_RD2_STP
out dx, al
 
mov dx, bx
add dx, D8390_P0_RCR
mov al, D8390_RCR_MON
out dx, al
 
mov dx, bx
add dx, D8390_P0_DCR
mov al, D8390_DCR_FT1_LS
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTART
mov al, MEM_8192
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTOP
mov al, MEM_16384
out dx, al
 
mov esi, test_data
mov ebx, 8192
mov ecx, 14
call eth_pio_write
 
mov ebx, 8192
mov ecx, 14
mov edi, test_buffer
call eth_pio_read
 
mov esi, test_buffer
mov edi, test_data
mov ecx, 13
cld
rep cmpsb
 
je ep_set_vendor
 
mov al, [eth_flags]
or al, FLAG_16BIT
mov [eth_flags], al
 
mov al, MEM_32768
mov [eth_memsize], al
 
mov al, 64
mov [eth_tx_start], al
 
add al, D8390_TXBUF_SIZE
mov [eth_rx_start], al
 
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_DCR
mov al, D8390_DCR_WTS_FT1_LS
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTART
mov al, MEM_16384
out dx, al
 
mov dx, bx
add dx, D8390_P0_PSTOP
mov al, MEM_32768
out dx, al
 
mov esi, test_data
mov ebx, 16384
mov ecx, 14
call eth_pio_write
 
mov ebx, 16384
mov ecx, 14
mov edi, test_buffer
call eth_pio_read
 
mov esi, test_buffer
mov edi, test_data
mov ecx, 13
cld
rep cmpsb
 
ep_set_vendor:
; this bit is odd - probably left over from my hacking
mov ax, [eth_nic_base]
cmp ax, 0
je rtl8029_exit
cmp ax, ISA_MAX_ADDR
jbe ep_001
mov al, [eth_flags]
or al, FLAG_16BIT
mov [eth_flags], al
 
ep_001:
mov al, VENDOR_NOVELL
mov [eth_vendor], al
 
mov ebx, 0
mov ecx, 16
mov edi, romdata
call eth_pio_read
 
 
mov ecx, ETH_ALEN
mov esi, romdata
mov edi, node_addr
 
mov bl, [eth_flags]
and bl, FLAG_16BIT
 
ep_002:
mov al, [esi]
mov [edi], al
 
inc edi
inc esi
cmp bl, FLAG_16BIT
jne ep_003
 
inc esi
 
ep_003:
loop ep_002
 
ep_check_have_vendor:
mov al, [eth_vendor]
cmp al, VENDOR_NONE
je rtl8029_exit
 
cmp al, VENDOR_3COM
je ep_reset_card
 
mov eax, [eth_bmem]
mov [eth_rmem], eax
 
ep_reset_card:
; Reset the card
call rtl8029_reset
 
; Indicate that we have successfully reset the card
mov eax, [pci_data]
mov [eth_status], eax
 
rtl8029_exit:
ret
 
 
 
;***************************************************************************
; Function
; rtl8029_poll
;
; Description
; Polls the ethernet card for a received packet
; Received data, if any, ends up in Ether_buffer
;
;***************************************************************************
rtl8029_poll:
mov eax, Ether_buffer
mov [eth_rx_data_ptr], eax
 
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_RSR
in al, dx
 
and al, D8390_RSTAT_PRX
cmp al, D8390_RSTAT_PRX
jne nsp_exit
 
mov dx, bx
add dx, D8390_P0_BOUND
in al, dx
inc al
 
cmp al, [eth_memsize]
jb nsp_001
 
mov al, [eth_rx_start]
 
nsp_001:
mov ch, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS1
out dx, al
 
mov dx, bx
add dx, D8390_P1_CURR
in al, dx ; get current page
mov cl, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0
out dx, al
 
cmp cl, [eth_memsize]
jb nsp_002
 
mov cl, [eth_rx_start]
 
nsp_002:
cmp cl, ch
je nsp_exit
 
xor ax, ax
mov ah, ch
 
mov [pktoff], ax
 
mov al, [eth_flags]
and al, FLAG_PIO
cmp al, FLAG_PIO
jne nsp_003
 
movzx ebx, word [pktoff]
mov edi, pkthdr
mov ecx, 4
call eth_pio_read
jmp nsp_004
 
nsp_003:
mov edi, [eth_rmem]
movzx eax, word [pktoff]
add edi, eax
mov eax, [edi]
mov [pkthdr], eax
 
nsp_004:
mov ax, [pktoff]
add ax, 4
mov [pktoff], ax
 
mov ax, [pkthdr + 2]
sub ax, 4
 
mov [eth_tmp_len], ax
 
cmp ax, ETH_ZLEN
jb nsp_exit
 
cmp ax, ETH_FRAME_LEN
ja nsp_exit
 
mov al, [pkthdr]
and al, D8390_RSTAT_PRX
cmp al, D8390_RSTAT_PRX
jne nsp_exit
 
; Right, we can now get the data
 
mov ax, [eth_tmp_len]
mov [eth_rx_data_len], ax
 
xor ebx, ebx
mov bh, [eth_memsize]
sub bx, [pktoff]
 
cmp [eth_tmp_len], bx
jbe nsp_005
 
mov al, [eth_flags]
and al, FLAG_PIO
cmp al, FLAG_PIO
jne nsp_006
 
push ebx
mov ecx, ebx
xor ebx, ebx
mov bx, [pktoff]
mov edi, [eth_rx_data_ptr]
call eth_pio_read
pop ebx
jmp nsp_007
 
nsp_006:
; Not implemented, as we are using PIO mode on this card
 
nsp_007:
xor ax, ax
mov ah, [eth_rx_start]
mov [pktoff], ax
 
mov eax, [eth_rx_data_ptr]
add eax, ebx
mov [eth_rx_data_ptr], eax
 
mov ax, [eth_tmp_len]
sub ax, bx
mov [eth_tmp_len], ax
 
nsp_005:
mov al, [eth_flags]
and al, FLAG_PIO
cmp al, FLAG_PIO
jne nsp_008
 
xor ebx, ebx
mov bx, [pktoff]
xor ecx, ecx
mov cx, [eth_tmp_len]
mov edi, [eth_rx_data_ptr]
call eth_pio_read
jmp nsp_009
 
nsp_008:
; Not implemented, as we are using PIO mode on this card
 
nsp_009:
mov al, [pkthdr+1]
cmp al, [eth_rx_start]
jne nsp_010
 
mov al, [eth_memsize]
 
nsp_010:
mov dx, [eth_nic_base]
add dx, D8390_P0_BOUND
dec al
out dx, al
 
nsp_exit:
ret
 
 
 
;***************************************************************************
; Function
; rtl8029_transmit
;
; Description
; Transmits a packet of data via the ethernet card
; Pointer to 48 bit destination address in edi
; Type of packet in bx
; size of packet in ecx
; pointer to packet data in esi
;
;***************************************************************************
rtl8029_transmit:
mov [eth_type], bx
 
pusha
 
mov esi, edi
xor bx, bx
mov bh, [eth_tx_start]
mov ecx, ETH_ALEN
call eth_pio_write
 
mov esi, node_addr
xor bx, bx
mov bh, [eth_tx_start]
add bx, ETH_ALEN
mov ecx, ETH_ALEN
call eth_pio_write
 
mov esi, eth_type
xor bx, bx
mov bh, [eth_tx_start]
add bx, ETH_ALEN
add bx, ETH_ALEN
mov ecx, 2
call eth_pio_write
 
popa
 
xor bx, bx
mov bh, [eth_tx_start]
add bx, ETH_HLEN
push ecx
call eth_pio_write
pop ecx
 
add ecx, ETH_HLEN
cmp ecx, ETH_ZLEN
jae nst_001
 
mov ecx, ETH_ZLEN
 
nst_001:
push ecx
 
mov bx, [eth_nic_base]
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0_RD2_STA
out dx, al
 
mov dx, bx
add dx, D8390_P0_TPSR
mov al, [eth_tx_start]
out dx, al
 
pop ecx
 
mov dx, bx
add dx, D8390_P0_TBCR0
mov al, cl
out dx, al
 
mov dx, bx
add dx, D8390_P0_TBCR1
mov al, ch
out dx, al
 
mov dx, bx
add dx, D8390_P0_COMMAND
mov al, D8390_COMMAND_PS0_TXP_RD2_STA
out dx, al
 
ret