Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4524 → Rev 4532

/drivers/ethernet/i8254x.asm
893,7 → 893,6
data fixups
end data
 
;section '.data' readable writable
include '../peimport.inc'
 
include_debug_strings
/drivers/ethernet/pcnet32.asm
14,32 → 14,30
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format MS COFF
format PE DLL native
entry START
 
API_VERSION = 0x01000100
CURRENT_API = 0x0200
COMPATIBLE_API = 0x0100
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
 
DEBUG = 1
MAX_DEVICES = 16
 
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors only
__DEBUG_LEVEL__ = 1 ; 1 = verbose, 2 = errors only
 
MAX_DEVICES = 4
MAX_ETH_FRAME_SIZE = 1514
 
TX_RING_SIZE = 4
RX_RING_SIZE = 4
 
section '.flat' readable writable executable
 
include '../struct.inc'
include '../macros.inc'
include '../proc32.inc'
include '../imports.inc'
include '../fdo.inc'
include '../netdrv.inc'
include '../netdrv_pe.inc'
 
public START
public service_proc
public version
 
 
PORT_AUI = 0x00
PORT_10BT = 0x01
PORT_GPSI = 0x02
279,86 → 277,72
TXCTL_MBO = 0x0000F000
TXCTL_BUFSZ = 0x00000FFF
 
;
 
MAX_PHYS = 32
 
 
virtual at ebx
struct device ETH_DEVICE
 
device:
rb 0x100-($ and 0xff) ; align 256
 
ETH_DEVICE
; Pcnet configuration structure
mode dw ?
tlen_rlen dw ?
phys_addr dp ?
reserved dw ?
filter dq ?
rx_ring_phys dd ?
tx_ring_phys dd ?
; end of pcnet config struct
 
; device specific
rb 0x100-($ and 0xff) ; align 256
 
rb 0x100-(($ - device) and 0xff) ; align 256
.private:
.mode_ dw ?
.tlen_rlen dw ?
.phys_addr dp ?
.reserved dw ?
.filter dq ?
.rx_ring_phys dd ?
.tx_ring_phys dd ?
rx_ring rb RX_RING_SIZE * sizeof.descriptor
 
rb 0x100-(($ - device) and 0xff) ; align 256
.rx_ring rb RX_RING_SIZE * descriptor.size
rb 0x100-($ and 0xff) ; align 256
 
rb 0x100-(($ - device) and 0xff) ; align 256
.tx_ring rb TX_RING_SIZE * descriptor.size
tx_ring rb TX_RING_SIZE * sizeof.descriptor
 
.cur_rx db ?
.cur_tx db ?
.last_tx db ?
.options dd ?
.full_duplex db ?
.chip_version dw ?
.mii db ?
.ltint db ?
.dxsuflo db ?
.fset db ?
.fdx db ?
cur_rx db ?
cur_tx db ?
last_tx db ?
options dd ?
full_duplex db ?
chip_version dw ?
mii db ?
ltint db ?
dxsuflo db ?
fset db ?
fdx db ?
 
.io_addr dd ?
.irq_line db ?
.pci_bus dd ?
.pci_dev dd ?
io_addr dd ?
irq_line db ?
pci_bus dd ?
pci_dev dd ?
 
.phy dw ?
phy dw ?
 
.read_csr dd ?
.write_csr dd ?
.read_bcr dd ?
.write_bcr dd ?
.read_rap dd ?
.write_rap dd ?
.sw_reset dd ?
read_csr dd ?
write_csr dd ?
read_bcr dd ?
write_bcr dd ?
read_rap dd ?
write_rap dd ?
sw_reset dd ?
 
device_size = $ - device
ends
 
end virtual
struct descriptor
 
struc descriptor {
.base dd ?
.length dw ?
.status dw ?
.msg_length dw ?
.misc dw ?
.virtual dd ?
base dd ?
length dw ?
status dw ?
msg_length dw ?
misc dw ?
virtual dd ?
 
.size:
}
ends
 
virtual at 0
descriptor descriptor
end virtual
 
 
 
 
section '.flat' code readable align 16
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
366,19 → 350,16
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc START stdcall, state:dword
proc START c, reason:dword, cmdline:dword
 
