Subversion Repositories Kolibri OS

Rev

Rev 5363 | Rev 7132 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5363 Rev 7122
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;                                                              ;;
6
;;                                                              ;;
7
;;  PCI32.INC                                                   ;;
7
;;  PCI32.INC                                                   ;;
8
;;                                                              ;;
8
;;                                                              ;;
9
;;  32 bit PCI driver code                                      ;;
9
;;  32 bit PCI driver code                                      ;;
10
;;                                                              ;;
10
;;                                                              ;;
11
;;  Version 0.3  April 9, 2007                                  ;;
11
;;  Version 0.3  April 9, 2007                                  ;;
12
;;  Version 0.2  December 21st, 2002                            ;;
12
;;  Version 0.2  December 21st, 2002                            ;;
13
;;                                                              ;;
13
;;                                                              ;;
14
;;  Author: Victor Prodan, victorprodan@yahoo.com               ;;
14
;;  Author: Victor Prodan, victorprodan@yahoo.com               ;;
15
;;          Mihailov Ilia, ghost.nsk@gmail.com                  ;;
15
;;          Mihailov Ilia, ghost.nsk@gmail.com                  ;;
16
;;    Credits:                                                  ;;
16
;;    Credits:                                                  ;;
17
;;          Ralf Brown                                          ;;
17
;;          Ralf Brown                                          ;;
18
;;          Mike Hibbett, mikeh@oceanfree.net                   ;;
18
;;          Mike Hibbett, mikeh@oceanfree.net                   ;;
19
;;                                                              ;;
19
;;                                                              ;;
20
;;  See file COPYING for details                                ;;
20
;;  See file COPYING for details                                ;;
21
;;                                                              ;;
21
;;                                                              ;;
22
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23
 
23
 
24
$Revision: 5363 $
24
$Revision: 7122 $
25
 
25
 
26
;***************************************************************************
26
;***************************************************************************
27
;   Function
27
;   Function
28
;      pci_api:
28
;      pci_api:
29
;
29
;
30
;   Description
30
;   Description
31
;       entry point for system PCI calls
31
;       entry point for system PCI calls
32
;***************************************************************************
32
;***************************************************************************
33
;mmio_pci_addr  equ  0x400               ; set actual PCI address here to activate user-MMIO
33
;mmio_pci_addr  equ  0x400               ; set actual PCI address here to activate user-MMIO
34
 
34
 
35
iglobal
35
iglobal
36
align 4
36
align 4
37
f62call:
37
f62call:
38
        dd      pci_fn_0
38
        dd      pci_fn_0
39
        dd      pci_fn_1
39
        dd      pci_fn_1
40
        dd      pci_fn_2
40
        dd      pci_fn_2
41
        dd      pci_service_not_supported       ;3
41
        dd      pci_service_not_supported       ;3
42
        dd      pci_read_reg            ;4 byte
42
        dd      pci_read_reg            ;4 byte
43
        dd      pci_read_reg            ;5 word
43
        dd      pci_read_reg            ;5 word
44
        dd      pci_read_reg            ;6 dword
44
        dd      pci_read_reg            ;6 dword
45
        dd      pci_service_not_supported   ;7
45
        dd      pci_service_not_supported   ;7
46
        dd      pci_write_reg           ;8 byte
46
        dd      pci_write_reg           ;8 byte
47
        dd      pci_write_reg           ;9 word
47
        dd      pci_write_reg           ;9 word
48
        dd      pci_write_reg           ;10 dword
48
        dd      pci_write_reg           ;10 dword
49
if defined mmio_pci_addr
49
if defined mmio_pci_addr
50
        dd      pci_mmio_init           ;11
50
        dd      pci_mmio_init           ;11
51
        dd      pci_mmio_map            ;12
51
        dd      pci_mmio_map            ;12
52
        dd      pci_mmio_unmap          ;13
52
        dd      pci_mmio_unmap          ;13
53
end if
53
end if
54
 
54
 
55
endg
55
endg
56
 
56
 
57
align 4
57
align 4
58
 
58
 
59
pci_api:
59
pci_api:
60
 
60
 
61
;cross
61
;cross
62
        mov     eax, ebx
62
        mov     eax, ebx
63
        mov     ebx, ecx
63
        mov     ebx, ecx
64
        mov     ecx, edx
64
        mov     ecx, edx
65
 
65
 
66
        cmp     [pci_access_enabled], 1
66
        cmp     [pci_access_enabled], 1
67
        jne     pci_service_not_supported
67
        jne     pci_service_not_supported
68
 
68
 
69
        movzx   edx, al
69
        movzx   edx, al
70
 
70
 
71
if defined mmio_pci_addr
71
if defined mmio_pci_addr
72
        cmp     al, 13
72
        cmp     al, 13
73
        ja      pci_service_not_supported
73
        ja      pci_service_not_supported
74
else
74
else
75
        cmp     al, 10
75
        cmp     al, 10
76
        ja      pci_service_not_supported
76
        ja      pci_service_not_supported
77
end if
77
end if
78
 
78
 
79
        call    dword [f62call+edx*4]
79
        call    dword [f62call+edx*4]
80
        mov     dword [esp+32], eax
80
        mov     dword [esp+32], eax
81
        ret
81
        ret
82
 
82
 
83
 
83
 
84
align 4
84
align 4
85
pci_api_drv:
85
pci_api_drv:
86
 
86
 
87
        cmp     [pci_access_enabled], 1
87
        cmp     [pci_access_enabled], 1
88
        jne     .fail
88
        jne     .fail
89
 
89
 
90
        cmp     eax, 2
90
        cmp     eax, 2
