Subversion Repositories Kolibri OS

Rev

Rev 5172 | Rev 5866 | 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
 
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'
5074 hidnplayr 37
include '../pci.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:
5172 hidnplayr 124
        invoke  PciRead32, [bus], [devfn], PCI_header.vendor_id
4476 hidnplayr 125
        test    eax, eax
126
        jz      .next
127
        cmp     eax, -1
128
        je      .next
129
 
5172 hidnplayr 130
        invoke  PciRead16, [bus], [devfn], PCI_header.subclass  ; class & subclass
4476 hidnplayr 131
        cmp     ax, 0x0607
132
        je      .found
133
 
134
  .next:
5172 hidnplayr 135
        test    [devfn], 7
136
        jnz     .next_fn
137
        invoke  PciRead8, [bus], [devfn], PCI_header.header_type
138
        test    al, al
139
        js      .next_fn
140
        or      [devfn], 7
141
 
142
  .next_fn:
4476 hidnplayr 143
        inc     [devfn]
144
        cmp     [devfn], 256
145
        jb      .next_dev
146
        mov     eax, [bus]
147
        inc     eax
148
        mov     [bus], eax
149
        cmp     eax, [last_bus]
150
        jna     .next_bus
151
 
152
        DEBUGF  1, "Search complete\n"
153
        xor     eax, eax
154
        inc     eax
155
        ret
156
 
157
  .found:
158
        DEBUGF  1, "Found cardbus bridge: bus=0x%x, dev=0x%x\n", [bus], [devfn]
159
 
5066 hidnplayr 160
        invoke  PciRead8, [bus], [devfn], PCI_header.header_type
5172 hidnplayr 161
        and     al, not 0x80                                            ; Mask the multifunction device bit
4476 hidnplayr 162
        DEBUGF  1, "Header type=0x%x\n", eax:2
5066 hidnplayr 163
        cmp     al, 2
164
        jne     .next
4476 hidnplayr 165
 
166
; Write PCI and cardbus numbers
167
 
5066 hidnplayr 168
        invoke  PciRead32, [bus], [devfn], PCI_header02.pci_bus_nr      ; PCcard latency settings + Card bus number, PCI bus number
169
        and     eax, 0xff000000                                         ; Keep original latency setting, clear the rest
4476 hidnplayr 170
        mov     al, byte[bus]
171
        mov     ah, byte[card_bus]
172
        mov     ebx, [card_bus]
173
        shl     ebx, 16
174
        or      eax, ebx
175
        DEBUGF  1, "Latency, bus,.. 0x%x\n", eax
5066 hidnplayr 176
        invoke  PciWrite32, [bus], [devfn], PCI_header02.pci_bus_nr, eax
4476 hidnplayr 177
 
178
; set ExCA legacy mode base
179
 
5066 hidnplayr 180
        invoke  PciWrite32, [bus], [devfn], 0x44, 1
4476 hidnplayr 181
 
182
; Enable power
183
 
5066 hidnplayr 184
        invoke  PciRead8, [bus], [devfn], 0x14                  ; get capabilities offset
4476 hidnplayr 185
        movzx   eax, al                                         ; (A0 for TI bridges)
186
        DEBUGF  1, "Capabilities offset=0x%x\n", eax:2
187
        add     al, 4                                           ; Power management control/status
5066 hidnplayr 188
        invoke  PciWrite16, [bus], [devfn], eax, 0x0100         ; Enable PME signaling, power state=D0
4476 hidnplayr 189
 
190
; Enable Bus master, io space, memory space
191
 
5066 hidnplayr 192
        invoke  PciWrite16, [bus], [devfn], PCI_header02.command, 0x0007
4476 hidnplayr 193
 
194
; Write CardBus Socket/ExCA base address
195
 
196
        mov     eax, 0x7f000000
197
        push    eax
5066 hidnplayr 198
        invoke  PciWrite32, [bus], [devfn], PCI_header02.base_addr, eax ; base is 4 Kbyte aligned
4476 hidnplayr 199
        pop     ebx
5066 hidnplayr 200
        invoke  MapIoMem, ebx, 4096, 0x1b
4476 hidnplayr 201
        mov     ecx, eax
202
 
203
; Check if a card is present in the socket
204
 
205
        mov     eax, [ecx + 8]                                  ; Socket present state register
206
        DEBUGF  1, "Socket present state reg: 0x%x\n", eax
207
        and     al, 10110110b                                   ; NotACard | CBCard | 16bitCard | CDetect1 | CDetect2
208
        cmp     al, 00100000b                                   ; Check for inserted cardbus card
209
        je      .CardbusInserted
210
 
211
; No card found... set PCI command back to 0
212
 
5066 hidnplayr 213
        invoke  PciWrite16, [bus], [devfn], PCI_header02.command, 0  ; To avoid conflicts with other sockets
4476 hidnplayr 214
        DEBUGF  1, "Cardbus KO\n"
215
        jmp     .next
216
 
217
  .CardbusInserted:
