/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 |