91
        ja      .fail
91
        ja      .fail
92
 
92
 
93
        jmp     dword [f62call+eax*4]
93
        jmp     dword [f62call+eax*4]
94
 
94
 
95
.fail:
95
.fail:
96
        or      eax, -1
96
        or      eax, -1
97
        ret
97
        ret
98
 
98
 
99
 
99
 
100
;; ============================================
100
;; ============================================
101
 
101
 
102
pci_fn_0:
102
pci_fn_0:
103
; PCI function 0: get pci version (AH.AL)
103
; PCI function 0: get pci version (AH.AL)
104
        movzx   eax, word [BOOT_VARS+0x9022]
104
        movzx   eax, word [BOOT_VARS+BOOT_PCI_DATA+2]
105
        ret
105
        ret
106
 
106
 
107
pci_fn_1:
107
pci_fn_1:
108
; PCI function 1: get last bus in AL
108
; PCI function 1: get last bus in AL
109
        mov     al, [BOOT_VARS+0x9021]
109
        mov     al, [BOOT_VARS+BOOT_PCI_DATA+1]
110
        ret
110
        ret
111
 
111
 
112
pci_fn_2:
112
pci_fn_2:
113
; PCI function 2: get pci access mechanism
113
; PCI function 2: get pci access mechanism
114
        mov     al, [BOOT_VARS+0x9020]
114
        mov     al, [BOOT_VARS+BOOT_PCI_DATA]
115
        ret
115
        ret
116
 
116
 
117
pci_service_not_supported:
117
pci_service_not_supported:
118
        or      eax, -1
118
        or      eax, -1
119
        mov     dword [esp+32], eax
119
        mov     dword [esp+32], eax
120
        ret
120
        ret
121
 
121
 
122
;***************************************************************************
122
;***************************************************************************
123
;   Function
123
;   Function
124
;      pci_make_config_cmd
124
;      pci_make_config_cmd
125
;
125
;
126
;   Description
126
;   Description
127
;       creates a command dword  for use with the PCI bus
127
;       creates a command dword  for use with the PCI bus
128
;       bus # in ah
128
;       bus # in ah
129
;       device+func in bh (dddddfff)
129
;       device+func in bh (dddddfff)
130
;       register in bl
130
;       register in bl
131
;
131
;
132
;      command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 )
132
;      command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 )
133
;***************************************************************************
133
;***************************************************************************
134
 
134
 
135
align 4
135
align 4
136
 
136
 
137
pci_make_config_cmd:
137
pci_make_config_cmd:
138
        shl     eax, 8     ; move bus to bits 16-23
138
        shl     eax, 8     ; move bus to bits 16-23
139
        mov     ax, bx     ; combine all
139
        mov     ax, bx     ; combine all
140
        and     eax, 0xffffff
140
        and     eax, 0xffffff
141
        or      eax, 0x80000000
141
        or      eax, 0x80000000
142
        ret
142
        ret
143
 
143
 
144
;***************************************************************************
144
;***************************************************************************
145
;   Function
145
;   Function
146
;      pci_read_reg:
146
;      pci_read_reg:
147
;
147
;
148
;   Description
148
;   Description
149
;       read a register from the PCI config space into EAX/AX/AL
149
;       read a register from the PCI config space into EAX/AX/AL
150
;       IN: ah=bus,device+func=bh,register address=bl
150
;       IN: ah=bus,device+func=bh,register address=bl
151
;           number of bytes to read (1,2,4) coded into AL, bits 0-1
151
;           number of bytes to read (1,2,4) coded into AL, bits 0-1
152
;           (0 - byte, 1 - word, 2 - dword)
152
;           (0 - byte, 1 - word, 2 - dword)
153
;***************************************************************************
153
;***************************************************************************
154
 
154
 
155
align 4
155
align 4
156
 
156
 
157
pci_read_reg:
157
pci_read_reg:
158
        push    ebx esi
158
        push    ebx esi
159
        cmp     byte [BOOT_VARS+0x9020], 2;what mechanism will we use?
159
        cmp     byte [BOOT_VARS+BOOT_PCI_DATA], 2;what mechanism will we use?
160
        je      pci_read_reg_2
160
        je      pci_read_reg_2
161
 
161
 
162
                ; mechanism 1
162
                ; mechanism 1
163
        mov     esi, eax ; save register size into ESI
163
        mov     esi, eax ; save register size into ESI
164
        and     esi, 3
164
        and     esi, 3
165
 
165
 
166
        call    pci_make_config_cmd
166
        call    pci_make_config_cmd
167
        mov     ebx, eax
167
        mov     ebx, eax
168
        mov     dx, 0xcf8
168
        mov     dx, 0xcf8
169
                ; set up addressing to config data
169
                ; set up addressing to config data
170
        mov     eax, ebx
170
        mov     eax, ebx
171
        and     al, 0xfc; make address dword-aligned
171
        and     al, 0xfc; make address dword-aligned
172
        out     dx, eax
172
        out     dx, eax
173
                ; get requested DWORD of config data
173
                ; get requested DWORD of config data
174
        mov     dl, 0xfc
174
        mov     dl, 0xfc
175
        and     bl, 3
175
        and     bl, 3
176
        or      dl, bl   ; add to port address first 2 bits of register address
176
        or      dl, bl   ; add to port address first 2 bits of register address
177
 
177
 
178
        or      esi, esi
178
        or      esi, esi
179
        jz      pci_read_byte1
179
        jz      pci_read_byte1
180
        cmp     esi, 1
180
        cmp     esi, 1
181
        jz      pci_read_word1
181
        jz      pci_read_word1
