Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1518 → Rev 1519

/kernel/branches/net/drivers/i8255x.asm
File deleted
Property changes:
Deleted: svn:keywords
-Revision
\ No newline at end of property
/kernel/branches/net/drivers/3c59x.asm
1,23 → 1,19
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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 ;;
;; ;;
;; 3Com network driver for KolibriOS ;;
;; ;;
;; Ported to KolibriOS net-branch by hidnplayr (28/05/10) ;;
;; ;;
;; Thanks to: scrap metal recyclers, whom provide me with ;;
;; loads of hardware ;;
;; diamond: who makes me understand KolibriOS ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Ethernet Driver for KolibriOS
;;
;; 3c59x.asm
;; Ported to KolibriOS net-branch by hidnplayr (28/05/10)
;;
;; Thanks to: scrap metal recyclers, whom provide me with loads of hardware
;; diamond: who makes me understand KolibriOS
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 3C59X.INC ;;
;; ;;
84,14 → 80,15
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
PROMISCIOUS equ 1
 
 
format MS COFF
 
API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
 
MAX_DEVICES equ 16
FORCE_FD equ 0 ; forcing full duplex mode makes sense at some cards and link types
PROMISCIOUS equ 0 ; enables promiscous mode
 
DEBUG equ 1
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 1
101,47 → 98,10
include 'fdo.inc'
include 'netdrv.inc'
 
 
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
 
public START
public service_proc
public version
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.rx_buffer dd ?
.tx_buffer dd ?
.dpd_buffer dd ?
.upd_buffer dd ?
.curr_upd dd ?
.prev_dpd dd ?
 
.io_addr dd ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
 
.prev_tx_frame dd ?
.ver_id db ?
.full_bus_master db ?
.has_hwcksm db ?
.preamble db ?
.dn_list_ptr_cleared db ?
.self_directed_packet rb 20
 
.size = $ - device
 
end virtual
 
 
struc DPD { ; Download Packet Descriptor
 
.next_ptr dd ?
172,17 → 132,11
upd UPD
end virtual
 
 
MAX_DEVICES equ 16
FORCE_FD equ 0 ; forcing full duplex mode makes sense at some cards and link types
 
 
; Ethernet frame symbols
ETH_ALEN equ 6
ETH_HLEN equ (2*ETH_ALEN+2)
ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for
; mininmum 64bytes frame length
 
; Registers
REG_POWER_MGMT_CTRL equ 0x7c
REG_UP_LIST_PTR equ 0x38
193,9 → 147,11
REG_TX_STATUS equ 0x1b
REG_RX_STATUS equ 0x18
REG_TX_DATA equ 0x10
 
; Common window registers
REG_INT_STATUS equ 0xe
REG_COMMAND equ 0xe
 
; Register window 7
REG_MASTER_STATUS equ 0xc
REG_POWER_MGMT_EVENT equ 0xc
203,6 → 159,7
REG_VLAN_ETHER_TYPE equ 0x4
REG_VLAN_MASK equ 0x0
REG_MASTER_ADDRESS equ 0x0
 
; Register window 6
REG_BYTES_XMITTED_OK equ 0xc
REG_BYTES_RCVD_OK equ 0xa
216,6 → 173,7
REG_MULTIPLE_COLLISIONS equ 0x2
REG_SQE_ERRORS equ 0x1
REG_CARRIER_LOST equ 0x0
 
; Register window 5
REG_INDICATION_ENABLE equ 0xc
REG_INTERRUPT_ENABLE equ 0xa
223,6 → 181,7
REG_RX_FILTER equ 0x8
REG_RX_EARLY_THRESH equ 0x6
REG_TX_START_THRESH equ 0x0
 
; Register window 4
REG_UPPER_BYTES_OK equ 0xe
REG_BAD_SSD equ 0xc
231,8 → 190,10
REG_NETWORK_DIAGNOSTIC equ 0x6
REG_FIFO_DIAGNOSTIC equ 0x4
REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported
 
; Bits in register window 4
BIT_AUTOSELECT equ 24
 
; Register window 3
REG_TX_FREE equ 0xc
REG_RX_FREE equ 0xa
240,6 → 201,7
REG_MAC_CONTROL equ 0x6
REG_MAX_PKT_SIZE equ 0x4
REG_INTERNAL_CONFIG equ 0x0
 
; Register window 2
REG_RESET_OPTIONS equ 0xc
REG_STATION_MASK_HI equ 0xa
248,6 → 210,7
REG_STATION_ADDRESS_HI equ 0x4
REG_STATION_ADDRESS_MID equ 0x2
REG_STATION_ADDRESS_LO equ 0x0
 
; Register window 1
REG_TRIGGER_BITS equ 0xc
REG_SOS_BITS equ 0xa
258,19 → 221,23
REG_SMB_STATUS equ 0x2
REG_SMB_ADDRESS equ 0x1
REG_SMB_FIFO_DATA equ 0x0
 
; Register window 0
REG_EEPROM_DATA equ 0xc
REG_EEPROM_COMMAND equ 0xa
REG_BIOS_ROM_DATA equ 0x8
REG_BIOS_ROM_ADDR equ 0x4
 
; Physical management bits
BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData
BIT_MGMT_DATA equ 1 ; MII management data bit
BIT_MGMT_CLK equ 0 ; MII management clock
 
; MII commands
MII_CMD_MASK equ (1111b shl 10)
MII_CMD_READ equ (0110b shl 10)
MII_CMD_WRITE equ (0101b shl 10)
 
; MII registers
REG_MII_BMCR equ 0 ; basic mode control register
REG_MII_BMSR equ 1 ; basic mode status register
277,15 → 244,19
REG_MII_ANAR equ 4 ; auto negotiation advertisement register
REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register
REG_MII_ANER equ 6 ; auto negotiation expansion register
 
; MII bits
BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete
BIT_MII_PREAMBLE_SUPPRESSION equ 6
 
; eeprom bits and commands
EEPROM_CMD_READ equ 0x80
EEPROM_BIT_BUSY equ 15
 
; eeprom registers
EEPROM_REG_OEM_NODE_ADDR equ 0xa
EEPROM_REG_CAPABILITIES equ 0x10
 
; Commands for command register
SELECT_REGISTER_WINDOW equ (1 shl 11)
 
306,7 → 277,6
EXTRA_PREAMBLE equ 0x4000
 
; Status
 
IntLatch equ 0x0001
HostError equ 0x0002
TxComplete equ 0x0004
315,18 → 285,15
RxEarly equ 0x0020
IntReq equ 0x0040
StatsFull equ 0x0080
DMADone equ 0x0100 ; 1 shl 8
DownComplete equ 0x0200 ; 1 shl 9
UpComplete equ 0x0400 ; 1 shl 10
DMADone equ 0x0100
DownComplete equ 0x0200
UpComplete equ 0x0400
DMAInProgress equ 0x0800 ; 1 shl 11 (DMA controller is still busy)
CmdInProgress equ 0x1000 ; 1 shl 12 (EL3_CMD is still busy)
 
S_5_INTS equ HostError + RxEarly + UpComplete + DownComplete ; + RxComplete + TxComplete + TxAvailable
S_5_INTS equ HostError + RxEarly + UpComplete + DownComplete ;+ TxComplete + RxComplete + TxAvailable
 
 
 
; Commands
 
TotalReset equ 0 shl 11
SelectWindow equ 1 shl 11
StartCoax equ 2 shl 11
354,30 → 321,48
StatsEnable equ 21 shl 11
StatsDisable equ 22 shl 11
StopCoax equ 23 shl 11
SetFilterBit equ 25 shl 11}
SetFilterBit equ 25 shl 11
 
 
; Rx mode bits
 
RxStation equ 1
RxMulticast equ 2
RxBroadcast equ 4
RxProm equ 8
 
 
; RX/TX buffers sizes
 
MAX_ETH_PKT_SIZE equ 1536 ; max packet size
NUM_RX_DESC equ 4 ; a power of 2 number
NUM_TX_DESC equ 4 ; a power of 2 number
RX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE*NUM_RX_DESC)
TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE*NUM_TX_DESC)
MAX_ETH_FRAME_SIZE equ 1520 ; size of ethernet frame + bytes alignment
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.dpd_buffer rd (dpd.size*NUM_TX_DESC)/4
.upd_buffer rd (upd.size*NUM_RX_DESC)/4
.curr_upd dd ?
.prev_dpd dd ?
 
.io_addr dd ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
 
.prev_tx_frame dd ?
.ver_id db ?
.full_bus_master db ?
.has_hwcksm db ?
.preamble db ?
.dn_list_ptr_cleared db ?
.self_directed_packet rb 20
 
.size = $ - device
 
end virtual
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
513,21 → 498,14
mov [device.pci_dev], cl
 
; 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]
 
; We've found the io address, find IRQ now
 
find_irq [device.pci_bus], [device.pci_dev], [device.irq_line]
 
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
allocate_and_clear [device.tx_buffer], (MAX_ETH_FRAME_SIZE*NUM_TX_DESC), .err
allocate_and_clear [device.rx_buffer], (MAX_ETH_FRAME_SIZE*NUM_RX_DESC), .err
allocate_and_clear [device.dpd_buffer], (dpd.size*NUM_TX_DESC), .err
allocate_and_clear [device.upd_buffer], (dpd.size*NUM_RX_DESC), .err
 
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
test eax, eax
579,8 → 557,6
; todo: reset device into virgin state
 
.err:
stdcall KernelFree, [device.rx_buffer]
stdcall KernelFree, [device.tx_buffer]
stdcall KernelFree, ebx
 
 
613,7 → 589,7
;***************************************************************************
 
align 4
probe: ; Tested - ok
probe:
 
DEBUGF 1,"Probing 3com card\n"
 
671,6 → 647,11
jnz .boomerang_func
mov [device.transmit], vortex_transmit
DEBUGF 1,"Device is a vortex type\n"
DEBUGF 1,"I'm sorry but vortex code hasnt been tested yet\n"
DEBUGF 1,"Please contact me on hidnplayr@kolibrios.org\n"
DEBUGF 1,"If you can help me finish it!\n"
or eax, -1
ret
jmp @f
.boomerang_func: ; full bus master, so use boomerang functions
mov [device.transmit], boomerang_transmit
812,6 → 793,9
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
ret
 
 
975,13 → 959,9
jnz .tx_reset_loop
.tx_set_prev:
; init last_dpd
mov eax, [device.dpd_buffer]
add eax, (NUM_TX_DESC-1)*dpd.size
lea eax, [device.dpd_buffer + (NUM_TX_DESC-1)*dpd.size]
mov [device.prev_dpd], eax
 
mov eax, [device.tx_buffer]
add eax, (NUM_TX_DESC-1)*MAX_ETH_FRAME_SIZE
mov [device.prev_tx_frame], eax
.tx_enable:
ret
 
1004,54 → 984,49
set_io REG_COMMAND
mov ax, RxReset or 0x4
out dx, ax
 
; wait for RxReset to complete
mov ecx, 200000
.rx_reset_loop:
.loop:
in ax, dx
test ah, 10000b ; check CmdInProgress
dec ecx
jnz .rx_reset_loop
jnz .loop
 
; create upd ring
lea eax, [device.upd_buffer]
GetRealAddr
mov edi, eax ; real addr of first descr
 
