Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1518 → Rev 1519

/kernel/branches/net/drivers/sis900.asm
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Ethernet driver for KolibriOS ;;
23,12 → 23,13
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; $Revision$
 
format MS COFF
 
API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
 
MAX_DEVICES equ 16
 
DEBUG equ 1
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1
47,45 → 48,48
TX_BUFF_SZ equ 1516 ;* Buffer size for each Tx buffer *
MAX_ETH_FRAME_SIZE equ 1516
 
TOTAL_BUFFERS_SIZE equ NUM_RX_DESC*RX_BUFF_SZ + NUM_TX_DESC*TX_BUFF_SZ
 
virtual at 0
virtual at ebx
device:
 
ETH_DEVICE
 
; device specific
.io_addr dd ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
.cur_rx db ?
.cur_tx db ?
.last_tx db ?
.pci_revision db ?
.table_entries: db ?
align 4
.special_func: dd 0
.txd: times (3 * NUM_TX_DESC) dd 0
.rxd: times (3 * NUM_RX_DESC) dd 0
.size:
end virtual
.table_entries db ?
 
; First page is designated to ETH_DEVICE, buffers start from second
ALLOCATION_SIZE = ((device.size+0FFFh) and not 0FFFh) + TOTAL_BUFFERS_SIZE
; Note that buffers must be contiguous in the physical memory;
; because KernelAlloc allocates contiguous physical pages only in 8-pages blocks,
; align ALLOCATION_SIZE up to 8*(page size) = 8000h
ALLOCATION_SIZE = (ALLOCATION_SIZE + 7FFFh) and not 7FFFh
dw ? ; align 4
 
MAX_DEVICES = 16 ; maximum number of devices which this driver can handle
.special_func dd ?
 
.txd rd (4 * NUM_TX_DESC)
.rxd rd (4 * NUM_RX_DESC)
 
PCI_HEADER_TYPE equ 0x0e ;8 bit
PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit
PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits
PCI_BASE_ADDRESS_SPACE_IO equ 0x01
PCI_VENDOR_ID equ 0x00 ;16 bit
PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC
.size = $ - device
 
end virtual
 
macro ee_delay {
push eax
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
in eax, dx
pop eax
}
 
 
section '.flat' code readable align 16
 
; Driver entry point - register our service when the driver is loading.
106,15 → 110,15
; pointer to IOCTL structure.
mov edx, [esp+4] ; edx -> IOCTL
; 2. Get request code and select a handler for the code.
mov eax, [edx+IOCTL.io_code]
mov eax, [IOCTL.io_code]
test eax, eax ; check for SRV_GETVERSION
jnz @f
; 3. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION.
; 3a. Output size must be at least 4 bytes.
cmp [edx+IOCTL.out_size], 4
cmp [IOCTL.out_size], 4
jl .fail
; 3b. Write result to the output buffer.
mov eax, [edx+IOCTL.output]
mov eax, [IOCTL.output]
mov [eax], dword API_VERSION
; 3c. Return success.
xor eax, eax
125,10 → 129,10
; 4. This is SRV_HOOK request, input defines the device to hook, no output.
; 4a. The driver works only with PCI devices,
; so input must be at least 3 bytes long.
cmp [edx + IOCTL.inp_size], 3
cmp [IOCTL.inp_size], 3
jl .fail
; 4b. First byte of input is bus type, 1 stands for PCI.
mov eax, [edx + IOCTL.input]
mov eax, [IOCTL.input]
cmp byte [eax], 1
jne .fail
; 4c. Second and third bytes of the input define the device: bus and dev.
136,77 → 140,65
mov bx, [eax+1]
; 4d. Check if the device was already hooked,
; scan through the list of known devices.
mov esi, DEV_LIST
mov ecx, [NUM_DEV]
; check if the device is already listed
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
lodsd
cmp bx, word [eax + device.pci_bus]
je .find_devicenum
mov ebx, [esi]
cmp ax , word [device.pci_bus] ; compare with pci and device num in device list (notice the usage of word instead of byte)
je .find_devicenum ; Device is already loaded, let's find it's device number
add esi, 4
loop .nextdevice
; 4e. This device doesn't have its own eth_device structure yet, let's create one
.firstdevice:
; 4f. Check that we have place for new device.
cmp [NUM_DEV], MAX_DEVICES
cmp [devices], MAX_DEVICES
jge .fail
; 4g. Allocate memory for device descriptor and receive+transmit buffers.
stdcall KernelAlloc, ALLOCATION_SIZE
stdcall KernelAlloc, device.size
test eax, eax
jz .fail
; 4h. Zero the structure.
push eax
mov edi, eax
mov ecx, (device.size + 3) shr 2
xor eax, eax
rep stosd
pop eax
; 4i. Save PCI coordinates, loaded to bx at 4c.
mov word [eax+device.pci_bus], bx
mov ebx, eax ; ebx is always used as a pointer to the structure (in driver, but also in kernel code)
; 4i. Save PCI coordinates
mov eax, [IOCTL.input]
mov cl , [eax+1]
mov [device.pci_bus], cl
mov cl , [eax+2]
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 SIS900_probe.
mov dword [ebx+device.reset], sis900_init
mov dword [ebx+device.transmit], transmit
; mov dword [ebx+device.get_MAC], read_mac
mov dword [ebx+device.set_MAC], write_mac
mov dword [ebx+device.unload], unload
mov dword [ebx+device.name], my_service
; Note that get_MAC pointer is filled in initialization by probe.
mov [device.reset], init
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
 
; 4k. Now, it's time to find the base io addres of the PCI device
; TODO: implement check if bus and dev exist on this machine
 
mov edx, PCI_BASE_ADDRESS_0
.reg_check:
push edx
stdcall PciRead16, dword [ebx+device.pci_bus], dword [ebx+device.pci_dev], edx
pop edx
test al, PCI_BASE_ADDRESS_SPACE_IO
jz .inc_reg
and eax, PCI_BASE_ADDRESS_IO_MASK
jnz .got_io
; Now, it's time to find the base io addres of the PCI device
find_io [device.pci_bus], [device.pci_dev], [device.io_addr]
 
.inc_reg:
add edx, 4
cmp edx, PCI_BASE_ADDRESS_5
jbe .reg_check
jmp .fail
; We've found the io address, find IRQ now
find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
 
.got_io:
mov [ebx+device.io_addr], eax
 
; 4l. We've found the io address, find IRQ now
stdcall PciRead8, dword [ebx+device.pci_bus], dword [ebx+device.pci_dev], 0x3c
mov byte [ebx+device.irq_line], al
 
; 4m. Add new device to the list (required for int_handler).
mov eax, [NUM_DEV]
mov [DEV_LIST+4*eax], ebx
inc [NUM_DEV]
mov eax, [devices]
mov [device_list+4*eax], ebx
inc [devices]
 
; 4m. Ok, the eth_device structure is ready, let's probe the device
 
call SIS900_probe
call probe
test eax, eax
jnz .destroy
; 4n. If device was successfully initialized, register it for the kernel.
231,7 → 223,7
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
dec [NUM_DEV]
dec [devices]
; todo: reset device into virgin state
 
.err:
263,14 → 255,6
ret
 
;********************************************************************
; Interface
; SIS900_reset
; SIS900_probe
; SIS900_poll
; SIS900_transmit
;
;********************************************************************
;********************************************************************
; Comments:
; Known to work with the following SIS900 ethernet cards:
; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x91
283,112 → 267,114
; ToDo:
; - Enable MII interface for reading speed
; and duplex settings.
;
; - Update Poll routine to support packet fragmentation.
;
; - Update receive routine to support packet fragmentation.
; - Add additional support for other sis900 based cards
;
;********************************************************************
 