182
        cmp     esi, 2
182
        cmp     esi, 2
183
        jz      pci_read_dword1
183
        jz      pci_read_dword1
184
        jmp     pci_fin_read1
184
        jmp     pci_fin_read1
185
 
185
 
186
pci_read_byte1:
186
pci_read_byte1:
187
        in      al, dx
187
        in      al, dx
188
        jmp     pci_fin_read1
188
        jmp     pci_fin_read1
189
pci_read_word1:
189
pci_read_word1:
190
        in      ax, dx
190
        in      ax, dx
191
        jmp     pci_fin_read1
191
        jmp     pci_fin_read1
192
pci_read_dword1:
192
pci_read_dword1:
193
        in      eax, dx
193
        in      eax, dx
194
pci_fin_read1:
194
pci_fin_read1:
195
        pop     esi ebx
195
        pop     esi ebx
196
        ret
196
        ret
197
pci_read_reg_2:
197
pci_read_reg_2:
198
 
198
 
199
        test    bh, 128 ;mech#2 only supports 16 devices per bus
199
        test    bh, 128 ;mech#2 only supports 16 devices per bus
200
        jnz     pci_read_reg_err
200
        jnz     pci_read_reg_err
201
 
201
 
202
        mov     esi, eax ; save register size into ESI
202
        mov     esi, eax ; save register size into ESI
203
        and     esi, 3
203
        and     esi, 3
204
 
204
 
205
        mov     dx, 0xcfa
205
        mov     dx, 0xcfa
206
 
206
 
207
                ; out 0xcfa,bus
207
                ; out 0xcfa,bus
208
        mov     al, ah
208
        mov     al, ah
209
        out     dx, al
209
        out     dx, al
210
                ; out 0xcf8,0x80
210
                ; out 0xcf8,0x80
211
        mov     dl, 0xf8
211
        mov     dl, 0xf8
212
        mov     al, 0x80
212
        mov     al, 0x80
213
        out     dx, al
213
        out     dx, al
214
                ; compute addr
214
                ; compute addr
215
        shr     bh, 3; func is ignored in mechanism 2
215
        shr     bh, 3; func is ignored in mechanism 2
216
        or      bh, 0xc0
216
        or      bh, 0xc0
217
        mov     dx, bx
217
        mov     dx, bx
218
 
218
 
219
        or      esi, esi
219
        or      esi, esi
220
        jz      pci_read_byte2
220
        jz      pci_read_byte2
221
        cmp     esi, 1
221
        cmp     esi, 1
222
        jz      pci_read_word2
222
        jz      pci_read_word2
223
        cmp     esi, 2
223
        cmp     esi, 2
224
        jz      pci_read_dword2
224
        jz      pci_read_dword2
225
        jmp     pci_fin_read2
225
        jmp     pci_fin_read2
226
 
226
 
227
pci_read_byte2:
227
pci_read_byte2:
228
        in      al, dx
228
        in      al, dx
229
        jmp     pci_fin_read2
229
        jmp     pci_fin_read2
230
pci_read_word2:
230
pci_read_word2:
231
        in      ax, dx
231
        in      ax, dx
232
        jmp     pci_fin_read2
232
        jmp     pci_fin_read2
233
pci_read_dword2:
233
pci_read_dword2:
234
        in      eax, dx
234
        in      eax, dx
235
pci_fin_read2:
235
pci_fin_read2:
236
 
236
 
237
        pop     esi ebx
237
        pop     esi ebx
238
        ret
238
        ret
239
 
239
 
240
pci_read_reg_err:
240
pci_read_reg_err:
241
        xor     eax, eax
241
        xor     eax, eax
242
        dec     eax
242
        dec     eax
243
        pop     esi ebx
243
        pop     esi ebx
244
        ret
244
        ret
245
 
245
 
246
 
246
 
247
;***************************************************************************
247
;***************************************************************************
248
;   Function
248
;   Function
249
;      pci_write_reg:
249
;      pci_write_reg:
250
;
250
;
251
;   Description
251
;   Description
252
;       write a register from ECX/CX/CL into the PCI config space
252
;       write a register from ECX/CX/CL into the PCI config space
253
;       IN: ah=bus,device+func=bh,register address (dword aligned)=bl,
253
;       IN: ah=bus,device+func=bh,register address (dword aligned)=bl,
254
;           value to write in ecx
254
;           value to write in ecx
255
;           number of bytes to write (1,2,4) coded into AL, bits 0-1
255
;           number of bytes to write (1,2,4) coded into AL, bits 0-1
256
;           (0 - byte, 1 - word, 2 - dword)
256
;           (0 - byte, 1 - word, 2 - dword)
257
;***************************************************************************
257
;***************************************************************************
258
 
258
 
259
align 4
259
align 4
260
 
260
 
261
pci_write_reg:
261
pci_write_reg:
262
        push    esi ebx
262
        push    esi ebx
263
        cmp     byte [BOOT_VARS+0x9020], 2;what mechanism will we use?
263
        cmp     byte [BOOT_VARS+BOOT_PCI_DATA], 2;what mechanism will we use?
264
        je      pci_write_reg_2
264
        je      pci_write_reg_2
265
 
265
 
266
                ; mechanism 1
266
                ; mechanism 1
267
        mov     esi, eax ; save register size into ESI
267
        mov     esi, eax ; save register size into ESI
268
        and     esi, 3
268
        and     esi, 3
269
 
269
 
270
        call    pci_make_config_cmd
270
        call    pci_make_config_cmd
271
        mov     ebx, eax
271
        mov     ebx, eax
272
        mov     dx, 0xcf8
272
        mov     dx, 0xcf8
