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