1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
4 ;; Distributed under terms of the GNU General Public License ;;
6 ;; PCMCIA aka cardbus driver for KolibriOS ;;
7 ;; Written by hidnplayr@gmail.com ;;
9 ;; Many credits go to Paolo Franchetti for his HWTEST program ;;
10 ;; (https://sites.google.com/site/pfranz73/) from which large ;;
11 ;; parts of code have been borrowed. ;;
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15 ; This module detects and initialises all Cardbus/pc-card/PCMCIA cards.
17 ; WARNING: Cards must be inserted before the driver starts, and shouldn't be removed.
18 ; This module doesn't handle insertions and removals.
22 ; Use GetPCIList instead of reading directly from PCI bus to detect bridge.
23 ; (See #5544 agp.asm for example).
24 ; Export a function in kernel to re-scan PCI device list (fix 'dirty hack').
25 ; Fix bugs (currently not working on all PCMCIA bridges).
31 COMPATIBLE_API
= 0x0100
32 API_VERSION
= (COMPATIBLE_API
shl 16) + CURRENT_API
34 CARDBUS_IO_BASE
= 0x1400
35 CARDBUS_IO_SIZE
= 0x100
41 section '.flat' readable writable executable
43 include '../proc32.inc'
44 include '../struct.inc'
45 include '../macros.inc'
49 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
53 ;; (standard driver proc) ;;
54 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56 proc START c
, reason:dword, cmdline:dword
58 cmp [reason
], DRV_ENTRY
61 DEBUGF
1, "Loading cardbus driver\n"
62 invoke RegService
, my_service
, service_proc
76 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
78 ;; proc SERVICE_PROC ;;
80 ;; (standard driver proc) ;;
81 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
83 proc service_proc stdcall
, ioctl:dword
86 mov eax, [edx + IOCTL.io_code
]
88 ;------------------------------------------------------
90 cmp eax, 0 ;SRV_GETVERSION
93 cmp [edx + IOCTL.out_size
], 4
95 mov eax, [edx + IOCTL.output
]
96 mov [eax], dword API_VERSION
117 DEBUGF
1, "Searching for cardbus bridges...\n"
133 invoke PciRead32
, [bus
], [devfn
], PCI_header.vendor_id
139 invoke PciRead16
, [bus
], [devfn
], PCI_header.subclass
; class & subclass
146 invoke PciRead8
, [bus
], [devfn
], PCI_header.header_type
161 DEBUGF
1, "Search complete\n"
167 DEBUGF
1, "Found cardbus bridge: bus=0x%x, dev=0x%x\n", [bus
], [devfn
]
169 invoke PciRead8
, [bus
], [devfn
], PCI_header.header_type
170 and al, not 0x80 ; Mask the multifunction device bit
171 DEBUGF
1, "Header type=0x%x\n", eax:2
175 ; Write PCI and cardbus numbers
177 invoke PciRead32
, [bus
], [devfn
], PCI_header02.pci_bus_nr
; PCcard latency settings + Card bus number, PCI bus number
178 and eax, 0xff000000 ; Keep original latency setting, clear the rest
180 mov ah, byte[card_bus
]
181 mov ebx, [card_bus
] ; sub bus nr???
184 DEBUGF
1, "Latency, bus,.. 0x%x\n", eax
185 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.pci_bus_nr
, eax
187 ; set ExCA legacy mode base
189 invoke PciWrite32
, [bus
], [devfn
], 0x44, 1
193 invoke PciRead8
, [bus
], [devfn
], PCI_header02.cap_list_offs
; get capabilities offset
194 movzx eax, al ; (A0 for TI bridges)
195 DEBUGF
1, "Capabilities offset=0x%x\n", eax:2
196 add al, 4 ; Power management control/status
197 invoke PciWrite16
, [bus
], [devfn
], eax, 0x0100 ; Enable PME signaling, power state=D0
199 ; Enable Bus master, io space, memory space
201 invoke PciWrite16
, [bus
], [devfn
], PCI_header02.command
, PCI_CMD_PIO
or PCI_CMD_MMIO
or PCI_CMD_MASTER
203 ; Write CardBus Socket/ExCA base address
207 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.base_addr
, eax ; base is 4 Kbyte aligned
209 invoke MapIoMem
, ebx, 4096, PG_SW
+PG_NOCACHE
212 ; Check if a card is present in the socket
214 mov eax, [ecx + 8] ; Socket present state register
215 DEBUGF
1, "Socket present state reg: 0x%x\n", eax
216 and al, 10110110b ; NotACard | CBCard | 16bitCard | CDetect1 | CDetect2
217 cmp al, 00100000b ; Check for inserted cardbus card
220 ; No card found... set PCI command back to 0
222 invoke PciWrite16
, [bus
], [devfn
], PCI_header02.command
, 0 ; To avoid conflicts with other sockets
223 DEBUGF
1, "Cardbus KO\n"
227 DEBUGF
1, "Card inserted\n"
228 ;mov word[ecx + 0x802], 0x00F9 ; Assert reset, output enable, vcc=vpp=3.3V
229 mov dword[ecx + 0x10], 0x33 ; Request 3.3V for Vcc and Vpp (Control register)
234 ;mov byte[ecx + 0x803], 0x40 ; stop reset
235 mov dword[ecx + 0xC], 0x4000 ; force Card CV test (Force register) ;;; WHY???
236 DEBUGF
1, "Resetting card\n"
238 ; Next power up test can be deferred until before writing to Bridge control PCI reg 0x3E
239 .
waitpower: ; For TI, you can check that bits 8-11 in PCI reg 80h are all 0
240 test dword[ecx + 8], 1 shl 3 ; Test PWRCYCLE bit
241 jz .waitpower
; Wait for power to go up
243 DEBUGF
1, "Interface is powered up\n"
245 ; Write MemBase-Limit 0 and 1, then IOBase-Limit 0 and 1
246 ; mem0 space limit = base => size is 4 kilobytes
247 ; set to 0 the second interval (mem1 and IO1)
248 ; IO0: size is 256 bytes
250 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.mbar_0
, 0x7EFFF000
251 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.mlimit_0
, 0x7EFFF000
252 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.mbar_1
, 0
253 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.mlimit_1
, 0
254 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.iobar_0
, CARDBUS_IO
255 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.iolimit_0
, CARDBUS_IO
+ 0xFC
256 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.iobar_1
, 0
257 invoke PciWrite32
, [bus
], [devfn
], PCI_header02.iolimit_1
, 0
258 invoke PciWrite8
, [bus
], [devfn
], PCI_header02.interrupt_line
, CARDBUS_IRQ
; IRQ line
259 invoke PciRead16
, [bus
], [devfn
], PCI_header02.bridge_ctrl
; Bridge control
260 or ax, 0x0700 ; Enable write posting, both memory windows prefetchable
261 invoke PciWrite16
, [bus
], [devfn
], PCI_header02.bridge_ctrl
, eax
262 DEBUGF
1, "Write posting enabled\n"
265 DEBUGF
1, "Bridge PCI registers:\n"
268 invoke PciRead32, [bus], [devfn], 4*(reg-1)
269 DEBUGF 1, "0x%x\n", eax
272 inc byte[0x80009021] ; LAST PCI bus count in kernel (dirty HACK!)
278 invoke PciRead32
, [card_bus
], 0, PCI_header.vendor_id
; Check if the card is awake yet
287 DEBUGF
1, "Timeout!\n"
288 ; TODO: disable card/bridge again ?
293 DEBUGF
1, "Card is enabled!\n"
295 invoke PciWrite32
, [card_bus
], 0, PCI_header02.base_addr
, CARDBUS_IO
; Supposing it's IO space that is needed
296 invoke PciWrite8
, [card_bus
], 0, PCI_header02.interrupt_line
, 0xC ; FIXME
297 invoke PciWrite16
, [card_bus
], 0, PCI_header02.command
, PCI_CMD_PIO
or PCI_CMD_MMIO
317 include '../peimport.inc'
319 my_service
db 'CARDBUS',0 ; max 16 chars include zero
321 include_debug_strings
; All data wich FDO uses will be included here