273
                ; set up addressing to config data
273
                ; set up addressing to config data
274
        mov     eax, ebx
274
        mov     eax, ebx
275
        and     al, 0xfc; make address dword-aligned
275
        and     al, 0xfc; make address dword-aligned
276
        out     dx, eax
276
        out     dx, eax
277
                ; write DWORD of config data
277
                ; write DWORD of config data
278
        mov     dl, 0xfc
278
        mov     dl, 0xfc
279
        and     bl, 3
279
        and     bl, 3
280
        or      dl, bl
280
        or      dl, bl
281
        mov     eax, ecx
281
        mov     eax, ecx
282
 
282
 
283
        or      esi, esi
283
        or      esi, esi
284
        jz      pci_write_byte1
284
        jz      pci_write_byte1
285
        cmp     esi, 1
285
        cmp     esi, 1
286
        jz      pci_write_word1
286
        jz      pci_write_word1
287
        cmp     esi, 2
287
        cmp     esi, 2
288
        jz      pci_write_dword1
288
        jz      pci_write_dword1
289
        jmp     pci_fin_write1
289
        jmp     pci_fin_write1
290
 
290
 
291
pci_write_byte1:
291
pci_write_byte1:
292
        out     dx, al
292
        out     dx, al
293
        jmp     pci_fin_write1
293
        jmp     pci_fin_write1
294
pci_write_word1:
294
pci_write_word1:
295
        out     dx, ax
295
        out     dx, ax
296
        jmp     pci_fin_write1
296
        jmp     pci_fin_write1
297
pci_write_dword1:
297
pci_write_dword1:
298
        out     dx, eax
298
        out     dx, eax
299
pci_fin_write1:
299
pci_fin_write1:
300
 
300
 
301
        xor     eax, eax
301
        xor     eax, eax
302
        pop     ebx esi
302
        pop     ebx esi
303
 
303
 
304
        ret
304
        ret
305
pci_write_reg_2:
305
pci_write_reg_2:
306
 
306
 
307
        test    bh, 128 ;mech#2 only supports 16 devices per bus
307
        test    bh, 128 ;mech#2 only supports 16 devices per bus
308
        jnz     pci_write_reg_err
308
        jnz     pci_write_reg_err
309
 
309
 
310
 
310
 
311
        mov     esi, eax ; save register size into ESI
311
        mov     esi, eax ; save register size into ESI
312
        and     esi, 3
312
        and     esi, 3
313
 
313
 
314
        mov     dx, 0xcfa
314
        mov     dx, 0xcfa
315
                ; out 0xcfa,bus
315
                ; out 0xcfa,bus
316
        mov     al, ah
316
        mov     al, ah
317
        out     dx, al
317
        out     dx, al
318
                ; out 0xcf8,0x80
318
                ; out 0xcf8,0x80
319
        mov     dl, 0xf8
319
        mov     dl, 0xf8
320
        mov     al, 0x80
320
        mov     al, 0x80
321
        out     dx, al
321
        out     dx, al
322
                ; compute addr
322
                ; compute addr
323
        shr     bh, 3; func is ignored in mechanism 2
323
        shr     bh, 3; func is ignored in mechanism 2
324
        or      bh, 0xc0
324
        or      bh, 0xc0
325
        mov     dx, bx
325
        mov     dx, bx
326
                ; write register
326
                ; write register
327
        mov     eax, ecx
327
        mov     eax, ecx
328
 
328
 
329
        or      esi, esi
329
        or      esi, esi
330
        jz      pci_write_byte2
330
        jz      pci_write_byte2
331
        cmp     esi, 1
331
        cmp     esi, 1
332
        jz      pci_write_word2
332
        jz      pci_write_word2
333
        cmp     esi, 2
333
        cmp     esi, 2
334
        jz      pci_write_dword2
334
        jz      pci_write_dword2
335
        jmp     pci_fin_write2
335
        jmp     pci_fin_write2
336
 
336
 
337
pci_write_byte2:
337
pci_write_byte2:
338
        out     dx, al
338
        out     dx, al
339
        jmp     pci_fin_write2
339
        jmp     pci_fin_write2
340
pci_write_word2:
340
pci_write_word2:
341
        out     dx, ax
341
        out     dx, ax
342
        jmp     pci_fin_write2
342
        jmp     pci_fin_write2
343
pci_write_dword2:
343
pci_write_dword2:
344
        out     dx, eax
344
        out     dx, eax
345
pci_fin_write2:
345
pci_fin_write2:
346
 
346
 
347
        xor     eax, eax
347
        xor     eax, eax
348
        pop     ebx esi
348
        pop     ebx esi
349
        ret
349
        ret
350
 
350
 
351
pci_write_reg_err:
351
pci_write_reg_err:
352
        xor     eax, eax
352
        xor     eax, eax
353
        dec     eax
353
        dec     eax
354
        pop     ebx esi
354
        pop     ebx esi
355
        ret
355
        ret
356
 
356
 
357
if defined mmio_pci_addr        ; must be set above
357
if defined mmio_pci_addr        ; must be set above
358
;***************************************************************************
358
;***************************************************************************
359
;   Function
359
;   Function
360
;      pci_mmio_init
360
;      pci_mmio_init
361
;
361
;
362
;   Description
362
;   Description
363
;       IN:  bx = device's PCI bus address (bbbbbbbbdddddfff)
363
;       IN:  bx = device's PCI bus address (bbbbbbbbdddddfff)
364
;   Returns  eax = user heap space available (bytes)
364
;   Returns  eax = user heap space available (bytes)
365
;   Error codes
365
;   Error codes
366
;       eax = -1 : PCI user access blocked,
366
;       eax = -1 : PCI user access blocked,
367
;       eax = -2 : device not registered for uMMIO service
367
;       eax = -2 : device not registered for uMMIO service
368
;       eax = -3 : user heap initialization failure
368
;       eax = -3 : user heap initialization failure
369
;***************************************************************************
369
;***************************************************************************
370
pci_mmio_init:
370
pci_mmio_init:
371
        cmp     bx, mmio_pci_addr
