Subversion Repositories Kolibri OS

Rev

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
;;                                                              ;;
8038 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2020. 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
 
8038 hidnplayr 34
        CARDBUS_IO_BASE         = 0x1400
35
        CARDBUS_IO_SIZE         = 0x100
36
        CARDBUS_IRQ             = 0x0A
4476 hidnplayr 37
 
38
        __DEBUG__               = 1
39
        __DEBUG_LEVEL__         = 1
40
 
5066 hidnplayr 41
section '.flat' readable writable executable
4476 hidnplayr 42
 
5066 hidnplayr 43
include '../proc32.inc'
4476 hidnplayr 44
include '../struct.inc'
45
include '../macros.inc'
5074 hidnplayr 46
include '../pci.inc'
4476 hidnplayr 47
include '../fdo.inc'
48
 
49
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
50
;;                        ;;
51
;; proc START             ;;
52
;;                        ;;
53
;; (standard driver proc) ;;
54
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
55
 
5066 hidnplayr 56
proc START c, reason:dword, cmdline:dword
4476 hidnplayr 57
 
5066 hidnplayr 58
        cmp     [reason], DRV_ENTRY
59
        jne     .fail
4476 hidnplayr 60
 
61
        DEBUGF  1, "Loading cardbus driver\n"
5066 hidnplayr 62
        invoke  RegService, my_service, service_proc
4476 hidnplayr 63
 
64
        call    detect
65
 
66
        ret
67
 
68
  .fail:
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
proc service_proc stdcall, ioctl:dword
84
 
85
        mov     edx, [ioctl]
86
        mov     eax, [edx + IOCTL.io_code]
87
 
88
;------------------------------------------------------
89
 
90
        cmp     eax, 0 ;SRV_GETVERSION
91
        jne     .fail
92
 
93
        cmp     [edx + IOCTL.out_size], 4
94
        jb      .fail
95
        mov     eax, [edx + IOCTL.output]
96
        mov     [eax], dword API_VERSION
97
 
98
        xor     eax, eax
99
        ret
100
 
101
  .fail:
102
        or      eax, -1
103
        ret
104
 
105
endp
106
 
107
align 4
108
proc detect
109
 
110
           locals
111
             last_bus dd ?
112
             card_bus dd ?
113
             bus      dd ?
114
             devfn    dd ?
115
           endl
116
 
117
        DEBUGF  1, "Searching for cardbus bridges...\n"
118
 
119
        xor     eax, eax
120
        mov     [bus], eax
121
        inc     eax
5066 hidnplayr 122
        invoke  PciApi
4476 hidnplayr 123
        cmp     eax, -1
124
        je      .err
125
        mov     [last_bus], eax
126
 
127
        inc     eax
128
        mov     [card_bus], eax
129
 
130
  .next_bus:
131
        and     [devfn], 0
132
  .next_dev:
5172 hidnplayr 133
        invoke  PciRead32, [bus], [devfn], PCI_header.vendor_id
4476 hidnplayr 134
        test    eax, eax
135
        jz      .next
136
        cmp     eax, -1
137
        je      .next
138
 
5172 hidnplayr 139
        invoke  PciRead16, [bus], [devfn], PCI_header.subclass  ; class & subclass
4476 hidnplayr 140
        cmp     ax, 0x0607
141
        je      .found
142
 
143
  .next:
5172 hidnplayr 144
        test    [devfn], 7
145
        jnz     .next_fn
146
        invoke  PciRead8, [bus], [devfn], PCI_header.header_type
147
        test    al, al
148
        js      .next_fn
149
        or      [devfn], 7
150
 
151
  .next_fn:
4476 hidnplayr 152
        inc     [devfn]
153
        cmp     [devfn], 256
154
        jb      .next_dev
155
        mov     eax, [bus]
156
        inc     eax
157
        mov     [bus], eax
158
        cmp     eax, [last_bus]
159
        jna     .next_bus
160
 
161
        DEBUGF  1, "Search complete\n"
162
        xor     eax, eax
163
        inc     eax
164
        ret
165
 
166
  .found:
167
        DEBUGF  1, "Found cardbus bridge: bus=0x%x, dev=0x%x\n", [bus], [devfn]
168
 
5066 hidnplayr 169
        invoke  PciRead8, [bus], [devfn], PCI_header.header_type
5172 hidnplayr 170
        and     al, not 0x80                                            ; Mask the multifunction device bit
4476 hidnplayr 171
        DEBUGF  1, "Header type=0x%x\n", eax:2
5066 hidnplayr 172
        cmp     al, 2
173
        jne     .next
4476 hidnplayr 174
 
175
; Write PCI and cardbus numbers
176
 
5066 hidnplayr 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
4476 hidnplayr 179
        mov     al, byte[bus]
180
        mov     ah, byte[card_bus]
