e3172037f7
git-svn-id: svn://kolibrios.org@129 a494cfbc-eb01-0410-851d-a64ba20cac60
596 lines
24 KiB
PHP
596 lines
24 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; RTL8139.INC ;;
|
|
;; ;;
|
|
;; Ethernet driver for Menuet OS ;;
|
|
;; ;;
|
|
;; Version 0.2 11 August 2003 ;;
|
|
;; ;;
|
|
;; Driver for chips of RealTek 8139 family ;;
|
|
;; References: ;;
|
|
;; www.realtek.com.hw - data sheets ;;
|
|
;; rtl8139.c - linux driver ;;
|
|
;; 8139too.c - linux driver ;;
|
|
;; ethernet driver template by Mike Hibbett ;;
|
|
;; ;;
|
|
;; The copyright statement is ;;
|
|
;; ;;
|
|
;; GNU GENERAL PUBLIC LICENSE ;;
|
|
;; Version 2, June 1991 ;;
|
|
;; ;;
|
|
;; Copyright 2003 Endre Kozma, ;;
|
|
;; endre.kozma@axelero.hu ;;
|
|
;; ;;
|
|
;; See file COPYING for details ;;
|
|
;; ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
ETH_ALEN equ 6
|
|
ETH_HLEN equ (2 * ETH_ALEN + 2)
|
|
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
|
|
; mininmum 64bytes frame length
|
|
|
|
PCI_REG_COMMAND equ 0x04 ; command register
|
|
PCI_BIT_PIO equ 0 ; bit0: io space control
|
|
PCI_BIT_MMIO equ 1 ; bit1: memory space control
|
|
PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master
|
|
|
|
RTL8139_REG_MAR0 equ 0x08 ; multicast filter register 0
|
|
RTL8139_REG_MAR4 equ 0x0c ; multicast filter register 4
|
|
RTL8139_REG_TSD0 equ 0x10 ; transmit status of descriptor
|
|
RTL8139_REG_TSAD0 equ 0x20 ; transmit start address of descriptor
|
|
RTL8139_REG_RBSTART equ 0x30 ; RxBuffer start address
|
|
RTL8139_REG_COMMAND equ 0x37 ; command register
|
|
RTL8139_REG_CAPR equ 0x38 ; current address of packet read
|
|
RTL8139_REG_IMR equ 0x3c ; interrupt mask register
|
|
RTL8139_REG_ISR equ 0x3e ; interrupt status register
|
|
RTL8139_REG_TXCONFIG equ 0x40 ; transmit configuration register
|
|
RTL8139_REG_TXCONFIG_0 equ 0x40 ; transmit configuration register 0
|
|
RTL8139_REG_TXCONFIG_1 equ 0x41 ; transmit configuration register 1
|
|
RTL8139_REG_TXCONFIG_2 equ 0x42 ; transmit configuration register 2
|
|
RTL8139_REG_TXCONFIG_3 equ 0x43 ; transmit configuration register 3
|
|
RTL8139_REG_RXCONFIG equ 0x44 ; receive configuration register 0
|
|
RTL8139_REG_RXCONFIG_0 equ 0x44 ; receive configuration register 0
|
|
RTL8139_REG_RXCONFIG_1 equ 0x45 ; receive configuration register 1
|
|
RTL8139_REG_RXCONFIG_2 equ 0x46 ; receive configuration register 2
|
|
RTL8139_REG_RXCONFIG_3 equ 0x47 ; receive configuration register 3
|
|
RTL8139_REG_MPC equ 0x4c ; missed packet counter
|
|
RTL8139_REG_9346CR equ 0x50 ; serial eeprom 93C46 command register
|
|
RTL8139_REG_CONFIG1 equ 0x52 ; configuration register 1
|
|
RTL8139_REG_CONFIG4 equ 0x5a ; configuration register 4
|
|
RTL8139_REG_HLTCLK equ 0x5b ; undocumented halt clock register
|
|
RTL8139_REG_BMCR equ 0x62 ; basic mode control register
|
|
RTL8139_REG_ANAR equ 0x66 ; auto negotiation advertisement register
|
|
|
|
; 5.1 packet header
|
|
RTL8139_BIT_RUNT equ 4 ; total packet length < 64 bytes
|
|
RTL8139_BIT_LONG equ 3 ; total packet length > 4k
|
|
RTL8139_BIT_CRC equ 2 ; crc error occured
|
|
RTL8139_BIT_FAE equ 1 ; frame alignment error occured
|
|
RTL8139_BIT_ROK equ 0 ; received packet is ok
|
|
; 5.4 command register
|
|
RTL8139_BIT_RST equ 4 ; reset bit
|
|
RTL8139_BIT_RE equ 3 ; receiver enabled
|
|
RTL8139_BIT_TE equ 2 ; transmitter enabled
|
|
RTL8139_BIT_BUFE equ 0 ; rx buffer is empty, no packet stored
|
|
; 5.6 interrupt status register
|
|
RTL8139_BIT_ISR_TOK equ 2 ; transmit ok
|
|
RTL8139_BIT_ISR_RER equ 1 ; receive error interrupt
|
|
RTL8139_BIT_ISR_ROK equ 0 ; receive ok
|
|
; 5.7 transmit configyration register
|
|
RTL8139_BIT_TX_MXDMA equ 8 ; Max DMA burst size per Tx DMA burst
|
|
RTL8139_BIT_TXRR equ 4 ; Tx Retry count 16+(TXRR*16)
|
|
; 5.8 receive configuration register
|
|
RTL8139_BIT_RXFTH equ 13 ; Rx fifo threshold
|
|
RTL8139_BIT_RBLEN equ 11 ; Ring buffer length indicator
|
|
RTL8139_BIT_RX_MXDMA equ 8 ; Max DMA burst size per Rx DMA burst
|
|
RTL8139_BIT_NOWRAP equ 7 ; transfered data wrapping
|
|
RTL8139_BIT_9356SEL equ 6 ; eeprom selector 9346/9356
|
|
RTL8139_BIT_AER equ 5 ; accept error packets
|
|
RTL8139_BIT_AR equ 4 ; accept runt packets
|
|
RTL8139_BIT_AB equ 3 ; accept broadcast packets
|
|
RTL8139_BIT_AM equ 2 ; accept multicast packets
|
|
RTL8139_BIT_APM equ 1 ; accept physical match packets
|
|
RTL8139_BIT_AAP equ 0 ; accept all packets
|
|
; 5.9 93C46/93C56 command register
|
|
RTL8139_BIT_93C46_EEM1 equ 7 ; RTL8139 eeprom operating mode1
|
|
RTL8139_BIT_93C46_EEM0 equ 6 ; RTL8139 eeprom operating mode0
|
|
RTL8139_BIT_93C46_EECS equ 3 ; chip select
|
|
RTL8139_BIT_93C46_EESK equ 2 ; serial data clock
|
|
RTL8139_BIT_93C46_EEDI equ 1 ; serial data input
|
|
RTL8139_BIT_93C46_EEDO equ 0 ; serial data output
|
|
; 5.11 configuration register 1
|
|
RTL8139_BIT_LWACT equ 4 ; see RTL8139_REG_CONFIG1
|
|
RTL8139_BIT_SLEEP equ 1 ; sleep bit at older chips
|
|
RTL8139_BIT_PWRDWN equ 0 ; power down bit at older chips
|
|
RTL8139_BIT_PMEn equ 0 ; power management enabled
|
|
; 5.14 configuration register 4
|
|
RTL8139_BIT_LWPTN equ 2 ; see RTL8139_REG_CONFIG4
|
|
; 6.2 transmit status register
|
|
RTL8139_BIT_ERTXTH equ 16 ; early TX threshold
|
|
RTL8139_BIT_TOK equ 15 ; transmit ok
|
|
RTL8139_BIT_OWN equ 13 ; tx DMA operation is completed
|
|
; 6.18 basic mode control register
|
|
RTL8139_BIT_ANE equ 12 ; auto negotiation enable
|
|
; 6.20 auto negotiation advertisement register
|
|
RTL8139_BIT_TXFD equ 8 ; 100base-T full duplex
|
|
RTL8139_BIT_TX equ 7 ; 100base-T
|
|
RTL8139_BIT_10FD equ 6 ; 10base-T full duplex
|
|
RTL8139_BIT_10 equ 5 ; 10base-T
|
|
RTL8139_BIT_SELECTOR equ 0 ; binary encoded selector CSMA/CD=00001
|
|
; RX/TX buffer size
|
|
RTL8139_RBLEN equ 0 ; 0==8K 1==16k 2==32k 3==64k
|
|
RTL8139_RX_BUFFER_SIZE equ (8192 shl RTL8139_RBLEN)
|
|
MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC
|
|
RTL8139_NUM_TX_DESC equ 4
|
|
RTL8139_TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE * RTL8139_NUM_TX_DESC)
|
|
RTL8139_TXRR equ 8 ; total retries = 16+(TXRR*16)
|
|
RTL8139_TX_MXDMA equ 6 ; 0==16 1==32 2==64 3==128
|
|
; 4==256 5==512 6==1024 7==2048
|
|
RTL8139_ERTXTH equ 8 ; in unit of 32 bytes e.g:(8*32)=256
|
|
RTL8139_RX_MXDMA equ 7 ; 0==16 1==32 2==64 3==128
|
|
; 4==256 5==512 6==1024 7==unlimited
|
|
RTL8139_RXFTH equ 7 ; 0==16 1==32 2==64 3==128
|
|
; 4==256 5==512 6==1024 7==no threshold
|
|
RTL8139_RX_CONFIG equ ((RTL8139_RBLEN shl RTL8139_BIT_RBLEN) \
|
|
or (RTL8139_RX_MXDMA shl RTL8139_BIT_RX_MXDMA) \
|
|
or (1 shl RTL8139_BIT_NOWRAP) \
|
|
or (RTL8139_RXFTH shl RTL8139_BIT_RXFTH) \
|
|
or (1 shl RTL8139_BIT_AB) or (1 shl RTL8139_BIT_APM) \
|
|
or (1 shl RTL8139_BIT_AER) or (1 shl RTL8139_BIT_AR) \
|
|
or (1 shl RTL8139_BIT_AM))
|
|
RTL8139_TX_TIMEOUT equ 30 ; 300 milliseconds timeout
|
|
|
|
EE_93C46_REG_ETH_ID equ 7 ; MAC offset
|
|
EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address
|
|
EE_93C56_READ_CMD equ (6 shl 8) ; 110b + 8bit address
|
|
EE_93C46_CMD_LENGTH equ 9 ; start bit + cmd + 6bit address
|
|
EE_93C56_CMD_LENGTH equ 11 ; start bit + cmd + 8bit ddress
|
|
|
|
VER_RTL8139 equ 1100000b
|
|
VER_RTL8139A equ 1110000b
|
|
; VER_RTL8139AG equ 1110100b
|
|
VER_RTL8139B equ 1111000b
|
|
VER_RTL8130 equ VER_RTL8139B
|
|
VER_RTL8139C equ 1110100b
|
|
VER_RTL8100 equ 1111010b
|
|
VER_RTL8100B equ 1110101b
|
|
VER_RTL8139D equ VER_RTL8100B
|
|
VER_RTL8139CP equ 1110110b
|
|
VER_RTL8101 equ 1110111b
|
|
|
|
IDX_RTL8139 equ 0
|
|
IDX_RTL8139A equ 1
|
|
IDX_RTL8139B equ 2
|
|
IDX_RTL8139C equ 3
|
|
IDX_RTL8100 equ 4
|
|
IDX_RTL8139D equ 5
|
|
IDX_RTL8139D equ 6
|
|
IDX_RTL8101 equ 7
|
|
|
|
|
|
; These two must be 4 byte aligned ( which they are )
|
|
rtl8139_rx_buff equ eth_data_start
|
|
rtl8139_tx_buff equ rtl8139_rx_buff + (RTL8139_RX_BUFFER_SIZE + MAX_ETH_FRAME_SIZE)
|
|
|
|
uglobal
|
|
align 4
|
|
rtl8139_rx_buff_offset: dd 0
|
|
curr_tx_desc: dd 0
|
|
endg
|
|
|
|
iglobal
|
|
hw_ver_array: db VER_RTL8139, VER_RTL8139A, VER_RTL8139B, VER_RTL8139C
|
|
db VER_RTL8100, VER_RTL8139D, VER_RTL8139CP, VER_RTL8101
|
|
HW_VER_ARRAY_SIZE = $-hw_ver_array
|
|
endg
|
|
|
|
uglobal
|
|
hw_ver_id: db 0
|
|
endg
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; rtl8139_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
|
|
; Destroyed registers
|
|
; eax, ebx, ecx, edx
|
|
;
|
|
;***************************************************************************
|
|
rtl8139_probe:
|
|
; enable the device
|
|
mov al, 2
|
|
mov ah, [pci_bus]
|
|
mov bh, [pci_dev]
|
|
mov bl, PCI_REG_COMMAND
|
|
call pci_read_reg
|
|
mov cx, ax
|
|
or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO)
|
|
and cl, not (1 shl PCI_BIT_MMIO)
|
|
mov al, 2
|
|
mov ah, [pci_bus]
|
|
mov bh, [pci_dev]
|
|
mov bl, PCI_REG_COMMAND
|
|
call pci_write_reg
|
|
; get chip version
|
|
mov edx, [io_addr]
|
|
add edx, RTL8139_REG_TXCONFIG_2
|
|
in ax, dx
|
|
shr ah, 2
|
|
shr ax, 6
|
|
and al, 01111111b
|
|
mov ecx, HW_VER_ARRAY_SIZE-1
|
|
.chip_ver_loop:
|
|
cmp al, [hw_ver_array+ecx]
|
|
je .chip_ver_found
|
|
dec ecx
|
|
jns .chip_ver_loop
|
|
xor cl, cl ; default RTL8139
|
|
.chip_ver_found:
|
|
mov [hw_ver_id], cl
|
|
; wake up the chip
|
|
mov edx, [io_addr]
|
|
add edx, RTL8139_REG_HLTCLK
|
|
mov al, 'R' ; run the clock
|
|
out dx, al
|
|
; unlock config and BMCR registers
|
|
add edx, RTL8139_REG_9346CR - RTL8139_REG_HLTCLK
|
|
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0)
|
|
out dx, al
|
|
; enable power management
|
|
add edx, RTL8139_REG_CONFIG1 - RTL8139_REG_9346CR
|
|
in al, dx
|
|
cmp byte [hw_ver_id], IDX_RTL8139B
|
|
jl .old_chip
|
|
; set LWAKE pin to active high (default value).
|
|
; it is for Wake-On-LAN functionality of some motherboards.
|
|
; this signal is used to inform the motherboard to execute a wake-up process.
|
|
; only at newer chips.
|
|
or al, (1 shl RTL8139_BIT_PMEn)
|
|
and al, not (1 shl RTL8139_BIT_LWACT)
|
|
out dx, al
|
|
add edx, RTL8139_REG_CONFIG4 - RTL8139_REG_CONFIG1
|
|
in al, dx
|
|
and al, not (1 shl RTL8139_BIT_LWPTN)
|
|
out dx, al
|
|
jmp .finish_wake_up
|
|
.old_chip:
|
|
; wake up older chips
|
|
and al, not ((1 shl RTL8139_BIT_SLEEP) or (1 shl RTL8139_BIT_PWRDWN))
|
|
out dx, al
|
|
.finish_wake_up:
|
|
; lock config and BMCR registers
|
|
xor al, al
|
|
mov edx, [io_addr]
|
|
add edx, RTL8139_REG_9346CR
|
|
out dx, al
|
|
;***************************************************************************
|
|
; Function
|
|
; rt8139_reset
|
|
; Description
|
|
; Place the chip (ie, the ethernet card) into a virgin state
|
|
; Destroyed registers
|
|
; eax, ebx, ecx, edx
|
|
;
|
|
;***************************************************************************
|
|
rtl8139_reset:
|
|
mov edx, [io_addr]
|
|
add edx, RTL8139_REG_COMMAND
|
|
mov al, 1 shl RTL8139_BIT_RST
|
|
out dx, al
|
|
mov cx, 1000 ; wait no longer for the reset
|
|
.wait_for_reset:
|
|
in al, dx
|
|
test al, 1 shl RTL8139_BIT_RST
|
|
jz .reset_completed ; RST remains 1 during reset
|
|
dec cx
|
|
jns .wait_for_reset
|
|
.reset_completed:
|
|
; get MAC (hardware address)
|
|
mov ecx, 2
|
|
.mac_read_loop:
|
|
lea eax, [EE_93C46_REG_ETH_ID+ecx]
|
|
push ecx
|
|
call rtl8139_read_eeprom
|
|
pop ecx
|
|
mov [node_addr+ecx*2], ax
|
|
dec ecx
|
|
jns .mac_read_loop
|
|
; unlock config and BMCR registers
|
|
mov edx, [io_addr]
|
|
add edx, RTL8139_REG_9346CR
|
|
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0)
|
|
out dx, al
|
|
; initialize multicast registers (no filtering)
|
|
mov eax, 0xffffffff
|
|
add edx, RTL8139_REG_MAR0 - RTL8139_REG_9346CR
|
|
out dx, eax
|
|
add edx, RTL8139_REG_MAR4 - RTL8139_REG_MAR0
|
|
out dx, eax
|
|
; enable Rx/Tx
|
|
mov al, (1 shl RTL8139_BIT_RE) or (1 shl RTL8139_BIT_TE)
|
|
add edx, RTL8139_REG_COMMAND - RTL8139_REG_MAR4
|
|
out dx, al
|
|
; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold
|
|
; accept broadcast packets, accept physical match packets
|
|
mov ax, RTL8139_RX_CONFIG
|
|
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND
|
|
out dx, ax
|
|
; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144
|
|
mov ax, (RTL8139_TX_MXDMA shl RTL8139_BIT_TX_MXDMA) \
|
|
or (RTL8139_TXRR shl RTL8139_BIT_TXRR)
|
|
add edx, RTL8139_REG_TXCONFIG - RTL8139_REG_RXCONFIG
|
|
out dx, ax
|
|
; enable auto negotiation
|
|
add edx, RTL8139_REG_BMCR - RTL8139_REG_TXCONFIG
|
|
in ax, dx
|
|
or ax, (1 shl RTL8139_BIT_ANE)
|
|
out dx, ax
|
|
; set auto negotiation advertisement
|
|
add edx, RTL8139_REG_ANAR - RTL8139_REG_BMCR
|
|
in ax, dx
|
|
or ax, (1 shl RTL8139_BIT_SELECTOR) or (1 shl RTL8139_BIT_10) \
|
|
or (1 shl RTL8139_BIT_10FD) or (1 shl RTL8139_BIT_TX) \
|
|
or (1 shl RTL8139_BIT_TXFD)
|
|
out dx, ax
|
|
; lock config and BMCR registers
|
|
xor eax, eax
|
|
add edx, RTL8139_REG_9346CR - RTL8139_REG_ANAR
|
|
out dx, al
|
|
; init RX/TX pointers
|
|
mov [rtl8139_rx_buff_offset], eax
|
|
mov [curr_tx_desc], eax
|
|
; clear missing packet counter
|
|
add edx, RTL8139_REG_MPC - RTL8139_REG_9346CR
|
|
out dx, eax
|
|
; disable all interrupts
|
|
add edx, RTL8139_REG_IMR - RTL8139_REG_MPC
|
|
out dx, ax
|
|
; set RxBuffer address, init RX buffer offset, init TX ring
|
|
mov eax, rtl8139_rx_buff
|
|
add edx, RTL8139_REG_RBSTART - RTL8139_REG_IMR
|
|
out dx, eax
|
|
; Indicate that we have successfully reset the card
|
|
mov eax, [pci_data]
|
|
mov [eth_status], eax
|
|
ret
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; rtl8139_read_eeprom
|
|
; Description
|
|
; reads eeprom type 93c46 and 93c56
|
|
; Parameters
|
|
; al - word to be read (6bit in case of 93c46 and 8bit otherwise)
|
|
; Return value
|
|
; ax - word read in
|
|
; Destroyed register(s)
|
|
; eax, cx, ebx, edx
|
|
;
|
|
;***************************************************************************
|
|
rtl8139_read_eeprom:
|
|
movzx ebx, al
|
|
mov edx, [io_addr]
|
|
add edx, RTL8139_REG_RXCONFIG
|
|
in al, dx
|
|
test al, (1 shl RTL8139_BIT_9356SEL)
|
|
jz .type_93c46
|
|
; and bl, 01111111b ; don't care first bit
|
|
or bx, EE_93C56_READ_CMD ; it contains start bit
|
|
mov cx, EE_93C56_CMD_LENGTH-1 ; cmd_loop counter
|
|
jmp .read_eeprom
|
|
.type_93c46:
|
|
and bl, 00111111b
|
|
or bx, EE_93C46_READ_CMD ; it contains start bit
|
|
mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter
|
|
.read_eeprom:
|
|
add edx, RTL8139_REG_9346CR - RTL8139_REG_RXCONFIG_0
|
|
; mov al, (1 shl RTL8139_BIT_93C46_EEM1)
|
|
; out dx, al
|
|
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \
|
|
or (1 shl RTL8139_BIT_93C46_EECS) ; wake up the eeprom
|
|
out dx, al
|
|
.cmd_loop:
|
|
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS)
|
|
bt bx, cx
|
|
jnc .zero_bit
|
|
or al, (1 shl RTL8139_BIT_93C46_EEDI)
|
|
.zero_bit:
|
|
out dx, al
|
|
; push eax
|
|
; in eax, dx ; eeprom delay
|
|
; pop eax
|
|
or al, (1 shl RTL8139_BIT_93C46_EESK)
|
|
out dx, al
|
|
; in eax, dx ; eeprom delay
|
|
dec cx
|
|
jns .cmd_loop
|
|
; in eax, dx ; eeprom delay
|
|
mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS)
|
|
out dx, al
|
|
mov cl, 0xf
|
|
.read_loop:
|
|
shl ebx, 1
|
|
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \
|
|
or (1 shl RTL8139_BIT_93C46_EECS) \
|
|
or (1 shl RTL8139_BIT_93C46_EESK)
|
|
out dx, al
|
|
; in eax, dx ; eeprom delay
|
|
in al, dx
|
|
and al, (1 shl RTL8139_BIT_93C46_EEDO)
|
|
jz .dont_set
|
|
inc ebx
|
|
.dont_set:
|
|
mov al, (1 shl RTL8139_BIT_93C46_EEM1) \
|
|
or (1 shl RTL8139_BIT_93C46_EECS)
|
|
out dx, al
|
|
; in eax, dx ; eeprom delay
|
|
dec cl
|
|
jns .read_loop
|
|
xor al, al
|
|
out dx, al
|
|
mov ax, bx
|
|
ret
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; rtl8139_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
|
|
; Destroyed registers
|
|
; eax, edx, esi, edi
|
|
; ToDo
|
|
; for waiting of timeout the rtl8139 internal timer
|
|
; should be used
|
|
;
|
|
;***************************************************************************
|
|
rtl8139_transmit:
|
|
cmp ecx, MAX_ETH_FRAME_SIZE
|
|
jg .finish ; packet is too long
|
|
push ecx
|
|
; check descriptor
|
|
mov ecx, [curr_tx_desc]
|
|
mov edx, [io_addr]
|
|
lea edx, [edx+ecx*4+RTL8139_REG_TSD0]
|
|
push edx ebx
|
|
in ax, dx
|
|
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
|
|
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
|
|
jz .send_packet
|
|
test ax, 0x1fff ; or no size given
|
|
jz .send_packet
|
|
; wait for timeout
|
|
mov ebx, RTL8139_TX_TIMEOUT
|
|
mov eax, 0x5 ; delay x/100 secs
|
|
int 0x40
|
|
in ax, dx
|
|
and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
|
|
cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN)
|
|
jz .send_packet
|
|
; chip hung, reset it
|
|
call rtl8139_reset
|
|
; reset the card
|
|
.send_packet:
|
|
; calculate tx_buffer address
|
|
pop ebx
|
|
push esi
|
|
mov eax, MAX_ETH_FRAME_SIZE
|
|
mul dword [curr_tx_desc]
|
|
mov esi, edi
|
|
lea edi, [rtl8139_tx_buff+eax]
|
|
mov eax, edi
|
|
cld
|
|
; copy destination address
|
|
movsd
|
|
movsw
|
|
; copy source address
|
|
mov esi, node_addr
|
|
movsd
|
|
movsw
|
|
; copy packet type
|
|
mov [edi], bx
|
|
add edi, 2
|
|
; copy the packet data
|
|
pop esi edx ecx
|
|
push ecx
|
|
shr ecx, 2
|
|
rep movsd
|
|
pop ecx
|
|
push ecx
|
|
and ecx, 3
|
|
rep movsb
|
|
; set address
|
|
add edx, RTL8139_REG_TSAD0 - RTL8139_REG_TSD0
|
|
out dx, eax
|
|
; set size and early threshold
|
|
pop eax ; pick up the size
|
|
add eax, ETH_HLEN
|
|
cmp eax, ETH_ZLEN
|
|
jnc .no_pad
|
|
mov eax, ETH_ZLEN
|
|
.no_pad:
|
|
or eax, (RTL8139_ERTXTH shl RTL8139_BIT_ERTXTH)
|
|
add edx, RTL8139_REG_TSD0 - RTL8139_REG_TSAD0
|
|
out dx, eax
|
|
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
|
|
inc dword [curr_tx_desc]
|
|
and dword [curr_tx_desc], 3
|
|
.finish:
|
|
ret
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; rtl8139_poll
|
|
;
|
|
; Description
|
|
; Polls the ethernet card for a received packet
|
|
; Received data, if any, ends up in Ether_buffer
|
|
; Destroyed register(s)
|
|
; eax, edx, ecx
|
|
;
|
|
;***************************************************************************
|
|
rtl8139_poll:
|
|
mov word [eth_rx_data_len], 0
|
|
mov edx, [io_addr]
|
|
add edx, RTL8139_REG_COMMAND
|
|
in al, dx
|
|
test al, (1 shl RTL8139_BIT_BUFE)
|
|
jnz .finish
|
|
; new packet received copy it from rx_buffer into Ether_buffer
|
|
mov eax, rtl8139_rx_buff
|
|
add eax, [rtl8139_rx_buff_offset]
|
|
; check if packet is ok
|
|
test byte [eax], (1 shl RTL8139_BIT_ROK)
|
|
jz .reset_rx
|
|
; packet is ok copy it into the Ether_buffer
|
|
movzx ecx, word [eax+2] ; packet length
|
|
sub ecx, 4 ; don't copy CRC
|
|
mov word [eth_rx_data_len], cx
|
|
push ecx
|
|
shr ecx, 2 ; first copy dword-wise
|
|
lea esi, [eax+4] ; don't copy the packet header
|
|
mov edi, Ether_buffer
|
|
cld
|
|
rep movsd ; copy the dwords
|
|
pop ecx
|
|
and ecx, 3
|
|
rep movsb ; copy the rest bytes
|
|
; update rtl8139_rx_buff_offset
|
|
movzx eax, word [eax+2] ; packet length
|
|
add eax, [rtl8139_rx_buff_offset]
|
|
add eax, 4+3 ; packet header is 4 bytes long + dword alignment
|
|
and eax, not 3 ; dword alignment
|
|
cmp eax, RTL8139_RX_BUFFER_SIZE
|
|
jl .no_wrap
|
|
sub eax, RTL8139_RX_BUFFER_SIZE
|
|
.no_wrap:
|
|
mov [rtl8139_rx_buff_offset], eax
|
|
; update CAPR register
|
|
sub eax, 0x10 ; value 0x10 is a constant for CAPR
|
|
add edx, RTL8139_REG_CAPR - RTL8139_REG_COMMAND
|
|
out dx, ax
|
|
.finish:
|
|
; clear active interrupt sources
|
|
mov edx, [io_addr]
|
|
add edx, RTL8139_REG_ISR
|
|
in ax, dx
|
|
out dx, ax
|
|
ret
|
|
.reset_rx:
|
|
in al, dx ; read command register
|
|
push eax
|
|
and al, not (1 shl RTL8139_BIT_RE)
|
|
out dx, al
|
|
pop eax
|
|
out dx, al
|
|
add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND
|
|
mov ax, RTL8139_RX_CONFIG
|
|
out dx, ax
|
|
ret
|