371
        cmp     bx, mmio_pci_addr
372
        jz      @f
372
        jz      @f
373
        mov     eax, -2
373
        mov     eax, -2
374
        ret
374
        ret
375
@@:
375
@@:
376
        call    init_heap  ; (if not initialized yet)
376
        call    init_heap  ; (if not initialized yet)
377
        or      eax, eax
377
        or      eax, eax
378
        jz      @f
378
        jz      @f
379
        ret
379
        ret
380
@@:
380
@@:
381
        mov     eax, -3
381
        mov     eax, -3
382
        ret
382
        ret
383
 
383
 
384
 
384
 
385
;***************************************************************************
385
;***************************************************************************
386
;   Function
386
;   Function
387
;      pci_mmio_map
387
;      pci_mmio_map
388
;
388
;
389
;   Description
389
;   Description
390
;       maps a block of PCI memory to user-accessible linear address
390
;       maps a block of PCI memory to user-accessible linear address
391
;
391
;
392
;       WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only!
392
;       WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only!
393
;       The target device address should be set in kernel var mmio_pci_addr
393
;       The target device address should be set in kernel var mmio_pci_addr
394
;
394
;
395
;       IN:  ah = BAR#;
395
;       IN:  ah = BAR#;
396
;       IN: ebx = block size (bytes);
396
;       IN: ebx = block size (bytes);
397
;       IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
397
;       IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages);
398
;
398
;
399
;   Returns eax = MMIO block's linear address in the userspace (if no error)
399
;   Returns eax = MMIO block's linear address in the userspace (if no error)
400
;
400
;
401
;
401
;
402
;   Error codes
402
;   Error codes
403
;       eax = -1 : user access to PCI blocked,
403
;       eax = -1 : user access to PCI blocked,
404
;       eax = -2 : an invalid BAR register referred
404
;       eax = -2 : an invalid BAR register referred
405
;       eax = -3 : no i/o space on that BAR
405
;       eax = -3 : no i/o space on that BAR
406
;       eax = -4 : a port i/o BAR register referred
406
;       eax = -4 : a port i/o BAR register referred
407
;       eax = -5 : dynamic userspace allocation problem
407
;       eax = -5 : dynamic userspace allocation problem
408
;***************************************************************************
408
;***************************************************************************
409
 
409
 
410
pci_mmio_map:
410
pci_mmio_map:
411
        and     edx, 0x0ffff
411
        and     edx, 0x0ffff
412
        cmp     ah, 6
412
        cmp     ah, 6
413
        jc      .bar_0_5
413
        jc      .bar_0_5
414
        jz      .bar_rom
414
        jz      .bar_rom
415
        mov     eax, -2
415
        mov     eax, -2
416
        ret
416
        ret
417
.bar_rom:
417
.bar_rom:
418
        mov     ah, 8   ; bar6 = Expansion ROM base address
418
        mov     ah, 8   ; bar6 = Expansion ROM base address
419
.bar_0_5:
419
.bar_0_5:
420
        push    ecx
420
        push    ecx
421
        add     ebx, 4095
421
        add     ebx, 4095
422
        and     ebx, -4096
422
        and     ebx, -4096
423
        push    ebx
423
        push    ebx
424
        mov     bl, ah  ; bl = BAR# (0..5), however bl=8 for BAR6
424
        mov     bl, ah  ; bl = BAR# (0..5), however bl=8 for BAR6
425
        shl     bl, 1
425
        shl     bl, 1
426
        shl     bl, 1
426
        shl     bl, 1
427
        add     bl, 0x10; now bl = BAR offset in PCI config. space
427
        add     bl, 0x10; now bl = BAR offset in PCI config. space
428
        mov     ax, mmio_pci_addr
428
        mov     ax, mmio_pci_addr
429
        mov     bh, al  ; bh = dddddfff
429
        mov     bh, al  ; bh = dddddfff
430
        mov     al, 2   ; al : DW to read
430
        mov     al, 2   ; al : DW to read
431
        call    pci_read_reg
431
        call    pci_read_reg
432
        or      eax, eax
432
        or      eax, eax
433
        jnz     @f
433
        jnz     @f
434
        mov     eax, -3 ; empty I/O space
434
        mov     eax, -3 ; empty I/O space
435
        jmp     mmio_ret_fail
435
        jmp     mmio_ret_fail
436
@@:
436
@@:
437
        test    eax, 1
437
        test    eax, 1
438
        jz      @f
438
        jz      @f
439
        mov     eax, -4 ; damned ports (not MMIO space)
439
        mov     eax, -4 ; damned ports (not MMIO space)
440
        jmp     mmio_ret_fail
440
        jmp     mmio_ret_fail
441
@@:
441
@@:
442
        pop     ecx     ; ecx = block size, bytes (expanded to whole page)
442
        pop     ecx     ; ecx = block size, bytes (expanded to whole page)
443
        mov     ebx, ecx; user_alloc destroys eax, ecx, edx, but saves ebx
443
        mov     ebx, ecx; user_alloc destroys eax, ecx, edx, but saves ebx
444
        and     eax, 0xFFFFFFF0
444
        and     eax, 0xFFFFFFF0
445
        push    eax           ; store MMIO physical address + keep 2DWords in the stack
445
        push    eax           ; store MMIO physical address + keep 2DWords in the stack
446
        stdcall user_alloc, ecx
446
        stdcall user_alloc, ecx
447
        or      eax, eax
447
        or      eax, eax
448
        jnz     mmio_map_over
448
        jnz     mmio_map_over
449
        mov     eax, -5 ; problem with page allocation
449
        mov     eax, -5 ; problem with page allocation
450
 
450
 
451
mmio_ret_fail:
451
mmio_ret_fail:
452
        pop     ecx
452
        pop     ecx
453
        pop     edx
453
        pop     edx
454
        ret
454
        ret
455
 
455
 
456
mmio_map_over:
456
mmio_map_over:
457
        mov     ecx, ebx; ecx = size (bytes, expanded to whole page)
457
        mov     ecx, ebx; ecx = size (bytes, expanded to whole page)
458
        shr     ecx, 12 ; ecx = number of pages
458
        shr     ecx, 12 ; ecx = number of pages
459
        mov     ebx, eax; ebx = linear address
459
        mov     ebx, eax; ebx = linear address
460
        pop     eax     ; eax = MMIO start
460
        pop     eax     ; eax = MMIO start
461
        pop     edx     ; edx = MMIO shift (pages)
461
        pop     edx     ; edx = MMIO shift (pages)
462
        shl     edx, 12 ; edx = MMIO shift (bytes)
462
        shl     edx, 12 ; edx = MMIO shift (bytes)
463
        add     eax, edx; eax = uMMIO physical address
463
        add     eax, edx; eax = uMMIO physical address
464
        or      eax, PG_SHARED
464
        or      eax, PG_SHARED
465
        or      eax, PG_UW
465
        or      eax, PG_UW
466
        or      eax, PG_NOCACHE
466
        or      eax, PG_NOCACHE
467
        mov     edi, ebx
467
        mov     edi, ebx
468
        call    commit_pages
468
        call    commit_pages
469
        mov     eax, edi
469
        mov     eax, edi
470
        ret
470
        ret
471
 
471
 
472
;***************************************************************************
472
;***************************************************************************
473
;   Function
473
;   Function
474
;      pci_mmio_unmap_page
474
;      pci_mmio_unmap_page
475
;
475
;
476
;   Description
476
;   Description
477
;       unmaps the linear space previously tied to a PCI memory block
477
;       unmaps the linear space previously tied to a PCI memory block
478
;
478
;
479
;       IN: ebx = linear address of space previously allocated by pci_mmio_map
479
;       IN: ebx = linear address of space previously allocated by pci_mmio_map
480
;       returns eax = 1 if successfully unmapped
480
;       returns eax = 1 if successfully unmapped
481
;
481
;
482
;   Error codes
482
;   Error codes
483
;       eax = -1 if no user PCI access allowed,
483
;       eax = -1 if no user PCI access allowed,
484
;       eax =  0 if unmapping failed
484
;       eax =  0 if unmapping failed
485
;***************************************************************************
485
;***************************************************************************
486
 
486
 
487
pci_mmio_unmap:
487
pci_mmio_unmap:
488
        stdcall user_free, ebx
488
        stdcall user_free, ebx
489
        ret
489
        ret
490
 
490
 
491
end if
491
end if
492
 
492
 
493
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
493
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
494
uglobal
494
uglobal
495
align 4
495
align 4
496
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
496
; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1)
497
pci_emu_dat:
497
pci_emu_dat:
498
                times   30*10 db 0
498
                times   30*10 db 0
499
endg
499
endg
500
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
500
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
501
align 4
501
align 4
502
sys_pcibios:
502
sys_pcibios:
503
        cmp     [pci_access_enabled], 1
503
        cmp     [pci_access_enabled], 1
504
        jne     .unsupported_func
504
        jne     .unsupported_func
505
        cmp     [pci_bios_entry], 0
505
        cmp     [pci_bios_entry], 0
506
        jz      .emulate_bios
506
        jz      .emulate_bios
507
 
507
 
508
        push    ds
508
        push    ds
509
        mov     ax, pci_data_sel
509
        mov     ax, pci_data_sel
510
        mov     ds, ax
510
        mov     ds, ax
511
        mov     eax, ebp
511
        mov     eax, ebp
512
        mov     ah, 0B1h
512
        mov     ah, 0B1h
513
        call    pword [cs:pci_bios_entry]
513
        call    pword [cs:pci_bios_entry]
514
        pop     ds
514
        pop     ds
515
 
515
 
516
        jmp     .return
516
        jmp     .return
517
        ;-=-=-=-=-=-=-=-=
517
        ;-=-=-=-=-=-=-=-=
518
.emulate_bios:
518
.emulate_bios:
519
        cmp     ebp, 1                  ; PCI_FUNCTION_ID
519
        cmp     ebp, 1                  ; PCI_FUNCTION_ID
520
        jnz     .not_PCI_BIOS_PRESENT
520
        jnz     .not_PCI_BIOS_PRESENT
521
        mov     edx, 'PCI '
521
        mov     edx, 'PCI '
522
        mov     al, [BOOT_VARS + 0x9020]
522
        mov     al, [BOOT_VARS + BOOT_PCI_DATA]
523
        mov     bx, [BOOT_VARS + 0x9022]
523
        mov     bx, [BOOT_VARS + BOOT_PCI_DATA + 2]
524
        mov     cl, [BOOT_VARS + 0x9021]
524
        mov     cl, [BOOT_VARS + BOOT_PCI_DATA + 1]