8038 hidnplayr 181
        mov     ebx, [card_bus]         ; sub bus nr???
4476 hidnplayr 182
        shl     ebx, 16
183
        or      eax, ebx
184
        DEBUGF  1, "Latency, bus,.. 0x%x\n", eax
5066 hidnplayr 185
        invoke  PciWrite32, [bus], [devfn], PCI_header02.pci_bus_nr, eax
4476 hidnplayr 186
 
187
; set ExCA legacy mode base
188
 
5066 hidnplayr 189
        invoke  PciWrite32, [bus], [devfn], 0x44, 1
4476 hidnplayr 190
 
191
; Enable power
192
 
5066 hidnplayr 193
        invoke  PciRead8, [bus], [devfn], 0x14                  ; get capabilities offset
4476 hidnplayr 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
5066 hidnplayr 197
        invoke  PciWrite16, [bus], [devfn], eax, 0x0100         ; Enable PME signaling, power state=D0
4476 hidnplayr 198
 
199
; Enable Bus master, io space, memory space
200
 
5066 hidnplayr 201
        invoke  PciWrite16, [bus], [devfn], PCI_header02.command, 0x0007
4476 hidnplayr 202
 
203
; Write CardBus Socket/ExCA base address
204
 
205
        mov     eax, 0x7f000000
206
        push    eax
5066 hidnplayr 207
        invoke  PciWrite32, [bus], [devfn], PCI_header02.base_addr, eax ; base is 4 Kbyte aligned
4476 hidnplayr 208
        pop     ebx
8038 hidnplayr 209
        invoke  MapIoMem, ebx, 4096, PG_SW+PG_NOCACHE
4476 hidnplayr 210
        mov     ecx, eax
211
 
212
; Check if a card is present in the socket
213
 
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
218
        je      .CardbusInserted
219
 
220
; No card found... set PCI command back to 0
221
 
5066 hidnplayr 222
        invoke  PciWrite16, [bus], [devfn], PCI_header02.command, 0  ; To avoid conflicts with other sockets
4476 hidnplayr 223
        DEBUGF  1, "Cardbus KO\n"
224
        jmp     .next
225
 
226
  .CardbusInserted:
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)
230
        ;push    ecx
8038 hidnplayr 231
        ;mov     esi, 1
5066 hidnplayr 232
        ;invoke  Sleep
4476 hidnplayr 233
        ;pop     ecx
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"
237
 
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
242
 
243
        DEBUGF  1, "Interface is powered up\n"
244
 
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
249
 
8038 hidnplayr 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
4476 hidnplayr 260
        or      ax, 0x0700                                      ; Enable write posting, both memory windows prefetchable
5066 hidnplayr 261
        invoke  PciWrite16, [bus], [devfn], PCI_header02.bridge_ctrl, eax
4476 hidnplayr 262
        DEBUGF  1, "Write posting enabled\n"
263
 
264
 
265
        DEBUGF  1, "Bridge PCI registers:\n"
266
rept    17 reg
267
{
5066 hidnplayr 268
        invoke  PciRead32, [bus], [devfn], 4*(reg-1)
4476 hidnplayr 269
        DEBUGF  1, "0x%x\n", eax
270
}
271
 
272
        inc     byte[0x80009021]                                ; LAST PCI bus count in kernel (dirty HACK!)
273
 
274
 
275
        mov     ecx, 100
276
  .waitactive:
277
        push    ecx
8038 hidnplayr 278
        invoke  PciRead32, [card_bus], 0, PCI_header.vendor_id         ; Check if the card is awake yet
4476 hidnplayr 279
        inc     eax
280
        jnz     .got_it
281
        mov     esi, 2
5066 hidnplayr 282
        invoke  Sleep
4476 hidnplayr 283
        pop     ecx
284
        dec     ecx
285
        jnz     .waitactive
286
 
287
        DEBUGF  1, "Timeout!\n"
288
        ; TODO: disable card/bridge again ?
289
        jmp     .next
290
 
291
  .got_it:
292
        pop     eax
293
        DEBUGF  1, "Card is enabled!\n"
294
 
5066 hidnplayr 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
4476 hidnplayr 298
 
299
        DEBUGF  1, "done\n"
300
 
301
        jmp     .next
302
 
303
  .err:
304
        DEBUGF  1, "Error\n"
305
        xor     eax, eax
306
 
307
        ret
308
 
309
endp
310
 
311
 
5066 hidnplayr 312
; End of code
4476 hidnplayr 313
 
5066 hidnplayr 314
data fixups
315
end data
4476 hidnplayr 316
 
5066 hidnplayr 317
include '../peimport.inc'
4476 hidnplayr 318
 
319
my_service      db 'CARDBUS',0                  ; max 16 chars include zero
320
 
321
include_debug_strings                           ; All data wich FDO uses will be included here