218
        DEBUGF  1, "Card inserted\n"
219
        ;mov     word[ecx + 0x802], 0x00F9       ; Assert reset, output enable, vcc=vpp=3.3V
220
        mov     dword[ecx + 0x10], 0x33         ; Request 3.3V for Vcc and Vpp (Control register)
221
        ;push    ecx
222
        ;mov     esi, 10
5066 hidnplayr 223
        ;invoke  Sleep
4476 hidnplayr 224
        ;pop     ecx
225
        ;mov     byte[ecx + 0x803], 0x40         ; stop reset
226
        mov     dword[ecx + 0xC], 0x4000        ; force Card CV test (Force register)   ;;; WHY???
227
        DEBUGF  1, "Resetting card\n"
228
 
229
; Next power up test can be deferred until before writing to Bridge control PCI reg 0x3E
230
  .waitpower:                                   ; For TI, you can check that bits 8-11 in PCI reg 80h are all 0
231
        test    dword[ecx + 8], 1 shl 3         ; Test PWRCYCLE bit
232
        jz      .waitpower                      ; Wait for power to go up
233
 
234
        DEBUGF  1, "Interface is powered up\n"
235
 
236
; Write MemBase-Limit 0 and 1, then IOBase-Limit 0 and 1
237
; mem0 space limit = base => size is 4 kilobytes
238
; set to 0 the second interval (mem1 and IO1)
239
; IO0: size is 256 bytes
240
 
241
irp     regvalue,   0x7efff000, 0x7effffff, 0x7effe000, 0x7effe000, CARDBUS_IO, CARDBUS_IO + 0xFF, 0, 0
242
{
243
common
244
        reg = 0x1C
245
forward
5066 hidnplayr 246
        invoke  PciWrite32, [bus], [devfn], reg, regvalue
4476 hidnplayr 247
        DEBUGF  1, "Writing 0x%x to 0x%x\n", regvalue, reg
248
        reg = reg + 4
249
}
250
 
5066 hidnplayr 251
        invoke  PciWrite8, [bus], [devfn], PCI_header02.interrupt_line, 0xc    ; IRQ line
4476 hidnplayr 252
 
5066 hidnplayr 253
        invoke  PciRead16, [bus], [devfn], PCI_header02.bridge_ctrl                 ; Bridge control
4476 hidnplayr 254
        or      ax, 0x0700                                      ; Enable write posting, both memory windows prefetchable
5066 hidnplayr 255
        invoke  PciWrite16, [bus], [devfn], PCI_header02.bridge_ctrl, eax
4476 hidnplayr 256
        DEBUGF  1, "Write posting enabled\n"
257
 
258
 
259
        DEBUGF  1, "Bridge PCI registers:\n"
260
rept    17 reg
261
{
5066 hidnplayr 262
        invoke  PciRead32, [bus], [devfn], 4*(reg-1)
4476 hidnplayr 263
        DEBUGF  1, "0x%x\n", eax
264
}
265
 
266
        inc     byte[0x80009021]                                ; LAST PCI bus count in kernel (dirty HACK!)
267
 
268
 
269
        mov     ecx, 100
270
  .waitactive:
271
        push    ecx
5066 hidnplayr 272
        invoke  PciRead32, [card_bus], 0, PCI_header02.vendor_id         ; Check if the card is awake yet
4476 hidnplayr 273
        inc     eax
274
        jnz     .got_it
275
        mov     esi, 2
5066 hidnplayr 276
        invoke  Sleep
4476 hidnplayr 277
        pop     ecx
278
        dec     ecx
279
        jnz     .waitactive
280
 
281
        DEBUGF  1, "Timeout!\n"
282
        ; TODO: disable card/bridge again ?
283
        jmp     .next
284
 
285
  .got_it:
286
        pop     eax
287
        DEBUGF  1, "Card is enabled!\n"
288
 
5066 hidnplayr 289
        invoke  PciWrite32, [card_bus], 0, PCI_header02.base_addr, CARDBUS_IO       ; Supposing it's IO space that is needed
290
        invoke  PciWrite8, [card_bus], 0, PCI_header02.interrupt_line, 0xC                      ; FIXME
291
        invoke  PciWrite16, [card_bus], 0, PCI_header02.command, PCI_CMD_PIO or PCI_CMD_MMIO
4476 hidnplayr 292
 
293
        DEBUGF  1, "done\n"
294
 
295
        jmp     .next
296
 
297
  .err:
298
        DEBUGF  1, "Error\n"
299
        xor     eax, eax
300
 
301
        ret
302
 
303
endp
304
 
305
 
5066 hidnplayr 306
; End of code
4476 hidnplayr 307
 
5066 hidnplayr 308
data fixups
309
end data
4476 hidnplayr 310
 
5066 hidnplayr 311
include '../peimport.inc'
4476 hidnplayr 312
 
313
my_service      db 'CARDBUS',0                  ; max 16 chars include zero
314
 
315
include_debug_strings                           ; All data wich FDO uses will be included here