; comment the next line out if you don't want debug info printed
; on the debug board. This option adds a lot of bytes to the driver
; so it's worth to comment it out.
; SIS900_DEBUG equ 1
ETH_ALEN equ 6 ; Size of Ethernet address
ETH_HLEN equ 14 ; Size of ethernet header
ETH_ZLEN equ 60 ; Minimum packet length
DSIZE equ 0x00000fff
CRC_SIZE equ 4
RFADDR_shift equ 16
 
SIS900_ETH_ALEN equ 6 ;* Size of Ethernet address *
SIS900_ETH_HLEN equ 14 ;* Size of ethernet header *
SIS900_ETH_ZLEN equ 60 ;* Minimum packet length *
SIS900_DSIZE equ 0x00000fff
SIS900_CRC_SIZE equ 4
SIS900_RFADDR_shift equ 16
;SIS900 Symbolic offsets to registers.
SIS900_cr equ 0x0 ; Command Register
SIS900_cfg equ 0x4 ; Configuration Register
SIS900_mear equ 0x8 ; EEPROM Access Register
SIS900_ptscr equ 0xc ; PCI Test Control Register
SIS900_isr equ 0x10 ; Interrupt Status Register
SIS900_imr equ 0x14 ; Interrupt Mask Register
SIS900_ier equ 0x18 ; Interrupt Enable Register
SIS900_epar equ 0x18 ; Enhanced PHY Access Register
SIS900_txdp equ 0x20 ; Transmit Descriptor Pointer Register
SIS900_txcfg equ 0x24 ; Transmit Configuration Register
SIS900_rxdp equ 0x30 ; Receive Descriptor Pointer Register
SIS900_rxcfg equ 0x34 ; Receive Configuration Register
SIS900_flctrl equ 0x38 ; Flow Control Register
SIS900_rxlen equ 0x3c ; Receive Packet Length Register
SIS900_rfcr equ 0x48 ; Receive Filter Control Register
SIS900_rfdr equ 0x4C ; Receive Filter Data Register
SIS900_pmctrl equ 0xB0 ; Power Management Control Register
SIS900_pmer equ 0xB4 ; Power Management Wake-up Event Register
;SIS900 Command Register Bits
SIS900_RELOAD equ 0x00000400
SIS900_ACCESSMODE equ 0x00000200
SIS900_RESET equ 0x00000100
SIS900_SWI equ 0x00000080
SIS900_RxRESET equ 0x00000020
SIS900_TxRESET equ 0x00000010
SIS900_RxDIS equ 0x00000008
SIS900_RxENA equ 0x00000004
SIS900_TxDIS equ 0x00000002
SIS900_TxENA equ 0x00000001
;SIS900 Configuration Register Bits
SIS900_DESCRFMT equ 0x00000100 ; 7016 specific
SIS900_REQALG equ 0x00000080
SIS900_SB equ 0x00000040
SIS900_POW equ 0x00000020
SIS900_EXD equ 0x00000010
SIS900_PESEL equ 0x00000008
SIS900_LPM equ 0x00000004
SIS900_BEM equ 0x00000001
SIS900_RND_CNT equ 0x00000400
SIS900_FAIR_BACKOFF equ 0x00000200
SIS900_EDB_MASTER_EN equ 0x00002000
;SIS900 Eeprom Access Reigster Bits
SIS900_MDC equ 0x00000040
SIS900_MDDIR equ 0x00000020
SIS900_MDIO equ 0x00000010 ; 7016 specific
SIS900_EECS equ 0x00000008
SIS900_EECLK equ 0x00000004
SIS900_EEDO equ 0x00000002
SIS900_EEDI equ 0x00000001
;SIS900 TX Configuration Register Bits
SIS900_ATP equ 0x10000000 ;Automatic Transmit Padding
SIS900_MLB equ 0x20000000 ;Mac Loopback Enable
SIS900_HBI equ 0x40000000 ;HeartBeat Ignore (Req for full-dup)
SIS900_CSI equ 0x80000000 ;CarrierSenseIgnore (Req for full-du
;SIS900 RX Configuration Register Bits
SIS900_AJAB equ 0x08000000 ;
SIS900_ATX equ 0x10000000 ;Accept Transmit Packets
SIS900_ARP equ 0x40000000 ;accept runt packets (<64bytes)
SIS900_AEP equ 0x80000000 ;accept error packets
;SIS900 Interrupt Reigster Bits
SIS900_WKEVT equ 0x10000000
SIS900_TxPAUSEEND equ 0x08000000
SIS900_TxPAUSE equ 0x04000000
SIS900_TxRCMP equ 0x02000000
SIS900_RxRCMP equ 0x01000000
SIS900_DPERR equ 0x00800000
SIS900_SSERR equ 0x00400000
SIS900_RMABT equ 0x00200000
SIS900_RTABT equ 0x00100000
SIS900_RxSOVR equ 0x00010000
SIS900_HIBERR equ 0x00008000
SIS900_SWINT equ 0x00001000
SIS900_MIBINT equ 0x00000800
SIS900_TxURN equ 0x00000400
SIS900_TxIDLE equ 0x00000200
SIS900_TxERR equ 0x00000100
SIS900_TxDESC equ 0x00000080
SIS900_TxOK equ 0x00000040
SIS900_RxORN equ 0x00000020
SIS900_RxIDLE equ 0x00000010
SIS900_RxEARLY equ 0x00000008
SIS900_RxERR equ 0x00000004
SIS900_RxDESC equ 0x00000002
SIS900_RxOK equ 0x00000001
;SIS900 Interrupt Enable Reigster Bits
SIS900_IE equ 0x00000001
;SIS900 Revision ID
; Symbolic offsets to registers.
cr equ 0x0 ; Command Register
cfg equ 0x4 ; Configuration Register
mear equ 0x8 ; EEPROM Access Register
ptscr equ 0xc ; PCI Test Control Register
isr equ 0x10 ; Interrupt Status Register
imr equ 0x14 ; Interrupt Mask Register
ier equ 0x18 ; Interrupt Enable Register
epar equ 0x18 ; Enhanced PHY Access Register
txdp equ 0x20 ; Transmit Descriptor Pointer Register
txcfg equ 0x24 ; Transmit Configuration Register
rxdp equ 0x30 ; Receive Descriptor Pointer Register
rxcfg equ 0x34 ; Receive Configuration Register
flctrl equ 0x38 ; Flow Control Register
rxlen equ 0x3c ; Receive Packet Length Register
rfcr equ 0x48 ; Receive Filter Control Register
rfdr equ 0x4C ; Receive Filter Data Register
pmctrl equ 0xB0 ; Power Management Control Register
pmer equ 0xB4 ; Power Management Wake-up Event Register
 
; Command Register Bits
RELOAD equ 0x00000400
ACCESSMODE equ 0x00000200
RESET equ 0x00000100
SWI equ 0x00000080
RxRESET equ 0x00000020
TxRESET equ 0x00000010
RxDIS equ 0x00000008
RxENA equ 0x00000004
TxDIS equ 0x00000002
TxENA equ 0x00000001
 
; Configuration Register Bits
DESCRFMT equ 0x00000100 ; 7016 specific
REQALG equ 0x00000080
SB equ 0x00000040
POW equ 0x00000020
EXD equ 0x00000010
PESEL equ 0x00000008
LPM equ 0x00000004
BEM equ 0x00000001
RND_CNT equ 0x00000400
FAIR_BACKOFF equ 0x00000200
EDB_MASTER_EN equ 0x00002000
 
; Eeprom Access Reigster Bits
MDC equ 0x00000040
MDDIR equ 0x00000020
MDIO equ 0x00000010 ; 7016 specific
EECS equ 0x00000008
EECLK equ 0x00000004
EEDO equ 0x00000002
EEDI equ 0x00000001
 
; TX Configuration Register Bits
ATP equ 0x10000000 ;Automatic Transmit Padding
MLB equ 0x20000000 ;Mac Loopback Enable
HBI equ 0x40000000 ;HeartBeat Ignore (Req for full-dup)
CSI equ 0x80000000 ;CarrierSenseIgnore (Req for full-du
 
; RX Configuration Register Bits
AJAB equ 0x08000000 ;
ATX equ 0x10000000 ;Accept Transmit Packets
ARP equ 0x40000000 ;accept runt packets (<64bytes)
AEP equ 0x80000000 ;accept error packets
 
; Interrupt Reigster Bits
WKEVT equ 0x10000000
TxPAUSEEND equ 0x08000000
TxPAUSE equ 0x04000000
TxRCMP equ 0x02000000
RxRCMP equ 0x01000000
DPERR equ 0x00800000
SSERR equ 0x00400000
RMABT equ 0x00200000
RTABT equ 0x00100000
RxSOVR equ 0x00010000
HIBERR equ 0x00008000
SWINT equ 0x00001000
MIBINT equ 0x00000800
TxURN equ 0x00000400
TxIDLE equ 0x00000200
TxERR equ 0x00000100
TxDESC equ 0x00000080
TxOK equ 0x00000040
RxORN equ 0x00000020
RxIDLE equ 0x00000010
RxEARLY equ 0x00000008
RxERR equ 0x00000004
RxDESC equ 0x00000002
RxOK equ 0x00000001
 
; Interrupt Enable Register Bits
IE equ RxOK + TxOK
 
; Revision ID
SIS900B_900_REV equ 0x03
SIS630A_900_REV equ 0x80
SIS630E_900_REV equ 0x81
397,712 → 383,731
SIS630ET_900_REV equ 0x84
SIS635A_900_REV equ 0x90
SIS900_960_REV equ 0x91
;SIS900 Receive Filter Control Register Bits
SIS900_RFEN equ 0x80000000
SIS900_RFAAB equ 0x40000000
SIS900_RFAAM equ 0x20000000
SIS900_RFAAP equ 0x10000000
SIS900_RFPromiscuous equ 0x70000000
;SIS900 Reveive Filter Data Mask
SIS900_RFDAT equ 0x0000FFFF
;SIS900 Eeprom Address
SIS900_EEPROMSignature equ 0x00
SIS900_EEPROMVendorID equ 0x02
SIS900_EEPROMDeviceID equ 0x03
SIS900_EEPROMMACAddr equ 0x08
SIS900_EEPROMChecksum equ 0x0b
 
; Receive Filter Control Register Bits
RFEN equ 0x80000000
RFAAB equ 0x40000000
RFAAM equ 0x20000000
RFAAP equ 0x10000000
RFPromiscuous equ 0x70000000
 
; Reveive Filter Data Mask
RFDAT equ 0x0000FFFF
 
; Eeprom Address
EEPROMSignature equ 0x00
EEPROMVendorID equ 0x02
EEPROMDeviceID equ 0x03
EEPROMMACAddr equ 0x08
EEPROMChecksum equ 0x0b
 
;The EEPROM commands include the alway-set leading bit.
;SIS900 Eeprom Command
SIS900_EEread equ 0x0180
SIS900_EEwrite equ 0x0140
SIS900_EEerase equ 0x01C0
SIS900_EEwriteEnable equ 0x0130
SIS900_EEwriteDisable equ 0x0100
SIS900_EEeraseAll equ 0x0120
SIS900_EEwriteAll equ 0x0110
SIS900_EEaddrMask equ 0x013F
SIS900_EEcmdShift equ 16
EEread equ 0x0180
EEwrite equ 0x0140
EEerase equ 0x01C0
EEwriteEnable equ 0x0130
EEwriteDisable equ 0x0100
EEeraseAll equ 0x0120
EEwriteAll equ 0x0110
EEaddrMask equ 0x013F
EEcmdShift equ 16
 
;For SiS962 or SiS963, request the eeprom software access
SIS900_EEREQ equ 0x00000400
SIS900_EEDONE equ 0x00000200
SIS900_EEGNT equ 0x00000100
EEREQ equ 0x00000400
EEDONE equ 0x00000200
EEGNT equ 0x00000100
 
SIS900_pci_revision equ ebx+device.pci_revision
sis900_get_mac_func equ ebx+device.get_MAC
sis900_special_func equ ebx+device.special_func
sis900_table_entries equ ebx+device.table_entries
cur_rx equ ebx+device.cur_rx
sys_msg_board_str equ SysMsgBoardStr
 
;***************************************************************************
; Function
; SIS900_probe
; Description
;
; probe
;
; Searches for an ethernet card, enables it and clears the rx buffer
; If a card was found, it enables the ethernet -> TCPIP link
;not done - still need to probe mii transcievers
;
; TODO: probe mii transceivers
;
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Str_Unsupported db 'Sorry your card is unsupported ',13,10,0
end if
SIS900_probe:
;******Wake Up Chip*******
stdcall PciWrite8, dword [ebx+device.pci_bus], dword [ebx+device.pci_dev], 0x40, 0
;*******Set some PCI Settings*********
call SIS900_adjust_pci_device
;*****Get Card Revision******
stdcall PciRead8, dword [ebx+device.pci_bus], dword [ebx+device.pci_dev], 0x08
mov [SIS900_pci_revision], al ;save the revision for later use
;****** Look up through the sis900_specific_table
mov esi,sis900_specific_table
.probe_loop:
align 4
probe:
 
stdcall PciWrite8, dword [device.pci_bus], dword [device.pci_dev], 0x40, 0 ; Wake Up Chip
 
make_bus_master [device.pci_bus], [device.pci_dev]
 
; Get Card Revision
stdcall PciRead8, dword [device.pci_bus], dword [device.pci_dev], 0x08
mov [pci_revision], al ; save the revision for later use
 
; Look up through the specific_table
mov esi, specific_table
.loop:
cmp dword [esi],0 ; Check if we reached end of the list
je .probe_loop_failed
je .error
cmp al,[esi] ; Check if revision is OK
je .probe_loop_ok
je .ok
add esi,12 ; Advance to next entry
jmp .probe_loop
.probe_loop_failed:
jmp SIS900_Probe_Unsupported
;*********Find Get Mac Function*********
.probe_loop_ok:
jmp .loop
 
.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 [sis900_get_mac_func],eax
mov [get_mac_func], eax
mov eax,[esi+8] ; Get pointer to special initialization fn
mov [sis900_special_func],eax
;******** Get MAC ********
call dword [sis900_get_mac_func]
;******** Call special initialization fn if requested ********
cmp dword [sis900_special_func],0
je .no_special_init
call dword [sis900_special_func]
.no_special_init:
;******** Set table entries ********
mov al,[SIS900_pci_revision]
cmp al,SIS635A_900_REV
jae .ent16
cmp al,SIS900B_900_REV
je .ent16
mov byte [sis900_table_entries],8
jmp .ent8
.ent16:
mov byte [sis900_table_entries],16
.ent8:
;*******Probe for mii transceiver*******
;TODO!!*********************
;*******Initialize Device*******
call sis900_init
ret
mov [special_func], eax
 
SIS900_Probe_Unsupported:
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Str_Unsupported
call sys_msg_board_str
end if
or eax, -1
ret
; Get MAC
call [get_mac_func]
 
; Call special initialization fn if requested
 
cmp [special_func],0
je @f
call [special_func]
@@:
 
; Set table entries
 
mov byte [table_entries], 16
cmp [pci_revision], SIS635A_900_REV
jae @f
cmp [pci_revision], SIS900B_900_REV
je @f
mov byte [table_entries], 8
@@:
 
; TODO: Probe for mii transceiver
 
 
;***************************************************************************
; Function: sis900_init
;
; Description: resets the ethernet controller chip and various
; init
;
; resets the ethernet controller chip and various
; data structures required for sending and receiving packets.
;
; Arguments:
;
; returns: none
;not done
;***************************************************************************
sis900_init:
call SIS900_reset ;Done
call SIS900_init_rxfilter ;Done
call SIS900_init_txd ;Done
call SIS900_init_rxd ;Done
call SIS900_set_rx_mode ;done
call SIS900_set_tx_mode
;call SIS900_check_mode
align 4
init:
 
call reset
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 = SIS900_RxOK
mov edx, [ebx+device.io_addr]
add edx, SIS900_imr
inc eax ; eax = 1 = RxOK
set_io 0
set_io imr
out dx, eax
 
; globally enable interrupts
add edx, SIS900_ier-SIS900_imr
 
set_io ier
out dx, eax ; eax is still 1
xor eax, eax
 
mov [device.mtu], 1514
 
ret
 
;***************************************************************************
; Function
; SIS900_reset
; Description
;
; reset
;
; disables interrupts and soft resets the controller chip
;
;done+
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Reset_Failed db 'Reset Failed ',0
end if
SIS900_reset:
movzx eax, [ebx+device.irq_line]
align 4
reset:
movzx eax, [device.irq_line]
stdcall AttachIntHandler, eax, int_handler, 0
push ebp
mov ebp, [ebx+device.io_addr] ; base address
;******Disable Interrupts and reset Receive Filter*******
xor eax, eax ; 0 to initialize
lea edx,[ebp+SIS900_ier]
out dx, eax ; Write 0 to location
lea edx,[ebp+SIS900_imr]
out dx, eax ; Write 0 to location
lea edx,[ebp+SIS900_rfcr]
out dx, eax ; Write 0 to location
;*******Reset Card***********************************************
lea edx,[ebp+SIS900_cr]
 
;--------------------------------------------
; Disable Interrupts and reset Receive Filter
 
set_io 0
set_io ier
xor eax, eax
out dx, eax
 
set_io imr
out dx, eax
 
set_io rfcr
out dx, eax
 
;-----------
; Reset Card
 
set_io cr
in eax, dx ; Get current Command Register
or eax, SIS900_RESET ; set flags
or eax, SIS900_RxRESET ;
or eax, SIS900_TxRESET ;
or eax, RESET + RxRESET + TxRESET ; set flags
out dx, eax ; Write new Command Register
;*******Wait Loop************************************************
push ebx
lea edx,[ebp+SIS900_isr]
mov ecx, 0x03000000 ; Status we would like to see from card
mov ebx, 2001 ; only loop 1000 times
SIS900_Wait:
dec ebx ; 1 less loop
jz SIS900_DoneWait_e ; 1000 times yet?
 
;----------
; Wait loop
 
set_io isr
mov ecx, 1000
.loop:
dec ecx
jz .error
in eax, dx ; move interrup status to eax
and eax, ecx
xor ecx, eax
jz SIS900_DoneWait
jmp SIS900_Wait
SIS900_DoneWait_e:
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Reset_Failed
call sys_msg_board_str
end if
SIS900_DoneWait:
pop ebx
;*******Set Configuration Register depending on Card Revision********
lea edx,[ebp+SIS900_cfg]
mov eax, SIS900_PESEL ; Configuration Register Bit
mov cl, [SIS900_pci_revision] ; card revision
cmp cl, SIS635A_900_REV
je SIS900_RevMatch
cmp cl, SIS900B_900_REV ; Check card revision
je SIS900_RevMatch
cmp eax, 0x03000000
jne .loop
 
;------------------------------------------------------
; Set Configuration Register depending on Card Revision
 
set_io cfg
mov eax, PESEL ; Configuration Register Bit
cmp [pci_revision], SIS635A_900_REV
je .match
cmp [pci_revision], SIS900B_900_REV ; Check card revision
je .match
out dx, eax ; no revision match
jmp SIS900_Reset_Complete
SIS900_RevMatch: ; Revision match
or eax, SIS900_RND_CNT ; Configuration Register Bit
jmp .done
 
.match: ; Revision match
or eax, RND_CNT ; Configuration Register Bit
out dx, eax
SIS900_Reset_Complete:
 
.done:
xor eax, eax
pop ebp
ret
 
.error:
DEBUGF 1, "Reset failed!\n"
or eax, -1
ret
 
 
;***************************************************************************
; Function: sis_init_rxfilter
;
; Description: sets receive filter address to our MAC address
; sis_init_rxfilter
;
; Arguments:
; sets receive filter address to our MAC address
;
; returns:
;done+
;***************************************************************************
SIS900_init_rxfilter:
push ebp
mov ebp, [ebx+device.io_addr] ; base address
;****Get Receive Filter Control Register ********
lea edx,[ebp+SIS900_rfcr]
in eax, dx ; get register
align 4
init_rxfilter:
 
;------------------------------------
; Get Receive Filter Control Register
 
set_io 0
set_io rfcr
in eax, dx
push eax
;****disable packet filtering before setting filter*******
mov eax, SIS900_RFEN ;move receive filter enable flag
not eax ;1s complement
and eax, [esp] ;disable receiver
out dx, eax ;set receive disabled
;********load MAC addr to filter data register*********
 
;-----------------------------------------------
; disable packet filtering before setting filter
 
and eax, not RFEN
out dx, eax
 
;--------------------------------------
; load MAC addr to filter data register
 
xor ecx, ecx
SIS900_RXINT_Mac_Write:
;high word of eax tells card which mac byte to write
RXINT_Mac_Write: ; high word of eax tells card which mac byte to write
mov eax, ecx
lea edx,[ebp+SIS900_rfcr]
set_io 0
set_io rfcr
shl eax, 16 ;
out dx, eax ;
lea edx,[ebp+SIS900_rfdr]
mov ax, word [ebx+device.mac+ecx*2] ; Get Mac ID word
set_io rfdr
mov ax, word [device.mac+ecx*2] ; Get Mac ID word
out dx, ax ; Send Mac ID
inc cl ; send next word
cmp cl, 3 ; more to send?
jne SIS900_RXINT_Mac_Write
;********enable packet filitering *****
jne RXINT_Mac_Write
 
;------------------------
; enable packet filtering
 
pop eax ;old register value
lea edx,[ebp+SIS900_rfcr]
or eax, SIS900_RFEN ;enable filtering
set_io rfcr
or eax, RFEN ;enable filtering
out dx, eax ;set register
pop ebp
 
ret
 
;***************************************************************************
;*
;* Function: sis_init_txd
;*
;* Description: initializes the Tx descriptor
;*
;* Arguments:
;*
;* returns:
;*done
;
; init_txd
;
; initializes the Tx descriptor
;
;***************************************************************************
SIS900_init_txd:
;********** initialize TX descriptor **************
mov [ebx+device.txd], dword 0 ;put link to next descriptor in link field
mov [ebx+device.txd+4],dword 0 ;clear status field
lea eax, [ebx+0x1000]
call GetPgAddr
mov [ebx+device.txd+8], eax ;save address to buffer ptr field
;*************** load Transmit Descriptor Register ***************
mov edx, [ebx+device.io_addr] ; base address
add edx, SIS900_txdp ; TX Descriptor Pointer
add eax, device.txd - 0x1000 ; First Descriptor
align 4
init_txd:
 
;-------------------------
; 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
 
ret
 
;***************************************************************************
;* Function: sis_init_rxd
;*
;* Description: initializes the Rx descriptor ring
;*
;* Arguments:
;*
;* Returns:
;*done
;
; init_rxd
;
; initializes the Rx descriptor ring
;
;***************************************************************************
SIS900_init_rxd:
xor ecx,ecx
mov [cur_rx], cl ;Set cuurent rx discriptor to 0
mov eax, ebx
call GetPgAddr
mov esi, eax
;******** init RX descriptors ********
SIS900_init_rxd_Loop:
mov edx, ecx ;current descriptor
imul edx, 12 ;
mov eax, ecx ;determine next link descriptor
inc eax ;
cmp eax, NUM_RX_DESC ;
jne SIS900_init_rxd_Loop_0 ;
xor eax, eax ;
SIS900_init_rxd_Loop_0: ;
imul eax, 12 ;
lea eax, [eax+esi+device.rxd]
mov [ebx+device.rxd+edx], eax ;save link to next descriptor
mov [ebx+device.rxd+edx+4],dword RX_BUFF_SZ ;status bits init to buf size
mov eax, ecx ;find where the buf is located
imul eax,RX_BUFF_SZ ;
lea eax, [eax+esi+0x1000+NUM_TX_DESC*TX_BUFF_SZ]
mov [ebx+device.rxd+edx+8], eax ;save buffer pointer
inc ecx ;next descriptor
cmp ecx, NUM_RX_DESC ;
jne SIS900_init_rxd_Loop ;
;********* load Receive Descriptor Register with address of first
; descriptor*********
mov edx, [ebx+device.io_addr]
add edx, SIS900_rxdp
lea eax, [esi+device.rxd]
align 4
init_rxd:
 
; init RX descriptors
mov ecx, NUM_RX_DESC
lea esi, [device.rxd]
 
.loop:
lea eax, [esi + 16]
GetRealAddr
mov dword [esi+0], eax
mov dword [esi+4], RX_BUFF_SZ
 
stdcall KernelAlloc, RX_BUFF_SZ
test eax, eax
jz .fail
mov dword [esi+12], eax
GetRealAddr
mov dword [esi+8], eax
add esi, 16
loop .loop
 
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
out dx, eax
 
mov [device.cur_rx], 0 ; Set curent rx discriptor to 0
 
.fail: ;;; TODO: abort instead!
ret
 
 
;***************************************************************************
;* Function: sis900_set_tx_mode
;*
;* Description:
;* sets the transmit mode to allow for full duplex
;*
;*
;* Arguments:
;*
;* Returns:
;*
;* Comments:
;* 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
;
; 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
;
;***************************************************************************
SIS900_set_tx_mode:
push ebp
mov ebp,[ebx+device.io_addr]
lea edx,[ebp+SIS900_cr]
align 4
set_tx_mode:
 
set_io 0
set_io cr
in eax, dx ; Get current Command Register
or eax, SIS900_TxENA ;Enable Receive
or eax, TxENA ; Enable Receive
out dx, eax
lea edx,[ebp+SIS900_txcfg]; Transmit config Register offset
mov eax, SIS900_ATP ;allow automatic padding
or eax, SIS900_HBI ;allow heartbeat ignore
or eax, SIS900_CSI ;allow carrier sense ignore
or eax, 0x00600000 ;Max DMA Burst
or eax, 0x00000100 ;TX Fill Threshold
or eax, 0x00000020 ;TX Drain Threshold
 
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
pop ebp
 
ret
 
;***************************************************************************
;* Function: sis900_set_rx_mode
;*
;* Description:
;* sets the receive mode to accept all broadcast packets and packets
;* with our MAC address, and reject all multicast packets. Also allows
;* full-duplex
;*
;* Arguments:
;*
;* Returns:
;*
;* Comments:
;* 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
;
; 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
;
;***************************************************************************
SIS900_set_rx_mode:
push ebp
mov ebp,[ebx+device.io_addr]
;**************update Multicast Hash Table in Receive Filter
align 4
set_rx_mode:
 
;----------------------------------------------
; update Multicast Hash Table in Receive Filter
 
xor cl, cl
SIS900_set_rx_mode_Loop:
mov eax, ecx
shl eax, 1
lea edx,[ebp+SIS900_rfcr] ; Receive Filter Control Reg offset
.loop:
set_io 0
set_io rfcr ; Receive Filter Control Reg offset
mov eax, 4 ;determine table entry
add al, cl
shl eax, 16
out dx, eax ;tell card which entry to modify
lea edx,[ebp+SIS900_rfdr] ; Receive Filter Control Reg offset
 
set_io rfdr ; Receive Filter Control Reg offset
mov eax, 0xffff ;entry value
out dx, ax ;write value to table in card
 
inc cl ;next entry
cmp cl,[sis900_table_entries] ;
jl SIS900_set_rx_mode_Loop
;*******Set Receive Filter Control Register*************
lea edx,[ebp+SIS900_rfcr] ; Receive Filter Control Register offset
mov eax, SIS900_RFAAB ;accecpt all broadcast packets
or eax, SIS900_RFAAM ;accept all multicast packets
or eax, SIS900_RFAAP ;Accept all packets
or eax, SIS900_RFEN ;enable receiver filter
cmp cl, [table_entries]
jl .loop
 
;------------------------------------
; 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************
lea edx,[ebp+SIS900_cr] ; Command Register offset
;----------------
; Enable Receiver
 
set_io cr
in eax, dx ; Get current Command Register
or eax, SIS900_RxENA ;Enable Receive
or eax, RxENA ; Enable Receive
out dx, eax
;*********Set
lea edx,[ebp+SIS900_rxcfg] ; Receive Config Register offset
mov eax, SIS900_ATX ;Accept Transmit Packets
 
;-------------------
; Configure Receiver
 
set_io rxcfg ; Receive Config Register offset
mov eax, ATX + 0x00600002
; Accept Transmit Packets
; (Req for full-duplex and PMD Loopback)
or eax, 0x00600000 ;Max DMA Burst
or eax, 0x00000002 ;RX Drain Threshold, 8X8 bytes or 64bytes
out dx, eax ;
pop ebp
; Max DMA Burst
; RX Drain Threshold, 8X8 bytes or 64bytes
out dx, eax
 
ret
 
;***************************************************************************
; * SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
; * @pci_dev: the sis900 pci device
; * @net_dev: the net device to get address for
; *
; * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
; * is shared by
; * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first
; * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access
; * by LAN, otherwise is not. After MAC address is read from EEPROM, send
; * EEDONE signal to refuse EEPROM access by LAN.
; * The EEPROM map of SiS962 or SiS963 is different to SiS900.
; * The signature field in SiS962 or SiS963 spec is meaningless.
; * MAC address is read into @net_dev->dev_addr.
; *done
;*
;* Return 0 is EAX = failure
;*Done+
;
; SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
;
; SiS962 or SiS963 model, use EEPROM to store MAC address.
; EEPROM is shared by LAN and 1394.
; When access EEPROM, send EEREQ signal to hardware first, and wait for EEGNT.
; If EEGNT is ON, EEPROM is permitted to be accessed by LAN, otherwise is not.
; After MAC address is read from EEPROM, send
; EEDONE signal to refuse EEPROM access by LAN.
; The EEPROM map of SiS962 or SiS963 is different to SiS900.
; The signature field in SiS962 or SiS963 spec is meaningless.
;
; Return 0 is EAX = failure
;
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Str_GetMac_Start db 'Attempting to get SIS900 Mac ID: ',13,10,0
SIS900_Debug_Str_GetMac_Failed db 'Access to EEprom Failed',13,10,0
SIS900_Debug_Str_GetMac_Address db 'Your Mac ID is: ',0
SIS900_Debug_Str_GetMac_Address2 db 'Your SIS96x Mac ID is: ',0
end if
align 4
SIS960_get_mac_addr:
push ebp
mov ebp,[ebx+device.io_addr]
;**********Send Request for eeprom access*********************
lea edx,[ebp+SIS900_mear] ; Eeprom access register
mov eax, SIS900_EEREQ ; Request access to eeprom
 
;-------------------------------
; Send Request for eeprom access
 
set_io 0
set_io mear ; Eeprom access register
mov eax, EEREQ ; Request access to eeprom
out dx, eax ; Send request
xor ecx,ecx ;
;******Loop 4000 times and if access not granted error out*****
SIS96X_Get_Mac_Wait:
 
;-----------------------------------------------------
; Loop 4000 times and if access not granted, error out
 
mov ecx, 4000
.loop:
in eax, dx ;get eeprom status
and eax, SIS900_EEGNT ;see if eeprom access granted flag is set
jnz SIS900_Got_EEP_Access ;if it is, go access the eeprom
inc ecx ;else keep waiting
cmp ecx, 4000 ;have we tried 4000 times yet?
jl SIS96X_Get_Mac_Wait ;if not ask again
xor eax, eax ;return zero in eax indicating failure
;*******Debug **********************
if defined SIS900_DEBUG
mov esi,SIS900_Debug_Str_GetMac_Failed
call sys_msg_board_str
end if
jmp SIS960_get_mac_addr_done
;**********EEprom access granted, read MAC from card*************
SIS900_Got_EEP_Access:
test eax, EEGNT ; see if eeprom access granted flag is set
jnz .got_access ; if it is, go access the eeprom
loop .loop ; else keep waiting
 
DEBUGF 1, "Access to EEprom failed!\n", 0
 
set_io mear ; Eeprom access register
mov eax, EEDONE ; tell eeprom we are done
out dx, eax
 
or eax, -1 ; error
ret
 
.got_access:
 
;------------------------------------------
; EEprom access granted, read MAC from card
 
; zero based so 3-16 bit reads will take place
 
mov ecx, 2
SIS96x_mac_read_loop:
mov eax, SIS900_EEPROMMACAddr ;Base Mac Address
.read_loop:
mov eax, EEPROMMACAddr ; Base Mac Address
add eax, ecx ;Current Mac Byte Offset
push ecx
call sis900_read_eeprom ;try to read 16 bits
call read_eeprom ; try to read 16 bits
pop ecx
mov word [ebx+device.mac+ecx*2], ax ;save 16 bits to the MAC ID varible
mov word [device.mac+ecx*2], ax ; save 16 bits to the MAC ID varible
dec ecx ;one less word to read
jns SIS96x_mac_read_loop ;if more read more
jns .read_loop ; if more read more
mov eax, 1 ;return non-zero indicating success
;*******Debug Print MAC ID to debug window**********************
if defined SIS900_DEBUG
mov esi,SIS900_Debug_Str_GetMac_Address2
call sys_msg_board_str
lea edx, [ebx+device.mac]
call Create_Mac_String
end if
;**********Tell EEPROM We are Done Accessing It*********************
SIS960_get_mac_addr_done:
lea edx,[ebp+SIS900_mear] ; Eeprom access register
mov eax, SIS900_EEDONE ;tell eeprom we are done
 
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
 
;-------------------------------------
; Tell EEPROM We are Done Accessing It
 
.done:
set_io 0
set_io mear ; Eeprom access register
mov eax, EEDONE ; tell eeprom we are done
out dx,eax
pop ebp
 
xor eax, eax ; ok
ret
 
 
 
 
;***************************************************************************
;* sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
;* @pci_dev: the sis900 pci device
;* @net_dev: the net device to get address for
;*
;* Older SiS900 and friends, use EEPROM to store MAC address.
;* MAC address is read from read_eeprom() into @net_dev->dev_addr.
;* done/untested
;
; get_mac_addr: - Get MAC address for stand alone SiS900 model
;
; Older SiS900 and friends, use EEPROM to store MAC address.
;
;***************************************************************************
SIS900_get_mac_addr:
;*******Debug **********************
if defined SIS900_DEBUG
mov esi,SIS900_Debug_Str_GetMac_Start
call sys_msg_board_str
end if
;******** check to see if we have sane EEPROM *******
mov eax, SIS900_EEPROMSignature ;Base Eeprom Signature
call sis900_read_eeprom ;try to read 16 bits
align 4
get_mac_addr:
 
;------------------------------------
; check to see if we have sane EEPROM
 
mov eax, EEPROMSignature ; Base Eeprom Signature
call read_eeprom ; try to read 16 bits
cmp ax, 0xffff
je SIS900_Bad_Eeprom
cmp ax, 0
je SIS900_Bad_Eeprom
;**************Read MacID**************
je .err
test ax, ax
je .err
 
;-----------
; Read MacID
 
; zero based so 3-16 bit reads will take place
 
mov ecx, 2
SIS900_mac_read_loop:
mov eax, SIS900_EEPROMMACAddr ;Base Mac Address
.loop:
mov eax, EEPROMMACAddr ;Base Mac Address
add eax, ecx ;Current Mac Byte Offset
push ecx
call sis900_read_eeprom ;try to read 16 bits
call read_eeprom ;try to read 16 bits
pop ecx
mov word [ebx+device.mac+ecx*2], ax ;save 16 bits to the MAC ID storage
mov word [device.mac+ecx*2], ax ;save 16 bits to the MAC ID storage
dec ecx ;one less word to read
jns SIS900_mac_read_loop ;if more read more
mov eax, 1 ;return non-zero indicating success
;*******Debug Print MAC ID to debug window**********************
if defined SIS900_DEBUG
mov esi,SIS900_Debug_Str_GetMac_Address
call sys_msg_board_str
lea edx, [ebx+device.mac]
call Create_Mac_String
end if
ret
jns mac_read_loop ;if more read more
 
SIS900_Bad_Eeprom:
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
 
xor eax, eax
;*******Debug **********************
if defined SIS900_DEBUG
mov esi,SIS900_Debug_Str_GetMac_Failed
call sys_msg_board_str
end if
ret
 
 
.err:
DEBUGF 1, "Access to EEprom failed!\n", 0
 
or eax, -1
ret
 
 
;***************************************************************************
;* Get_Mac_SIS635_900_REV: - Get MAC address for model 635
;*
;*
;
; Get_Mac_SIS635_900_REV: - Get MAC address for model 635
;
;***************************************************************************
align 4
Get_Mac_SIS635_900_REV:
if defined SIS900_DEBUG
mov esi,SIS900_Debug_Str_GetMac_Start
call sys_msg_board_str
end if
push ebp
mov ebp,[ebx+device.io_addr]
lea edx,[ebp+SIS900_rfcr]
 
set_io 0
set_io rfcr
in eax,dx
mov edi,eax ; EDI=rfcrSave
lea edx,[ebp+SIS900_cr]
or eax,SIS900_RELOAD
 
set_io cr
or eax, RELOAD
out dx,eax
 
xor eax,eax
out dx,eax
 
;-----------------------------------------------
; Disable packet filtering before setting filter
lea edx,[ebp+SIS900_rfcr]
 
set_io rfcr
mov eax,edi
and edi,not SIS900_RFEN
and edi, not RFEN
out dx,eax
 
;---------------------------------
; Load MAC to filter data register
xor ecx,ecx
lea esi,[ebx+device.mac]
.get_mac_loop:
lea edx,[ebp+SIS900_rfcr]
 
mov ecx, 3
lea edi, [device.mac]
.loop:
set_io 0
set_io rfcr
mov eax,ecx
shl eax,SIS900_RFADDR_shift
shl eax, RFADDR_shift
out dx,eax
lea edx,[ebp+SIS900_rfdr]
 
set_io rfdr
in eax,dx
mov [esi],ax
add esi,2
inc ecx
cmp ecx,3
jne .get_mac_loop
stosw
loop .loop
 
;------------------------
; Enable packet filtering
;lea edx,[ebp+SIS900_rfcr]
 
; set_io rfcr
;mov eax,edi
;or eax,SIS900_RFEN
; or eax, RFEN
;out dx, eax
;*******Debug Print MAC ID to debug window**********************
if defined SIS900_DEBUG
mov esi,SIS900_Debug_Str_GetMac_Address
call sys_msg_board_str
lea edx, [ebx+device.mac]
call Create_Mac_String
end if
pop ebp
 
xor eax, eax
ret
 
;***************************************************************************
;* Function: sis900_read_eeprom
;*
;* Description: reads and returns a given location from EEPROM
;*
;* Arguments: eax - location: requested EEPROM location
;*
;* Returns: eax : contents of requested EEPROM location
;*
; Read Serial EEPROM through EEPROM Access Register, Note that location is
; in word (16 bits) unit */
;done+
;
; read_eeprom
;
; reads and returns a given location from EEPROM
;
; IN: si = addr
; OUT: ax = data
;
;***************************************************************************
sis900_read_eeprom:
push esi
push edx
push ecx
push ebx
push ebp
mov ebp,[ebx+device.io_addr]
mov ebx, eax ;location of Mac byte to read
or ebx, SIS900_EEread ;
lea edx,[ebp+SIS900_mear] ; Eeprom access register
align 4
read_eeprom:
 
set_io 0
set_io mear
 
xor eax, eax ; start send
out dx,eax
call SIS900_Eeprom_Delay_1
mov eax, SIS900_EECLK
ee_delay
 
or eax, EECLK
out dx, eax
call SIS900_Eeprom_Delay_1
;************ Shift the read command (9) bits out. *********
mov cl, 8 ;
sis900_read_eeprom_Send:
mov eax, 1
shl eax, cl
and eax, ebx
jz SIS900_Read_Eeprom_8
mov eax, 9
jmp SIS900_Read_Eeprom_9
SIS900_Read_Eeprom_8:
mov eax, 8
SIS900_Read_Eeprom_9:
ee_delay
 
;------------------------------------
; Send the read command
 
or esi, EEread
mov ecx, 1 shl 9
 
.loop:
mov eax, EECS
test esi, ecx
jz @f
or eax, EEDI
@@:
out dx, eax
call SIS900_Eeprom_Delay_1
or eax, SIS900_EECLK
ee_delay
 
or eax, EECLK
out dx, eax
call SIS900_Eeprom_Delay_1
cmp cl, 0
je sis900_read_eeprom_Send_Done
dec cl
jmp sis900_read_eeprom_Send
;*********************
sis900_read_eeprom_Send_Done:
mov eax, SIS900_EECS ;
ee_delay
 
shr esi, 1
jnc .loop
 
mov eax, EECS
out dx, eax
call SIS900_Eeprom_Delay_1
;********** Read 16-bits of data in ***************
mov cx, 16 ;16 bits to read
sis900_read_eeprom_Send2:
mov eax, SIS900_EECS
ee_delay
 
;------------------------
; Read 16-bits of data in
 
xor esi, esi
mov cx, 16
.loop2:
mov eax, EECS
out dx, eax
call SIS900_Eeprom_Delay_1
or eax, SIS900_EECLK
ee_delay
 
or eax, EECLK
out dx, eax
call SIS900_Eeprom_Delay_1
ee_delay
 
in eax, dx
shl ebx, 1
and eax, SIS900_EEDO
jz SIS900_Read_Eeprom_0
or ebx, 1
SIS900_Read_Eeprom_0:
dec cx
jnz sis900_read_eeprom_Send2
;************** Terminate the EEPROM access. **************
shl esi, 1
test eax, EEDO
jz @f
inc esi
@@:
loop .loop2
 
;----------------------------
; Terminate the EEPROM access
 
xor eax, eax
out dx, eax
call SIS900_Eeprom_Delay_1
mov eax, SIS900_EECLK
ee_delay
 
mov eax, EECLK
out dx, eax
mov eax, ebx
and eax, 0x0000ffff ;return only 16 bits
pop ebp
pop ebx
pop ecx
pop edx
pop esi
ee_delay
 
movzx eax, si
 
ret
;***************************************************************************
; Function
; SIS900_Eeprom_Delay_1
; Description
;
;
;
;
;***************************************************************************
SIS900_Eeprom_Delay_1:
push eax
in eax, dx
pop eax
ret
 
 
 
align 4
write_mac:
DEBUGF 1,'Setting MAC is not supported for SIS900 card.\n'
add esp, 6
1109,116 → 1114,125
ret
 
;***************************************************************************
; Function
;
; int_handler
; Description
;
; handles received IRQs, which signal received packets
;
; Currently only supports one descriptor per packet, if packet is fragmented
; between multiple descriptors you will lose part of the packet
;
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Pull_Packet_good db 'Good Packet Waiting: ',13,10,0
SIS900_Debug_Pull_Bad_Packet_Status db 'Bad Packet Waiting: Status',13,10,0
SIS900_Debug_Pull_Bad_Packet_Size db 'Bad Packet Waiting: Size',13,10,0
end if
align 4
int_handler:
; find pointer of device which made IRQ occur
mov esi, DEV_LIST
mov ecx, [NUM_DEV]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .nothing
.nextdevice:
mov ebx, [esi]
mov edx, [ebx+device.io_addr]
add edx, SIS900_isr
set_io 0
set_io isr
in eax, dx ; note that this clears all interrupts
test al, SIS900_RxOK
test ax, IE
jnz .got_it
loop .nextdevice
.nothing:
ret
.got_it:
;**************Get Status **************
movzx eax, [ebx+device.cur_rx] ;find current discriptor
imul eax, 12 ;
mov ecx, [ebx+device.rxd+eax+4] ; get receive status
;**************Check Status **************
 
test ax, RxOK
jz .no_rx
 
push ax
 
;-----------
; Get Status
movzx eax, [device.cur_rx] ; find current discriptor
shl eax, 4 ; * 16
mov ecx, dword[device.rxd+eax+4] ; get receive status
 
;-------------------------------------------
;Check RX_Status to see if packet is waiting
test ecx, 0x80000000
jnz SIS900_poll_IS_packet
jnz .is_packet
ret
;**********There is a packet waiting check it for errors**************
SIS900_poll_IS_packet:
 
;----------------------------------------------
; There is a packet waiting check it for errors
.is_packet:
test ecx, 0x67C0000 ;see if there are any errors
jnz SIS900_Poll_Error_Status
;**************Check size of packet*************
and ecx, SIS900_DSIZE ;get packet size minus CRC
cmp ecx, SIS900_CRC_SIZE
;make sure packet contains data
jle SIS900_Poll_Error_Size
;*******Copy Good Packet to receive buffer******
sub ecx, SIS900_CRC_SIZE ;dont want crc
jnz .error_status
 
;---------------------
; Check size of packet
and ecx, DSIZE ; get packet size minus CRC
sub ecx, CRC_SIZE ; make sure packet contains data
jle .error_size
 
; update statistics
inc dword [ebx+device.packets_rx]
add dword [ebx+device.bytes_rx], ecx
adc dword [ebx+device.bytes_rx+4], 0
push ecx
stdcall KernelAlloc, ecx
pop ecx
test eax, eax
jz int_handler.nothing
inc dword [device.packets_rx]
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx+4], 0
 
push ebx
push .return ; return address for EthReceiver
;**********Continue copying packet****************
push ecx eax ; save buffer pointer and size for EthReceiver
mov edi, eax
movzx esi, byte [ebx+device.cur_rx]
imul esi, RX_BUFF_SZ
lea esi, [esi+ebx+0x1000+NUM_TX_DESC*TX_BUFF_SZ]
; first copy dword-wise, divide size by 4
shr ecx, 2
rep movsd ; copy the dwords
mov ecx, [esp+4]
and ecx, 3 ;
rep movsb
;********Debug, tell user we have a good packet*************
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Pull_Packet_good
call sys_msg_board_str
end if
push .return
push ecx ; packet size
push [device.rxd+eax+12] ; packet ptr
DEBUGF 1, "Packet received OK\n"
jmp EthReceiver
.return:
pop ebx
jmp SIS900_Poll_Cnt
;*************Error occured let user know through debug window***********
SIS900_Poll_Error_Status:
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Pull_Bad_Packet_Status
call sys_msg_board_str
end if
jmp SIS900_Poll_Cnt
SIS900_Poll_Error_Size:
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Pull_Bad_Packet_Size
call sys_msg_board_str
end if
;*************Increment to next available descriptor**************
SIS900_Poll_Cnt:
 
;Reset status, allow ethernet card access to descriptor
movzx eax, [ebx+device.cur_rx]
lea eax, [eax*3]
mov ecx, RX_BUFF_SZ
mov [ebx+device.rxd+eax*4+4], ecx ;
inc [ebx+device.cur_rx] ;get next descriptor
and [ebx+device.cur_rx],NUM_RX_DESC-1 ;only 4 descriptors 0-3
;******Enable Receiver************
mov edx, [ebx+device.io_addr]
add edx, SIS900_cr ; Command Register offset
movzx ecx, [device.cur_rx]
shl ecx, 4 ; *16
mov ecx, [device.rxd+ecx]
stdcall KernelAlloc, RX_BUFF_SZ
test eax, eax
jz .fail
mov dword [ecx+12], eax
GetRealAddr
mov dword [ecx+8], eax
mov dword [ecx+4], RX_BUFF_SZ
 
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, SIS900_RxENA ;Enable Receive
or eax, RxENA ; Enable Receiver
out dx, eax
 
pop ax
jmp .no_rx
 
.error_status:
 
DEBUGF 1, "Packet error: %x\n", ecx
jmp .continue
 
.error_size:
 
DEBUGF 1, "Packet too large/small\n"
jmp .continue
 
.no_rx:
test ax, TxOk
jz .no_tx
 
;;; TODO: free all unused buffers
stdcall KernelFree, eax
 
.no_tx:
 
ret
 
 
 
;***************************************************************************
; Function
; transmit
1231,167 → 1245,46
; only one transmit descriptor is used
;
;***************************************************************************
if defined SIS900_DEBUG
SIS900_Debug_Transmit_Packet db 'Transmitting Packet: ',13,10,0
SIS900_Debug_Transmit_Packet_Err db 'Transmitting Packet Error: ',13,10,0
end if
str1 db 'Transmitting packet:',13,10,0
str2 db ' ',0
align 4
transmit:
 
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
jg transmit_finish
 
cmp dword [esp+8], 60
jl transmit_finish
push ebp
mov ebp, [ebx+device.io_addr] ; Base Address
;******** Stop the transmitter ********
lea edx,[ebp+SIS900_cr] ; Command Register offset
in eax, dx ; Get current Command Register
or eax, SIS900_TxDIS ; Disable Transmitter
out dx, eax
;*******load Transmit Descriptor Register *******
lea edx,[ebp+SIS900_txdp]
mov eax, ebx
call GetPgAddr
add eax, device.txd
out dx, eax
;******* copy packet to descriptor*******
mov esi, [esp+8]
lea edi, [ebx+0x1000]
mov ecx, [esp+12]
mov edx, ecx
shr ecx, 2
and edx, 3
rep movsd
mov ecx, edx
rep movsb
;**************set length tag**************
mov ecx, [esp+12] ;restore packet size
and ecx, SIS900_DSIZE ;
inc [ebx+device.packets_tx]
add dword [ebx+device.bytes_tx], ecx
adc dword [ebx+device.bytes_tx+4], 0
;**************pad to minimum packet size **************not needed
;cmp ecx, SIS900_ETH_ZLEN
;jge SIS900_transmit_Size_Ok
;push ecx
;mov ebx, SIS900_ETH_ZLEN
;sub ebx, ecx
;mov ecx, ebx
;rep movsb
;pop ecx
SIS900_transmit_Size_Ok:
or ecx, 0x80000000 ;card owns descriptor
mov [ebx+device.txd+4], ecx
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Transmit_Packet
call sys_msg_board_str
end if
;***************restart the transmitter ********
lea edx,[ebp+SIS900_cr]
in eax, dx ; Get current Command Register
or eax, SIS900_TxENA ; Enable Transmitter
out dx, eax
;****make sure packet transmitted successfully****
; mov esi,10
; call delay_ms
mov eax, [ebx+device.txd+4]
and eax, 0x6200000
jz SIS900_transmit_OK
;**************Tell user there was an error through debug window
if defined SIS900_DEBUG
mov esi, SIS900_Debug_Transmit_Packet_Err
call sys_msg_board_str
end if
SIS900_transmit_OK:
pop ebp
transmit_finish:
ret
 
;***************************************************************************
;* Function: Create_Mac_String
;*
;* Description: Converts the 48 bit value to a string for display
;*
;* String Format: XX:XX:XX:XX:XX:XX
;*
;* Arguments: node_addr is location of 48 bit MAC ID
;*
;* Returns: Prints string to general debug window
;*
;*
;done
;***************************************************************************
if defined SIS900_DEBUG
movzx ecx, [device.cur_tx]
mov ecx, [device.txd+ecx*16]
 
SIS900_Char_String db '0','1','2','3','4','5','6','7','8','9'
db 'A','B','C','D','E','F'
Mac_str_build: times 20 db 0
Create_Mac_String:
pusha
xor ecx, ecx
Create_Mac_String_loop:
mov al,byte [edx+ecx];[node_addr+ecx]
push eax
shr eax, 4
and eax, 0x0f
mov bl, byte [SIS900_Char_String+eax]
mov [Mac_str_build+ecx*3], bl
pop eax
and eax, 0x0f
mov bl, byte [SIS900_Char_String+eax]
mov [Mac_str_build+1+ecx*3], bl
cmp ecx, 5
je Create_Mac_String_done
mov bl, ':'
mov [Mac_str_build+2+ecx*3], bl
inc ecx
jmp Create_Mac_String_loop
Create_Mac_String_done: ;Insert CR and Zero Terminate
mov [Mac_str_build+2+ecx*3],byte 13
mov [Mac_str_build+3+ecx*3],byte 10
mov [Mac_str_build+4+ecx*3],byte 0
mov esi, Mac_str_build
call sys_msg_board_str ;Print String to message board
popa
;; 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
 
ret
end if
;***************************************************************************
;* Set device to be a busmaster in case BIOS neglected to do so.
;* Also adjust PCI latency timer to a reasonable value, 64.
;***************************************************************************
SIS900_adjust_pci_device:
;*******Get current setting************************
stdcall PciRead16, dword [ebx+device.pci_bus], dword [ebx+device.pci_dev], 0x04
;******see if its already set as bus master********
mov cx, ax
and cx,5
cmp cx,5
je SIS900_adjust_pci_device_Latency
;******Make card a bus master*******
mov cx, ax ;value to write
or cx,5
stdcall PciWrite16, dword [ebx+device.pci_bus], dword [ebx+device.pci_dev], 0x04, ecx
;******Check latency setting***********
SIS900_adjust_pci_device_Latency:
;*******Get current latency setting************************
stdcall PciRead8, dword [ebx+device.pci_bus], dword [ebx+device.pci_dev], 0x0D
;******see if its aat least 64 clocks********
cmp al,64
jge SIS900_adjust_pci_device_Done
;******Set latency to 32 clocks*******
stdcall PciWrite8, dword [ebx+device.pci_bus], dword [ebx+device.pci_dev], 0x0D, 64
;******Check latency setting***********
SIS900_adjust_pci_device_Done:
ret
 
 
; End of code
 
align 4 ; Place all initialised data here
 
NUM_DEV dd 0
devices dd 0
 
sis900_specific_table:
specific_table:
; dd SIS630A_900_REV,Get_Mac_SIS630A_900_REV,0
; dd SIS630E_900_REV,Get_Mac_SIS630E_900_REV,0
dd SIS630S_900_REV,Get_Mac_SIS635_900_REV,0
1399,10 → 1292,10
dd SIS630ET_900_REV,Get_Mac_SIS635_900_REV,0;SIS630ET_900_REV_SpecialFN
dd SIS635A_900_REV,Get_Mac_SIS635_900_REV,0
dd SIS900_960_REV,SIS960_get_mac_addr,0
dd SIS900B_900_REV,SIS900_get_mac_addr,0
dd 0,0,0,0 ; end of list
dd SIS900B_900_REV,get_mac_addr,0
dd 0 ; end of list
 
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'SIS900',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
1409,5 → 1302,5
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
DEV_LIST rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling