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 |