525
        xor     ah, ah
525
        xor     ah, ah
526
        jmp     .return_abcd
526
        jmp     .return_abcd
527
 
527
 
528
.not_PCI_BIOS_PRESENT:
528
.not_PCI_BIOS_PRESENT:
529
        cmp     ebp, 2                  ; FIND_PCI_DEVICE
529
        cmp     ebp, 2                  ; FIND_PCI_DEVICE
530
        jne     .not_FIND_PCI_DEVICE
530
        jne     .not_FIND_PCI_DEVICE
531
        mov     ebx, pci_emu_dat
531
        mov     ebx, pci_emu_dat
532
..nxt:
532
..nxt:
533
        cmp     [ebx], dx
533
        cmp     [ebx], dx
534
        jne     ..no
534
        jne     ..no
535
        cmp     [ebx + 2], cx
535
        cmp     [ebx + 2], cx
536
        jne     ..no
536
        jne     ..no
537
        dec     si
537
        dec     si
538
        jns     ..no
538
        jns     ..no
539
        mov     bx, [ebx + 4]
539
        mov     bx, [ebx + 4]
540
        xor     ah, ah
540
        xor     ah, ah
541
        jmp     .return_ab
541
        jmp     .return_ab
542
..no:
542
..no:
543
        cmp     word[ebx], 0
543
        cmp     word[ebx], 0
544
        je      ..dev_not_found
544
        je      ..dev_not_found
545
        add     ebx, 10
545
        add     ebx, 10
546
        jmp     ..nxt
546
        jmp     ..nxt
547
..dev_not_found:
547
..dev_not_found:
548
        mov     ah, 0x86                ; DEVICE_NOT_FOUND
548
        mov     ah, 0x86                ; DEVICE_NOT_FOUND
549
        jmp     .return_a
549
        jmp     .return_a
550
 
550
 
551
.not_FIND_PCI_DEVICE:
551
.not_FIND_PCI_DEVICE:
552
        cmp     ebp, 3                  ; FIND_PCI_CLASS_CODE
552
        cmp     ebp, 3                  ; FIND_PCI_CLASS_CODE
553
        jne     .not_FIND_PCI_CLASS_CODE
553
        jne     .not_FIND_PCI_CLASS_CODE
554
        mov     esi, pci_emu_dat
554
        mov     esi, pci_emu_dat
555
        shl     ecx, 8
555
        shl     ecx, 8
556
..nxt2:
556
..nxt2:
557
        cmp     [esi], ecx
557
        cmp     [esi], ecx
558
        jne     ..no2
558
        jne     ..no2
559
        mov     bx, [esi]
559
        mov     bx, [esi]
560
        xor     ah, ah
560
        xor     ah, ah
561
        jmp     .return_ab
561
        jmp     .return_ab
562
..no2:
562
..no2:
563
        cmp     dword[esi], 0
563
        cmp     dword[esi], 0
564
        je      ..dev_not_found
564
        je      ..dev_not_found
565
        add     esi, 10
565
        add     esi, 10
566
        jmp     ..nxt2
566
        jmp     ..nxt2
567
 
567
 
568
.not_FIND_PCI_CLASS_CODE:
568
.not_FIND_PCI_CLASS_CODE:
569
        cmp     ebp, 8                  ; READ_CONFIG_*
569
        cmp     ebp, 8                  ; READ_CONFIG_*
570
        jb      .not_READ_CONFIG
570
        jb      .not_READ_CONFIG
571
        cmp     ebp, 0x0A
571
        cmp     ebp, 0x0A
572
        ja      .not_READ_CONFIG
572
        ja      .not_READ_CONFIG
573
        mov     eax, ebp
573
        mov     eax, ebp
574
        mov     ah, bh
574
        mov     ah, bh
575
        mov     edx, edi
575
        mov     edx, edi
576
        mov     bh, bl
576
        mov     bh, bl
577
        mov     bl, dl
577
        mov     bl, dl
578
        call    pci_read_reg
578
        call    pci_read_reg
579
        mov     ecx, eax
579
        mov     ecx, eax
580
        xor     ah, ah                  ; SUCCESSFUL
580
        xor     ah, ah                  ; SUCCESSFUL
581
        jmp     .return_abc
581
        jmp     .return_abc
582
.not_READ_CONFIG:
582
.not_READ_CONFIG:
583
        cmp     ebp, 0x0B               ; WRITE_CONFIG_*
583
        cmp     ebp, 0x0B               ; WRITE_CONFIG_*
584
        jb      .not_WRITE_CONFIG
584
        jb      .not_WRITE_CONFIG
585
        cmp     ebp, 0x0D
585
        cmp     ebp, 0x0D
586
        ja      .not_WRITE_CONFIG
586
        ja      .not_WRITE_CONFIG
587
        lea     eax, [ebp+1]
587
        lea     eax, [ebp+1]
588
        mov     ah, bh
588
        mov     ah, bh
589
        mov     edx, edi
589
        mov     edx, edi
590
        mov     bh, bl
590
        mov     bh, bl
591
        mov     bl, dl
591
        mov     bl, dl
592
        call    pci_write_reg
592
        call    pci_write_reg
593
        xor     ah, ah                  ; SUCCESSFUL
593
        xor     ah, ah                  ; SUCCESSFUL
594
        jmp     .return_abc
594
        jmp     .return_abc
595
.not_WRITE_CONFIG:
595
.not_WRITE_CONFIG:
596
.unsupported_func:
596
.unsupported_func:
597
        mov     ah, 0x81                ; FUNC_NOT_SUPPORTED
597
        mov     ah, 0x81                ; FUNC_NOT_SUPPORTED