mov eax, [device.upd_buffer]
mov [device.curr_upd], eax
call GetPgAddr
mov esi, eax
lea esi, [device.upd_buffer] ; ptr to first descr
lea edx, [device.upd_buffer + (NUM_RX_DESC-1)*upd.size] ; ptr to last descr
 
mov eax, [device.rx_buffer]
call GetPgAddr
mov edi, eax
mov ecx, NUM_RX_DESC
 
mov edx, [device.upd_buffer]
add edx, (NUM_RX_DESC-1)*upd.size
.upd_loop:
mov [edx + upd.next_ptr], edi
 
mov eax, [device.upd_buffer]
push ecx edx
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
pop edx ecx
mov [esi + upd.realaddr], eax
call GetPgAddr
mov [esi + upd.frag_addr], eax
and [esi + upd.pkt_status], 0
mov [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
 
push ebx
mov ebx, [device.rx_buffer]
DEBUGF 1,"UPD: lin=%x phys=%x len=%x next ptr=%x\n", [esi+upd.realaddr]:8, [esi+upd.frag_addr]:8, [esi+upd.frag_len]:8, edi
DEBUGF 1,"UPD: cur=%x prev=%x\n", esi, edx
 
mov ecx, NUM_RX_DESC
.upd_loop:
mov [edx + upd.next_ptr], esi ; edx = upd buff
 
and [eax + upd.pkt_status], 0 ; eax = next upd buff
mov [eax + upd.frag_addr], edi
mov [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
mov [eax + upd.realaddr], ebx
 
add edi, MAX_ETH_FRAME_SIZE
add ebx, MAX_ETH_FRAME_SIZE
mov edx, esi
add esi, upd.size
mov edx, eax
add eax, upd.size
 
add edi, upd.size
dec ecx
jnz .upd_loop
 
pop ebx
 
mov eax, [device.upd_buffer]
call GetPgAddr
lea eax, [device.upd_buffer]
mov [device.curr_upd], eax
GetRealAddr
set_io 0
set_io REG_UP_LIST_PTR
out dx, eax
2228,6 → 2203,8
mov ax, (10100b shl 11) + 1 ; StartDMADown
out dx, ax
.finish:
call KernelFree
add esp, 4
ret
 
 
2245,26 → 2222,32
align 4
boomerang_transmit:
 
DEBUGF 1,"Sending packet (boomerang)\n"
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 .finish ; packet is too long
jg .fail
 
call check_tx_status
 
test al, al
jnz tx_reset
 
; calculate descriptor address
mov eax, [device.prev_dpd]
DEBUGF 1,"Previous DPD: %x\n", eax
add eax, dpd.size
mov ecx, [device.dpd_buffer]
add ecx, NUM_TX_DESC*dpd.size
cmp eax, ecx
cmovae eax, [device.dpd_buffer] ; Wrap if needed
mov esi, [device.prev_dpd]
DEBUGF 1,"Previous DPD: %x\n", esi
add esi, dpd.size
lea ecx, [device.dpd_buffer + (NUM_TX_DESC)*dpd.size]
cmp esi, ecx
jl @f
lea esi, [device.dpd_buffer] ; Wrap if needed
@@:
DEBUGF 1,"Found a free DPD: %x\n", esi
 
DEBUGF 1,"Found a free DPD: %x\n", eax
push eax
; check DnListPtr
set_io 0
set_io REG_DN_LIST_PTR
2272,91 → 2255,56
; mark if Dn_List_Ptr is cleared
test eax, eax
setz [device.dn_list_ptr_cleared]
 
; finish if no more free descriptor is available - FIXME!
cmp eax, [esp]
pop eax
jz .finish
; cmp eax, esi
; jz .finish
 
 
push eax ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; calculate tx_buffer address
mov edi, [device.prev_tx_frame]
DEBUGF 1,"Previous TX frame:: %x\n", edi
add edi, MAX_ETH_FRAME_SIZE
 
mov ecx, [device.tx_buffer]
add ecx, NUM_TX_DESC*MAX_ETH_FRAME_SIZE
cmp edi, ecx
cmovae edi, [device.tx_buffer] ; Wrap if needed
 
DEBUGF 1,"Found place in TX buffer: %x\n", edi
push edi ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 
; update statistics
inc [device.packets_tx]
 
mov ecx, [esp+8+8]
mov ecx, [esp+8] ; buffer size
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
 
; copy packet data
mov esi, [esp+4+8]
DEBUGF 1,"Copying %u bytes from %x to %x\n", ecx, esi, edi
shr cx , 1
jnc .nb
movsb
.nb:
shr cx , 1
jnc .nw
movsw
.nw:
rep movsd
 
; program DPD
mov eax, [esp] ; Tx buffer address
and [esi+dpd.next_ptr], 0
mov eax, [esp+4] ; Tx buffer address
mov [esi+dpd.realaddr], eax
call GetPgAddr
mov edi, [esp]
and edi, 4096 - 1
or edi, eax
mov [esi+dpd.frag_addr], eax
mov ecx, [esp+8] ; packet size
or ecx, 0x80000000 ; last fragment
mov [esi+dpd.frag_len], ecx
 
mov eax, [esp+4] ; descriptor
DEBUGF 1,"Frag addr is: %x\n", edi
and [eax+dpd.next_ptr], 0
mov [eax+dpd.frag_addr], edi
mov ecx, [esp+8] ; packet size
; or ecx, 0x8000 ; transmission complete notification
 
mov ecx, [esp+8+8] ; packet size
or ecx, 0x80000000 ; last fragment
DEBUGF 1,"Frag size + flag is: %x\n", ecx
mov [eax+dpd.frag_len], ecx
or ecx, 1 shl 31
 
mov ecx, [esp+8+8] ; packet size
or ecx, 0x8000 ; transmission complete notification
; test byte [device.has_hwcksm], 0xff
; jz @f
; or ecx, (1 shl 26) ; set AddTcpChecksum
;@@:
DEBUGF 1,"Frag start_hdr + flag is: %x\n", ecx
mov [eax+dpd.frame_start_hdr], ecx
mov [esi+dpd.frame_start_hdr], ecx
 
DEBUGF 1,"DPD: lin=%x phys=%x len=%x start hdr=%x\n", [esi+dpd.realaddr]:8, [esi+dpd.frag_addr]:8, [esi+dpd.frag_len]:8, [esi+dpd.frame_start_hdr]:8
 
; calculate physical address
mov edi, eax
call GetPgAddr
and edi, 4096 - 1
or eax, edi
; calculate physical address of dpd
mov eax, esi
GetRealAddr
cmp [device.dn_list_ptr_cleared], 0
jz .add_to_list
 
DEBUGF 1,"DN list ptr: %x\n", eax
; write Dn_List_Ptr
DEBUGF 1,"DPD phys addr=%x\n", eax
set_io 0
set_io REG_DN_LIST_PTR
out dx, eax
jmp .finish_pop
jmp .finish
 
.add_to_list:
 
DEBUGF 1,"Adding To list\n"
 
push eax
; DnStall
set_io 0
set_io REG_COMMAND
2364,7 → 2312,6
out dx, ax
 
; wait for DnStall to complete
 
DEBUGF 1,"Waiting for DnStall\n"
mov ecx, 6000
.wait_for_stall:
2376,7 → 2323,6
 
.dnstall_ok:
DEBUGF 1,"DnStall ok!\n"
mov eax, [esp] ; prev_tx_frame
mov ecx, [device.prev_dpd]
mov [ecx+dpd.next_ptr], eax
 
2383,12 → 2329,12
set_io 0
set_io REG_DN_LIST_PTR
in eax, dx
 
test eax, eax
pop eax
jnz .dnunstall
 
; if Dn_List_Ptr has been cleared fill it up
DEBUGF 1,"DnList Ptr has been cleared\n"
mov eax, [esp]
out dx, eax
 
.dnunstall:
2398,15 → 2344,16
mov ax, ((110b shl 11)+3)
out dx, ax
 
.finish_pop:
pop [device.prev_tx_frame]
pop [device.prev_dpd]
 
.finish:
mov [device.prev_dpd], esi
xor eax, eax
ret
ret 8
 
.fail:
stdcall KernelFree, [esp+4]
ret 8
 
 
;---------------------------------
; Write MAC
 
2581,7 → 2528,9
 
.read_frame:
; program buffer address to read in
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
push ecx
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
pop ecx
test eax, eax
jz .finish
 
2672,7 → 2621,7
align 4
int_boomerang:
 
; DEBUGF 1,"\nIRQ %x Boomerang\n",eax:2
DEBUGF 1,"\nIRQ %x Boomerang\n",eax:2
 
; find pointer of device wich made IRQ occur
 
2679,7 → 2628,6
mov esi, BOOMERANG_LIST
mov ecx, [BOOMERANG_DEVICES]
 
; DEBUGF 1,"Devices: %u\n", ecx
test ecx, ecx
jz .fail
.nextdevice:
2705,7 → 2653,6
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
 
push ax
; disable all INTS
 
2713,13 → 2660,6
mov ax, SetIntrEnb
out dx, ax
 
;; acknowledge all int sources
;
; mov ax, word [esp]
; and ax, 0xff
; or ax, AckIntr
; out dx, ax
 
;--------------------------------------------------------------------------
test word[esp], UpComplete
jz .noRX
2730,75 → 2670,59
DEBUGF 1,"UpComplete\n"
 
; check if packet is uploaded
mov eax, [device.curr_upd]
test byte [eax+upd.pkt_status+1], 0x80 ; upPktComplete
mov esi, [device.curr_upd]
test byte [esi+upd.pkt_status+1], 0x80 ; upPktComplete
jz .finish
DEBUGF 1, "Current upd: %x\n", esi
; packet is uploaded check for any error
.check_error:
test byte [eax+upd.pkt_status+1], 0x40 ; upError
test byte [esi+upd.pkt_status+1], 0x40 ; upError
jz .copy_packet_length
DEBUGF 1,"Error in packet\n"
and [eax+upd.pkt_status], 0 ; mark packet as read
and [esi+upd.pkt_status], 0 ; mark packet as read
jmp .finish
.copy_packet_length:
mov ecx, [eax+upd.pkt_status]
mov ecx, [esi+upd.pkt_status]
and ecx, 0x1fff
cmp ecx, MAX_ETH_PKT_SIZE
jbe .copy_packet
and [eax+upd.pkt_status], 0
jmp .finish
 
.copy_packet:
DEBUGF 1, " data hw addr:%x\n", [eax+upd.frag_addr]
; cmp ecx, MAX_ETH_PKT_SIZE
; jbe .copy_packet
; and [esi+upd.pkt_status], 0
; jmp .finish
; .copy_packet:
 
mov esi, [eax+upd.realaddr]
DEBUGF 1, "Received %u bytes in buffer %x\n", ecx, [esi+upd.realaddr]:8
 
push esi ecx
stdcall KernelAlloc, ecx ; Allocate a buffer to put packet into
pop ecx esi
test eax, eax
jz .finish
 
push dword .loop ;.finish
push ecx eax
mov edi, eax
push ecx
push [esi+upd.realaddr]
 
DEBUGF 1, " copying %u bytes from %x to %x\n", ecx, esi, edi
 
; update statistics
inc [device.packets_rx]
 
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
 
; copy packet data
shr cx , 1
jnc .nb
movsb
.nb:
shr cx , 1
jnc .nw
movsw
.nw:
rep movsd
; update UPD (Alloc new buffer for next packet)
stdcall KernelAlloc, MAX_ETH_FRAME_SIZE
mov [esi + upd.realaddr], eax
GetRealAddr
mov [esi + upd.frag_addr], eax
and [esi + upd.pkt_status], 0
mov [esi + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31)
 
mov eax, [device.curr_upd]
DEBUGF 1, "current upd: %x\n", eax
and [eax + upd.pkt_status], 0 ; clear the ring buffer entry for reuse
mov [eax + upd.frag_len], MAX_ETH_FRAME_SIZE or (1 shl 31) ;;;
add eax, upd.size
; Update UPD pointer
add esi, upd.size
lea ecx, [device.upd_buffer+(NUM_RX_DESC)*upd.size]
cmp esi, ecx
jl @f
lea esi, [device.upd_buffer]
@@:
mov [device.curr_upd], esi
DEBUGF 1, "Next upd: %x\n", esi
 
mov ecx, [device.upd_buffer]
add ecx, (NUM_RX_DESC)*upd.size
 
cmp eax, ecx
cmovae eax, [device.upd_buffer]
mov [device.curr_upd], eax
DEBUGF 1, "next upd: %x\n", eax
 
jmp EthReceiver
.loop:
 
.loop:
mov ebx, [esp]
jmp .receive
 
2811,14 → 2735,38
in eax, dx
test ah, 0x20 ; UpStalled
jz .noUpUnStall
 
DEBUGF 1, "upUnStalling\n"
; issue upUnStall command
set_io REG_COMMAND
mov ax, ((11b shl 12)+1) ; upUnStall
out dx, ax
DEBUGF 1, "upUnStalling\n"
 
;;;; FIXME: make upunstall work
 
.noUpUnStall:
.noRX:
test word[esp], DownComplete
jz .noTX
DEBUGF 1, "Downcomplete!\n"
 
.noRX:
mov ecx, NUM_TX_DESC
lea esi, [device.dpd_buffer]
.txloop:
test [esi+dpd.frame_start_hdr], 1 shl 31
jz .maybenext
 
and [esi+dpd.frame_start_hdr], 0
push ecx
stdcall KernelFree, [esi+dpd.realaddr]
pop ecx
 
.maybenext:
add esi, dpd.size
dec ecx
jnz .txloop
 
.noTX:
pop ax
 
set_io 0
2826,11 → 2774,6
or ax, AckIntr
out dx, ax
 
; set_io REG_COMMAND
; mov ax, AckIntr + IntLatch
; out dx, ax
 
 
set_io REG_INT_STATUS
in ax, dx
test ax, S_5_INTS
2841,7 → 2784,6
mov ax, SetIntrEnb + S_5_INTS
out dx, ax
 
 
ret
 
 
2848,11 → 2790,8
 
 
; End of code
 
align 4 ; Place all initialised data here
 
 
 
macro strtbl name, [string]
{
common
2866,7 → 2805,7
 
VORTEX_DEVICES dd 0
BOOMERANG_DEVICES dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db '3C59X',0 ; max 16 chars include zero
 
 
3001,7 → 2940,6
; 3c920B-EMB-WNM Tornado
HW_VERSIONS_SIZE = $ - hw_versions
 
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
/kernel/branches/net/drivers/RTL8029.asm
1,10 → 1,13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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 ;;
;; ;;
;; RTL8029/ne2000 driver for KolibriOS ;;
;; ;;
;; based on RTL8029.asm driver for menuetos ;;
;; and realtek8029.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; with help from CleverMouse ;;
;; ;;
11,19 → 14,15
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; current status (september 2009) - UNSTABLE ;;
;; ;;
;; based on RTL8029.asm driver for menuetos ;;
;; and realtek8029.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;$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
33,11 → 32,6
include 'fdo.inc'
include 'netdrv.inc'
 
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
 
 
virtual at ebx
 
device:
68,8 → 62,6
public service_proc
public version
 
MAX_DEVICES equ 16 ; Max number of devices this driver may handle
 
P0_PSTART equ 0x01
P0_PSTOP equ 0x02
P0_BOUND equ 0x03
234,8 → 226,8
 
; check if the device is already listed
 
mov esi, DEVICE_LIST
mov ecx, [DEVICES]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice_pci
 
269,8 → 261,8
 
.isa:
 
mov esi, DEVICE_LIST
mov ecx, [DEVICES]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice_isa
mov al , [eax+3]
305,9 → 297,9
test eax, eax
jnz .err ; If an error occured, exit
 
mov eax, [DEVICES]
mov [DEVICE_LIST+4*eax], ebx
inc [DEVICES]
mov eax, [devices]
mov [device_list+4*eax], ebx
inc [devices]
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
346,7 → 338,7
 
create_new_struct:
 
cmp [DEVICES], MAX_DEVICES
cmp [devices], MAX_DEVICES
jge .fail
 
push edx
670,6 → 662,9
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
; Indicate that we have successfully reset the card
DEBUGF 2,"Done!\n"
 
733,10 → 728,14
adc dword [device.bytes_tx + 4], 0
 
.finish:
call Kernelfree
add esp, 4
xor eax, eax
ret
 
.err:
call Kernelfree
add esp, 4
or eax, -1
ret
 
752,8 → 751,8
DEBUGF 2,"IRQ %x ",eax:2
 
; find pointer of device wich made INT occur
mov esi, DEVICE_LIST
mov ecx, [DEVICES]
mov esi, device_list
mov ecx, [devices]
.nextdevice:
mov ebx, [esi]
 
1197,8 → 1196,8
;all initialized data place here
align 4
 
DEVICES dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8029/ne2000',0 ;max 16 chars include zero
 
device_1 db 'Realtek 8029',0
1213,7 → 1212,7
 
section '.data' data readable writable align 16 ;place all uninitialized data place here
 
DEVICE_LIST rd MAX_DEVICES
device_list rd MAX_DEVICES
 
 
 
/kernel/branches/net/drivers/RTL8139.asm
5,21 → 5,23
;; ;;
;; Realtek 8139 driver for KolibriOS ;;
;; ;;
;; based on RTL8139.asm driver for menuetos ;;
;; and realtek8139.asm for SolarOS by Eugen Brasoveanu ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; 0.1 - x march 2009 ;;
;; 0.2 - 8 november 2009 ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
format MS COFF
 
API_VERSION equ 0x01000100
DRIVER_VERSION equ 5
 
MAX_DEVICES equ 16
 
DEBUG equ 1
__DEBUG__ equ 1
__DEBUG_LEVEL__ equ 2
29,46 → 31,10
include 'fdo.inc'
include 'netdrv.inc'
 
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
 
public START
public service_proc
public version
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.rx_buffer dd ?
.tx_buffer dd ?
.rx_data_offset dd ?
.io_addr dd ?
.curr_tx_desc db ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
.hw_ver_id db ?
 
.size = $ - device
 
end virtual
 
 
; RTL8139 specific defines
 
MAX_RTL8139 equ 16 ; Max number of devices this driver may handle
TX_TIMEOUT equ 30 ; 300 milliseconds timeout
 
PCI_REG_CMD 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
 
REG_IDR0 equ 0x00
REG_MAR0 equ 0x08 ; multicast filter register 0
REG_MAR4 equ 0x0c ; multicast filter register 4
169,8 → 135,8
 
RX_BUFFER_SIZE equ (8192 shl RBLEN);+16
MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC
 
NUM_TX_DESC equ 4
TX_BUF_SIZE equ 4096 ; size of one tx buffer (set to 4kb because of KolibriOS's page size)
 
EE_93C46_REG_ETH_ID equ 7 ; MAC offset
EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address
228,7 → 194,31
TSR_CRS equ 1 SHL 31
 
 
virtual at ebx
 
device:
 
ETH_DEVICE
 
.rx_buffer dd ?
.tx_buffer dd ?
.rx_data_offset dd ?
.io_addr dd ?
.curr_tx_desc db ?
.last_tx_desc db ?
.pci_bus db ?
.pci_dev db ?
.irq_line db ?
.hw_ver_id db ?
 
.TX_DESC rd NUM_TX_DESC
 
.size = $ - device
 
end virtual
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
298,8 → 288,8
 
; check if the device is already listed
 
mov esi, RTL8139_LIST
mov ecx, [RTL8139_DEV]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
315,7 → 305,7
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [RTL8139_DEV], MAX_RTL8139 ; First check if the driver can handle one more card
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jge .fail
 
push edx
355,7 → 345,7
 
 
allocate_and_clear [device.rx_buffer], (RX_BUFFER_SIZE+MAX_ETH_FRAME_SIZE), .err
allocate_and_clear [device.tx_buffer], (TX_BUF_SIZE*NUM_TX_DESC), .err
;; allocate_and_clear [device.tx_buffer], (TX_BUF_SIZE*NUM_TX_DESC), .err
 
; Ok, the eth_device structure is ready, let's probe the device
 
363,11 → 353,10
test eax, eax
jnz .err ; If an error occured, exit
 
mov eax, [RTL8139_DEV] ; Add the device structure to our device list
mov [RTL8139_LIST+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [RTL8139_DEV] ;
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
 
393,7 → 382,7
 
.err:
stdcall KernelFree, dword [device.rx_buffer]
stdcall KernelFree, dword [device.tx_buffer]
;; stdcall KernelFree, dword [device.tx_buffer]
stdcall KernelFree, ebx
 
 
613,6 → 602,7
 
mov [device.rx_data_offset], eax
mov [device.curr_tx_desc], al
mov [device.last_tx_desc], al
 
; clear packet/byte counters
 
625,21 → 615,6
set_io REG_MPC
out dx , eax
 
; Set up the 4 Txbuffer descriptors
 
set_io REG_TSAD0
mov eax, [device.tx_buffer]
mov ecx, 4
.loop:
push eax
call GetPgAddr
DEBUGF 1,"Desc: %x ", eax
out dx , eax
add dx , 4
pop eax
add eax, TX_BUF_SIZE
loop .loop
 
; set RxBuffer address, init RX buffer offset
 
mov eax, [device.rx_buffer]
658,6 → 633,9
 
call read_mac
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
; Indicate that we have successfully reset the card
 
DEBUGF 2,"Done!\n"
675,7 → 653,6
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
686,91 → 663,88
[eax+13]:2,[eax+12]:2
 
cmp dword [esp+8], MAX_ETH_FRAME_SIZE
jg .finish ; packet is too long
jg .fail
cmp dword [esp+8], 60
jl .finish ; packet is too short
jl .fail
 
; check descriptor
DEBUGF 1,"Checking descriptor, "
; check if we own the discriptor
set_io 0
movzx ecx, [device.curr_tx_desc]
mov edx, [device.io_addr]
lea edx, [edx+ecx*4+REG_TSD0]
shl ecx, 2
lea edx, [edx+ecx+REG_TSD0]
in ax, dx
test ax, 0x1fff ; or no size given
jz .send_packet
and ax, (1 shl BIT_TOK) or (1 shl BIT_OWN)
cmp ax, (1 shl BIT_TOK) or (1 shl BIT_OWN)
jz .send_packet
; wait for timeout
DEBUGF 1,"Waiting for timeout, "
test ax, (1 shl BIT_OWN)
jz .wait_to_send
 
push edx ebx ; TODO : rtl8139 internal timer should be used instead
stdcall Sleep, TX_TIMEOUT ; ? What registers does this destroy ?
pop ebx edx
 
in ax, dx
and ax, (1 shl BIT_TOK) or (1 shl BIT_OWN)
cmp ax, (1 shl BIT_TOK) or (1 shl BIT_OWN)
jz .send_packet ; if chip hung, reset it
push dx
call reset ; reset the card
pop dx
.send_packet:
DEBUGF 1,"Sending packet, "
; Set the buffer address
set_io 0
lea edx, [edx+ecx+REG_TSAD0]
mov eax, [esp+4]
mov [device.TX_DESC+ecx], eax
GetRealAddr
out dx, eax
 
push edx
movzx eax, [device.curr_tx_desc] ; calculate the current tx_buffer address
mov edx, TX_BUF_SIZE ;MAX_ETH_FRAME_SIZE ;
mul edx ;
mov edi, [device.tx_buffer] ;
add edi, eax ; Store it in edi
pop edx
; And the size of the buffer
set_io 0
lea edx, [edx+ecx+REG_TSD0]
mov eax, [esp+8]
; or eax, (ERTXTH shl BIT_ERTXTH) ; Early threshold
out dx , eax
 
mov esi, [esp+4] ; Copy data to that address
mov ecx, [esp+8] ;
shr ecx, 2 ;
rep movsd ;
mov ecx, [esp+8] ;
and ecx, 3 ;
rep movsb ;
 
inc [device.packets_tx] ;
mov eax, [esp+8] ; Get packet size in eax
 
; Update stats
inc [device.packets_tx]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
 
; or eax, (ERTXTH shl BIT_ERTXTH) ; Set descriptor size and the early tx treshold into the correct Transmission status register (TSD0, TSD1, TSD2 or TSD3)
out dx , eax ;
 
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
; get next descriptor
inc [device.curr_tx_desc]
and [device.curr_tx_desc], 3
 
DEBUGF 1," - Packet Sent! "
.finish:
DEBUGF 1," - Done!\n"
ret
DEBUGF 1,"Packet Sent! "
xor eax, eax
ret 8
 
.wait_to_send:
 
DEBUGF 1,"Waiting for timeout\n"
 
mov esi, 30
stdcall Sleep
 
in ax, dx
test ax, (1 shl BIT_OWN)
jnz .send_packet
 
pusha
call reset ; if chip hung, reset it
popa
 
jmp .send_packet
 
.fail:
DEBUGF 1,"failed!\n"
or eax, -1
ret 8
 
 
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
DEBUGF 1,"IRQ %x ",eax:2 ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
DEBUGF 1,"IRQ %x\n", eax:2 ; no, you cant replace 'eax:2' with 'al', this must be a bug in FDO
 
; find pointer of device wich made IRQ occur
 
mov esi, RTL8139_LIST
mov ecx, [RTL8139_DEV]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .fail
.nextdevice:
799,7 → 773,6
 
;----------------------------------------------------
; Received packet ok?
 
test ax, ISR_ROK
jz @f
push ax
836,7 → 809,6
test eax, eax ; Test if we allocated succesfully
jz .abort
 
 
mov edi, eax ; Where we will copy too
 
mov esi, [esp] ; The buffer we will copy from
914,60 → 886,78
 
;----------------------------------------------------
; Transmit error ?
 
@@:
test ax, ISR_TER
jz @f
 
; push ax
; cmp [device.curr_tx_desc], 4
; jz .notxd
;
; set_io 0
; movzx ecx, [device.curr_tx_desc]
; lea edx, [edx+ecx*4+REG_TSD0]
; in eax, dx
;
; .notxd:
; test eax, TSR_TUN
; jz .nobun
; DEBUGF 2, "TX: FIFO Buffer underrun!\n"
;
; .nobun:
; test eax, TSR_OWC
; jz .noowc
; DEBUGF 2, "TX: OWC!\n"
;
; .noowc:
; test eax, TSR_TABT
; jz .notabt
; DEBUGF 2, "TX: TABT!\n"
;
; .notabt:
; test eax, TSR_CRS
; jz .nocsl
; DEBUGF 2, "TX: Carrier Sense Lost!\n"
;
; .nocsl:
; pop ax
 
;----------------------------------------------------
; Transmit ok ?
@@:
test ax, ISR_TOK
jz @f
 
push ax
cmp [device.curr_tx_desc], 4
jz .notxd
mov si, 4
.txdesloop:
movzx ecx, [device.last_tx_desc]
shl ecx, 2
 
set_io 0
movzx ecx, [device.curr_tx_desc]
lea edx, [edx+ecx*4+REG_TSD0]
set_io REG_TSD0
add edx, ecx
in eax, dx
 
.notxd:
test eax, TSR_TUN
jz .nobun
DEBUGF 2, "TX: FIFO Buffer underrun!\n"
test eax, TSR_TOK
jz .notthisone
mov eax, TSR_OWN
out dx , eax
DEBUGF 1,"TX OK: free buffer %x\n", [device.TX_DESC+ecx]:8
stdcall KernelFree, [device.TX_DESC+ecx]
.notthisone:
 
.nobun:
test eax, TSR_OWC
jz .noowc
DEBUGF 2, "TX: OWC!\n"
inc [device.last_tx_desc]
and [device.last_tx_desc], 3
 
.noowc:
test eax, TSR_TABT
jz .notabt
DEBUGF 2, "TX: TABT!\n"
dec si
jnz .txdesloop
 
.notabt:
test eax, TSR_CRS
jz .nocsl
DEBUGF 2, "TX: Carrier Sense Lost!\n"
 
.nocsl:
; test eax, TSR_OWN or TSR_TOK
; jz .nofd
; DEBUGF 1, "TX: Transmit OK (desc: %u)\n", ecx
;
; .nofd:
.done:
pop ax
 
;----------------------------------------------------
; Transmit ok ?
 
@@:
test ax, ISR_TOK
jz @f
 
DEBUGF 1, "TX: Transmit OK (desc: %u)\n", [device.curr_tx_desc]:1
 
;----------------------------------------------------
; Rx buffer overflow ?
 
@@:
test ax, ISR_RXOVW
jz @f
975,16 → 965,14
push ax
DEBUGF 2,"RX-buffer overflow!\n"
 
mov edx, [device.io_addr]
add edx, REG_ISR
set_io 0
set_io REG_ISR
mov ax , ISR_FIFOOVW or ISR_RXOVW
out dx , ax
pop ax
 
;----------------------------------------------------
; Packet underrun? ?
 
 
; Packet underrun?
@@:
test ax, ISR_PUN
jz @f
993,16 → 981,15
 
;----------------------------------------------------
; Receive FIFO overflow ?
 
@@:
test ax, ISR_FIFOOVW
jz @f
 
push ax
DEBUGF 2,"RX fifo overflox!\n"
DEBUGF 2,"RX fifo overflow!\n"
 
mov edx, [device.io_addr]
add edx, REG_ISR
set_io 0
set_io REG_ISR
mov ax , ISR_FIFOOVW or ISR_RXOVW
out dx , ax
pop ax
1009,7 → 996,6
 
;----------------------------------------------------
; Something about Cable changed ?
 
@@:
test ax, ISR_LENCHG
jz .fail
1017,11 → 1003,7
DEBUGF 2,"Cable changed!\n"
call cable
 
; If none of the above events happened, just exit clearing int
 
.fail:
 
DEBUGF 1,"\n"
ret
 
 
1213,10 → 1195,11
 
; End of code
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
align 4 ; Place all initialised data here
 
RTL8139_DEV dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'RTL8139',0 ; max 16 chars include zero
 
device_1 db 'Realtek 8139',0
1229,7 → 1212,8
device_8 db 'Realtek 8101',0
device_unknown db 'Unknown RTL8139 clone', 0
 
crosslist dd device_1
crosslist:
dd device_1
dd device_2
dd device_3
dd device_4
1239,7 → 1223,8
dd device_8
dd device_unknown
 
hw_ver_array db VER_RTL8139 ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
hw_ver_array: ; This array is used by the probe routine to find out wich version of the RTL8139 we are working with
db VER_RTL8139
db VER_RTL8139A
db VER_RTL8139B
db VER_RTL8139C
1253,7 → 1238,5
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
RTL8139_LIST rd MAX_RTL8139 ; This list contains all pointers to device structures the driver is handling
 
/kernel/branches/net/drivers/dec21x4x.asm
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; DEC 21x4x driver for KolibriOS ;;
11,8 → 11,6
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; 0.1 - 5 june 2010 ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
21,7 → 19,10
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
31,15 → 32,10
include 'fdo.inc'
include 'netdrv.inc'
 
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
 
public START
public service_proc
public version
 
 
virtual at ebx
 
device:
46,7 → 42,6
 
ETH_DEVICE
 
; device specific
.rx_p_des dd ? ; descriptors ring with received packets
.tx_p_des dd ? ; descriptors ring with 'to transmit' packets
.tx_free_des dd ? ; Tx descriptors available
63,10 → 58,6
 
end virtual
 
 
 
MAX_DEVICES equ 16
 
;-------------------------------------------
; configuration registers
;-------------------------------------------
381,7 → 372,7
 
; check if the device is already listed
 
mov esi, DEVICE_LIST
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
442,7 → 433,7
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
mov eax, [devices] ; Add the device structure to our device list
mov [DEVICE_LIST+4*eax], ebx ; (IRQ handler uses this list to find device)
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
call probe ; this function will output in eax
771,6 → 762,9
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
DEBUGF 1,"Reset done\n"
 
ret
1000,15 → 994,18
 
DEBUGF 1,"transmit ok\n"
xor eax, eax
call Kernelfree
add esp, 4
ret
 
.fail:
DEBUGF 1,"transmit failed\n"
or eax, -1
call Kernelfree
add esp, 4
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
1025,7 → 1022,7
mov ecx, [devices]
test ecx, ecx
jz .fail
mov esi, DEVICE_LIST
mov esi, device_list
.nextdevice:
mov ebx, dword [esi]
 
1701,11 → 1698,10
 
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'DEC21X4X',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
1712,6 → 1708,6
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
DEVICE_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
 
 
/kernel/branches/net/drivers/netdrv.inc
187,28 → 187,37
}
 
macro NET_DEVICE {
.type dd ?
 
.type dd ? ; Type field
.mtu dd ? ; Maximal Transmission Unit
.name dd ? ; Ptr to 0 terminated string
 
.unload dd ? ; Ptrs to driver functions
.reset dd ? ;
.transmit dd ? ;
 
.bytes_tx dq ? ; Statistics, updated by the driver
.bytes_rx dq ? ;
.packets_tx dd ? ;
.packets_rx dd ? ;
 
.end:
}
 
;struc ETH_DEVICE {
macro ETH_DEVICE {
NET_DEVICE
; pointers to procedures
.unload dd ?
.reset dd ?
.transmit dd ?
 
.set_mode dd ?
.get_mode dd ?
 
.set_MAC dd ?
.get_MAC dd ?
.set_mode dd ?
.get_mode dd ?
; status
.bytes_tx dq ?
.bytes_rx dq ?
.packets_tx dd ?
.packets_rx dd ?
 
.mode dd ?
.name dd ?
.mac dp ?
dp ? ; qword alignment
 
}
 
 
215,19 → 224,12
 
macro SLIP_DEVICE {
NET_DEVICE
; pointers to procedures
.unload dd ?
.reset dd ?
.transmit dd ?
 
.set_mode dd ?
.get_mode dd ?
; status
.bytes_tx dq ?
.bytes_rx dq ?
.packets_tx dd ?
.packets_rx dd ?
 
.mode dd ?
.name dd ?
 
}
 
macro GetRealAddr {
235,7 → 237,7
push eax
call GetPgAddr
and dword [esp], (PAGESIZE - 1)
add eax, dword [esp]
or eax, dword [esp]
add esp, 4
 
}
/kernel/branches/net/drivers/pcnet32.asm
1,27 → 1,28
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; PCnet32 driver for KolibriOS ;;
;; ;;
;; Based on the PCnet32 driver for MenuetOS, by Jarek Pelczar ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Status: under construction ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; $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
 
MAX_PCNET equ 4
MAX_ETH_FRAME_SIZE equ 1514
 
include 'proc32.inc'
include 'imports.inc'
28,11 → 29,6
include 'fdo.inc'
include 'netdrv.inc'
 
 
OS_BASE equ 0
new_app_base equ 0x60400000
PROC_BASE equ OS_BASE+0x0080000
 
public START
public service_proc
public version
154,257 → 150,250
 
; PCI Bus defines
 
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
PORT_AUI equ 0x00
PORT_10BT equ 0x01
PORT_GPSI equ 0x02
PORT_MII equ 0x03
PORT_PORTSEL equ 0x03
PORT_ASEL equ 0x04
PORT_100 equ 0x40
PORT_FD equ 0x80
 
PCNET_PORT_AUI equ 0x00
PCNET_PORT_10BT equ 0x01
PCNET_PORT_GPSI equ 0x02
PCNET_PORT_MII equ 0x03
PCNET_PORT_PORTSEL equ 0x03
PCNET_PORT_ASEL equ 0x04
PCNET_PORT_100 equ 0x40
PCNET_PORT_FD equ 0x80
DMA_MASK equ 0xffffffff
 
PCNET_DMA_MASK equ 0xffffffff
LOG_TX_BUFFERS equ 2
LOG_RX_BUFFERS equ 2
 
PCNET_LOG_TX_BUFFERS equ 2
PCNET_LOG_RX_BUFFERS equ 2
TX_RING_SIZE equ 4
TX_RING_MOD_MASK equ (TX_RING_SIZE-1)
TX_RING_LEN_BITS equ (LOG_TX_BUFFERS shl 12)
 
PCNET_TX_RING_SIZE equ 4
PCNET_TX_RING_MOD_MASK equ (PCNET_TX_RING_SIZE-1)
PCNET_TX_RING_LEN_BITS equ (PCNET_LOG_TX_BUFFERS shl 12)
RX_RING_SIZE equ 4
RX_RING_MOD_MASK equ (RX_RING_SIZE-1)
RX_RING_LEN_BITS equ (LOG_RX_BUFFERS shl 4)
 
PCNET_RX_RING_SIZE equ 4
PCNET_RX_RING_MOD_MASK equ (PCNET_RX_RING_SIZE-1)
PCNET_RX_RING_LEN_BITS equ (PCNET_LOG_RX_BUFFERS shl 4)
PKT_BUF_SZ equ 1544
PKT_BUF_SZ_NEG equ 0xf9f8
 
PCNET_PKT_BUF_SZ equ 1544
PCNET_PKT_BUF_SZ_NEG equ 0xf9f8
WIO_RDP equ 0x10
WIO_RAP equ 0x12
WIO_RESET equ 0x14
WIO_BDP equ 0x16
DWIO_RDP equ 0x10
DWIO_RAP equ 0x14
DWIO_RESET equ 0x18
DWIO_BDP equ 0x1C
TOTAL_SIZE equ 0x20
 
PCNET_WIO_RDP equ 0x10
PCNET_WIO_RAP equ 0x12
PCNET_WIO_RESET equ 0x14
PCNET_WIO_BDP equ 0x16
PCNET_DWIO_RDP equ 0x10
PCNET_DWIO_RAP equ 0x14
PCNET_DWIO_RESET equ 0x18
PCNET_DWIO_BDP equ 0x1C
PCNET_TOTAL_SIZE equ 0x20
 
; CSR registers
 
PCNET_CSR_CSR equ 0x00
PCNET_CSR_IAB0 equ 0x01
PCNET_CSR_IAB1 equ 0x02
PCNET_CSR_IMR equ 0x03
PCNET_CSR_TFEAT equ 0x04
PCNET_CSR_EXTCTL1 equ 0x05
PCNET_CSR_DTBLLEN equ 0x06
PCNET_CSR_EXTCTL2 equ 0x07
PCNET_CSR_MAR0 equ 0x08
PCNET_CSR_MAR1 equ 0x09
PCNET_CSR_MAR2 equ 0x0A
PCNET_CSR_MAR3 equ 0x0B
PCNET_CSR_PAR0 equ 0x0C
PCNET_CSR_PAR1 equ 0x0D
PCNET_CSR_PAR2 equ 0x0E
PCNET_CSR_MODE equ 0x0F
PCNET_CSR_RXADDR0 equ 0x18
PCNET_CSR_RXADDR1 equ 0x19
PCNET_CSR_TXADDR0 equ 0x1E
PCNET_CSR_TXADDR1 equ 0x1F
PCNET_CSR_TXPOLL equ 0x2F
PCNET_CSR_RXPOLL equ 0x31
PCNET_CSR_RXRINGLEN equ 0x4C
PCNET_CSR_TXRINGLEN equ 0x4E
PCNET_CSR_DMACTL equ 0x50
PCNET_CSR_BUSTIMER equ 0x52
PCNET_CSR_MEMERRTIMEO equ 0x64
PCNET_CSR_ONNOWMISC equ 0x74
PCNET_CSR_ADVFEAT equ 0x7A
PCNET_CSR_MACCFG equ 0x7D
PCNET_CSR_CHIPID0 equ 0x58
PCNET_CSR_CHIPID1 equ 0x59
CSR_CSR equ 0x00
CSR_IAB0 equ 0x01
CSR_IAB1 equ 0x02
CSR_IMR equ 0x03
CSR_TFEAT equ 0x04
CSR_EXTCTL1 equ 0x05
CSR_DTBLLEN equ 0x06
CSR_EXTCTL2 equ 0x07
CSR_MAR0 equ 0x08
CSR_MAR1 equ 0x09
CSR_MAR2 equ 0x0A
CSR_MAR3 equ 0x0B
CSR_PAR0 equ 0x0C
CSR_PAR1 equ 0x0D
CSR_PAR2 equ 0x0E
CSR_MODE equ 0x0F
CSR_RXADDR0 equ 0x18
CSR_RXADDR1 equ 0x19
CSR_TXADDR0 equ 0x1E
CSR_TXADDR1 equ 0x1F
CSR_TXPOLL equ 0x2F
CSR_RXPOLL equ 0x31
CSR_RXRINGLEN equ 0x4C
CSR_TXRINGLEN equ 0x4E
CSR_DMACTL equ 0x50
CSR_BUSTIMER equ 0x52
CSR_MEMERRTIMEO equ 0x64
CSR_ONNOWMISC equ 0x74
CSR_ADVFEAT equ 0x7A
CSR_MACCFG equ 0x7D
CSR_CHIPID0 equ 0x58
CSR_CHIPID1 equ 0x59
 
; Control and Status Register (CSR0)
 
PCNET_CSR_INIT equ 1 shl 0
PCNET_CSR_START equ 1 shl 1
PCNET_CSR_STOP equ 1 shl 2
PCNET_CSR_TX equ 1 shl 3
PCNET_CSR_TXON equ 1 shl 4
PCNET_CSR_RXON equ 1 shl 5
PCNET_CSR_INTEN equ 1 shl 6
PCNET_CSR_INTR equ 1 shl 7
PCNET_CSR_IDONE equ 1 shl 8
PCNET_CSR_TINT equ 1 shl 9
PCNET_CSR_RINT equ 1 shl 10
PCNET_CSR_MERR equ 1 shl 11
PCNET_CSR_MISS equ 1 shl 12
PCNET_CSR_CERR equ 1 shl 13
CSR_INIT equ 1 shl 0
CSR_START equ 1 shl 1
CSR_STOP equ 1 shl 2
CSR_TX equ 1 shl 3
CSR_TXON equ 1 shl 4
CSR_RXON equ 1 shl 5
CSR_INTEN equ 1 shl 6
CSR_INTR equ 1 shl 7
CSR_IDONE equ 1 shl 8
CSR_TINT equ 1 shl 9
CSR_RINT equ 1 shl 10
CSR_MERR equ 1 shl 11
CSR_MISS equ 1 shl 12
CSR_CERR equ 1 shl 13
 
; Interrupt masks and deferral control (CSR3)
 
PCNET_IMR_BSWAP equ 0x0004
PCNET_IMR_ENMBA equ 0x0008 ; enable modified backoff alg
PCNET_IMR_DXMT2PD equ 0x0010
PCNET_IMR_LAPPEN equ 0x0020 ; lookahead packet processing enb
PCNET_IMR_DXSUFLO equ 0x0040 ; disable TX stop on underflow
PCNET_IMR_IDONE equ 0x0100
PCNET_IMR_TINT equ 0x0200
PCNET_IMR_RINT equ 0x0400
PCNET_IMR_MERR equ 0x0800
PCNET_IMR_MISS equ 0x1000
IMR_BSWAP equ 0x0004
IMR_ENMBA equ 0x0008 ; enable modified backoff alg
IMR_DXMT2PD equ 0x0010
IMR_LAPPEN equ 0x0020 ; lookahead packet processing enb
IMR_DXSUFLO equ 0x0040 ; disable TX stop on underflow
IMR_IDONE equ 0x0100
IMR_TINT equ 0x0200
IMR_RINT equ 0x0400
IMR_MERR equ 0x0800
IMR_MISS equ 0x1000
 
PCNET_IMR equ PCNET_IMR_TINT+PCNET_IMR_RINT+PCNET_IMR_IDONE+PCNET_IMR_MERR+PCNET_IMR_MISS
IMR equ IMR_TINT+IMR_RINT+IMR_IDONE+IMR_MERR+IMR_MISS
 
; Test and features control (CSR4)
 
PCNET_TFEAT_TXSTRTMASK equ 0x0004
PCNET_TFEAT_TXSTRT equ 0x0008
PCNET_TFEAT_RXCCOFLOWM equ 0x0010 ; Rx collision counter oflow
PCNET_TFEAT_RXCCOFLOW equ 0x0020
PCNET_TFEAT_UINT equ 0x0040
PCNET_TFEAT_UINTREQ equ 0x0080
PCNET_TFEAT_MISSOFLOWM equ 0x0100
PCNET_TFEAT_MISSOFLOW equ 0x0200
PCNET_TFEAT_STRIP_FCS equ 0x0400
PCNET_TFEAT_PAD_TX equ 0x0800
PCNET_TFEAT_TXDPOLL equ 0x1000
PCNET_TFEAT_DMAPLUS equ 0x4000
TFEAT_TXSTRTMASK equ 0x0004
TFEAT_TXSTRT equ 0x0008
TFEAT_RXCCOFLOWM equ 0x0010 ; Rx collision counter oflow
TFEAT_RXCCOFLOW equ 0x0020
TFEAT_UINT equ 0x0040
TFEAT_UINTREQ equ 0x0080
TFEAT_MISSOFLOWM equ 0x0100
TFEAT_MISSOFLOW equ 0x0200
TFEAT_STRIP_FCS equ 0x0400
TFEAT_PAD_TX equ 0x0800
TFEAT_TXDPOLL equ 0x1000
TFEAT_DMAPLUS equ 0x4000
 
; Extended control and interrupt 1 (CSR5)
 
PCNET_EXTCTL1_SPND equ 0x0001 ; suspend
PCNET_EXTCTL1_MPMODE equ 0x0002 ; magic packet mode
PCNET_EXTCTL1_MPENB equ 0x0004 ; magic packet enable
PCNET_EXTCTL1_MPINTEN equ 0x0008 ; magic packet interrupt enable
PCNET_EXTCTL1_MPINT equ 0x0010 ; magic packet interrupt
PCNET_EXTCTL1_MPPLBA equ 0x0020 ; magic packet phys. logical bcast
PCNET_EXTCTL1_EXDEFEN equ 0x0040 ; excessive deferral interrupt enb.
PCNET_EXTCTL1_EXDEF equ 0x0080 ; excessive deferral interrupt
PCNET_EXTCTL1_SINTEN equ 0x0400 ; system interrupt enable
PCNET_EXTCTL1_SINT equ 0x0800 ; system interrupt
PCNET_EXTCTL1_LTINTEN equ 0x4000 ; last TX interrupt enb
PCNET_EXTCTL1_TXOKINTD equ 0x8000 ; TX OK interrupt disable
EXTCTL1_SPND equ 0x0001 ; suspend
EXTCTL1_MPMODE equ 0x0002 ; magic packet mode
EXTCTL1_MPENB equ 0x0004 ; magic packet enable
EXTCTL1_MPINTEN equ 0x0008 ; magic packet interrupt enable
EXTCTL1_MPINT equ 0x0010 ; magic packet interrupt
EXTCTL1_MPPLBA equ 0x0020 ; magic packet phys. logical bcast
EXTCTL1_EXDEFEN equ 0x0040 ; excessive deferral interrupt enb.
EXTCTL1_EXDEF equ 0x0080 ; excessive deferral interrupt
EXTCTL1_SINTEN equ 0x0400 ; system interrupt enable
EXTCTL1_SINT equ 0x0800 ; system interrupt
EXTCTL1_LTINTEN equ 0x4000 ; last TX interrupt enb
EXTCTL1_TXOKINTD equ 0x8000 ; TX OK interrupt disable
 
; RX/TX descriptor len (CSR6)
 
PCNET_DTBLLEN_RLEN equ 0x0F00
PCNET_DTBLLEN_TLEN equ 0xF000
DTBLLEN_RLEN equ 0x0F00
DTBLLEN_TLEN equ 0xF000
 
; Extended control and interrupt 2 (CSR7)
 
PCNET_EXTCTL2_MIIPDTINTE equ 0x0001
PCNET_EXTCTL2_MIIPDTINT equ 0x0002
PCNET_EXTCTL2_MCCIINTE equ 0x0004
PCNET_EXTCTL2_MCCIINT equ 0x0008
PCNET_EXTCTL2_MCCINTE equ 0x0010
PCNET_EXTCTL2_MCCINT equ 0x0020
PCNET_EXTCTL2_MAPINTE equ 0x0040
PCNET_EXTCTL2_MAPINT equ 0x0080
PCNET_EXTCTL2_MREINTE equ 0x0100
PCNET_EXTCTL2_MREINT equ 0x0200
PCNET_EXTCTL2_STINTE equ 0x0400
PCNET_EXTCTL2_STINT equ 0x0800
PCNET_EXTCTL2_RXDPOLL equ 0x1000
PCNET_EXTCTL2_RDMD equ 0x2000
PCNET_EXTCTL2_RXFRTG equ 0x4000
PCNET_EXTCTL2_FASTSPNDE equ 0x8000
EXTCTL2_MIIPDTINTE equ 0x0001
EXTCTL2_MIIPDTINT equ 0x0002
EXTCTL2_MCCIINTE equ 0x0004
EXTCTL2_MCCIINT equ 0x0008
EXTCTL2_MCCINTE equ 0x0010
EXTCTL2_MCCINT equ 0x0020
EXTCTL2_MAPINTE equ 0x0040
EXTCTL2_MAPINT equ 0x0080
EXTCTL2_MREINTE equ 0x0100
EXTCTL2_MREINT equ 0x0200
EXTCTL2_STINTE equ 0x0400
EXTCTL2_STINT equ 0x0800
EXTCTL2_RXDPOLL equ 0x1000
EXTCTL2_RDMD equ 0x2000
EXTCTL2_RXFRTG equ 0x4000
EXTCTL2_FASTSPNDE equ 0x8000
 
; Mode (CSR15)
 
PCNET_MODE_RXD equ 0x0001 ; RX disable
PCNET_MODE_TXD equ 0x0002 ; TX disable
PCNET_MODE_LOOP equ 0x0004 ; loopback enable
PCNET_MODE_TXCRCD equ 0x0008
PCNET_MODE_FORCECOLL equ 0x0010
PCNET_MODE_RETRYD equ 0x0020
PCNET_MODE_INTLOOP equ 0x0040
PCNET_MODE_PORTSEL equ 0x0180
PCNET_MODE_RXVPAD equ 0x2000
PCNET_MODE_RXNOBROAD equ 0x4000
PCNET_MODE_PROMISC equ 0x8000
MODE_RXD equ 0x0001 ; RX disable
MODE_TXD equ 0x0002 ; TX disable
MODE_LOOP equ 0x0004 ; loopback enable
MODE_TXCRCD equ 0x0008
MODE_FORCECOLL equ 0x0010
MODE_RETRYD equ 0x0020
MODE_INTLOOP equ 0x0040
MODE_PORTSEL equ 0x0180
MODE_RXVPAD equ 0x2000
MODE_RXNOBROAD equ 0x4000
MODE_PROMISC equ 0x8000
 
; BCR (Bus Control Registers)
 
PCNET_BCR_MMRA equ 0x00 ; Master Mode Read Active
PCNET_BCR_MMW equ 0x01 ; Master Mode Write Active
PCNET_BCR_MISCCFG equ 0x02
PCNET_BCR_LED0 equ 0x04
PCNET_BCR_LED1 equ 0x05
PCNET_BCR_LED2 equ 0x06
PCNET_BCR_LED3 equ 0x07
PCNET_BCR_DUPLEX equ 0x09
PCNET_BCR_BUSCTL equ 0x12
PCNET_BCR_EECTL equ 0x13
PCNET_BCR_SSTYLE equ 0x14
PCNET_BCR_PCILAT equ 0x16
PCNET_BCR_PCISUBVENID equ 0x17
PCNET_BCR_PCISUBSYSID equ 0x18
PCNET_BCR_SRAMSIZE equ 0x19
PCNET_BCR_SRAMBOUND equ 0x1A
PCNET_BCR_SRAMCTL equ 0x1B
PCNET_BCR_MIICTL equ 0x20
PCNET_BCR_MIIADDR equ 0x21
PCNET_BCR_MIIDATA equ 0x22
PCNET_BCR_PCIVENID equ 0x23
PCNET_BCR_PCIPCAP equ 0x24
PCNET_BCR_DATA0 equ 0x25
PCNET_BCR_DATA1 equ 0x26
PCNET_BCR_DATA2 equ 0x27
PCNET_BCR_DATA3 equ 0x28
PCNET_BCR_DATA4 equ 0x29
PCNET_BCR_DATA5 equ 0x2A
PCNET_BCR_DATA6 equ 0x2B
PCNET_BCR_DATA7 equ 0x2C
PCNET_BCR_ONNOWPAT0 equ 0x2D
PCNET_BCR_ONNOWPAT1 equ 0x2E
PCNET_BCR_ONNOWPAT2 equ 0x2F
PCNET_BCR_PHYSEL equ 0x31
BCR_MMRA equ 0x00 ; Master Mode Read Active
BCR_MMW equ 0x01 ; Master Mode Write Active
BCR_MISCCFG equ 0x02
BCR_LED0 equ 0x04
BCR_LED1 equ 0x05
BCR_LED2 equ 0x06
BCR_LED3 equ 0x07
BCR_DUPLEX equ 0x09
BCR_BUSCTL equ 0x12
BCR_EECTL equ 0x13
BCR_SSTYLE equ 0x14
BCR_PCILAT equ 0x16
BCR_PCISUBVENID equ 0x17
BCR_PCISUBSYSID equ 0x18
BCR_SRAMSIZE equ 0x19
BCR_SRAMBOUND equ 0x1A
BCR_SRAMCTL equ 0x1B
BCR_MIICTL equ 0x20
BCR_MIIADDR equ 0x21
BCR_MIIDATA equ 0x22
BCR_PCIVENID equ 0x23
BCR_PCIPCAP equ 0x24
BCR_DATA0 equ 0x25
BCR_DATA1 equ 0x26
BCR_DATA2 equ 0x27
BCR_DATA3 equ 0x28
BCR_DATA4 equ 0x29
BCR_DATA5 equ 0x2A
BCR_DATA6 equ 0x2B
BCR_DATA7 equ 0x2C
BCR_ONNOWPAT0 equ 0x2D
BCR_ONNOWPAT1 equ 0x2E
BCR_ONNOWPAT2 equ 0x2F
BCR_PHYSEL equ 0x31
 
; RX status register
 
PCNET_RXSTAT_BPE equ 0x0080 ; bus parity error
PCNET_RXSTAT_ENP equ 0x0100 ; end of packet
PCNET_RXSTAT_STP equ 0x0200 ; start of packet
PCNET_RXSTAT_BUFF equ 0x0400 ; buffer error
PCNET_RXSTAT_CRC equ 0x0800 ; CRC error
PCNET_RXSTAT_OFLOW equ 0x1000 ; rx overrun
PCNET_RXSTAT_FRAM equ 0x2000 ; framing error
PCNET_RXSTAT_ERR equ 0x4000 ; error summary
PCNET_RXSTAT_OWN equ 0x8000
RXSTAT_BPE equ 0x0080 ; bus parity error
RXSTAT_ENP equ 0x0100 ; end of packet
RXSTAT_STP equ 0x0200 ; start of packet
RXSTAT_BUFF equ 0x0400 ; buffer error
RXSTAT_CRC equ 0x0800 ; CRC error
RXSTAT_OFLOW equ 0x1000 ; rx overrun
RXSTAT_FRAM equ 0x2000 ; framing error
RXSTAT_ERR equ 0x4000 ; error summary
RXSTAT_OWN equ 0x8000
 
; TX status register
 
PCNET_TXSTAT_TRC equ 0x0000000F ; transmit retries
PCNET_TXSTAT_RTRY equ 0x04000000 ; retry
PCNET_TXSTAT_LCAR equ 0x08000000 ; lost carrier
PCNET_TXSTAT_LCOL equ 0x10000000 ; late collision
PCNET_TXSTAT_EXDEF equ 0x20000000 ; excessive deferrals
PCNET_TXSTAT_UFLOW equ 0x40000000 ; transmit underrun
PCNET_TXSTAT_BUFF equ 0x80000000 ; buffer error
TXSTAT_TRC equ 0x0000000F ; transmit retries
TXSTAT_RTRY equ 0x04000000 ; retry
TXSTAT_LCAR equ 0x08000000 ; lost carrier
TXSTAT_LCOL equ 0x10000000 ; late collision
TXSTAT_EXDEF equ 0x20000000 ; excessive deferrals
TXSTAT_UFLOW equ 0x40000000 ; transmit underrun
TXSTAT_BUFF equ 0x80000000 ; buffer error
 
PCNET_TXCTL_OWN equ 0x80000000
PCNET_TXCTL_ERR equ 0x40000000 ; error summary
PCNET_TXCTL_ADD_FCS equ 0x20000000 ; add FCS to pkt
PCNET_TXCTL_MORE_LTINT equ 0x10000000
PCNET_TXCTL_ONE equ 0x08000000
PCNET_TXCTL_DEF equ 0x04000000
PCNET_TXCTL_STP equ 0x02000000
PCNET_TXCTL_ENP equ 0x01000000
PCNET_TXCTL_BPE equ 0x00800000
PCNET_TXCTL_MBO equ 0x0000F000
PCNET_TXCTL_BUFSZ equ 0x00000FFF
TXCTL_OWN equ 0x80000000
TXCTL_ERR equ 0x40000000 ; error summary
TXCTL_ADD_FCS equ 0x20000000 ; add FCS to pkt
TXCTL_MORE_LTINT equ 0x10000000
TXCTL_ONE equ 0x08000000
TXCTL_DEF equ 0x04000000
TXCTL_STP equ 0x02000000
TXCTL_ENP equ 0x01000000
TXCTL_BPE equ 0x00800000
TXCTL_MBO equ 0x0000F000
TXCTL_BUFSZ equ 0x00000FFF
 
MAX_ETH_FRAME_SIZE equ 1514
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
474,11 → 463,11
 
; check if the device is already listed
 
mov ecx, [PCNET_DEV]
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
mov esi, PCNET_LIST
mov esi, device_list
; mov eax, [IOCTL.input] ; get the pci bus and device numbers
mov ax , [eax+1] ;
.nextdevice:
491,7 → 480,7
; This device doesnt have its own eth_device structure yet, lets create one
 
.firstdevice:
cmp [PCNET_DEV], MAX_PCNET ; First check if the driver can handle one more card
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jge .fail
 
push edx
529,15 → 518,15
DEBUGF 1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
[device.pci_dev]:1,[device.pci_bus]:1,[device.irq_line]:1,[device.io_addr]:4
 
allocate_and_clear [device.tx_buffer], (PCNET_RX_RING_SIZE * PCNET_PKT_BUF_SZ), .err
allocate_and_clear [device.rx_buffer], (PCNET_TX_RING_SIZE * PCNET_PKT_BUF_SZ), .err
allocate_and_clear [device.rx_ring], (PCNET_RX_RING_SIZE * buf_head.size), .err
;;; allocate_and_clear [device.tx_buffer], (RX_RING_SIZE * PKT_BUF_SZ), .err
allocate_and_clear [device.rx_buffer], (TX_RING_SIZE * PKT_BUF_SZ), .err
allocate_and_clear [device.rx_ring], (RX_RING_SIZE * buf_head.size), .err
 
mov eax, [device.rx_ring]
call GetPgAddr
mov [device.rx_ring_phys], eax
 
allocate_and_clear [device.tx_ring], (PCNET_TX_RING_SIZE * buf_head.size), .err
allocate_and_clear [device.tx_ring], (TX_RING_SIZE * buf_head.size), .err
 
mov eax, [device.tx_ring]
call GetPgAddr
545,9 → 534,9
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
mov eax, [PCNET_DEV] ; Add the device structure to our device list
mov [PCNET_LIST+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [PCNET_DEV] ;
mov eax, [devices] ; Add the device structure to our device list
mov [device_list+4*eax], ebx ; (IRQ handler uses this list to find device)
inc [devices] ;
 
call probe ; this function will output in eax
test eax, eax
576,11 → 565,11
 
.destroy:
; todo: reset device into virgin state
dec [PCNET_DEV]
dec [devices]
.err:
DEBUGF 1,"Error, removing all data !\n"
stdcall KernelFree, [device.rx_buffer]
stdcall KernelFree, [device.tx_buffer]
;;; stdcall KernelFree, [device.tx_buffer]
stdcall KernelFree, ebx
 
.fail:
626,22 → 615,22
; first, fill in some of the structure variables
 
mov edi, [device.rx_ring]
mov ecx, PCNET_RX_RING_SIZE
mov ecx, RX_RING_SIZE
mov eax, [device.rx_buffer]
call GetPgAddr
.rx_init:
mov [edi + buf_head.base], eax
mov [edi + buf_head.length], PCNET_PKT_BUF_SZ_NEG
mov [edi + buf_head.length], PKT_BUF_SZ_NEG
mov [edi + buf_head.status], 0x8000
and dword [edi + buf_head.msg_length], 0
and dword [edi + buf_head.reserved], 0
add eax, PCNET_PKT_BUF_SZ
add eax, PKT_BUF_SZ
; inc eax
add edi, buf_head.size
loop .rx_init
 
mov edi, [device.tx_ring]
mov ecx, PCNET_TX_RING_SIZE
mov ecx, TX_RING_SIZE
mov eax, [device.tx_buffer]
call GetPgAddr
.tx_init:
649,11 → 638,11
and dword [edi + buf_head.length], 0
and dword [edi + buf_head.msg_length], 0
and dword [edi + buf_head.reserved], 0
add eax, PCNET_PKT_BUF_SZ
add eax, PKT_BUF_SZ
add edi, buf_head.size
loop .tx_init
 
mov [device.tlen_rlen], (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
mov [device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
 
; First, we must try to use Word operations
call switch_to_wio
667,12 → 656,12
 
; Try Word I/O
mov ax , 88
add edx, PCNET_WIO_RAP
add edx, WIO_RAP
out dx , ax
nop
nop
in ax , dx
sub edx, PCNET_WIO_RAP
sub edx, WIO_RAP
cmp ax , 88
jne .try_dwio
 
692,7 → 681,7
jne .no_dev
 
; Try Dword I/O
set_io PCNET_DWIO_RAP
set_io DWIO_RAP
mov eax, 88
out dx , eax
nop
715,11 → 704,11
ret
.L1:
 
mov ecx, PCNET_CSR_CHIPID0
mov ecx, CSR_CHIPID0
call [device.access_read_csr]
mov esi, eax
 
mov ecx, PCNET_CSR_CHIPID1
mov ecx, CSR_CHIPID1
call [device.access_read_csr]
shl eax, 16
or eax, esi
790,7 → 779,7
.L8:
mov [device.name], device_l8
; mov [device.fdx], 1
mov ecx, PCNET_CSR_RXPOLL
mov ecx, CSR_RXPOLL
call [device.access_read_bcr]
call [device.access_write_bcr]
jmp .L10
803,12 → 792,12
 
cmp [device.fset], 1
jne .L11
mov ecx, PCNET_BCR_BUSCTL
mov ecx, BCR_BUSCTL
call [device.access_read_bcr]
or eax, 0x800
call [device.access_write_bcr]
 
mov ecx, PCNET_CSR_DMACTL
mov ecx, CSR_DMACTL
call [device.access_read_csr]
; and eax, 0xc00
; or eax, 0xc00
820,16 → 809,16
.L11:
 
DEBUGF 1,"PCI done\n"
mov eax, PCNET_PORT_ASEL
mov eax, PORT_ASEL
mov [device.options], eax
mov [device.mode_], word 0x0003
mov [device.tlen_rlen], word (PCNET_TX_RING_LEN_BITS or PCNET_RX_RING_LEN_BITS)
mov [device.tlen_rlen], word (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
 
mov dword [device.filter], 0
mov dword [device.filter+4], 0
 
mov eax, PCNET_IMR
mov ecx, PCNET_CSR_IMR ; Write interrupt mask
mov eax, IMR
mov ecx, CSR_IMR ; Write interrupt mask
call [device.access_write_csr]
 
 
858,7 → 847,7
 
DEBUGF 1,"Switching to 32-bit mode\n"
 
mov ecx, PCNET_DWIO_RDP
mov ecx, DWIO_RDP
mov eax, 0
call wio_write_csr
 
867,7 → 856,7
; Lets find out if we are really in 32-bit mode now..
 
set_io 0
set_io PCNET_DWIO_RAP
set_io DWIO_RAP
mov eax, 88
out dx , eax
nop
885,10 → 874,10
.yes_dwio:
 
; set/reset autoselect bit
mov ecx, PCNET_BCR_MISCCFG
mov ecx, BCR_MISCCFG
call [device.access_read_bcr]
and eax,not 2
test [device.options], PCNET_PORT_ASEL
test [device.options], PORT_ASEL
jz .L1
or eax, 2
.L1:
898,24 → 887,24
; Handle full duplex setting
cmp byte [device.full_duplex], 0
je .L2
mov ecx, PCNET_BCR_DUPLEX
mov ecx, BCR_DUPLEX
call [device.access_read_bcr]
and eax, not 3
test [device.options], PCNET_PORT_FD
test [device.options], PORT_FD
jz .L3
or eax, 1
cmp [device.options], PCNET_PORT_FD or PCNET_PORT_AUI
cmp [device.options], PORT_FD or PORT_AUI
jne .L4
or eax, 2
jmp .L4
.L3:
test [device.options], PCNET_PORT_ASEL
test [device.options], PORT_ASEL
jz .L4
cmp [device.chip_version], 0x2627
jne .L4
or eax, 3
.L4:
mov ecx, PCNET_BCR_DUPLEX
mov ecx, BCR_DUPLEX
call [device.access_write_bcr]
.L2:
 
924,8 → 913,8
mov ecx, 124
call [device.access_read_csr]
mov ecx, [device.options]
and ecx, PCNET_PORT_PORTSEL
cmp ecx, PCNET_PORT_GPSI
and ecx, PORT_PORTSEL
cmp ecx, PORT_GPSI
jne .L5
or eax, 0x10
.L5:
932,16 → 921,16
call [device.access_write_csr]
cmp [device.mii], 0
je .L6
test [device.options], PCNET_PORT_ASEL
test [device.options], PORT_ASEL
jnz .L6
mov ecx, PCNET_BCR_MIICTL
mov ecx, BCR_MIICTL
call [device.access_read_bcr]
and eax,not 0x38
test [device.options], PCNET_PORT_FD
test [device.options], PORT_FD
jz .L7
or eax, 0x10
.L7:
test [device.options], PCNET_PORT_100
test [device.options], PORT_100
jz .L8
or eax, 0x08
.L8:
948,9 → 937,9
call [device.access_write_bcr]
jmp .L9
.L6:
test [device.options], PCNET_PORT_ASEL
test [device.options], PORT_ASEL
jz .L9
mov ecx, PCNET_BCR_MIICTL
mov ecx, BCR_MIICTL
DEBUGF 1,"ASEL, enable auto-negotiation\n"
call [device.access_read_bcr]
and eax, not 0x98
965,7 → 954,7
call [device.access_write_csr]
.L10:
mov eax, [device.options]
and eax, PCNET_PORT_PORTSEL
and eax, PORT_PORTSEL
shl eax, 7
mov [device.mode_], ax
mov dword [device.filter], -1
1027,7 → 1016,7
call [device.access_read_csr]
 
xor ecx, ecx
mov eax, PCNET_CSR_INTEN or PCNET_CSR_START
mov eax, CSR_INTEN or CSR_START
call [device.access_write_csr]
 
DEBUGF 1,"PCNET reset complete\n"
1037,6 → 1026,9
mov ecx, 6
rep stosd
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
 
ret
 
 
1068,12 → 1060,13
 
; check descriptor
movzx eax, [device.cur_tx]
imul edi, eax, PCNET_PKT_BUF_SZ
imul edi, eax, PKT_BUF_SZ
shl eax, 4
add edi, [device.tx_buffer]
add eax, [device.tx_ring]
test byte [eax + buf_head.status + 1], 80h
jnz .nospace
 
; descriptor is free, copy data
mov esi, [esp+4]
mov ecx, [esp+8]
1083,6 → 1076,7
rep movsd
mov ecx, edx
rep movsb
 
; set length
mov ecx, [esp+8]
neg ecx
1093,7 → 1087,7
; trigger an immediate send
xor ecx, ecx ; CSR0
call [device.access_read_csr]
or eax, PCNET_CSR_TX
or eax, CSR_TX
call [device.access_write_csr]
 
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
1109,11 → 1103,17
add dword [device.bytes_tx], ecx
adc dword [device.bytes_tx + 4], 0
DEBUGF 2," - Done!\n"
 
call Kernelfree
add esp, 4
ret
 
.nospace:
DEBUGF 1, 'ERROR: no free transmit descriptors\n'
; todo: maybe somehow notify the kernel about the error?
 
call Kernelfree
add esp, 4
ret
 
 
1131,8 → 1131,8
 
; find pointer of device wich made IRQ occur
 
mov esi, PCNET_LIST
mov ecx, [PCNET_DEV]
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .abort
.nextdevice:
1167,15 → 1167,15
call [device.access_write_csr]
; Received packet ok?
 
test ax, PCNET_CSR_RINT
test ax, CSR_RINT
jz @f
 
.receiver_test_loop:
movzx eax, [device.cur_rx]
; and eax, PCNET_RX_RING_MOD_MASK
; and eax, RX_RING_MOD_MASK
mov edi, eax
 
imul esi, eax, PCNET_PKT_BUF_SZ ;
imul esi, eax, PKT_BUF_SZ ;
add esi, [device.rx_buffer] ; esi now points to rx buffer
 
shl edi, 4 ; desc * 16 (16 is size of one ring entry)
1183,13 → 1183,13
 
mov cx , [edi + buf_head.status]
 
test cx , PCNET_RXSTAT_OWN ; If this bit is set, the controller OWN's the packet, if not, we do
test cx , RXSTAT_OWN ; If this bit is set, the controller OWN's the packet, if not, we do
jnz .abort
 
test cx , PCNET_RXSTAT_ENP
test cx , RXSTAT_ENP
jz .abort
 
test cx , PCNET_RXSTAT_STP
test cx , RXSTAT_STP
jz .abort
 
movzx ecx, [edi + buf_head.msg_length] ; get packet length in ecx
1224,8 → 1224,8
.nw:
rep movsd
 
; mov word [eax + buf_head.length], PCNET_PKT_BUF_SZ_NEG
mov word [eax + buf_head.status], PCNET_RXSTAT_OWN ; Set OWN bit back to 1 (controller may write to tx-buffer again now)
; mov word [eax + buf_head.length], PKT_BUF_SZ_NEG
mov word [eax + buf_head.status], RXSTAT_OWN ; Set OWN bit back to 1 (controller may write to tx-buffer again now)
 
inc [device.cur_rx] ; update descriptor
and [device.cur_rx], 3 ;
1257,13 → 1257,13
add edx, 2
xor eax, eax
 
mov ecx, PCNET_CSR_PAR0
mov ecx, CSR_PAR0
@@:
pop ax
call [device.access_write_csr]
DEBUGF 1,"."
inc ecx
cmp ecx, PCNET_CSR_PAR2
cmp ecx, CSR_PAR2
jl @r
 
DEBUGF 1,"\n"
1338,13 → 1338,13
; eax - data
wio_read_csr:
 
add edx, PCNET_WIO_RAP
add edx, WIO_RAP
mov ax , cx
out dx , ax
add edx, PCNET_WIO_RDP - PCNET_WIO_RAP
add edx, WIO_RDP - WIO_RAP
in ax , dx
and eax, 0xffff
sub edx, PCNET_WIO_RDP
sub edx, WIO_RDP
 
ret
 
1353,13 → 1353,13
; ecx - index
wio_write_csr:
 
add edx, PCNET_WIO_RAP
add edx, WIO_RAP
xchg eax, ecx
out dx , ax
xchg eax, ecx
add edx, PCNET_WIO_RDP - PCNET_WIO_RAP
add edx, WIO_RDP - WIO_RAP
out dx , ax
sub edx, PCNET_WIO_RDP
sub edx, WIO_RDP
 
ret
 
1369,13 → 1369,13
; eax - data
wio_read_bcr:
 
add edx, PCNET_WIO_RAP
add edx, WIO_RAP
mov ax , cx
out dx , ax
add edx, PCNET_WIO_BDP - PCNET_WIO_RAP
add edx, WIO_BDP - WIO_RAP
in ax , dx
and eax, 0xffff
sub edx, PCNET_WIO_BDP
sub edx, WIO_BDP
 
ret
 
1384,13 → 1384,13
; ecx - index
wio_write_bcr:
 
add edx, PCNET_WIO_RAP
add edx, WIO_RAP
xchg eax, ecx
out dx , ax
xchg eax, ecx
add edx, PCNET_WIO_BDP - PCNET_WIO_RAP
add edx, WIO_BDP - WIO_RAP
out dx , ax
sub edx, PCNET_WIO_BDP
sub edx, WIO_BDP
 
ret
 
1397,10 → 1397,10
 
wio_read_rap:
 
add edx, PCNET_WIO_RAP
add edx, WIO_RAP
in ax , dx
and eax, 0xffff
sub edx, PCNET_WIO_RAP
sub edx, WIO_RAP
 
ret
 
1407,9 → 1407,9
; eax - val
wio_write_rap:
 
add edx, PCNET_WIO_RAP
add edx, WIO_RAP
out dx , ax
sub edx, PCNET_WIO_RAP
sub edx, WIO_RAP
 
ret
 
1416,10 → 1416,10
wio_reset:
 
push eax
add edx, PCNET_WIO_RESET
add edx, WIO_RESET
in ax , dx
pop eax
sub edx, PCNET_WIO_RESET
sub edx, WIO_RESET
 
ret
 
1429,13 → 1429,13
; eax - data
dwio_read_csr:
 
add edx, PCNET_DWIO_RAP
add edx, DWIO_RAP
mov eax, ecx
out dx , eax
add edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
add edx, DWIO_RDP - DWIO_RAP
in eax, dx
and eax, 0xffff
sub edx, PCNET_DWIO_RDP
sub edx, DWIO_RDP
 
ret
 
1444,13 → 1444,13
; eax - data
dwio_write_csr:
 
add edx, PCNET_DWIO_RAP
add edx, DWIO_RAP
xchg eax, ecx
out dx , eax
add edx, PCNET_DWIO_RDP - PCNET_DWIO_RAP
add edx, DWIO_RDP - DWIO_RAP
xchg eax, ecx
out dx , eax
sub edx, PCNET_DWIO_RDP
sub edx, DWIO_RDP
 
ret
 
1459,13 → 1459,13
; eax - data
dwio_read_bcr:
 
add edx, PCNET_DWIO_RAP
add edx, DWIO_RAP
mov eax, ecx
out dx , eax
add edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
add edx, DWIO_BDP - DWIO_RAP
in eax, dx
and eax, 0xffff
sub edx, PCNET_DWIO_BDP
sub edx, DWIO_BDP
 
ret
 
1474,13 → 1474,13
; eax - data
dwio_write_bcr:
 
add edx, PCNET_DWIO_RAP
add edx, DWIO_RAP
xchg eax, ecx
out dx , eax
add edx, PCNET_DWIO_BDP - PCNET_DWIO_RAP
add edx, DWIO_BDP - DWIO_RAP
xchg eax, ecx
out dx , eax
sub edx, PCNET_DWIO_BDP
sub edx, DWIO_BDP
 
ret
 
1487,10 → 1487,10
 
dwio_read_rap:
 
add edx, PCNET_DWIO_RAP
add edx, DWIO_RAP
in eax, dx
and eax, 0xffff
sub edx, PCNET_DWIO_RAP
sub edx, DWIO_RAP
 
ret
 
1498,9 → 1498,9
; eax - val
dwio_write_rap:
 
add edx, PCNET_DWIO_RAP
add edx, DWIO_RAP
out dx , eax
sub edx, PCNET_DWIO_RAP
sub edx, DWIO_RAP
 
ret
 
1508,10 → 1508,10
dwio_reset:
 
push eax
add edx, PCNET_DWIO_RESET
add edx, DWIO_RESET
in eax, dx
pop eax
sub edx, PCNET_DWIO_RESET
sub edx, DWIO_RESET
 
ret
 
1518,12 → 1518,11
 
 
; End of code
 
align 4 ; Place all initialised data here
 
PCNET_DEV dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
my_service db 'PCnet',0 ; max 16 chars include zero
devices dd 0
version dd (DRIVER_VERSION shl 16) or (API_VERSION and 0xFFFF)
my_service db 'PCnet32',0 ; max 16 chars include zero
 
device_l2 db "PCnet/PCI 79C970",0
device_l4 db "PCnet/PCI II 79C970A",0
1534,25 → 1533,25
device_l9 db "PCnet/FAST III 79C975",0
 
options_mapping:
dd PCNET_PORT_ASEL ; 0 Auto-select
dd PCNET_PORT_AUI ; 1 BNC/AUI
dd PCNET_PORT_AUI ; 2 AUI/BNC
dd PCNET_PORT_ASEL ; 3 not supported
dd PCNET_PORT_10BT or PCNET_PORT_FD ; 4 10baseT-FD
dd PCNET_PORT_ASEL ; 5 not supported
dd PCNET_PORT_ASEL ; 6 not supported
dd PCNET_PORT_ASEL ; 7 not supported
dd PCNET_PORT_ASEL ; 8 not supported
dd PCNET_PORT_MII ; 9 MII 10baseT
dd PCNET_PORT_MII or PCNET_PORT_FD ; 10 MII 10baseT-FD
dd PCNET_PORT_MII ; 11 MII (autosel)
dd PCNET_PORT_10BT ; 12 10BaseT
dd PCNET_PORT_MII or PCNET_PORT_100 ; 13 MII 100BaseTx
dd PCNET_PORT_MII or PCNET_PORT_100 or PCNET_PORT_FD ; 14 MII 100BaseTx-FD
dd PCNET_PORT_ASEL ; 15 not supported
dd PORT_ASEL ; 0 Auto-select
dd PORT_AUI ; 1 BNC/AUI
dd PORT_AUI ; 2 AUI/BNC
dd PORT_ASEL ; 3 not supported
dd PORT_10BT or PORT_FD ; 4 10baseT-FD
dd PORT_ASEL ; 5 not supported
dd PORT_ASEL ; 6 not supported
dd PORT_ASEL ; 7 not supported
dd PORT_ASEL ; 8 not supported
dd PORT_MII ; 9 MII 10baseT
dd PORT_MII or PORT_FD ; 10 MII 10baseT-FD
dd PORT_MII ; 11 MII (autosel)
dd PORT_10BT ; 12 10BaseT
dd PORT_MII or PORT_100 ; 13 MII 100BaseTx
dd PORT_MII or PORT_100 or PORT_FD ; 14 MII 100BaseTx-FD
dd PORT_ASEL ; 15 not supported
 
include_debug_strings ; All data wich FDO uses will be included here
 
section '.data' data readable writable align 16 ; place all uninitialized data place here
 
PCNET_LIST rd MAX_PCNET ; 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
/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