Rev 4476 | Rev 5074 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4476 | hidnplayr | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
||
3 | ;; Copyright (C) KolibriOS team 2004-2014. All rights reserved. ;; |
||
4 | ;; Distributed under terms of the GNU General Public License ;; |
||
5 | ;; ;; |
||
6 | ;; PCMCIA aka cardbus driver for KolibriOS ;; |
||
7 | ;; Written by hidnplayr@gmail.com ;; |
||
8 | ;; ;; |
||
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. ;; |
||
12 | ;; ;; |
||
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
14 | |||
15 | ; This module detects and initialises all Cardbus/pc-card/PCMCIA cards. |
||
16 | |||
17 | ; WARNING: Cards must be inserted before the driver starts, and shouldn't be removed. |
||
18 | ; This module doesn't handle insertions and removals. |
||
19 | |||
5066 | hidnplayr | 20 | format PE DLL native |
21 | entry START |
||
4476 | hidnplayr | 22 | |
5066 | hidnplayr | 23 | CURRENT_API = 0x0200 |
24 | COMPATIBLE_API = 0x0100 |
||
25 | API_VERSION = (COMPATIBLE_API shl 16) + CURRENT_API |
||
4476 | hidnplayr | 26 | |
27 | CARDBUS_IO = 0xFC00 |
||
28 | |||
29 | __DEBUG__ = 1 |
||
30 | __DEBUG_LEVEL__ = 1 |
||
31 | |||
5066 | hidnplayr | 32 | section '.flat' readable writable executable |
4476 | hidnplayr | 33 | |
5066 | hidnplayr | 34 | include '../proc32.inc' |
4476 | hidnplayr | 35 | include '../struct.inc' |
36 | include '../macros.inc' |
||
5066 | hidnplayr | 37 | include '../pci_pe.inc' |
4476 | hidnplayr | 38 | include '../fdo.inc' |
39 | |||
40 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
41 | ;; ;; |
||
42 | ;; proc START ;; |
||
43 | ;; ;; |
||
44 | ;; (standard driver proc) ;; |
||
45 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
46 | |||
5066 | hidnplayr | 47 | proc START c, reason:dword, cmdline:dword |
4476 | hidnplayr | 48 | |
5066 | hidnplayr | 49 | cmp [reason], DRV_ENTRY |
50 | jne .fail |
||
4476 | hidnplayr | 51 | |
52 | DEBUGF 1, "Loading cardbus driver\n" |
||
5066 | hidnplayr | 53 | invoke RegService, my_service, service_proc |
4476 | hidnplayr | 54 | |
55 | call detect |
||
56 | |||
57 | ret |
||
58 | |||
59 | .fail: |
||
60 | xor eax, eax |
||
61 | ret |
||
62 | |||
63 | endp |
||
64 | |||
65 | |||
66 | |||
67 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
68 | ;; ;; |
||
69 | ;; proc SERVICE_PROC ;; |
||
70 | ;; ;; |
||
71 | ;; (standard driver proc) ;; |
||
72 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
73 | |||
74 | proc service_proc stdcall, ioctl:dword |
||
75 | |||
76 | mov edx, [ioctl] |
||
77 | mov eax, [edx + IOCTL.io_code] |
||
78 | |||
79 | ;------------------------------------------------------ |
||
80 | |||
81 | cmp eax, 0 ;SRV_GETVERSION |
||
82 | jne .fail |
||
83 | |||
84 | cmp [edx + IOCTL.out_size], 4 |
||
85 | jb .fail |
||
86 | mov eax, [edx + IOCTL.output] |
||
87 | mov [eax], dword API_VERSION |
||
88 | |||
89 | xor eax, eax |
||
90 | ret |
||
91 | |||
92 | .fail: |
||
93 | or eax, -1 |
||
94 | ret |
||
95 | |||
96 | endp |
||
97 | |||
98 | align 4 |
||
99 | proc detect |
||
100 | |||
101 | locals |
||
102 | last_bus dd ? |
||
103 | card_bus dd ? |
||
104 | bus dd ? |
||
105 | devfn dd ? |
||
106 | endl |
||
107 | |||
108 | DEBUGF 1, "Searching for cardbus bridges...\n" |
||
109 | |||
110 | xor eax, eax |
||
111 | mov [bus], eax |
||
112 | inc eax |
||
5066 | hidnplayr | 113 | invoke PciApi |
4476 | hidnplayr | 114 | cmp eax, -1 |
115 | je .err |
||
116 | mov [last_bus], eax |
||
117 | |||
118 | inc eax |
||
119 | mov [card_bus], eax |
||
120 | |||
121 | .next_bus: |
||
122 | and [devfn], 0 |
||
123 | .next_dev: |
||
5066 | hidnplayr | 124 | invoke PciRead32, [bus], [devfn], PCI_header02.vendor_id |
4476 | hidnplayr | 125 | test eax, eax |
126 | jz .next |
||
127 | cmp eax, -1 |
||
128 | je .next |
||
129 | |||
5066 | hidnplayr | 130 | invoke PciRead16, [bus], [devfn], 0x0a ; class & subclass |
4476 | hidnplayr | 131 | cmp ax, 0x0607 |
132 | je .found |
||
133 | |||
134 | .next: |
||
135 | inc [devfn] |
||
136 | cmp [devfn], 256 |
||
137 | jb .next_dev |
||
138 | mov eax, [bus] |
||
139 | inc eax |
||
140 | mov [bus], eax |
||
141 | cmp eax, [last_bus] |
||
142 | jna .next_bus |
||
143 | |||
144 | DEBUGF 1, "Search complete\n" |
||
145 | xor eax, eax |
||
146 | inc eax |
||
147 | ret |
||
148 | |||
149 | .found: |
||
150 | DEBUGF 1, "Found cardbus bridge: bus=0x%x, dev=0x%x\n", [bus], [devfn] |
||
151 | |||
5066 | hidnplayr | 152 | invoke PciRead8, [bus], [devfn], PCI_header.header_type |
4476 | hidnplayr | 153 | DEBUGF 1, "Header type=0x%x\n", eax:2 |
5066 | hidnplayr | 154 | cmp al, 2 |
155 | jne .next |
||
4476 | hidnplayr | 156 | |
157 | ; Write PCI and cardbus numbers |
||
158 | |||
5066 | hidnplayr | 159 | invoke PciRead32, [bus], [devfn], PCI_header02.pci_bus_nr ; PCcard latency settings + Card bus number, PCI bus number |
160 | and eax, 0xff000000 ; Keep original latency setting, clear the rest |
||
4476 | hidnplayr | 161 | mov al, byte[bus] |
162 | mov ah, byte[card_bus] |
||
163 | mov ebx, [card_bus] |
||
164 | shl ebx, 16 |
||
165 | or eax, ebx |
||
166 | DEBUGF 1, "Latency, bus,.. 0x%x\n", eax |
||
5066 | hidnplayr | 167 | invoke PciWrite32, [bus], [devfn], PCI_header02.pci_bus_nr, eax |
4476 | hidnplayr | 168 | |
169 | ; set ExCA legacy mode base |
||
170 | |||
5066 | hidnplayr | 171 | invoke PciWrite32, [bus], [devfn], 0x44, 1 |
4476 | hidnplayr | 172 | |
173 | ; Enable power |
||
174 | |||
5066 | hidnplayr | 175 | invoke PciRead8, [bus], [devfn], 0x14 ; get capabilities offset |
4476 | hidnplayr | 176 | movzx eax, al ; (A0 for TI bridges) |
177 | DEBUGF 1, "Capabilities offset=0x%x\n", eax:2 |
||
178 | add al, 4 ; Power management control/status |
||
5066 | hidnplayr | 179 | invoke PciWrite16, [bus], [devfn], eax, 0x0100 ; Enable PME signaling, power state=D0 |
4476 | hidnplayr | 180 | |
181 | ; Enable Bus master, io space, memory space |
||
182 | |||
5066 | hidnplayr | 183 | invoke PciWrite16, [bus], [devfn], PCI_header02.command, 0x0007 |
4476 | hidnplayr | 184 | |
185 | ; Write CardBus Socket/ExCA base address |
||
186 | |||
187 | mov eax, 0x7f000000 |
||
188 | push eax |
||
5066 | hidnplayr | 189 | invoke PciWrite32, [bus], [devfn], PCI_header02.base_addr, eax ; base is 4 Kbyte aligned |
4476 | hidnplayr | 190 | pop ebx |
5066 | hidnplayr | 191 | invoke MapIoMem, ebx, 4096, 0x1b |
4476 | hidnplayr | 192 | mov ecx, eax |
193 | |||
194 | ; Check if a card is present in the socket |
||
195 | |||
196 | mov eax, [ecx + 8] ; Socket present state register |
||
197 | DEBUGF 1, "Socket present state reg: 0x%x\n", eax |
||
198 | and al, 10110110b ; NotACard | CBCard | 16bitCard | CDetect1 | CDetect2 |
||
199 | cmp al, 00100000b ; Check for inserted cardbus card |
||
200 | je .CardbusInserted |
||
201 | |||
202 | ; No card found... set PCI command back to 0 |
||
203 | |||
5066 | hidnplayr | 204 | invoke PciWrite16, [bus], [devfn], PCI_header02.command, 0 ; To avoid conflicts with other sockets |
4476 | hidnplayr | 205 | DEBUGF 1, "Cardbus KO\n" |
206 | jmp .next |
||
207 | |||
208 | .CardbusInserted: |
||
209 | DEBUGF 1, "Card inserted\n" |
||
210 | ;mov word[ecx + 0x802], 0x00F9 ; Assert reset, output enable, vcc=vpp=3.3V |
||
211 | mov dword[ecx + 0x10], 0x33 ; Request 3.3V for Vcc and Vpp (Control register) |
||
212 | ;push ecx |
||
213 | ;mov esi, 10 |
||
5066 | hidnplayr | 214 | ;invoke Sleep |
4476 | hidnplayr | 215 | ;pop ecx |
216 | ;mov byte[ecx + 0x803], 0x40 ; stop reset |
||
217 | mov dword[ecx + 0xC], 0x4000 ; force Card CV test (Force register) ;;; WHY??? |
||
218 | DEBUGF 1, "Resetting card\n" |
||
219 | |||
220 | ; Next power up test can be deferred until before writing to Bridge control PCI reg 0x3E |
||
221 | .waitpower: ; For TI, you can check that bits 8-11 in PCI reg 80h are all 0 |
||
222 | test dword[ecx + 8], 1 shl 3 ; Test PWRCYCLE bit |
||
223 | jz .waitpower ; Wait for power to go up |
||
224 | |||
225 | DEBUGF 1, "Interface is powered up\n" |
||
226 | |||
227 | ; Write MemBase-Limit 0 and 1, then IOBase-Limit 0 and 1 |
||
228 | ; mem0 space limit = base => size is 4 kilobytes |
||
229 | ; set to 0 the second interval (mem1 and IO1) |
||
230 | ; IO0: size is 256 bytes |
||
231 | |||
232 | irp regvalue, 0x7efff000, 0x7effffff, 0x7effe000, 0x7effe000, CARDBUS_IO, CARDBUS_IO + 0xFF, 0, 0 |
||
233 | { |
||
234 | common |
||
235 | reg = 0x1C |
||
236 | forward |
||
5066 | hidnplayr | 237 | invoke PciWrite32, [bus], [devfn], reg, regvalue |
4476 | hidnplayr | 238 | DEBUGF 1, "Writing 0x%x to 0x%x\n", regvalue, reg |
239 | reg = reg + 4 |
||
240 | } |
||
241 | |||
5066 | hidnplayr | 242 | invoke PciWrite8, [bus], [devfn], PCI_header02.interrupt_line, 0xc ; IRQ line |
4476 | hidnplayr | 243 | |
5066 | hidnplayr | 244 | invoke PciRead16, [bus], [devfn], PCI_header02.bridge_ctrl ; Bridge control |
4476 | hidnplayr | 245 | or ax, 0x0700 ; Enable write posting, both memory windows prefetchable |
5066 | hidnplayr | 246 | invoke PciWrite16, [bus], [devfn], PCI_header02.bridge_ctrl, eax |
4476 | hidnplayr | 247 | DEBUGF 1, "Write posting enabled\n" |
248 | |||
249 | |||
250 | DEBUGF 1, "Bridge PCI registers:\n" |
||
251 | rept 17 reg |
||
252 | { |
||
5066 | hidnplayr | 253 | invoke PciRead32, [bus], [devfn], 4*(reg-1) |
4476 | hidnplayr | 254 | DEBUGF 1, "0x%x\n", eax |
255 | } |
||
256 | |||
257 | inc byte[0x80009021] ; LAST PCI bus count in kernel (dirty HACK!) |
||
258 | |||
259 | |||
260 | mov ecx, 100 |
||
261 | .waitactive: |
||
262 | push ecx |
||
5066 | hidnplayr | 263 | invoke PciRead32, [card_bus], 0, PCI_header02.vendor_id ; Check if the card is awake yet |
4476 | hidnplayr | 264 | inc eax |
265 | jnz .got_it |
||
266 | mov esi, 2 |
||
5066 | hidnplayr | 267 | invoke Sleep |
4476 | hidnplayr | 268 | pop ecx |
269 | dec ecx |
||
270 | jnz .waitactive |
||
271 | |||
272 | DEBUGF 1, "Timeout!\n" |
||
273 | ; TODO: disable card/bridge again ? |
||
274 | jmp .next |
||
275 | |||
276 | .got_it: |
||
277 | pop eax |
||
278 | DEBUGF 1, "Card is enabled!\n" |
||
279 | |||
5066 | hidnplayr | 280 | invoke PciWrite32, [card_bus], 0, PCI_header02.base_addr, CARDBUS_IO ; Supposing it's IO space that is needed |
281 | invoke PciWrite8, [card_bus], 0, PCI_header02.interrupt_line, 0xC ; FIXME |
||
282 | invoke PciWrite16, [card_bus], 0, PCI_header02.command, PCI_CMD_PIO or PCI_CMD_MMIO |
||
4476 | hidnplayr | 283 | |
284 | DEBUGF 1, "done\n" |
||
285 | |||
286 | jmp .next |
||
287 | |||
288 | .err: |
||
289 | DEBUGF 1, "Error\n" |
||
290 | xor eax, eax |
||
291 | |||
292 | ret |
||
293 | |||
294 | endp |
||
295 | |||
296 | |||
5066 | hidnplayr | 297 | ; End of code |
4476 | hidnplayr | 298 | |
5066 | hidnplayr | 299 | data fixups |
300 | end data |
||
4476 | hidnplayr | 301 | |
5066 | hidnplayr | 302 | include '../peimport.inc' |
4476 | hidnplayr | 303 | |
304 | my_service db 'CARDBUS',0 ; max 16 chars include zero |
||
305 | |||
306 | include_debug_strings ; All data wich FDO uses will be included here |