598
.return:
598
.return:
599
        mov     dword[esp + 4 ], edi
599
        mov     dword[esp + 4 ], edi
600
        mov     dword[esp + 8], esi
600
        mov     dword[esp + 8], esi
601
.return_abcd:
601
.return_abcd:
602
        mov     dword[esp + 24], edx
602
        mov     dword[esp + 24], edx
603
.return_abc:
603
.return_abc:
604
        mov     dword[esp + 28], ecx
604
        mov     dword[esp + 28], ecx
605
.return_ab:
605
.return_ab:
606
        mov     dword[esp + 20], ebx
606
        mov     dword[esp + 20], ebx
607
.return_a:
607
.return_a:
608
        mov     dword[esp + 32], eax
608
        mov     dword[esp + 32], eax
609
        ret
609
        ret
610
 
610
 
611
proc pci_enum
611
proc pci_enum
612
        push    ebp
612
        push    ebp
613
        mov     ebp, esp
613
        mov     ebp, esp
614
        push    0
614
        push    0
615
virtual at ebp-4
615
virtual at ebp-4
616
.devfn          db      ?
616
.devfn          db      ?
617
.bus            db      ?
617
.bus            db      ?
618
end virtual
618
end virtual
619
.loop:
619
.loop:
620
        mov     ah, [.bus]
620
        mov     ah, [.bus]
621
        mov     al, 2
621
        mov     al, 2
622
        mov     bh, [.devfn]
622
        mov     bh, [.devfn]
623
        mov     bl, 0
623
        mov     bl, 0
624
        call    pci_read_reg
624
        call    pci_read_reg
625
        cmp     eax, 0xFFFFFFFF
625
        cmp     eax, 0xFFFFFFFF
626
        jnz     .has_device
626
        jnz     .has_device
627
        test    byte [.devfn], 7
627
        test    byte [.devfn], 7
628
        jnz     .next_func
628
        jnz     .next_func
629
        jmp     .no_device
629
        jmp     .no_device
630
.has_device:
630
.has_device:
631
        push    eax
631
        push    eax
632
        movi    eax, sizeof.PCIDEV
632
        movi    eax, sizeof.PCIDEV
633
        call    malloc
633
        call    malloc
634
        pop     ecx
634
        pop     ecx
635
        test    eax, eax
635
        test    eax, eax
636
        jz      .nomemory
636
        jz      .nomemory
637
        mov     edi, eax
637
        mov     edi, eax
638
        mov     [edi+PCIDEV.vendor_device_id], ecx
638
        mov     [edi+PCIDEV.vendor_device_id], ecx
639
        mov     eax, pcidev_list
639
        mov     eax, pcidev_list
640
        mov     ecx, [eax+PCIDEV.bk]
640
        mov     ecx, [eax+PCIDEV.bk]
641
        mov     [edi+PCIDEV.bk], ecx
641
        mov     [edi+PCIDEV.bk], ecx
642
        mov     [edi+PCIDEV.fd], eax
642
        mov     [edi+PCIDEV.fd], eax
643
        mov     [ecx+PCIDEV.fd], edi
643
        mov     [ecx+PCIDEV.fd], edi
644
        mov     [eax+PCIDEV.bk], edi
644
        mov     [eax+PCIDEV.bk], edi
645
        mov     eax, dword [.devfn]
645
        mov     eax, dword [.devfn]
646
        mov     dword [edi+PCIDEV.devfn], eax
646
        mov     dword [edi+PCIDEV.devfn], eax
647
        mov     dword [edi+PCIDEV.owner], 0
647
        mov     dword [edi+PCIDEV.owner], 0
648
        mov     bh, al
648
        mov     bh, al
649
        mov     al, 2
649
        mov     al, 2
650
        mov     bl, 8
650
        mov     bl, 8
651
        call    pci_read_reg
651
        call    pci_read_reg
652
        shr     eax, 8
652
        shr     eax, 8
653
        mov     [edi+PCIDEV.class], eax
653
        mov     [edi+PCIDEV.class], eax
654
        test    byte [.devfn], 7
654
        test    byte [.devfn], 7
655
        jnz     .next_func
655
        jnz     .next_func
656
        mov     ah, [.bus]
656
        mov     ah, [.bus]
657
        mov     al, 0
657
        mov     al, 0
658
        mov     bh, [.devfn]
658
        mov     bh, [.devfn]
659
        mov     bl, 0Eh
659
        mov     bl, 0Eh
660
        call    pci_read_reg
660
        call    pci_read_reg
661
        test    al, al
661
        test    al, al
662
        js      .next_func
662
        js      .next_func
663
.no_device:
663
.no_device:
664
        or      byte [.devfn], 7
664
        or      byte [.devfn], 7
665
.next_func:
665
.next_func:
666
        inc     dword [.devfn]
666
        inc     dword [.devfn]
667
        mov     ah, [.bus]
667
        mov     ah, [.bus]
668
        cmp     ah, [BOOT_VARS+0x9021]
668
        cmp     ah, [BOOT_VARS+BOOT_PCI_DATA+1]
669
        jbe     .loop
669
        jbe     .loop
670
.nomemory:
670
.nomemory:
671
        leave
671
        leave
672
        ret
672
        ret
673
endp
673
endp
674
 
674
 
675
; Export for drivers. Just returns the pointer to the pci-devices list.
675
; Export for drivers. Just returns the pointer to the pci-devices list.
676
proc get_pcidev_list
676
proc get_pcidev_list
677
        mov     eax, pcidev_list
677
        mov     eax, pcidev_list
678
        ret
678
        ret
679
endp
679
endp