cmp [state], 1
jne .exit
cmp [reason], DRV_ENTRY
jne .fail
 
.entry:
 
DEBUGF 1,"Loading driver\n"
stdcall RegService, my_service, service_proc
DEBUGF 2,"Loading driver\n"
invoke RegService, my_service, service_proc
ret
 
.fail:
.exit:
xor eax, eax
ret
 
434,9 → 415,9
mov ax, [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte[device.pci_bus]
cmp al, byte[ebx + device.pci_bus]
jne @f
cmp ah, byte[device.pci_dev]
cmp ah, byte[ebx + device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
@@:
add esi, 4
448,33 → 429,35
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, device_size, .fail
allocate_and_clear ebx, sizeof.device, .fail
 
; Fill in the direct call addresses into the struct
 
mov [device.reset], reset
mov [device.transmit], transmit
mov [device.unload], unload
mov [device.name], my_service
mov [ebx + device.reset], reset
mov [ebx + device.transmit], transmit
mov [ebx + device.unload], unload
mov [ebx + device.name], my_service
 
; save the pci bus and device numbers
 
mov eax, [edx + IOCTL.input]
movzx ecx, byte[eax+1]
mov [device.pci_bus], ecx
mov [ebx + device.pci_bus], ecx
movzx ecx, byte[eax+2]
mov [device.pci_dev], ecx
mov [ebx + device.pci_dev], ecx
 
; Now, it's time to find the base io addres of the PCI device
 
PCI_find_io
stdcall PCI_find_io, [ebx + device.pci_bus], [ebx + device.pci_dev]
mov [ebx + device.io_addr], eax
 
; We've found the io address, find IRQ now
 
PCI_find_irq
invoke PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
mov [ebx + device.irq_line], al
 
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
[ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.io_addr]:4
 
; Ok, the eth_device structure is ready, let's probe the device
; Because initialization fires IRQ, IRQ handler must be aware of this device
486,8 → 469,8
test eax, eax
jnz .destroy ; If an error occured, exit
 
mov [device.type], NET_TYPE_ETH
call NetRegDev
mov [ebx + device.type], NET_TYPE_ETH
invoke NetRegDev
cmp eax, -1
je .destroy
 
497,7 → 480,7
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
call NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
invoke NetPtrToNum ; This kernel procedure converts a pointer to device struct in ebx
; into a device number in edi
mov eax, edi ; Application wants it in eax instead
DEBUGF 1,"Kernel says: %u\n", eax
511,7 → 494,7
dec [devices]
.err:
DEBUGF 2,"Error, removing all data !\n"
stdcall KernelFree, ebx
invoke KernelFree, ebx
 
.fail:
or eax, -1
533,7 → 516,7
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (RTL8139_LIST)
; - Remove device from local list (device_list)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
551,7 → 534,7
align 4
probe:
 
mov edx, [device.io_addr]
mov edx, [ebx + device.io_addr]
 
call wio_reset
 
600,13 → 583,13
jmp .L1
 
.no_dev:
DEBUGF 1,"device not found!\n"
DEBUGF 2,"device not found!\n"
mov eax, 1
ret
 
.L1:
mov ecx, CSR_CHIPID0
call [device.read_csr]
call [ebx + device.read_csr]
 
mov esi, eax
shr esi, 12
616,16 → 599,16
jne .no_dev
 
mov ecx, CSR_CHIPID1
call [device.read_csr]
call [ebx + device.read_csr]
shl eax, 4
or eax, esi
mov [device.chip_version], ax
mov [ebx + device.chip_version], ax
 
mov [device.fdx], 0
mov [device.mii], 0
mov [device.fset], 0
mov [device.dxsuflo], 0
mov [device.ltint], 0
mov [ebx + device.fdx], 0
mov [ebx + device.mii], 0
mov [ebx + device.fset], 0
mov [ebx + device.dxsuflo], 0
mov [ebx + device.ltint], 0
 
cmp ax, 0x2420
je .L2
632,7 → 615,7
cmp ax, 0x2430
je .L2
 
mov [device.fdx], 1
mov [ebx + device.fdx], 1
 
cmp ax, 0x2621
je .L4
650,70 → 633,73
DEBUGF 1,"Invalid chip rev\n"
jmp .no_dev
.L2:
mov [device.name], device_l2
mov [ebx + device.name], device_l2
jmp .L10
.L4:
mov [device.name], device_l4
; mov [device.fdx], 1
mov [ebx + device.name], device_l4
; mov [ebx + device.fdx], 1
jmp .L10
.L5:
mov [device.name], device_l5
; mov [device.fdx], 1
mov [device.mii], 1
mov [device.fset], 1
mov [device.ltint], 1
mov [ebx + device.name], device_l5
; mov [ebx + device.fdx], 1
mov [ebx + device.mii], 1
mov [ebx + device.fset], 1
mov [ebx + device.ltint], 1
jmp .L10
.L6:
mov [device.name], device_l6
; mov [device.fdx], 1
mov [device.mii], 1
mov [device.fset], 1
mov [ebx + device.name], device_l6
; mov [ebx + device.fdx], 1
mov [ebx + device.mii], 1
mov [ebx + device.fset], 1
jmp .L10
.L7:
mov [device.name], device_l7
; mov [device.fdx], 1
mov [device.mii], 1
mov [ebx + device.name], device_l7
; mov [ebx + device.fdx], 1
mov [ebx + device.mii], 1
jmp .L10
.L8:
mov [device.name], device_l8
; mov [device.fdx], 1
mov [ebx + device.name], device_l8
; mov [ebx + device.fdx], 1
mov ecx, CSR_RXPOLL
call dword [device.read_bcr]
call dword [device.write_bcr]
call dword [ebx + device.read_bcr]
call dword [ebx + device.write_bcr]
jmp .L10
.L9:
mov [device.name], device_l9
; mov [device.fdx], 1
mov [device.mii], 1
mov [ebx + device.name], device_l9
; mov [ebx + device.fdx], 1
mov [ebx + device.mii], 1
.L10:
DEBUGF 1,"device name: %s\n", [device.name]
DEBUGF 1,"device name: %s\n", [ebx + device.name]
 
cmp [device.fset], 1
cmp [ebx + device.fset], 1
jne .L11
mov ecx, BCR_BUSCTL
call [device.read_bcr]
call [ebx + device.read_bcr]
or eax, 0x800
call [device.write_bcr]
call [ebx + device.write_bcr]
 
mov ecx, CSR_DMACTL
call [device.read_csr]
call [ebx + device.read_csr]
; and eax, 0xc00
; or eax, 0xc00
mov eax, 0xc00
call [device.write_csr]
call [ebx + device.write_csr]
 
mov [device.dxsuflo],1
mov [device.ltint],1
mov [ebx + device.dxsuflo],1
mov [ebx + device.ltint],1
.L11:
 
PCI_make_bus_master
; Make the device a bus master
invoke PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
or al, PCI_CMD_MASTER
invoke PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
 
mov [device.options], PORT_ASEL
mov [device.mode_], MODE_RXD + MODE_TXD ; disable receive and transmit
mov [device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
mov [ebx + device.options], PORT_ASEL
mov [ebx + device.mode], MODE_RXD + MODE_TXD ; disable receive and transmit
mov [ebx + device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
 
mov dword [device.filter], 0
mov dword [device.filter+4], 0
mov dword[ebx + device.filter], 0
mov dword[ebx + device.filter+4], 0
 
align 4
reset:
720,118 → 706,117
 
; attach int handler
 
movzx eax, [device.irq_line]
movzx eax, [ebx + device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
stdcall AttachIntHandler, eax, int_handler, dword 0
invoke AttachIntHandler, eax, int_handler, ebx
test eax, eax
jnz @f
DEBUGF 2,"Could not attach int handler!\n"
; or eax, -1
; ret
or eax, -1
ret
@@:
 
mov edx, [device.io_addr]
mov edx, [ebx + device.io_addr]
call [ebx + device.sw_reset]
 
call [device.sw_reset]
 
; Switch pcnet32 to 32bit mode
mov ecx, BCR_SSTYLE
mov eax, 2
call [device.write_bcr]
call [ebx + device.write_bcr]
 
; set/reset autoselect bit
mov ecx, BCR_MISCCFG
call [device.read_bcr]
call [ebx + device.read_bcr]
and eax, not 2
test [device.options], PORT_ASEL
test [ebx + device.options], PORT_ASEL
jz @f
or eax, 2
@@:
call [device.write_bcr]
call [ebx + device.write_bcr]
 
; Handle full duplex setting
cmp byte [device.full_duplex], 0
cmp byte [ebx + device.full_duplex], 0
je .duplex_ok
mov ecx, BCR_DUPLEX
call [device.read_bcr]
call [ebx + device.read_bcr]
and eax, not 3
test [device.options], PORT_FD
test [ebx + device.options], PORT_FD
jz @f
or eax, 1
cmp [device.options], PORT_FD or PORT_AUI
cmp [ebx + device.options], PORT_FD or PORT_AUI
jne .set_duplex
or eax, 2
jmp .set_duplex
@@:
test [device.options], PORT_ASEL
test [ebx + device.options], PORT_ASEL
jz .set_duplex
cmp [device.chip_version], 0x2627
cmp [ebx + device.chip_version], 0x2627
jne .set_duplex
or eax, 3
.set_duplex:
mov ecx, BCR_DUPLEX
call [device.write_bcr]
call [ebx + device.write_bcr]
.duplex_ok:
 
; set/reset GPSI bit in test register
mov ecx, 124
call [device.read_csr]
mov ecx, [device.options]
call [ebx + device.read_csr]
mov ecx, [ebx + device.options]
and ecx, PORT_PORTSEL
cmp ecx, PORT_GPSI
jne @f
or eax, 0x10
@@:
call [device.write_csr]
cmp [device.mii], 0
call [ebx + device.write_csr]
cmp [ebx + device.mii], 0
je .L6
test [device.options], PORT_ASEL
test [ebx + device.options], PORT_ASEL
jnz .L6
mov ecx, BCR_MIICTL
call [device.read_bcr]
call [ebx + device.read_bcr]
and eax, not 0x38
test [device.options], PORT_FD
test [ebx + device.options], PORT_FD
jz @f
or eax, 0x10
@@:
test [device.options], PORT_100
test [ebx + device.options], PORT_100
jz @f
or eax, 0x08
@@:
call [device.write_bcr]
call [ebx + device.write_bcr]
jmp .L9
.L6:
test [device.options], PORT_ASEL
test [ebx + device.options], PORT_ASEL
jz .L9
mov ecx, BCR_MIICTL
DEBUGF 1,"ASEL, enable auto-negotiation\n"
call [device.read_bcr]
call [ebx + device.read_bcr]
and eax, not 0x98
or eax, 0x20
call [device.write_bcr]
call [ebx + device.write_bcr]
.L9:
cmp [device.ltint], 0
cmp [ebx + device.ltint], 0
je @f
mov ecx, 5
call [device.read_csr]
call [ebx + device.read_csr]
or eax, (1 shl 14)
call [device.write_csr]
call [ebx + device.write_csr]
@@:
mov eax, [device.options]
mov eax, [ebx + device.options]
and eax, PORT_PORTSEL
shl eax, 7
mov [device.mode_], ax
mov dword [device.filter], -1
mov dword [device.filter+4], -1
mov [ebx + device.mode], ax
mov dword [ebx + device.filter], -1
mov dword [ebx + device.filter+4], -1
 
 
 
;-----------------------------
 
test [device.mii], 1
test [ebx + device.mii], 1
jz .no_mii
 
mov [device.phy], 0
mov [ebx + device.phy], 0
 
.mii_loop:
mov ecx, MII_PHYSID1
850,9 → 835,9
 
jmp .got_phy
 
cmp [device.phy], 31
cmp [ebx + device.phy], 31
jne .next
mov ax, [device.chip_version]
mov ax, [ebx + device.chip_version]
inc ax
and ax, 0xfffe
cmp ax, 0x2624 ; 79c971 & 79c972 have phantom phy at id 31
859,17 → 844,16
je .got_phy
 
.next:
inc [device.phy]
cmp [device.phy], MAX_PHYS
inc [ebx + device.phy]
cmp [ebx + device.phy], MAX_PHYS
jb .mii_loop
 
DEBUGF 2, "No PHY found!\n"
 
or eax, -1
ret
 
.got_phy:
DEBUGF 1, "Found PHY at 0x%x\n", [device.phy]:4
DEBUGF 1, "Found PHY at 0x%x\n", [ebx + device.phy]:4
 
.no_mii:
 
877,44 → 861,44
 
call read_mac
 
lea esi, [device.mac]
lea edi, [device.phys_addr]
lea esi, [ebx + device.mac]
lea edi, [ebx + device.phys_addr]
movsd
movsw
 
call init_ring
 
mov edx, [device.io_addr] ; init ring destroys edx
mov edx, [ebx + device.io_addr] ; init ring destroys edx
 
lea eax, [device.private]
GetRealAddr
lea eax, [ebx + device.mode]
invoke GetPhysAddr
push eax
and eax, 0xffff
mov ecx, 1
call [device.write_csr]
call [ebx + device.write_csr]
pop eax
shr eax, 16
mov ecx, 2
call [device.write_csr]
call [ebx + device.write_csr]
 
mov ecx, 4
mov eax, 0x0915
call [device.write_csr]
call [ebx + device.write_csr]
 
; Set the interrupt mask
mov ecx, CSR_IMR
mov eax, IMR
call [device.write_csr]
call [ebx + device.write_csr]
 
; Initialise the device
xor ecx, ecx
mov eax, CSR_INIT
call [device.write_csr]
call [ebx + device.write_csr]
 
mov esi, 100
; xor ecx, ecx
@@:
call [device.read_csr]
call [ebx + device.read_csr]
test ax, CSR_IDONE
jnz @f
 
926,13 → 910,13
; Start the device and enable interrupts
xor ecx, ecx
mov eax, CSR_START + CSR_INTEN
call [device.write_csr]
call [ebx + device.write_csr]
 
; Set the mtu, kernel will be able to send now
mov [device.mtu], 1514
mov [ebx + device.mtu], 1514
 
; get link status
mov [device.state], ETH_LINK_UNKOWN
mov [ebx + device.state], ETH_LINK_UNKOWN
 
call check_media
 
946,41 → 930,41
 
DEBUGF 1,"init ring\n"
 
lea edi, [device.rx_ring]
lea edi, [ebx + device.rx_ring]
mov eax, edi
GetRealAddr
mov [device.rx_ring_phys], eax
invoke GetPhysAddr
mov [ebx + device.rx_ring_phys], eax
mov ecx, RX_RING_SIZE
.rx_init:
push ecx
stdcall KernelAlloc, PKT_BUF_SZ
invoke KernelAlloc, PKT_BUF_SZ
pop ecx
mov [edi + descriptor.virtual], eax
GetRealAddr
invoke GetPhysAddr
mov [edi + descriptor.base], eax
mov [edi + descriptor.length], - PKT_BUF_SZ
mov [edi + descriptor.status], RXSTAT_OWN
mov dword [edi + descriptor.msg_length], 0 ; also clears misc field
add edi, descriptor.size
add edi, sizeof.descriptor
dec ecx
jnz .rx_init
 
lea edi, [device.tx_ring]
lea edi, [ebx + device.tx_ring]
mov eax, edi
GetRealAddr
mov [device.tx_ring_phys], eax
invoke GetPhysAddr
mov [ebx + device.tx_ring_phys], eax
mov ecx, TX_RING_SIZE
.tx_init:
mov [edi + descriptor.status], 0
add edi, descriptor.size
add edi, sizeof.descriptor
dec ecx
jnz .tx_init
 
mov [device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
mov [ebx + device.tlen_rlen], (TX_RING_LEN_BITS or RX_RING_LEN_BITS)
 
mov [device.cur_tx], 0
mov [device.last_tx], 0
mov [device.cur_rx], 0
mov [ebx + device.cur_tx], 0
mov [ebx + device.last_tx], 0
mov [ebx + device.cur_rx], 0
 
ret
 
991,41 → 975,42
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; In: pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [esp+4], [esp+8]
mov eax, [esp+4]
proc transmit stdcall bufferptr, buffersize
 
pushf
cli
 
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
mov eax, [bufferptr]
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], 1514
ja .nospace ; packet is too long
cmp dword [esp+8], 60
jb .nospace ; packet is too short
cmp [buffersize], 1514
ja .fail
cmp [buffersize], 60
jb .fail
 
; check descriptor
lea edi, [device.tx_ring]
movzx eax, [device.cur_tx]
lea edi, [ebx + device.tx_ring]
movzx eax, [ebx + device.cur_tx]
shl eax, 4
add edi, eax
 
test [edi + descriptor.status], TXCTL_OWN
jnz .nospace
jnz .fail
; descriptor is free, use it
mov eax, [esp+4]
mov eax, [bufferptr]
mov [edi + descriptor.virtual], eax
GetRealAddr
invoke GetPhysAddr
mov [edi + descriptor.base], eax
; set length
mov eax, [esp+8]
mov eax, [buffersize]
neg eax
mov [edi + descriptor.length], ax
; put to transfer queue
1032,33 → 1017,35
mov [edi + descriptor.status], TXCTL_OWN + TXCTL_STP + TXCTL_ENP
 
; trigger an immediate send
mov edx, [device.io_addr]
mov edx, [ebx + device.io_addr]
xor ecx, ecx ; CSR0
call [device.read_csr]
call [ebx + device.read_csr]
or eax, CSR_TX
call [device.write_csr]
call [ebx + device.write_csr]
 
; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ...
inc [device.cur_tx]
and [device.cur_tx], TX_RING_SIZE - 1
inc [ebx + device.cur_tx]
and [ebx + device.cur_tx], TX_RING_SIZE - 1
 
; Update stats
inc [device.packets_tx]
mov eax, [esp+8]
add dword [device.bytes_tx], eax
adc dword [device.bytes_tx + 4], 0
inc [ebx + device.packets_tx]
mov eax, [buffersize]
add dword[ebx + device.bytes_tx], eax
adc dword[ebx + device.bytes_tx + 4], 0
 
.finish:
DEBUGF 1," - Done!\n"
popf
xor eax, eax
ret 8
ret
 
.nospace:
DEBUGF 2, "ERROR: no free transmit descriptors\n"
stdcall KernelFree, [esp+4]
.fail:
DEBUGF 2, "Send failed\n"
invoke KernelFree, [bufferptr]
popf
or eax, -1
ret 8
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;
1082,12 → 1069,11
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
mov edx, [device.io_addr]
mov edx, [ebx + device.io_addr]
push ecx
xor ecx, ecx ; CSR0
call [device.read_csr] ; get IRQ reason
call [device.write_csr] ; write it back to ACK
call [ebx + device.read_csr] ; get IRQ reason
call [ebx + device.write_csr] ; write it back to ACK
pop ecx
and ax, CSR_RINT or CSR_TINT
jnz .got_it
1102,7 → 1088,7
ret
 
.got_it:
DEBUGF 1,"Device: %x status: %x\n", ebx, eax:2
DEBUGF 1,"Device: %x status: %x\n", ebx, eax:4
 
push ax
test ax, CSR_RINT
1111,9 → 1097,9
push ebx
.rx_loop:
pop ebx
movzx eax, [device.cur_rx]
movzx eax, [ebx + device.cur_rx]
shl eax, 4
lea edi, [device.rx_ring]
lea edi, [ebx + device.rx_ring]
add edi, eax ; edi now points to current rx ring entry
 
mov ax, [edi + descriptor.status]
1129,7 → 1115,8
jz .not_receive
 
movzx ecx, [edi + descriptor.msg_length] ; get packet length in ecx
sub ecx, 4 ;
sub ecx, 4 ; We dont need the CRC
DEBUGF 1,"Got %u bytes\n", ecx
 
; Set pointers for ETH_input
push ebx
1139,23 → 1126,21
push [edi + descriptor.virtual] ; packet address
 
; Update stats
add dword [device.bytes_rx], ecx
adc dword [device.bytes_rx + 4], 0
inc [device.packets_rx]
add dword[ebx + device.bytes_rx], ecx
adc dword[ebx + device.bytes_rx + 4], 0
inc [ebx + device.packets_rx]
 
; now allocate a new buffer
stdcall KernelAlloc, PKT_BUF_SZ ; Allocate a buffer for the next packet
invoke KernelAlloc, PKT_BUF_SZ ; Allocate a buffer for the next packet
mov [edi + descriptor.virtual], eax ; set virtual address
GetRealAddr
mov [edi + descriptor.base], eax ; and real address
 
; mov word [edi + descriptor.length], - PKT_BUF_SZ
invoke GetPhysAddr
mov [edi + descriptor.base], eax ; and physical address
mov [edi + descriptor.status], RXSTAT_OWN ; give it back to PCnet controller
 
inc [device.cur_rx] ; set next receive descriptor
and [device.cur_rx], RX_RING_SIZE - 1
inc [ebx + device.cur_rx] ; set next receive descriptor
and [ebx + device.cur_rx], RX_RING_SIZE - 1
 
jmp Eth_input
jmp [Eth_input]
 
.not_receive:
pop ax
1164,8 → 1149,8
jz .not_transmit
 
.tx_loop:
lea edi, [device.tx_ring]
movzx eax, [device.last_tx]
lea edi, [ebx + device.tx_ring]
movzx eax, [ebx + device.last_tx]
shl eax, 4
add edi, eax
 
1180,10 → 1165,10
 
DEBUGF 1,"Removing packet %x from memory\n", eax
 
stdcall KernelFree, eax
invoke KernelFree, eax
 
inc [device.last_tx]
and [device.last_tx], TX_RING_SIZE - 1
inc [ebx + device.last_tx]
and [ebx + device.last_tx], TX_RING_SIZE - 1
jmp .tx_loop
 
.not_transmit:
1205,9 → 1190,10
align 4
write_mac: ; in: mac pushed onto stack (as 3 words)
 
DEBUGF 1,"Writing MAC: %x-%x-%x-%x-%x-%x",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
DEBUGF 1,"Writing MAC: %x-%x-%x-%x-%x-%x\n",\
[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
 
mov edx, [device.io_addr]
mov edx, [ebx + device.io_addr]
add dx, 2
xor eax, eax
 
1214,14 → 1200,11
mov ecx, CSR_PAR0
@@:
pop ax
call [device.write_csr]
DEBUGF 1,"."
call [ebx + device.write_csr]
inc ecx
cmp ecx, CSR_PAR2
jb @r
 
DEBUGF 1,"\n"
 
; Notice this procedure does not ret, but continues to read_mac instead.
 
;;;;;;;;;;;;;;;;;;;;;;
1231,28 → 1214,27
;;;;;;;;;;;;;;;;;;;;;;
align 4
read_mac:
DEBUGF 1,"Reading MAC:\n"
DEBUGF 1,"Reading MAC\n"
 
mov edx, [device.io_addr]
add dx, 6
@@:
dec dx
dec dx
mov edx, [ebx + device.io_addr]
lea edi, [ebx + device.mac]
in ax, dx
push ax
cmp edx, [device.io_addr]
ja @r
stosw
 
DEBUGF 1,"%x-%x-%x-%x-%x-%x\n",[esp+0]:2,[esp+1]:2,[esp+2]:2,[esp+3]:2,[esp+4]:2,[esp+5]:2
inc dx
inc dx
in ax, dx
stosw
 
lea edi, [device.mac]
pop ax
inc dx
inc dx
in ax, dx
stosw
pop ax
stosw
pop ax
stosw
 
DEBUGF 1,"MAC = %x-%x-%x-%x-%x-%x\n",\
[ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,\
[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
 
ret
 
align 4
1260,13 → 1242,13
 
DEBUGF 1,"Switching to 16-bit mode\n"
 
mov [device.read_csr], wio_read_csr
mov [device.write_csr], wio_write_csr
mov [device.read_bcr], wio_read_bcr
mov [device.write_bcr], wio_write_bcr
mov [device.read_rap], wio_read_rap
mov [device.write_rap], wio_write_rap
mov [device.sw_reset], wio_reset
mov [ebx + device.read_csr], wio_read_csr
mov [ebx + device.write_csr], wio_write_csr
mov [ebx + device.read_bcr], wio_read_bcr
mov [ebx + device.write_bcr], wio_write_bcr
mov [ebx + device.read_rap], wio_read_rap
mov [ebx + device.write_rap], wio_write_rap
mov [ebx + device.sw_reset], wio_reset
 
ret
 
1275,13 → 1257,13
 
DEBUGF 1,"Switching to 32-bit mode\n"
 
mov [device.read_csr], dwio_read_csr
mov [device.write_csr], dwio_write_csr
mov [device.read_bcr], dwio_read_bcr
mov [device.write_bcr], dwio_write_bcr
mov [device.read_rap], dwio_read_rap
mov [device.write_rap], dwio_write_rap
mov [device.sw_reset], dwio_reset
mov [ebx + device.read_csr], dwio_read_csr
mov [ebx + device.write_csr], dwio_write_csr
mov [ebx + device.read_bcr], dwio_read_bcr
mov [ebx + device.write_bcr], dwio_write_bcr
mov [ebx + device.read_rap], dwio_read_rap
mov [ebx + device.write_rap], dwio_write_rap
mov [ebx + device.sw_reset], dwio_reset
 
ret
 
1485,16 → 1467,16
mdio_read:
 
and ecx, 0x1f
mov ax, [device.phy]
mov ax, [ebx + device.phy]
and ax, 0x1f
shl ax, 5
or ax, cx
 
mov ecx, BCR_MIIADDR
call [device.write_bcr]
call [ebx + device.write_bcr]
 
mov ecx, BCR_MIIDATA
call [device.read_bcr]
call [ebx + device.read_bcr]
 
ret
 
1504,17 → 1486,17
 
push eax
and ecx, 0x1f
mov ax, [device.phy]
mov ax, [ebx + device.phy]
and ax, 0x1f
shl ax, 5
or ax, cx
 
mov ecx, BCR_MIIADDR
call [device.write_bcr]
call [ebx + device.write_bcr]
 
pop eax
mov ecx, BCR_MIIDATA
call [device.write_bcr]
call [ebx + device.write_bcr]
 
ret
 
1524,11 → 1506,11
 
DEBUGF 1, "check_media\n"
 
test [device.mii], 1
test [ebx + device.mii], 1
jnz mii_link_ok
 
mov ecx, BCR_LED0
call [device.read_bcr]
call [ebx + device.read_bcr]
cmp eax, 0xc0
 
DEBUGF 1, "link status=0x%x\n", ax
1539,10 → 1521,12
 
; End of code
 
align 4 ; Place all initialised data here
 
devices dd 0
version dd (5 shl 16) or (API_VERSION and 0xFFFF)
data fixups
end data
 
include '../peimport.inc'
 
my_service db 'PCnet',0 ; max 16 chars include zero
 
device_l2 db "PCnet/PCI 79C970",0
1573,6 → 1557,7
 
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
 
align 4
devices dd 0
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
/drivers/pci_pe.inc
62,16 → 62,13
 
push esi
xor eax, eax
mov esi, PCI_BASE_ADDRESS_0
mov esi, PCI_header00.base_addr_0
.check:
invoke PciRead32, [bus], [dev], esi
 
test eax, PCI_BASE_ADDRESS_IO_MASK
jz .inc
 
test eax, PCI_BASE_ADDRESS_SPACE_IO
jz .inc
 
and eax, PCI_BASE_ADDRESS_IO_MASK
pop esi
ret
78,7 → 75,7
 
.inc:
add esi, 4
cmp esi, PCI_BASE_ADDRESS_5
cmp esi, PCI_header00.base_addr_5
jbe .check
pop esi
xor eax, eax
95,10 → 92,8
mov esi, PCI_header00.base_addr_0
.check:
invoke PciRead32, [bus], [dev], esi
 
test eax, PCI_BASE_ADDRESS_SPACE_IO ; mmio address?
jnz .inc
 
test eax, 100b ; 64 bit?
jnz .inc
and eax, not 1111b