Subversion Repositories Kolibri OS

Rev

Rev 5363 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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