Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 5065 → Rev 5066

/drivers/bus/cardbus.asm
File deleted
\ No newline at end of file
/drivers/ethernet/bcm57xx.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
/drivers/pci_pe.inc
10,42 → 10,97
 
struct PCI_header
 
vendor_id dw ?
device_id dw ?
command dw ?
status dw ?
revision_id db ?
prog_if db ?
subclass db ?
class_code db ?
cache_line_size db ?
latency_timer db ?
header_type db ?
bist db ?
vendor_id dw ? ; 0x00
device_id dw ? ; 0x02
command dw ? ; 0x04
status dw ? ; 0x06
revision_id db ? ; 0x08
prog_if db ? ; 0x09
subclass db ? ; 0x0A
class_code db ? ; 0x0B
cache_line_size db ? ; 0x0C
latency_timer db ? ; 0x0D
header_type db ? ; 0x0E
bist db ? ; 0x0F
 
ends
 
struct PCI_header00 PCI_header
 
base_addr_0 dd ?
base_addr_1 dd ?
base_addr_2 dd ?
base_addr_3 dd ?
base_addr_4 dd ?
base_addr_5 dd ?
cardbus_cis_ptr dd ?
subsys_vendor dw ?
subsys_id dw ?
exp_rom_addr dd ?
cap_ptr db ?
reserved rb 7
interrupt_line db ?
interrupt_pin db ?
min_grant db ?
max_latency db ?
base_addr_0 dd ? ; 0x10
base_addr_1 dd ? ; 0x14
base_addr_2 dd ? ; 0x18
base_addr_3 dd ? ; 0x1C
base_addr_4 dd ? ; 0x20
base_addr_5 dd ? ; 0x24
cardbus_cis_ptr dd ? ; 0x28
subsys_vendor dw ? ; 0x2C
subsys_id dw ? ; 0x2E
exp_rom_addr dd ? ; 0x30
cap_ptr db ? ; 0x34
rb 7 ; reserved
interrupt_line db ? ; 0x3C
interrupt_pin db ? ; 0x3D
min_grant db ? ; 0x3E
max_latency db ? ; 0x3F
 
ends
 
struct PCI_header01 PCI_header
 
base_addr_0 dd ? ; 0x10
base_addr_1 dd ? ; 0x14
prim_bus_nr db ? ; 0x18
sec_bus_nr db ? ; 0x19
sub_bus_nr db ? ; 0x1A
sec_lat_tmr db ? ; 0x1B
io_base db ? ; 0x1C
io_limit db ? ; 0x1D
sec_status dw ? ; 0x1E
mem_base dw ? ; 0x20
mem_limit dw ? ; 0x22
pref_mem_base dw ? ; 0x24
pref_mem_limit dw ? ; 0x26
pref_base_up dd ? ; 0x28
pref_limit_up dd ? ; 0x2C
io_base_up dw ? ; 0x30
io_limit_up dw ? ; 0x32
cap_ptr db ? ; 0x34
rb 3 ; reserved
exp_rom_addr dd ? ; 0x38
interrupt_line db ? ; 0x3C
interrupt_pin db ? ; 0x3E
bridge_ctrl dw ? ; 0x3F
 
ends
 
struct PCI_header02 PCI_header
 
base_addr dd ? ; 0x10
cap_list_offs db ? ; 0x14
rb 1 ; reserved
sec_stat dw ? ; 0x16
pci_bus_nr db ? ; 0x18
cardbus_bus_nr db ? ; 0x19
sub_bus_nr db ? ; 0x1A
cardbus_lat_tmr db ? ; 0x1B
mbar_0 dd ? ; 0x1C
mlimit_0 dd ? ; 0x20
mbar_1 dd ? ; 0x24
mlimit_1 dd ? ; 0x28
iobar_0 dd ? ; 0x2C
iolimit_0 dd ? ; 0x30
iobar_1 dd ? ; 0x34
iolimit_1 dd ? ; 0x38
interrupt_line db ? ; 0x3C
interrupt_pin db ? ; 0x3D
bridge_ctrl dw ? ; 0x3E
subs_did dw ? ; 0x40
subs_vid dw ? ; 0x42
legacy_bar dd ? ; 0x44
 
ends
 
; Base address bits
PCI_BASE_ADDRESS_SPACE_IO = 0x01
PCI_BASE_ADDRESS_IO_MASK = 0xFFFFFFFC
/drivers/unfinished/agp.asm
0,0 → 1,284
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; simple AGP driver for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
format PE DLL native
entry START
 
