Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 2909 → Rev 2910

/kernel/branches/net/drivers/sis900.asm
25,10 → 25,10
 
format MS COFF
 
NUM_RX_DESC = 4 ;* Number of RX descriptors *
NUM_TX_DESC = 1 ;* Number of TX descriptors *
RX_BUFF_SZ = 1520 ;* Buffer size for each Rx buffer *
TX_BUFF_SZ = 1516 ;* Buffer size for each Tx buffer *
NUM_RX_DESC = 4 ; Number of RX descriptors
NUM_TX_DESC = 4 ; Number of TX descriptors
RX_BUFF_SZ = 1520 ; Buffer size for each Rx buffer
TX_BUFF_SZ = 1516 ; Buffer size for each Tx buffer
MAX_ETH_FRAME_SIZE = 1516
 
API_VERSION = 0x01000100
40,6 → 40,164
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
DSIZE = 0x00000fff
CRC_SIZE = 4
RFADDR_shift = 16
 
; If you are having problems sending/receiving packet try changing the
; Max DMA Burst, Possible settings are as follows:
;
; 0x00000000 = 512 bytes
; 0x00100000 = 4 bytes
; 0x00200000 = 8 bytes
; 0x00300000 = 16 bytes
; 0x00400000 = 32 bytes
; 0x00500000 = 64 bytes
; 0x00600000 = 128 bytes
; 0x00700000 = 256 bytes
 
RX_DMA = 0x00600000
TX_DMA = 0x00600000
 
;-------------------------------------------------------------------------------------------------
; Symbolic offsets to registers.
cr = 0x0 ; Command Register
cfg = 0x4 ; Configuration Register
mear = 0x8 ; EEPROM Access Register
ptscr = 0xc ; PCI Test Control Register
isr = 0x10 ; Interrupt Status Register
imr = 0x14 ; Interrupt Mask Register
ier = 0x18 ; Interrupt Enable Register
epar = 0x18 ; Enhanced PHY Access Register
txdp = 0x20 ; Transmit Descriptor Pointer Register
txcfg = 0x24 ; Transmit Configuration Register
rxdp = 0x30 ; Receive Descriptor Pointer Register
rxcfg = 0x34 ; Receive Configuration Register
flctrl = 0x38 ; Flow Control Register
rxlen = 0x3c ; Receive Packet Length Register
rfcr = 0x48 ; Receive Filter Control Register
rfdr = 0x4C ; Receive Filter Data Register
pmctrl = 0xB0 ; Power Management Control Register
pmer = 0xB4 ; Power Management Wake-up Event Register
 
; Command Register Bits
RELOAD = 0x00000400
ACCESSMODE = 0x00000200
RESET = 0x00000100
SWI = 0x00000080
RxRESET = 0x00000020
TxRESET = 0x00000010
RxDIS = 0x00000008
RxENA = 0x00000004
TxDIS = 0x00000002
TxENA = 0x00000001
 
; Configuration Register Bits
DESCRFMT = 0x00000100 ; 7016 specific
REQALG = 0x00000080
SB = 0x00000040
POW = 0x00000020
EXD = 0x00000010
PESEL = 0x00000008
LPM = 0x00000004
BEM = 0x00000001
RND_CNT = 0x00000400
FAIR_BACKOFF = 0x00000200
EDB_MASTER_EN = 0x00002000
 
; Eeprom Access Reigster Bits
MDC = 0x00000040
MDDIR = 0x00000020
MDIO = 0x00000010 ; 7016 specific
EECS = 0x00000008
EECLK = 0x00000004
EEDO = 0x00000002
EEDI = 0x00000001
 
