Subversion Repositories Kolibri OS

Rev

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