CURRENT_API = 0x0200
COMPATIBLE_API = 0x0100
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
 
FAST_WRITE = 0 ; may cause problems with some motherboards
 
section '.flat' readable writable executable
 
include '../proc32.inc'
include '../struct.inc'
include '../macros.inc'
include '../pci_pe.inc'
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc START c, reason:dword, cmdline:dword
 
cmp [reason], DRV_ENTRY
jne .fail
 
mov esi, msgInit
invoke SysMsgBoardStr
invoke RegService, my_service, service_proc
 
call detect
 
ret
 
.fail:
xor eax, eax
ret
 
endp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [edx + IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne .fail
 
cmp [edx + IOCTL.out_size], 4
jb .fail
mov eax, [edx + IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
.fail:
or eax, -1
ret
 
endp
 
align 4
proc detect
locals
last_bus dd ?
endl
 
mov esi, msgSearch
invoke SysMsgBoardStr
 
xor eax, eax
mov [bus], eax
inc eax
invoke PciApi ; get last bus
cmp eax, -1
je .error
mov [last_bus], eax
 
.next_bus:
and [devfn], 0
.next_dev:
invoke PciRead16, [bus], [devfn], PCI_header.subclass ; subclass/vendor
cmp ax, 0x0300 ; display controller - vga compatable controller
je .found
cmp ax, 0x0302 ; display controller - 3d controller
je .found
cmp ax, 0x0380 ; display controller - other display controller
je .found
 
.next:
inc [devfn]
cmp [devfn], 256
jb .next_dev
mov eax, [bus]
inc eax
mov [bus], eax
cmp eax, [last_bus]
jna .next_bus
 
.error:
mov esi, msgFail
invoke SysMsgBoardStr
 
xor eax, eax
inc eax
ret
 
.found:
invoke PciRead8, [bus], [devfn], PCI_header00.prog_if
test al, 1 shl 4 ; got capabilities list?
jnz .got_capabilities_list
 
; TODO: Do it the old way: detect device and check with a list of known capabilities
; stupid pre PCI 2.2 board....
 
jmp .next
 
.got_capabilities_list:
invoke PciRead8, [bus], [devfn], PCI_header00.cap_ptr
and eax, 11111100b ; always dword aligned
mov edi, eax
 
.read_capability:
invoke PciRead32, [bus], [devfn], edi ; read capability
cmp al, 0x02 ; AGP
je .got_agp
movzx edi, ah ; pointer to next capability
test edi, edi
jnz .read_capability
jmp .next
 
.got_agp:
shr eax, 16
mov [revision], al ; high nibble = major revision
; low nibble = minor revision
add edi, 4
and al, 0xf0
cmp al, 0x30
je .agp_3
 
.agp_2:
mov esi, msgAGP2
invoke SysMsgBoardStr
 
invoke PciRead32, [bus], [devfn], edi ; read AGP status
.agp_2_:
test al, 100b
jnz .100b
test al, 10b
jnz .010b
test al, 1b
jz .error
 
.001b:
mov [cmd], 001b
mov esi, msg1
invoke SysMsgBoardStr
jmp .agp_go
 
.010b:
mov [cmd], 010b
mov esi, msg2
invoke SysMsgBoardStr
jmp .agp_go
 
.100b:
mov [cmd], 100b
mov esi, msg4
invoke SysMsgBoardStr
jmp .agp_go
 
.agp_2m:
mov esi, msgAGP2m
invoke SysMsgBoardStr
jmp .agp_2_
 
.agp_3:
mov esi, msgAGP3
invoke SysMsgBoardStr
 
invoke PciRead32, [bus], [devfn], edi ; read AGP status
test al, 1 shl 3
jz .agp_2m
 
test eax, 10b
jnz .8x
mov [cmd], 01b
mov esi, msg4
invoke SysMsgBoardStr
jmp .agp_go
 
.8x:
mov [cmd], 10b
mov esi, msg8
invoke SysMsgBoardStr
 
.agp_go:
 
if FAST_WRITE
test ax, 1 shl 4
jz @f
or [cmd], 1 shl 4
mov esi, msgfast
invoke SysMsgBoardStr
@@:
end if
 
test ax, 1 shl 9 ; Side band addressing
jz @f
or [cmd], 1 shl 9
mov esi, msgside
invoke SysMsgBoardStr
@@:
 
add edi, 4
mov eax, [cmd]
or eax, 1 shl 8 ; enable AGP
invoke PciWrite32, [bus], [devfn], edi, eax ; write AGP cmd
 
mov esi, msgOK
invoke SysMsgBoardStr
 
ret
 
endp
 
 
; End of code
 
data fixups
end data
 
include '../peimport.inc'
 
my_service db 'AGP', 0 ; max 16 chars include zero
 
msgInit db 'AGP driver loaded.', 13, 10, 0
msgSearch db 'Searching for AGP card...', 13, 10, 0
msgFail db 'device not found', 13, 10, 0
msgOK db 'AGP device enabled', 13, 10, 0
msgAGP2 db 'AGP2 device found', 13, 10, 0
msgAGP3 db 'AGP3 device found', 13, 10, 0
msgAGP2m db 'Running in AGP2 mode', 13, 10, 0
msg8 db '8x speed', 13, 10, 0
msg4 db '4x speed', 13, 10, 0
msg2 db '2x speed', 13, 10, 0
msg1 db '1x speed', 13, 10, 0
msgfast db 'Fast Write', 13, 10, 0
msgside db 'Side band addressing', 13, 10, 0
 
; uninitialized data
 
revision db ?
cmd dd ?
bus dd ?
devfn dd ?
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/unfinished/bcm57xx.asm
0,0 → 1,424
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; Broadcom NetXtreme 57xx driver for KolibriOS ;;
;; ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;; Broadcom's programmers's manual for the BCM57xx ;;
;; http://www.broadcom.com/collateral/pg/57XX-PG105-R.pdf ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
format PE DLL native
entry START
 
CURRENT_API = 0x0200
COMPATIBLE_API = 0x0100
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
 
MAX_DEVICES = 16
 
__DEBUG__ = 1
__DEBUG_LEVEL__ = 2
 
section '.flat' readable writable executable
 
include '../proc32.inc'
include '../struct.inc'
include '../macros.inc'
include '../fdo.inc'
include '../netdrv_pe.inc'
 
struct device ETH_DEVICE
 
mmio_addr dd ?
pci_bus dd ?
pci_dev dd ?
irq_line db ?
 
cur_tx dd ?
last_tx dd ?
 
rb 0x100 - ($ and 0xff) ; align 256
rx_desc rd 256/8
 
rb 0x100 - ($ and 0xff) ; align 256
tx_desc rd 256/8
 
ends
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc START c, reason:dword, cmdline:dword
 
cmp [reason], DRV_ENTRY
jne .fail
 
DEBUGF 1,"Loading driver\n"
invoke RegService, my_service, service_proc
ret
 
.fail:
xor eax, eax
ret
 
endp
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [edx + IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne @F
 
cmp [edx + IOCTL.out_size], 4
jb .fail
mov eax, [edx + IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
;------------------------------------------------------
@@:
cmp eax, 1 ;SRV_HOOK
jne .fail
 
cmp [edx + IOCTL.inp_size], 3 ; Data input must be at least 3 bytes
jb .fail
 
mov eax, [edx + IOCTL.input]
cmp byte [eax], 1 ; 1 means device number and bus number (pci) are given
jne .fail ; other types arent supported for this card yet
 
; check if the device is already listed
 
mov esi, device_list
mov ecx, [devices]
test ecx, ecx
jz .firstdevice
 
; mov eax, [edx + IOCTL.input] ; get the pci bus and device numbers
mov ax, [eax+1] ;
.nextdevice:
mov ebx, [esi]
cmp al, byte [ebx + device.pci_bus]
jne .next
cmp ah, byte [ebx + device.pci_dev]
je .find_devicenum ; Device is already loaded, let's find it's device number
.next:
add esi, 4
loop .nextdevice
 
 
; This device doesnt have its own eth_device structure yet, lets create one
.firstdevice:
cmp [devices], MAX_DEVICES ; First check if the driver can handle one more card
jae .fail
 
allocate_and_clear ebx, sizeof.device, .fail ; Allocate the buffer for device structure
 
; Fill in the direct call addresses into the struct
 
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 [ebx + device.pci_bus], ecx
movzx ecx, byte [eax+2]
mov [ebx + device.pci_dev], ecx
 
; Now, it's time to find the base mmio addres of the PCI device
 
stdcall PCI_find_mmio32, [ebx + device.pci_bus], [ebx + device.pci_dev]
 
; Create virtual mapping of the physical memory
 
push 1Bh ; PG_SW+PG_NOCACHE
push 10000h ; size of the map
push eax
invoke MapIoMem
mov [ebx + device.mmio_addr], eax
 
; We've found the mmio address, find IRQ now
 
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",\
[ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.mmio_addr]:8
 
; Ok, the eth_device structure is ready, let's probe the device
call probe ; this function will output in eax
test eax, eax
jnz .err ; If an error occured, exit
 
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 [ebx + device.type], NET_TYPE_ETH
invoke NetRegDev
 
cmp eax, -1
je .destroy
 
ret
 
; If the device was already loaded, find the device number and return it in eax
 
.find_devicenum:
DEBUGF 1,"Trying to find device number of already registered device\n"
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
ret
 
; If an error occured, remove all allocated data and exit (returning -1 in eax)
 
.destroy:
; todo: reset device into virgin state
 
.err:
invoke KernelFree, ebx
 
.fail:
or eax, -1
ret
 
;------------------------------------------------------
endp
 
 
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
;; ;;
;; Actual Hardware dependent code starts here ;;
;; ;;
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
 
unload:
; TODO: (in this particular order)
;
; - Stop the device
; - Detach int handler
; - Remove device from local list (device_list)
; - call unregister function in kernel
; - Remove all allocated structures and buffers the card used
 
or eax, -1
 
ret
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; probe: enables the device (if it really is BCM57XX)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
probe:
 
DEBUGF 1,"Probe\n"
 
; 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
 
 
; TODO: validate the device
 
 
 
 
reset:
 
DEBUGF 1,"Reset\n"
 
movzx eax, [ebx + device.irq_line]
DEBUGF 1,"Attaching int handler to irq %x\n", eax:1
invoke AttachIntHandler, eax, int_handler, ebx
test eax, eax
jnz @f
DEBUGF 1,"\nCould not attach int handler!\n"
; or eax, -1
; ret
@@:
 
call read_mac
 
; Set the mtu, kernel will be able to send now
mov [ebx + device.mtu], 1514
 
; Set link state to unknown
mov [ebx + device.state], ETH_LINK_UNKNOWN
 
ret
 
 
 
 
align 4
read_mac:
 
DEBUGF 1,"Read MAC\n"
 
mov esi, [ebx + device.mmio_addr]
lea edi, [ebx + device.mac]
movsd
movsw
 
.mac_ok:
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
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Transmit ;;
;; ;;
;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
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 [buffersize], 1514
ja .fail
cmp [buffersize], 60
jb .fail
 
 
 
 
 
; Update stats
inc [ebx + device.packets_tx]
mov eax, [buffersize]
add dword[ebx + device.bytes_tx], eax
adc dword[ebx + device.bytes_tx + 4], 0
 
DEBUGF 1,"Transmit OK\n"
popf
xor eax, eax
ret
 
.fail:
DEBUGF 2,"Transmit failed\n"
invoke KernelFree, [bufferptr]
popf
or eax, -1
ret
 
endp
 
 
;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Interrupt handler ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;
 
align 4
int_handler:
 
push ebx esi edi
 
DEBUGF 1,"INT\n"
;-------------------------------------------
; Find pointer of device wich made IRQ occur
 
mov ecx, [devices]
test ecx, ecx
jz .nothing
mov esi, device_list
.nextdevice:
mov ebx, [esi]
 
; mov edi, [ebx + device.mmio_addr]
; mov eax, [edi + REG_ICR]
test eax, eax
jnz .got_it
.continue:
add esi, 4
dec ecx
jnz .nextdevice
.nothing:
pop edi esi ebx
xor eax, eax
 
ret
 
.got_it:
 
DEBUGF 1,"Device: %x Status: %x ", ebx, eax
 
pop edi esi ebx
xor eax, eax
inc eax
 
ret
 
 
 
 
; End of code
 
data fixups
end data
 
include '../peimport.inc'
 
my_service db 'BCM57XX',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here
 
align 4
devices dd 0
device_list rd MAX_DEVICES ; This list contains all pointers to device structures the driver is handling
 
 
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/drivers/unfinished/cardbus.asm
0,0 → 1,306
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; PCMCIA aka cardbus driver for KolibriOS ;;
;; Written by hidnplayr@gmail.com ;;
;; ;;
;; Many credits go to Paolo Franchetti for his HWTEST program ;;
;; (https://sites.google.com/site/pfranz73/) from which large ;;
;; parts of code have been borrowed. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; This module detects and initialises all Cardbus/pc-card/PCMCIA cards.
 
; WARNING: Cards must be inserted before the driver starts, and shouldn't be removed.
; This module doesn't handle insertions and removals.
 
format PE DLL native
entry START
 
CURRENT_API = 0x0200
COMPATIBLE_API = 0x0100
API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API
 
CARDBUS_IO = 0xFC00
 
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
section '.flat' readable writable executable
 
include '../proc32.inc'
include '../struct.inc'
include '../macros.inc'
include '../pci_pe.inc'
include '../fdo.inc'
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc START ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc START c, reason:dword, cmdline:dword
 
cmp [reason], DRV_ENTRY
jne .fail
 
DEBUGF 1, "Loading cardbus driver\n"
invoke RegService, my_service, service_proc
 
call detect
 
ret
 
.fail:
xor eax, eax
ret
 
endp
 
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; proc SERVICE_PROC ;;
;; ;;
;; (standard driver proc) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
proc service_proc stdcall, ioctl:dword
 
mov edx, [ioctl]
mov eax, [edx + IOCTL.io_code]
 
;------------------------------------------------------
 
cmp eax, 0 ;SRV_GETVERSION
jne .fail
 
cmp [edx + IOCTL.out_size], 4
jb .fail
mov eax, [edx + IOCTL.output]
mov [eax], dword API_VERSION
 
xor eax, eax
ret
 
.fail:
or eax, -1
ret
 
endp
 
align 4
proc detect
 
locals
last_bus dd ?
card_bus dd ?
bus dd ?
devfn dd ?
endl
 
DEBUGF 1, "Searching for cardbus bridges...\n"
 
xor eax, eax
mov [bus], eax
inc eax
invoke PciApi
cmp eax, -1
je .err
mov [last_bus], eax
 
inc eax
mov [card_bus], eax
 
.next_bus:
and [devfn], 0
.next_dev:
invoke PciRead32, [bus], [devfn], PCI_header02.vendor_id
test eax, eax
jz .next
cmp eax, -1
je .next
 
invoke PciRead16, [bus], [devfn], 0x0a ; class & subclass
cmp ax, 0x0607
je .found
 
.next:
inc [devfn]
cmp [devfn], 256
jb .next_dev
mov eax, [bus]
inc eax
mov [bus], eax
cmp eax, [last_bus]
jna .next_bus
 
DEBUGF 1, "Search complete\n"
xor eax, eax
inc eax
ret
 
.found:
DEBUGF 1, "Found cardbus bridge: bus=0x%x, dev=0x%x\n", [bus], [devfn]
 
invoke PciRead8, [bus], [devfn], PCI_header.header_type
DEBUGF 1, "Header type=0x%x\n", eax:2
cmp al, 2
jne .next
 
; Write PCI and cardbus numbers
 
invoke PciRead32, [bus], [devfn], PCI_header02.pci_bus_nr ; PCcard latency settings + Card bus number, PCI bus number
and eax, 0xff000000 ; Keep original latency setting, clear the rest
mov al, byte[bus]
mov ah, byte[card_bus]
mov ebx, [card_bus]
shl ebx, 16
or eax, ebx
DEBUGF 1, "Latency, bus,.. 0x%x\n", eax
invoke PciWrite32, [bus], [devfn], PCI_header02.pci_bus_nr, eax
 
; set ExCA legacy mode base
 
invoke PciWrite32, [bus], [devfn], 0x44, 1
 
; Enable power
 
invoke PciRead8, [bus], [devfn], 0x14 ; get capabilities offset
movzx eax, al ; (A0 for TI bridges)
DEBUGF 1, "Capabilities offset=0x%x\n", eax:2
add al, 4 ; Power management control/status
invoke PciWrite16, [bus], [devfn], eax, 0x0100 ; Enable PME signaling, power state=D0
 
; Enable Bus master, io space, memory space
 
invoke PciWrite16, [bus], [devfn], PCI_header02.command, 0x0007
 
; Write CardBus Socket/ExCA base address
 
mov eax, 0x7f000000
push eax
invoke PciWrite32, [bus], [devfn], PCI_header02.base_addr, eax ; base is 4 Kbyte aligned
pop ebx
invoke MapIoMem, ebx, 4096, 0x1b
mov ecx, eax
 
; Check if a card is present in the socket
 
mov eax, [ecx + 8] ; Socket present state register
DEBUGF 1, "Socket present state reg: 0x%x\n", eax
and al, 10110110b ; NotACard | CBCard | 16bitCard | CDetect1 | CDetect2
cmp al, 00100000b ; Check for inserted cardbus card
je .CardbusInserted
 
; No card found... set PCI command back to 0
 
invoke PciWrite16, [bus], [devfn], PCI_header02.command, 0 ; To avoid conflicts with other sockets
DEBUGF 1, "Cardbus KO\n"
jmp .next
 
.CardbusInserted:
DEBUGF 1, "Card inserted\n"
;mov word[ecx + 0x802], 0x00F9 ; Assert reset, output enable, vcc=vpp=3.3V
mov dword[ecx + 0x10], 0x33 ; Request 3.3V for Vcc and Vpp (Control register)
;push ecx
;mov esi, 10
;invoke Sleep
;pop ecx
;mov byte[ecx + 0x803], 0x40 ; stop reset
mov dword[ecx + 0xC], 0x4000 ; force Card CV test (Force register) ;;; WHY???
DEBUGF 1, "Resetting card\n"
 
; Next power up test can be deferred until before writing to Bridge control PCI reg 0x3E
.waitpower: ; For TI, you can check that bits 8-11 in PCI reg 80h are all 0
test dword[ecx + 8], 1 shl 3 ; Test PWRCYCLE bit
jz .waitpower ; Wait for power to go up
 
DEBUGF 1, "Interface is powered up\n"
 
; Write MemBase-Limit 0 and 1, then IOBase-Limit 0 and 1
; mem0 space limit = base => size is 4 kilobytes
; set to 0 the second interval (mem1 and IO1)
; IO0: size is 256 bytes
 
irp regvalue, 0x7efff000, 0x7effffff, 0x7effe000, 0x7effe000, CARDBUS_IO, CARDBUS_IO + 0xFF, 0, 0
{
common
reg = 0x1C
forward
invoke PciWrite32, [bus], [devfn], reg, regvalue
DEBUGF 1, "Writing 0x%x to 0x%x\n", regvalue, reg
reg = reg + 4
}
 
invoke PciWrite8, [bus], [devfn], PCI_header02.interrupt_line, 0xc ; IRQ line
 
invoke PciRead16, [bus], [devfn], PCI_header02.bridge_ctrl ; Bridge control
or ax, 0x0700 ; Enable write posting, both memory windows prefetchable
invoke PciWrite16, [bus], [devfn], PCI_header02.bridge_ctrl, eax
DEBUGF 1, "Write posting enabled\n"
 
 
DEBUGF 1, "Bridge PCI registers:\n"
rept 17 reg
{
invoke PciRead32, [bus], [devfn], 4*(reg-1)
DEBUGF 1, "0x%x\n", eax
}
 
inc byte[0x80009021] ; LAST PCI bus count in kernel (dirty HACK!)
 
 
mov ecx, 100
.waitactive:
push ecx
invoke PciRead32, [card_bus], 0, PCI_header02.vendor_id ; Check if the card is awake yet
inc eax
jnz .got_it
mov esi, 2
invoke Sleep
pop ecx
dec ecx
jnz .waitactive
 
DEBUGF 1, "Timeout!\n"
; TODO: disable card/bridge again ?
jmp .next
 
.got_it:
pop eax
DEBUGF 1, "Card is enabled!\n"
 
invoke PciWrite32, [card_bus], 0, PCI_header02.base_addr, CARDBUS_IO ; Supposing it's IO space that is needed
invoke PciWrite8, [card_bus], 0, PCI_header02.interrupt_line, 0xC ; FIXME
invoke PciWrite16, [card_bus], 0, PCI_header02.command, PCI_CMD_PIO or PCI_CMD_MMIO
 
DEBUGF 1, "done\n"
 
jmp .next
 
.err:
DEBUGF 1, "Error\n"
xor eax, eax
 
ret
 
endp
 
 
; End of code
 
data fixups
end data
 
include '../peimport.inc'
 
my_service db 'CARDBUS',0 ; max 16 chars include zero
 
include_debug_strings ; All data wich FDO uses will be included here