; TX Configuration Register Bits
ATP = 0x10000000 ; Automatic Transmit Padding
MLB = 0x20000000 ; Mac Loopback Enable
HBI = 0x40000000 ; HeartBeat Ignore (Req for full-dup)
CSI = 0x80000000 ; CarrierSenseIgnore (Req for full-du
 
; RX Configuration Register Bits
AJAB = 0x08000000 ;
ATX = 0x10000000 ; Accept Transmit Packets
ARP = 0x40000000 ; accept runt packets (<64bytes)
AEP = 0x80000000 ; accept error packets
 
; Interrupt Register Bits
WKEVT = 0x10000000
TxPAUSEEND = 0x08000000
TxPAUSE = 0x04000000
TxRCMP = 0x02000000 ; Transmit Reset Complete
RxRCMP = 0x01000000 ; Receive Reset Complete
DPERR = 0x00800000
SSERR = 0x00400000
RMABT = 0x00200000
RTABT = 0x00100000
RxSOVR = 0x00010000
HIBERR = 0x00008000
SWINT = 0x00001000
MIBINT = 0x00000800
TxURN = 0x00000400
TxIDLE = 0x00000200
TxERR = 0x00000100
TxDESC = 0x00000080
TxOK = 0x00000040
RxORN = 0x00000020
RxIDLE = 0x00000010
RxEARLY = 0x00000008
RxERR = 0x00000004
RxDESC = 0x00000002
RxOK = 0x00000001
 
; Interrupt Enable Register Bits
IE = RxOK + TxOK
 
; Revision ID
SIS900B_900_REV = 0x03
SIS630A_900_REV = 0x80
SIS630E_900_REV = 0x81
SIS630S_900_REV = 0x82
SIS630EA1_900_REV = 0x83
SIS630ET_900_REV = 0x84
SIS635A_900_REV = 0x90
SIS900_960_REV = 0x91
 
; Receive Filter Control Register Bits
RFEN = 0x80000000 ; enable
RFAAB = 0x40000000 ; accept all broadcasts
RFAAM = 0x20000000 ; accept all multicasts
RFAAP = 0x10000000 ; accept all packets
 
; Reveive Filter Data Mask
RFDAT = 0x0000FFFF
 
; Eeprom Address
EEPROMSignature = 0x00
EEPROMVendorID = 0x02
EEPROMDeviceID = 0x03
EEPROMMACAddr = 0x08
EEPROMChecksum = 0x0b
 
; The EEPROM commands include the alway-set leading bit.
EEread = 0x0180
EEwrite = 0x0140
EEerase = 0x01C0
EEwriteEnable = 0x0130
EEwriteDisable = 0x0100
EEeraseAll = 0x0120
EEwriteAll = 0x0110
EEaddrMask = 0x013F
EEcmdShift = 16
 
; For SiS962 or SiS963, request the eeprom software access
EEREQ = 0x00000400
EEDONE = 0x00000200
EEGNT = 0x00000100
 
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
48,6 → 206,7
public START
public version
 
 
virtual at ebx
device:
 
63,10 → 222,6
.pci_revision db ?
.table_entries db ?
 
dw ? ; align 4
 
.special_func dd ?
 
.txd rd (4 * NUM_TX_DESC)
.rxd rd (4 * NUM_RX_DESC)
 
170,9 → 325,8
mov [device.pci_dev], cl
; 4j. Fill in the direct call addresses into the struct.
; Note that get_MAC pointer is filled in initialization by probe.
mov [device.reset], init
mov [device.reset], reset
mov [device.transmit], transmit
; mov [device.get_MAC], read_mac
mov [device.set_MAC], write_mac
mov [device.unload], unload
mov [device.name], my_service
246,175 → 400,11
 
ret
 
;********************************************************************
; Comments:
; Known to work with the following SIS900 ethernet cards:
; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x91
; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x90
;
; If your card is not listed, try it and let me know if it
; functions properly and it will be aded to the list. If not
; we may be able to add support for it.
;
; ToDo:
; - Enable MII interface for reading speed
; and duplex settings.
; - Update receive routine to support packet fragmentation.
; - Add additional support for other sis900 based cards
;
;********************************************************************
 
ETH_ALEN = 6 ; Size of Ethernet address
ETH_HLEN = 14 ; Size of ethernet header
ETH_ZLEN = 60 ; Minimum packet length
DSIZE = 0x00000fff
CRC_SIZE = 4
RFADDR_shift = 16
 
; Symbolic offsets to registers.
cr = 0x0 ; Command Register
cfg = 0x4 ; Configuration Register
mear = 0x8 ; EEPROM Access Register
ptscr = 0xc ; PCI Test Control Register
isr = 0x10 ; Interrupt Status Register
imr = 0x14 ; Interrupt Mask Register
ier = 0x18 ; Interrupt Enable Register
epar = 0x18 ; Enhanced PHY Access Register
txdp = 0x20 ; Transmit Descriptor Pointer Register
txcfg = 0x24 ; Transmit Configuration Register
rxdp = 0x30 ; Receive Descriptor Pointer Register
rxcfg = 0x34 ; Receive Configuration Register
flctrl = 0x38 ; Flow Control Register
rxlen = 0x3c ; Receive Packet Length Register
rfcr = 0x48 ; Receive Filter Control Register
rfdr = 0x4C ; Receive Filter Data Register
pmctrl = 0xB0 ; Power Management Control Register
pmer = 0xB4 ; Power Management Wake-up Event Register
 
; Command Register Bits
RELOAD = 0x00000400
ACCESSMODE = 0x00000200
RESET = 0x00000100
SWI = 0x00000080
RxRESET = 0x00000020
TxRESET = 0x00000010
RxDIS = 0x00000008
RxENA = 0x00000004
TxDIS = 0x00000002
TxENA = 0x00000001
 
; Configuration Register Bits
DESCRFMT = 0x00000100 ; 7016 specific
REQALG = 0x00000080
SB = 0x00000040
POW = 0x00000020
EXD = 0x00000010
PESEL = 0x00000008
LPM = 0x00000004
BEM = 0x00000001
RND_CNT = 0x00000400
FAIR_BACKOFF = 0x00000200
EDB_MASTER_EN = 0x00002000
 
; Eeprom Access Reigster Bits
MDC = 0x00000040
MDDIR = 0x00000020
MDIO = 0x00000010 ; 7016 specific
EECS = 0x00000008
EECLK = 0x00000004
EEDO = 0x00000002
EEDI = 0x00000001
 
; TX Configuration Register Bits
ATP = 0x10000000 ;Automatic Transmit Padding
MLB = 0x20000000 ;Mac Loopback Enable
HBI = 0x40000000 ;HeartBeat Ignore (Req for full-dup)
CSI = 0x80000000 ;CarrierSenseIgnore (Req for full-du
 
; RX Configuration Register Bits
AJAB = 0x08000000 ;
ATX = 0x10000000 ;Accept Transmit Packets
ARP = 0x40000000 ;accept runt packets (<64bytes)
AEP = 0x80000000 ;accept error packets
 
; Interrupt Reigster Bits
WKEVT = 0x10000000
TxPAUSEEND = 0x08000000
TxPAUSE = 0x04000000
TxRCMP = 0x02000000
RxRCMP = 0x01000000
DPERR = 0x00800000
SSERR = 0x00400000
RMABT = 0x00200000
RTABT = 0x00100000
RxSOVR = 0x00010000
HIBERR = 0x00008000
SWINT = 0x00001000
MIBINT = 0x00000800
TxURN = 0x00000400
TxIDLE = 0x00000200
TxERR = 0x00000100
TxDESC = 0x00000080
TxOK = 0x00000040
RxORN = 0x00000020
RxIDLE = 0x00000010
RxEARLY = 0x00000008
RxERR = 0x00000004
RxDESC = 0x00000002
RxOK = 0x00000001
 
; Interrupt Enable Register Bits
IE = RxOK + TxOK
 
; Revision ID
SIS900B_900_REV = 0x03
SIS630A_900_REV = 0x80
SIS630E_900_REV = 0x81
SIS630S_900_REV = 0x82
SIS630EA1_900_REV = 0x83
SIS630ET_900_REV = 0x84
SIS635A_900_REV = 0x90
SIS900_960_REV = 0x91
 
; Receive Filter Control Register Bits
RFEN = 0x80000000
RFAAB = 0x40000000
RFAAM = 0x20000000
RFAAP = 0x10000000
RFPromiscuous = 0x70000000
 
; Reveive Filter Data Mask
RFDAT = 0x0000FFFF
 
; Eeprom Address
EEPROMSignature = 0x00
EEPROMVendorID = 0x02
EEPROMDeviceID = 0x03
EEPROMMACAddr = 0x08
EEPROMChecksum = 0x0b
 
;The EEPROM commands include the alway-set leading bit.
EEread = 0x0180
EEwrite = 0x0140
EEerase = 0x01C0
EEwriteEnable = 0x0130
EEwriteDisable = 0x0100
EEeraseAll = 0x0120
EEwriteAll = 0x0110
EEaddrMask = 0x013F
EEcmdShift = 16
 
;For SiS962 or SiS963, request the eeprom software access
EEREQ = 0x00000400
EEDONE = 0x00000200
EEGNT = 0x00000100
 
 
;***************************************************************************
;
; probe
;
; Searches for an ethernet card, enables it and clears the rx buffer
; checks the card and enables it
;
; TODO: probe mii transceivers
;
423,11 → 413,13
probe:
DEBUGF 1, "Probe\n"
 
; wake up device CHECKME
movzx eax, [device.pci_bus]
movzx edx, [device.pci_dev]
stdcall PciWrite8, eax, edx, 0x40, 0 ; Wake Up Chip
stdcall PciWrite8, eax, edx, 0x40, 0
 
make_bus_master [device.pci_bus], [device.pci_dev]
adjust_latency [device.pci_bus], [device.pci_dev], 64
 
; Get Card Revision
movzx eax, [device.pci_bus]
437,38 → 429,21
 
; Look up through the specific_table
mov esi, specific_table
.loop:
.tableloop:
cmp dword [esi], 0 ; Check if we reached end of the list
je .error
je .notsupported
cmp al, [esi] ; Check if revision is OK
je .ok
add esi, 12 ; Advance to next entry
jmp .loop
jmp .tableloop
 
.error:
DEBUGF 1, "Device not supported!\n"
or eax, -1
ret
 
; Find Get Mac Function
.ok:
mov eax, [esi + 4] ; Get pointer to "get MAC" function
mov [device.get_MAC], eax
mov eax, [esi + 8] ; Get pointer to special initialization fn
mov [device.special_func], eax
 
; Get MAC
call [device.get_MAC]
 
; Call special initialization fn if requested
 
cmp [device.special_func], 0
je @f
call [device.special_func]
@@:
 
; Set table entries
 
mov [device.table_entries], 16
cmp [device.pci_revision], SIS635A_900_REV
jae @f
479,56 → 454,16
 
; TODO: Probe for mii transceiver
 
jmp reset
 
;***************************************************************************
;
; init
;
; resets the ethernet controller chip and various
; data structures required for sending and receiving packets.
;
;***************************************************************************
align 4
init:
DEBUGF 1, "Init\n"
.notsupported:
DEBUGF 1, "Device not supported\n"
or eax, -1
 
call reset
jnz .ret
call init_rxfilter
call init_txd
call init_rxd
call set_rx_mode
call set_tx_mode
;call check_mode
 
; enable interrupts on packet receive
 
xor eax, eax
inc eax ; eax = 1 = RxOK
set_io 0
set_io imr
out dx, eax
 
; globally enable interrupts
 
set_io ier
out dx, eax ; eax is still 1
xor eax, eax
 
mov [device.mtu], 1514
 
.ret:
ret
 
;***************************************************************************
;
; reset
;
; disables interrupts and soft resets the controller chip
;
;***************************************************************************
align 4
reset:
 
DEBUGF 1, "reset\n"
 
movzx eax, [device.irq_line]
563,10 → 498,11
mov ecx, 1000
.loop:
dec ecx
jz .error
in eax, dx ; move interrup status to eax
test eax, 0x03000000 ; CHECKME
jz .fail
in eax, dx ; read interrupt status
test eax, TxRCMP + RxRCMP
jz .loop
DEBUGF 1, "status=%x\n", eax
 
;------------------------------------------------------
; Set Configuration Register depending on Card Revision
576,58 → 512,30
cmp [device.pci_revision], SIS635A_900_REV
je .match
cmp [device.pci_revision], SIS900B_900_REV ; Check card revision
je .match
out dx, eax ; no revision match
jmp .done
 
jne .done
.match: ; Revision match
or eax, RND_CNT ; Configuration Register Bit
.done:
out dx, eax
 
.done:
xor eax, eax
ret
DEBUGF 1, "Initialising RX Filter\n"
 
.error:
DEBUGF 1, "Reset failed!\n"
or eax, -1
ret
 
 
;***************************************************************************
;
; sis_init_rxfilter
;
; sets receive filter address to our MAC address
;
;***************************************************************************
align 4
init_rxfilter:
DEBUGF 1, "Init RxFilter\n"
 
;------------------------------------
; Get Receive Filter Control Register
 
set_io 0
set_io rfcr
in eax, dx
push eax
 
;-----------------------------------------------
; disable packet filtering before setting filter
 
and eax, not RFEN
out dx, eax
 
;--------------------------------------
; load MAC addr to filter data register
 
xor ecx, ecx
RXINT_Mac_Write: ; high word of eax tells card which mac byte to write
.macloop:
mov eax, ecx
set_io 0
set_io rfcr
shl eax, 16 ;
shl eax, 16 ; high word of eax tells card which mac byte to write
out dx, eax ;
set_io rfdr
mov ax, word [device.mac+ecx*2] ; Get Mac ID word
634,71 → 542,52
out dx, ax ; Send Mac ID
inc cl ; send next word
cmp cl, 3 ; more to send?
jne RXINT_Mac_Write
jne .macloop
 
;------------------------
; enable packet filtering
 
pop eax ;old register value
set_io rfcr
or eax, RFEN ;enable filtering
out dx, eax ;set register
 
ret
DEBUGF 1, "Initialising TX Descriptors\n"
 
;***************************************************************************
;
; init_txd
;
; initializes the Tx descriptor
;
;***************************************************************************
align 4
init_txd:
DEBUGF 1, "Init TxD\n"
mov ecx, NUM_TX_DESC
lea esi, [device.txd]
.txdescloop:
lea eax, [esi + 16] ; next ptr
GetRealAddr
mov dword [esi], eax ; link to next desc
mov dword [esi + 4], 0 ; status field
mov dword [esi + 8], 0 ; ptr to buffer
add esi, 16
dec ecx
jnz .txdescloop
 
;-------------------------
; initialize TX descriptor
 
mov dword [device.txd], 0 ; put link to next descriptor in link field
mov dword [device.txd + 4], 0 ; clear status field
mov dword [device.txd + 8], 0 ; ptr to buffer
 
;----------------------------------
; load Transmit Descriptor Register
 
set_io 0
set_io txdp ; TX Descriptor Pointer
lea eax, [device.txd]
GetRealAddr
out dx, eax ; move the pointer
mov dword [esi - 16], eax ; correct last descriptor link ptr
 
ret
set_io txdp ; TX Descriptor Pointer
; lea eax, [device.txd]
; GetRealAddr
out dx, eax
 
;***************************************************************************
;
; init_rxd
;
; initializes the Rx descriptor ring
;
;***************************************************************************
align 4
init_rxd:
DEBUGF 1, "Init RxD\n"
mov [device.cur_tx], 0 ; Set current tx descriptor to 0
 
; init RX descriptors
DEBUGF 1, "Initialising RX Descriptors\n"
 
mov ecx, NUM_RX_DESC
lea esi, [device.rxd]
 
.loop:
.rxdescloop:
lea eax, [esi + 16] ; next ptr
GetRealAddr
mov dword [esi], eax
mov dword [esi + 4], RX_BUFF_SZ ; size
 
push ecx
push ecx esi
stdcall KernelAlloc, RX_BUFF_SZ
pop ecx
pop esi ecx
test eax, eax
jz .fail
mov dword [esi + 12], eax ; address
706,95 → 595,24
mov dword [esi + 8], eax ; real address
add esi, 16
dec ecx
jnz .loop
jnz .rxdescloop
 
lea eax, [device.rxd]
GetRealAddr
mov dword [esi - 16], eax ; correct last descriptor link ptr
 
; And output ptr to first desc, to device
 
set_io 0
set_io rxdp
; lea eax, [device.rxd]
; GetRealAddr
out dx, eax
 
mov [device.cur_rx], 0 ; Set curent rx discriptor to 0
mov [device.cur_rx], 0 ; Set current rx descriptor to 0
 
.fail: ;;; TODO: abort instead!
ret
DEBUGF 1, "setting RX mode\n"
 
 
;***************************************************************************
;
; set_tx_mode
;
; sets the transmit mode to allow for full duplex
;
; If you are having problems transmitting packet try changing the
; Max DMA Burst, Possible settings are as follows:
;
; 0x00000000 = 512 bytes
; 0x00100000 = 4 bytes
; 0x00200000 = 8 bytes
; 0x00300000 = 16 bytes
; 0x00400000 = 32 bytes
; 0x00500000 = 64 bytes
; 0x00600000 = 128 bytes
; 0x00700000 = 256 bytes
;
;***************************************************************************
align 4
set_tx_mode:
DEBUGF 1, "set TX mode\n"
 
set_io 0
set_io cr
in eax, dx ; Get current Command Register
or eax, TxENA ; Enable Receive
out dx, eax
 
set_io txcfg ; Transmit config Register offset
mov eax, ATP + HBI + CSI +0x00600120
; allow automatic padding
; allow heartbeat ignore
; allow carrier sense ignore
; Max DMA Burst (128 bytes)
; TX Fill Threshold
; TX Drain Threshold
out dx, eax
 
ret
 
;***************************************************************************
;
; set_rx_mode
;
; sets the receive mode to accept all broadcast packets and packets
; with our MAC address, and reject all multicast packets. Also allows
; full-duplex
;
; If you are having problems receiving packet try changing the
; Max DMA Burst, Possible settings are as follows:
;
; 0x00000000 = 512 bytes
; 0x00100000 = 4 bytes
; 0x00200000 = 8 bytes
; 0x00300000 = 16 bytes
; 0x00400000 = 32 bytes
; 0x00500000 = 64 bytes
; 0x00600000 = 128 bytes
; 0x00700000 = 256 bytes
;
;***************************************************************************
align 4
set_rx_mode:
DEBUGF 1, "set RX mode\n"
 
;----------------------------------------------
; update Multicast Hash Table in Receive Filter
 
xor cl, cl
.loop:
.rxfilterloop:
set_io 0
set_io rfcr ; Receive Filter Control Reg offset
mov eax, 4 ; determine table entry
808,39 → 626,51
 
inc cl ; next entry
cmp cl, [device.table_entries]
jl .loop
jb .rxfilterloop
 
;------------------------------------
; Set Receive Filter Control Register
 
set_io rfcr ; Receive Filter Control Register offset
mov eax, RFAAB + RFAAM + RFAAP + RFEN
; accecpt all broadcast packets
; accept all multicast packets
; Accept all packets
; enable receiver filter
out dx, eax
;----------------
; Enable Receiver
 
set_io rxcfg ; Receive Config Register offset
mov eax, ATX + RX_DMA + 2 ; 0x2 : RX Drain Threshold = 8*8=64 bytes
out dx, eax
 
DEBUGF 1, "setting TX mode\n"
 
set_io txcfg ; Transmit config Register offset
mov eax, ATP + HBI + CSI + TX_DMA + 0x120
; TX Fill threshold = 0x100
; TX Drain Threshold = 0x20
out dx, eax
 
DEBUGF 1, "Enabling interrupts\n"
 
set_io imr
mov eax, IE ; Interrupt enable mask
out dx, eax
 
set_io cr
in eax, dx ; Get current Command Register
in eax, dx
or eax, RxENA ; Enable Receive
out dx, eax
 
;-------------------
; Configure Receiver
 
set_io rxcfg ; Receive Config Register offset
mov eax, ATX + 0x00600002
; Accept Transmit Packets
; (Req for full-duplex and PMD Loopback)
; Max DMA Burst
; RX Drain Threshold, 8X8 bytes or 64bytes
set_io ier ; Interrupt enable
mov eax, 1
out dx, eax
 
mov [device.mtu], 1514
xor eax, eax
 
ret
 
.fail:
DEBUGF 1, "Resetting device failed\n"
or eax, -1
 
ret
 
 
;***************************************************************************
;
; SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
981,13 → 811,12
;***************************************************************************
align 4
Get_Mac_SIS635_900_REV:
 
DEBUGF 1, "SIS635 - get mac: "
 
set_io 0
set_io rfcr
in eax, dx
mov edi, eax ; EDI=rfcrSave
mov esi, eax
 
set_io cr
or eax, RELOAD
1000,14 → 829,14
; Disable packet filtering before setting filter
 
set_io rfcr
mov eax, edi
and edi, not RFEN
mov eax, esi
and eax, not RFEN
out dx, eax
 
;---------------------------------
; Load MAC to filter data register
 
mov ecx, 3
xor ecx, ecx
lea edi, [device.mac]
.loop:
set_io 0
1017,17 → 846,19
out dx, eax
 
set_io rfdr
in eax, dx
in ax, dx
stosw
loop .loop
inc ecx
cmp ecx, 3
jb .loop
 
;------------------------
; Enable packet filtering
 
; set_io rfcr
; mov eax, edi
; or eax, RFEN
; out dx, eax
set_io rfcr
mov eax, esi
or eax, RFEN
out dx, eax
 
DEBUGF 2,"%x-%x-%x-%x-%x-%x\n",[device.mac]:2,[device.mac+1]:2,[device.mac+2]:2,[device.mac+3]:2,[device.mac+4]:2,[device.mac+5]:2
 
1129,8 → 960,79
add esp, 6
ret
 
 
 
 
;***************************************************************************
; Function
; transmit
; Description
; Transmits a packet of data via the ethernet card
; buffer pointer in [esp+4]
; size of buffer in [esp+8]
; pointer to device structure in ebx
;
;***************************************************************************
align 4
transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2
 
cmp dword [esp + 8], MAX_ETH_FRAME_SIZE
ja .error
cmp dword [esp + 8], 60
jb .error
 
movzx ecx, [device.cur_tx]
shl ecx, 4 ; *16
lea ecx, [device.txd + ecx]
 
;; TODO: check if desc is empty (for example: check for eax, 0x6200000 at [ecx+4]
;;; or: count number of available descriptors
 
mov eax, [esp + 4]
mov dword [ecx + 12], eax
GetRealAddr
mov dword [ecx + 8], eax ; buffer address
 
mov eax, [esp + 8]
and eax, DSIZE
or eax, 0x80000000 ; card owns descriptor
mov dword [ecx + 4], eax ; status field
 
set_io 0
set_io cr
in eax, dx
or eax, TxENA ; Enable the transmit state machine
out dx, eax
 
inc [device.cur_tx]
and [device.cur_tx], NUM_TX_DESC-1
 
; update stats
mov ecx, [esp + 8]
inc [device.packets_tx]
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
 
.finish:
DEBUGF 1,"Packet sent!\n"
xor eax, eax
ret 8
 
.error:
DEBUGF 1,"ERROR!\n"
stdcall KernelFree, [esp+4]
or eax, -1
ret 8
 
 
;***************************************************************************
;
; int_handler
;
; handles received IRQs, which signal received packets
1141,7 → 1043,6
;***************************************************************************
align 4
int_handler:
DEBUGF 1, "Int!\n"
 
; find pointer of device which made IRQ occur
mov esi, device_list
1160,6 → 1061,8
ret
.got_it:
 
DEBUGF 1,"IRQ! status=%x\n", ax
 
test ax, RxOK
jz .no_rx
 
1167,7 → 1070,7
 
;-----------
; Get Status
movzx eax, [device.cur_rx] ; find current discriptor
movzx eax, [device.cur_rx] ; find current descriptor
shl eax, 4 ; * 16
mov ecx, dword[device.rxd+eax+4] ; get receive status
 
1187,7 → 1090,7
; Check size of packet
and ecx, DSIZE ; get packet size minus CRC
sub ecx, CRC_SIZE ; make sure packet contains data
jle .error_size
jbe .error_size
 
; update statistics
inc dword [device.packets_rx]
1197,7 → 1100,7
push ebx
push .return
push ecx ; packet size
push [device.rxd+eax+12] ; packet ptr
pushd [device.rxd + eax + 12] ; packet ptr
DEBUGF 1, "Packet received OK\n"
jmp EthReceiver
.return:
1204,12 → 1107,12
pop ebx
 
; Reset status, allow ethernet card access to descriptor
movzx ecx, [device.cur_rx]
shl ecx, 4 ; *16
mov ecx, [device.rxd+ecx]
stdcall KernelAlloc, RX_BUFF_SZ
test eax, eax
jz .fail
movzx ecx, [device.cur_rx]
shl ecx, 4 ; *16
lea ecx, [device.rxd + ecx]
mov dword [ecx+12], eax
GetRealAddr
mov dword [ecx+8], eax
1218,30 → 1121,21
inc [device.cur_rx] ; get next descriptor
and [device.cur_rx], NUM_RX_DESC-1 ; only 4 descriptors 0-3
 
; Enable Receiver
set_io 0
set_io cr ; Command Register offset
in eax, dx ; Get current Command Register
or eax, RxENA ; Enable Receiver
out dx, eax
; Enable Receiver CHECKME
; set_io 0
; set_io cr ; Command Register offset
; in eax, dx ; Get current Command Register
; or eax, RxENA ; Enable Receiver
; out dx, eax
 
pop ax
jmp .no_rx
 
.error_status:
.no_rx:
test ax, TxOK
jz .no_tx
 
DEBUGF 1, "Packet error: %x\n", ecx
jmp .fail
DEBUGF 1, "TX ok!\n"
 
.error_size:
 
DEBUGF 1, "Packet too large/small\n"
jmp .fail
 
.no_rx:
;; test ax, TxOk
;; jz .no_tx
 
;;; TODO: free all unused buffers
;; stdcall KernelFree, eax
 
1249,7 → 1143,14
 
ret
 
.error_status:
DEBUGF 1, "Packet error: %x\n", ecx
jmp .fail
 
.error_size:
DEBUGF 1, "Packet too large/small\n"
jmp .fail
 
.fail:
DEBUGF 1, "FAILED\n"
jmp $
1256,59 → 1157,7
ret
 
 
;***************************************************************************
; Function
; transmit
; Description
; Transmits a packet of data via the ethernet card
; buffer pointer in [esp+4]
; size of buffer in [esp+8]
; pointer to device structure in ebx
;
; only one transmit descriptor is used
;
;***************************************************************************
align 4
transmit:
 
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
ja .error
 
cmp dword [esp+8], 60
jb .error
 
movzx ecx, [device.cur_tx]
shl ecx, 4
mov ecx, [device.txd+ecx]
 
;; TODO: check if desc is empty (for example: check for eax, 0x6200000 at [ecx+4]
;;; or: count number of available descriptors
 
mov eax, [esp+4]
mov dword [ecx + 12], eax
GetRealAddr
mov dword [ecx + 8], eax
 
mov eax, [esp+8]
and eax, DSIZE
or eax, 0x80000000 ; card owns descriptor
mov dword [ecx + 4], eax
 
; update stats
inc [device.packets_tx]
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
 
.finish:
xor eax, eax
ret 8
 
.error:
stdcall KernelFree, [esp+4]
or eax, -1
ret 8
 
 
; End of code
 
align 4 ; Place all initialised data here