Rev 2288 | Rev 3393 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2288 | Rev 2455 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2011. 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: 2288 $ |
24 | $Revision: 2455 $ |
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_VAR+0x9022] |
104 | movzx eax, word [BOOT_VAR+0x9022] |
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_VAR+0x9021] |
109 | mov al, [BOOT_VAR+0x9021] |
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_VAR+0x9020] |
114 | mov al, [BOOT_VAR+0x9020] |
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 | cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use? |
158 | cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use? |
159 | je pci_read_reg_2 |
159 | je pci_read_reg_2 |
160 | 160 | ||
161 | ; mechanism 1 |
161 | ; mechanism 1 |
162 | push esi ; save register size into ESI |
162 | push esi ; save register size into ESI |
163 | mov esi, eax |
163 | mov esi, eax |
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 | ; get current state |
168 | ; get current state |
169 | mov dx, 0xcf8 |
169 | mov dx, 0xcf8 |
170 | in eax, dx |
170 | in eax, dx |
171 | push eax |
171 | push eax |
172 | ; set up addressing to config data |
172 | ; set up addressing to config data |
173 | mov eax, ebx |
173 | mov eax, ebx |
174 | and al, 0xfc; make address dword-aligned |
174 | and al, 0xfc; make address dword-aligned |
175 | out dx, eax |
175 | out dx, eax |
176 | ; get requested DWORD of config data |
176 | ; get requested DWORD of config data |
177 | mov dl, 0xfc |
177 | mov dl, 0xfc |
178 | and bl, 3 |
178 | and bl, 3 |
179 | or dl, bl ; add to port address first 2 bits of register address |
179 | or dl, bl ; add to port address first 2 bits of register address |
180 | 180 | ||
181 | or esi, esi |
181 | or esi, esi |
182 | jz pci_read_byte1 |
182 | jz pci_read_byte1 |
183 | cmp esi, 1 |
183 | cmp esi, 1 |
184 | jz pci_read_word1 |
184 | jz pci_read_word1 |
185 | cmp esi, 2 |
185 | cmp esi, 2 |
186 | jz pci_read_dword1 |
186 | jz pci_read_dword1 |
187 | jmp pci_fin_read1 |
187 | jmp pci_fin_read1 |
188 | 188 | ||
189 | pci_read_byte1: |
189 | pci_read_byte1: |
190 | in al, dx |
190 | in al, dx |
191 | jmp pci_fin_read1 |
191 | jmp pci_fin_read1 |
192 | pci_read_word1: |
192 | pci_read_word1: |
193 | in ax, dx |
193 | in ax, dx |
194 | jmp pci_fin_read1 |
194 | jmp pci_fin_read1 |
195 | pci_read_dword1: |
195 | pci_read_dword1: |
196 | in eax, dx |
196 | in eax, dx |
197 | jmp pci_fin_read1 |
197 | jmp pci_fin_read1 |
198 | pci_fin_read1: |
198 | pci_fin_read1: |
199 | ; restore configuration control |
199 | ; restore configuration control |
200 | xchg eax, [esp] |
200 | xchg eax, [esp] |
201 | mov dx, 0xcf8 |
201 | mov dx, 0xcf8 |
202 | out dx, eax |
202 | out dx, eax |
203 | 203 | ||
204 | pop eax |
204 | pop eax |
205 | pop esi |
205 | pop esi |
206 | ret |
206 | ret |
207 | pci_read_reg_2: |
207 | pci_read_reg_2: |
208 | 208 | ||
209 | test bh, 128 ;mech#2 only supports 16 devices per bus |
209 | test bh, 128 ;mech#2 only supports 16 devices per bus |
210 | jnz pci_read_reg_err |
210 | jnz pci_read_reg_err |
211 | 211 | ||
212 | push esi; save register size into ESI |
212 | push esi; save register size into ESI |
213 | mov esi, eax |
213 | mov esi, eax |
214 | and esi, 3 |
214 | and esi, 3 |
215 | 215 | ||
216 | push eax |
216 | push eax |
217 | ;store current state of config space |
217 | ;store current state of config space |
218 | mov dx, 0xcf8 |
218 | mov dx, 0xcf8 |
219 | in al, dx |
219 | in al, dx |
220 | mov ah, al |
220 | mov ah, al |
221 | mov dl, 0xfa |
221 | mov dl, 0xfa |
222 | in al, dx |
222 | in al, dx |
223 | 223 | ||
224 | xchg eax, [esp] |
224 | xchg eax, [esp] |
225 | ; out 0xcfa,bus |
225 | ; out 0xcfa,bus |
226 | mov al, ah |
226 | mov al, ah |
227 | out dx, al |
227 | out dx, al |
228 | ; out 0xcf8,0x80 |
228 | ; out 0xcf8,0x80 |
229 | mov dl, 0xf8 |
229 | mov dl, 0xf8 |
230 | mov al, 0x80 |
230 | mov al, 0x80 |
231 | out dx, al |
231 | out dx, al |
232 | ; compute addr |
232 | ; compute addr |
233 | shr bh, 3; func is ignored in mechanism 2 |
233 | shr bh, 3; func is ignored in mechanism 2 |
234 | or bh, 0xc0 |
234 | or bh, 0xc0 |
235 | mov dx, bx |
235 | mov dx, bx |
236 | 236 | ||
237 | or esi, esi |
237 | or esi, esi |
238 | jz pci_read_byte2 |
238 | jz pci_read_byte2 |
239 | cmp esi, 1 |
239 | cmp esi, 1 |
240 | jz pci_read_word2 |
240 | jz pci_read_word2 |
241 | cmp esi, 2 |
241 | cmp esi, 2 |
242 | jz pci_read_dword2 |
242 | jz pci_read_dword2 |
243 | jmp pci_fin_read2 |
243 | jmp pci_fin_read2 |
244 | 244 | ||
245 | pci_read_byte2: |
245 | pci_read_byte2: |
246 | in al, dx |
246 | in al, dx |
247 | jmp pci_fin_read2 |
247 | jmp pci_fin_read2 |
248 | pci_read_word2: |
248 | pci_read_word2: |
249 | in ax, dx |
249 | in ax, dx |
250 | jmp pci_fin_read2 |
250 | jmp pci_fin_read2 |
251 | pci_read_dword2: |
251 | pci_read_dword2: |
252 | in eax, dx |
252 | in eax, dx |
253 | ; jmp pci_fin_read2 |
253 | ; jmp pci_fin_read2 |
254 | pci_fin_read2: |
254 | pci_fin_read2: |
255 | 255 | ||
256 | ; restore configuration space |
256 | ; restore configuration space |
257 | xchg eax, [esp] |
257 | xchg eax, [esp] |
258 | mov dx, 0xcfa |
258 | mov dx, 0xcfa |
259 | out dx, al |
259 | out dx, al |
260 | mov dl, 0xf8 |
260 | mov dl, 0xf8 |
261 | mov al, ah |
261 | mov al, ah |
262 | out dx, al |
262 | out dx, al |
263 | 263 | ||
264 | pop eax |
264 | pop eax |
265 | pop esi |
265 | pop esi |
266 | ret |
266 | ret |
267 | 267 | ||
268 | pci_read_reg_err: |
268 | pci_read_reg_err: |
269 | xor eax, eax |
269 | xor eax, eax |
270 | dec eax |
270 | dec eax |
271 | ret |
271 | ret |
272 | 272 | ||
273 | 273 | ||
274 | ;*************************************************************************** |
274 | ;*************************************************************************** |
275 | ; Function |
275 | ; Function |
276 | ; pci_write_reg: |
276 | ; pci_write_reg: |
277 | ; |
277 | ; |
278 | ; Description |
278 | ; Description |
279 | ; write a register from ECX/CX/CL into the PCI config space |
279 | ; write a register from ECX/CX/CL into the PCI config space |
280 | ; IN: ah=bus,device+func=bh,register address (dword aligned)=bl, |
280 | ; IN: ah=bus,device+func=bh,register address (dword aligned)=bl, |
281 | ; value to write in ecx |
281 | ; value to write in ecx |
282 | ; number of bytes to write (1,2,4) coded into AL, bits 0-1 |
282 | ; number of bytes to write (1,2,4) coded into AL, bits 0-1 |
283 | ; (0 - byte, 1 - word, 2 - dword) |
283 | ; (0 - byte, 1 - word, 2 - dword) |
284 | ;*************************************************************************** |
284 | ;*************************************************************************** |
285 | 285 | ||
286 | align 4 |
286 | align 4 |
287 | 287 | ||
288 | pci_write_reg: |
288 | pci_write_reg: |
289 | cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use? |
289 | cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use? |
290 | je pci_write_reg_2 |
290 | je pci_write_reg_2 |
291 | 291 | ||
292 | ; mechanism 1 |
292 | ; mechanism 1 |
293 | push esi ; save register size into ESI |
293 | push esi ; save register size into ESI |
294 | mov esi, eax |
294 | mov esi, eax |
295 | and esi, 3 |
295 | and esi, 3 |
296 | 296 | ||
297 | call pci_make_config_cmd |
297 | call pci_make_config_cmd |
298 | mov ebx, eax |
298 | mov ebx, eax |
299 | ; get current state into ecx |
299 | ; get current state into ecx |
300 | mov dx, 0xcf8 |
300 | mov dx, 0xcf8 |
301 | in eax, dx |
301 | in eax, dx |
302 | push eax |
302 | push eax |
303 | ; set up addressing to config data |
303 | ; set up addressing to config data |
304 | mov eax, ebx |
304 | mov eax, ebx |
305 | and al, 0xfc; make address dword-aligned |
305 | and al, 0xfc; make address dword-aligned |
306 | out dx, eax |
306 | out dx, eax |
307 | ; write DWORD of config data |
307 | ; write DWORD of config data |
308 | mov dl, 0xfc |
308 | mov dl, 0xfc |
309 | and bl, 3 |
309 | and bl, 3 |
310 | or dl, bl |
310 | or dl, bl |
311 | mov eax, ecx |
311 | mov eax, ecx |
312 | 312 | ||
313 | or esi, esi |
313 | or esi, esi |
314 | jz pci_write_byte1 |
314 | jz pci_write_byte1 |
315 | cmp esi, 1 |
315 | cmp esi, 1 |
316 | jz pci_write_word1 |
316 | jz pci_write_word1 |
317 | cmp esi, 2 |
317 | cmp esi, 2 |
318 | jz pci_write_dword1 |
318 | jz pci_write_dword1 |
319 | jmp pci_fin_write1 |
319 | jmp pci_fin_write1 |
320 | 320 | ||
321 | pci_write_byte1: |
321 | pci_write_byte1: |
322 | out dx, al |
322 | out dx, al |
323 | jmp pci_fin_write1 |
323 | jmp pci_fin_write1 |
324 | pci_write_word1: |
324 | pci_write_word1: |
325 | out dx, ax |
325 | out dx, ax |
326 | jmp pci_fin_write1 |
326 | jmp pci_fin_write1 |
327 | pci_write_dword1: |
327 | pci_write_dword1: |
328 | out dx, eax |
328 | out dx, eax |
329 | jmp pci_fin_write1 |
329 | jmp pci_fin_write1 |
330 | pci_fin_write1: |
330 | pci_fin_write1: |
331 | 331 | ||
332 | ; restore configuration control |
332 | ; restore configuration control |
333 | pop eax |
333 | pop eax |
334 | mov dl, 0xf8 |
334 | mov dl, 0xf8 |
335 | out dx, eax |
335 | out dx, eax |
336 | 336 | ||
337 | xor eax, eax |
337 | xor eax, eax |
338 | pop esi |
338 | pop esi |
339 | 339 | ||
340 | ret |
340 | ret |
341 | pci_write_reg_2: |
341 | pci_write_reg_2: |
342 | 342 | ||
343 | test bh, 128 ;mech#2 only supports 16 devices per bus |
343 | test bh, 128 ;mech#2 only supports 16 devices per bus |
344 | jnz pci_write_reg_err |
344 | jnz pci_write_reg_err |
345 | 345 | ||
346 | 346 | ||
347 | push esi; save register size into ESI |
347 | push esi; save register size into ESI |
348 | mov esi, eax |
348 | mov esi, eax |
349 | and esi, 3 |
349 | and esi, 3 |
350 | 350 | ||
351 | push eax |
351 | push eax |
352 | ;store current state of config space |
352 | ;store current state of config space |
353 | mov dx, 0xcf8 |
353 | mov dx, 0xcf8 |
354 | in al, dx |
354 | in al, dx |
355 | mov ah, al |
355 | mov ah, al |
356 | mov dl, 0xfa |
356 | mov dl, 0xfa |
357 | in al, dx |
357 | in al, dx |
358 | xchg eax, [esp] |
358 | xchg eax, [esp] |
359 | ; out 0xcfa,bus |
359 | ; out 0xcfa,bus |
360 | mov al, ah |
360 | mov al, ah |
361 | out dx, al |
361 | out dx, al |
362 | ; out 0xcf8,0x80 |
362 | ; out 0xcf8,0x80 |
363 | mov dl, 0xf8 |
363 | mov dl, 0xf8 |
364 | mov al, 0x80 |
364 | mov al, 0x80 |
365 | out dx, al |
365 | out dx, al |
366 | ; compute addr |
366 | ; compute addr |
367 | shr bh, 3; func is ignored in mechanism 2 |
367 | shr bh, 3; func is ignored in mechanism 2 |
368 | or bh, 0xc0 |
368 | or bh, 0xc0 |
369 | mov dx, bx |
369 | mov dx, bx |
370 | ; write register |
370 | ; write register |
371 | mov eax, ecx |
371 | mov eax, ecx |
372 | 372 | ||
373 | or esi, esi |
373 | or esi, esi |
374 | jz pci_write_byte2 |
374 | jz pci_write_byte2 |
375 | cmp esi, 1 |
375 | cmp esi, 1 |
376 | jz pci_write_word2 |
376 | jz pci_write_word2 |
377 | cmp esi, 2 |
377 | cmp esi, 2 |
378 | jz pci_write_dword2 |
378 | jz pci_write_dword2 |
379 | jmp pci_fin_write2 |
379 | jmp pci_fin_write2 |
380 | 380 | ||
381 | pci_write_byte2: |
381 | pci_write_byte2: |
382 | out dx, al |
382 | out dx, al |
383 | jmp pci_fin_write2 |
383 | jmp pci_fin_write2 |
384 | pci_write_word2: |
384 | pci_write_word2: |
385 | out dx, ax |
385 | out dx, ax |
386 | jmp pci_fin_write2 |
386 | jmp pci_fin_write2 |
387 | pci_write_dword2: |
387 | pci_write_dword2: |
388 | out dx, eax |
388 | out dx, eax |
389 | jmp pci_fin_write2 |
389 | jmp pci_fin_write2 |
390 | pci_fin_write2: |
390 | pci_fin_write2: |
391 | ; restore configuration space |
391 | ; restore configuration space |
392 | pop eax |
392 | pop eax |
393 | mov dx, 0xcfa |
393 | mov dx, 0xcfa |
394 | out dx, al |
394 | out dx, al |
395 | mov dl, 0xf8 |
395 | mov dl, 0xf8 |
396 | mov al, ah |
396 | mov al, ah |
397 | out dx, al |
397 | out dx, al |
398 | 398 | ||
399 | xor eax, eax |
399 | xor eax, eax |
400 | pop esi |
400 | pop esi |
401 | ret |
401 | ret |
402 | 402 | ||
403 | pci_write_reg_err: |
403 | pci_write_reg_err: |
404 | xor eax, eax |
404 | xor eax, eax |
405 | dec eax |
405 | dec eax |
406 | ret |
406 | ret |
407 | 407 | ||
408 | if defined mmio_pci_addr ; must be set above |
408 | if defined mmio_pci_addr ; must be set above |
409 | ;*************************************************************************** |
409 | ;*************************************************************************** |
410 | ; Function |
410 | ; Function |
411 | ; pci_mmio_init |
411 | ; pci_mmio_init |
412 | ; |
412 | ; |
413 | ; Description |
413 | ; Description |
414 | ; IN: bx = device's PCI bus address (bbbbbbbbdddddfff) |
414 | ; IN: bx = device's PCI bus address (bbbbbbbbdddddfff) |
415 | ; Returns eax = user heap space available (bytes) |
415 | ; Returns eax = user heap space available (bytes) |
416 | ; Error codes |
416 | ; Error codes |
417 | ; eax = -1 : PCI user access blocked, |
417 | ; eax = -1 : PCI user access blocked, |
418 | ; eax = -2 : device not registered for uMMIO service |
418 | ; eax = -2 : device not registered for uMMIO service |
419 | ; eax = -3 : user heap initialization failure |
419 | ; eax = -3 : user heap initialization failure |
420 | ;*************************************************************************** |
420 | ;*************************************************************************** |
421 | pci_mmio_init: |
421 | pci_mmio_init: |
422 | cmp bx, mmio_pci_addr |
422 | cmp bx, mmio_pci_addr |
423 | jz @f |
423 | jz @f |
424 | mov eax, -2 |
424 | mov eax, -2 |
425 | ret |
425 | ret |
426 | @@: |
426 | @@: |
427 | call init_heap ; (if not initialized yet) |
427 | call init_heap ; (if not initialized yet) |
428 | or eax, eax |
428 | or eax, eax |
429 | jz @f |
429 | jz @f |
430 | ret |
430 | ret |
431 | @@: |
431 | @@: |
432 | mov eax, -3 |
432 | mov eax, -3 |
433 | ret |
433 | ret |
434 | 434 | ||
435 | 435 | ||
436 | ;*************************************************************************** |
436 | ;*************************************************************************** |
437 | ; Function |
437 | ; Function |
438 | ; pci_mmio_map |
438 | ; pci_mmio_map |
439 | ; |
439 | ; |
440 | ; Description |
440 | ; Description |
441 | ; maps a block of PCI memory to user-accessible linear address |
441 | ; maps a block of PCI memory to user-accessible linear address |
442 | ; |
442 | ; |
443 | ; WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only! |
443 | ; WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only! |
444 | ; The target device address should be set in kernel var mmio_pci_addr |
444 | ; The target device address should be set in kernel var mmio_pci_addr |
445 | ; |
445 | ; |
446 | ; IN: ah = BAR#; |
446 | ; IN: ah = BAR#; |
447 | ; IN: ebx = block size (bytes); |
447 | ; IN: ebx = block size (bytes); |
448 | ; IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages); |
448 | ; IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages); |
449 | ; |
449 | ; |
450 | ; Returns eax = MMIO block's linear address in the userspace (if no error) |
450 | ; Returns eax = MMIO block's linear address in the userspace (if no error) |
451 | ; |
451 | ; |
452 | ; |
452 | ; |
453 | ; Error codes |
453 | ; Error codes |
454 | ; eax = -1 : user access to PCI blocked, |
454 | ; eax = -1 : user access to PCI blocked, |
455 | ; eax = -2 : an invalid BAR register referred |
455 | ; eax = -2 : an invalid BAR register referred |
456 | ; eax = -3 : no i/o space on that BAR |
456 | ; eax = -3 : no i/o space on that BAR |
457 | ; eax = -4 : a port i/o BAR register referred |
457 | ; eax = -4 : a port i/o BAR register referred |
458 | ; eax = -5 : dynamic userspace allocation problem |
458 | ; eax = -5 : dynamic userspace allocation problem |
459 | ;*************************************************************************** |
459 | ;*************************************************************************** |
460 | 460 | ||
461 | pci_mmio_map: |
461 | pci_mmio_map: |
462 | and edx, 0x0ffff |
462 | and edx, 0x0ffff |
463 | cmp ah, 6 |
463 | cmp ah, 6 |
464 | jc .bar_0_5 |
464 | jc .bar_0_5 |
465 | jz .bar_rom |
465 | jz .bar_rom |
466 | mov eax, -2 |
466 | mov eax, -2 |
467 | ret |
467 | ret |
468 | .bar_rom: |
468 | .bar_rom: |
469 | mov ah, 8 ; bar6 = Expansion ROM base address |
469 | mov ah, 8 ; bar6 = Expansion ROM base address |
470 | .bar_0_5: |
470 | .bar_0_5: |
471 | push ecx |
471 | push ecx |
472 | add ebx, 4095 |
472 | add ebx, 4095 |
473 | and ebx, -4096 |
473 | and ebx, -4096 |
474 | push ebx |
474 | push ebx |
475 | mov bl, ah ; bl = BAR# (0..5), however bl=8 for BAR6 |
475 | mov bl, ah ; bl = BAR# (0..5), however bl=8 for BAR6 |
476 | shl bl, 1 |
476 | shl bl, 1 |
477 | shl bl, 1 |
477 | shl bl, 1 |
478 | add bl, 0x10; now bl = BAR offset in PCI config. space |
478 | add bl, 0x10; now bl = BAR offset in PCI config. space |
479 | mov ax, mmio_pci_addr |
479 | mov ax, mmio_pci_addr |
480 | mov bh, al ; bh = dddddfff |
480 | mov bh, al ; bh = dddddfff |
481 | mov al, 2 ; al : DW to read |
481 | mov al, 2 ; al : DW to read |
482 | call pci_read_reg |
482 | call pci_read_reg |
483 | or eax, eax |
483 | or eax, eax |
484 | jnz @f |
484 | jnz @f |
485 | mov eax, -3 ; empty I/O space |
485 | mov eax, -3 ; empty I/O space |
486 | jmp mmio_ret_fail |
486 | jmp mmio_ret_fail |
487 | @@: |
487 | @@: |
488 | test eax, 1 |
488 | test eax, 1 |
489 | jz @f |
489 | jz @f |
490 | mov eax, -4 ; damned ports (not MMIO space) |
490 | mov eax, -4 ; damned ports (not MMIO space) |
491 | jmp mmio_ret_fail |
491 | jmp mmio_ret_fail |
492 | @@: |
492 | @@: |
493 | pop ecx ; ecx = block size, bytes (expanded to whole page) |
493 | pop ecx ; ecx = block size, bytes (expanded to whole page) |
494 | mov ebx, ecx; user_alloc destroys eax, ecx, edx, but saves ebx |
494 | mov ebx, ecx; user_alloc destroys eax, ecx, edx, but saves ebx |
495 | and eax, 0xFFFFFFF0 |
495 | and eax, 0xFFFFFFF0 |
496 | push eax ; store MMIO physical address + keep 2DWords in the stack |
496 | push eax ; store MMIO physical address + keep 2DWords in the stack |
497 | stdcall user_alloc, ecx |
497 | stdcall user_alloc, ecx |
498 | or eax, eax |
498 | or eax, eax |
499 | jnz mmio_map_over |
499 | jnz mmio_map_over |
500 | mov eax, -5 ; problem with page allocation |
500 | mov eax, -5 ; problem with page allocation |
501 | 501 | ||
502 | mmio_ret_fail: |
502 | mmio_ret_fail: |
503 | pop ecx |
503 | pop ecx |
504 | pop edx |
504 | pop edx |
505 | ret |
505 | ret |
506 | 506 | ||
507 | mmio_map_over: |
507 | mmio_map_over: |
508 | mov ecx, ebx; ecx = size (bytes, expanded to whole page) |
508 | mov ecx, ebx; ecx = size (bytes, expanded to whole page) |
509 | shr ecx, 12 ; ecx = number of pages |
509 | shr ecx, 12 ; ecx = number of pages |
510 | mov ebx, eax; ebx = linear address |
510 | mov ebx, eax; ebx = linear address |
511 | pop eax ; eax = MMIO start |
511 | pop eax ; eax = MMIO start |
512 | pop edx ; edx = MMIO shift (pages) |
512 | pop edx ; edx = MMIO shift (pages) |
513 | shl edx, 12 ; edx = MMIO shift (bytes) |
513 | shl edx, 12 ; edx = MMIO shift (bytes) |
514 | add eax, edx; eax = uMMIO physical address |
514 | add eax, edx; eax = uMMIO physical address |
515 | or eax, PG_SHARED |
515 | or eax, PG_SHARED |
516 | or eax, PG_UW |
516 | or eax, PG_UW |
517 | or eax, PG_NOCACHE |
517 | or eax, PG_NOCACHE |
518 | mov edi, ebx |
518 | mov edi, ebx |
519 | call commit_pages |
519 | call commit_pages |
520 | mov eax, edi |
520 | mov eax, edi |
521 | ret |
521 | ret |
522 | 522 | ||
523 | ;*************************************************************************** |
523 | ;*************************************************************************** |
524 | ; Function |
524 | ; Function |
525 | ; pci_mmio_unmap_page |
525 | ; pci_mmio_unmap_page |
526 | ; |
526 | ; |
527 | ; Description |
527 | ; Description |
528 | ; unmaps the linear space previously tied to a PCI memory block |
528 | ; unmaps the linear space previously tied to a PCI memory block |
529 | ; |
529 | ; |
530 | ; IN: ebx = linear address of space previously allocated by pci_mmio_map |
530 | ; IN: ebx = linear address of space previously allocated by pci_mmio_map |
531 | ; returns eax = 1 if successfully unmapped |
531 | ; returns eax = 1 if successfully unmapped |
532 | ; |
532 | ; |
533 | ; Error codes |
533 | ; Error codes |
534 | ; eax = -1 if no user PCI access allowed, |
534 | ; eax = -1 if no user PCI access allowed, |
535 | ; eax = 0 if unmapping failed |
535 | ; eax = 0 if unmapping failed |
536 | ;*************************************************************************** |
536 | ;*************************************************************************** |
537 | 537 | ||
538 | pci_mmio_unmap: |
538 | pci_mmio_unmap: |
539 | stdcall user_free, ebx |
539 | stdcall user_free, ebx |
540 | ret |
540 | ret |
541 | 541 | ||
542 | end if |
542 | end if |
543 | 543 | ||
544 | ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
544 | ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
545 | uglobal |
545 | uglobal |
546 | align 4 |
546 | align 4 |
547 | ; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1) |
547 | ; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1) |
548 | pci_emu_dat: |
548 | pci_emu_dat: |
549 | times 30*10 db 0 |
549 | times 30*10 db 0 |
550 | endg |
550 | endg |
551 | ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
551 | ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
552 | align 4 |
552 | align 4 |
553 | sys_pcibios: |
553 | sys_pcibios: |
554 | cmp [pci_access_enabled], 1 |
554 | cmp [pci_access_enabled], 1 |
555 | jne .unsupported_func |
555 | jne .unsupported_func |
556 | cmp [pci_bios_entry], 0 |
556 | cmp [pci_bios_entry], 0 |
557 | jz .emulate_bios |
557 | jz .emulate_bios |
558 | 558 | ||
559 | push ds |
559 | push ds |
560 | mov ax, pci_data_sel |
560 | mov ax, pci_data_sel |
561 | mov ds, ax |
561 | mov ds, ax |
562 | mov eax, ebp |
562 | mov eax, ebp |
563 | mov ah, 0B1h |
563 | mov ah, 0B1h |
564 | call pword [cs:pci_bios_entry] |
564 | call pword [cs:pci_bios_entry] |
565 | pop ds |
565 | pop ds |
566 | 566 | ||
567 | jmp .return |
567 | jmp .return |
568 | ;-=-=-=-=-=-=-=-= |
568 | ;-=-=-=-=-=-=-=-= |
569 | .emulate_bios: |
569 | .emulate_bios: |
570 | cmp ebp, 1 ; PCI_FUNCTION_ID |
570 | cmp ebp, 1 ; PCI_FUNCTION_ID |
571 | jnz .not_PCI_BIOS_PRESENT |
571 | jnz .not_PCI_BIOS_PRESENT |
572 | mov edx, 'PCI ' |
572 | mov edx, 'PCI ' |
573 | mov al, [BOOT_VAR + 0x9020] |
573 | mov al, [BOOT_VAR + 0x9020] |
574 | mov bx, [BOOT_VAR + 0x9022] |
574 | mov bx, [BOOT_VAR + 0x9022] |
575 | mov cl, [BOOT_VAR + 0x9021] |
575 | mov cl, [BOOT_VAR + 0x9021] |
576 | xor ah, ah |
576 | xor ah, ah |
577 | jmp .return_abcd |
577 | jmp .return_abcd |
578 | 578 | ||
579 | .not_PCI_BIOS_PRESENT: |
579 | .not_PCI_BIOS_PRESENT: |
580 | cmp ebp, 2 ; FIND_PCI_DEVICE |
580 | cmp ebp, 2 ; FIND_PCI_DEVICE |
581 | jne .not_FIND_PCI_DEVICE |
581 | jne .not_FIND_PCI_DEVICE |
582 | mov ebx, pci_emu_dat |
582 | mov ebx, pci_emu_dat |
583 | ..nxt: |
583 | ..nxt: |
584 | cmp [ebx], dx |
584 | cmp [ebx], dx |
585 | jne ..no |
585 | jne ..no |
586 | cmp [ebx + 2], cx |
586 | cmp [ebx + 2], cx |
587 | jne ..no |
587 | jne ..no |
588 | dec si |
588 | dec si |
589 | jns ..no |
589 | jns ..no |
590 | mov bx, [ebx + 4] |
590 | mov bx, [ebx + 4] |
591 | xor ah, ah |
591 | xor ah, ah |
592 | jmp .return_ab |
592 | jmp .return_ab |
593 | ..no: |
593 | ..no: |
594 | cmp word[ebx], 0 |
594 | cmp word[ebx], 0 |
595 | je ..dev_not_found |
595 | je ..dev_not_found |
596 | add ebx, 10 |
596 | add ebx, 10 |
597 | jmp ..nxt |
597 | jmp ..nxt |
598 | ..dev_not_found: |
598 | ..dev_not_found: |
599 | mov ah, 0x86 ; DEVICE_NOT_FOUND |
599 | mov ah, 0x86 ; DEVICE_NOT_FOUND |
600 | jmp .return_a |
600 | jmp .return_a |
601 | 601 | ||
602 | .not_FIND_PCI_DEVICE: |
602 | .not_FIND_PCI_DEVICE: |
603 | cmp ebp, 3 ; FIND_PCI_CLASS_CODE |
603 | cmp ebp, 3 ; FIND_PCI_CLASS_CODE |
604 | jne .not_FIND_PCI_CLASS_CODE |
604 | jne .not_FIND_PCI_CLASS_CODE |
605 | mov esi, pci_emu_dat |
605 | mov esi, pci_emu_dat |
606 | shl ecx, 8 |
606 | shl ecx, 8 |
607 | ..nxt2: |
607 | ..nxt2: |
608 | cmp [esi], ecx |
608 | cmp [esi], ecx |
609 | jne ..no2 |
609 | jne ..no2 |
610 | mov bx, [esi] |
610 | mov bx, [esi] |
611 | xor ah, ah |
611 | xor ah, ah |
612 | jmp .return_ab |
612 | jmp .return_ab |
613 | ..no2: |
613 | ..no2: |
614 | cmp dword[esi], 0 |
614 | cmp dword[esi], 0 |
615 | je ..dev_not_found |
615 | je ..dev_not_found |
616 | add esi, 10 |
616 | add esi, 10 |
617 | jmp ..nxt2 |
617 | jmp ..nxt2 |
618 | 618 | ||
619 | .not_FIND_PCI_CLASS_CODE: |
619 | .not_FIND_PCI_CLASS_CODE: |
620 | cmp ebp, 8 ; READ_CONFIG_* |
620 | cmp ebp, 8 ; READ_CONFIG_* |
621 | jb .not_READ_CONFIG |
621 | jb .not_READ_CONFIG |
622 | cmp ebp, 0x0A |
622 | cmp ebp, 0x0A |
623 | ja .not_READ_CONFIG |
623 | ja .not_READ_CONFIG |
624 | mov eax, ebp |
624 | mov eax, ebp |
625 | mov ah, bh |
625 | mov ah, bh |
626 | mov edx, edi |
626 | mov edx, edi |
627 | mov bh, bl |
627 | mov bh, bl |
628 | mov bl, dl |
628 | mov bl, dl |
629 | call pci_read_reg |
629 | call pci_read_reg |
630 | mov ecx, eax |
630 | mov ecx, eax |
631 | xor ah, ah ; SUCCESSFUL |
631 | xor ah, ah ; SUCCESSFUL |
632 | jmp .return_abc |
632 | jmp .return_abc |
633 | .not_READ_CONFIG: |
633 | .not_READ_CONFIG: |
634 | cmp ebp, 0x0B ; WRITE_CONFIG_* |
634 | cmp ebp, 0x0B ; WRITE_CONFIG_* |
635 | jb .not_WRITE_CONFIG |
635 | jb .not_WRITE_CONFIG |
636 | cmp ebp, 0x0D |
636 | cmp ebp, 0x0D |
637 | ja .not_WRITE_CONFIG |
637 | ja .not_WRITE_CONFIG |
638 | lea eax, [ebp+1] |
638 | lea eax, [ebp+1] |
639 | mov ah, bh |
639 | mov ah, bh |
640 | mov edx, edi |
640 | mov edx, edi |
641 | mov bh, bl |
641 | mov bh, bl |
642 | mov bl, dl |
642 | mov bl, dl |
643 | call pci_write_reg |
643 | call pci_write_reg |
644 | xor ah, ah ; SUCCESSFUL |
644 | xor ah, ah ; SUCCESSFUL |
645 | jmp .return_abc |
645 | jmp .return_abc |
646 | .not_WRITE_CONFIG: |
646 | .not_WRITE_CONFIG: |
647 | .unsupported_func: |
647 | .unsupported_func: |
648 | mov ah, 0x81 ; FUNC_NOT_SUPPORTED |
648 | mov ah, 0x81 ; FUNC_NOT_SUPPORTED |
649 | .return: |
649 | .return: |
650 | mov dword[esp + 4 ], edi |
650 | mov dword[esp + 4 ], edi |
651 | mov dword[esp + 8], esi |
651 | mov dword[esp + 8], esi |
652 | .return_abcd: |
652 | .return_abcd: |
653 | mov dword[esp + 24], edx |
653 | mov dword[esp + 24], edx |
654 | .return_abc: |
654 | .return_abc: |
655 | mov dword[esp + 28], ecx |
655 | mov dword[esp + 28], ecx |
656 | .return_ab: |
656 | .return_ab: |
657 | mov dword[esp + 20], ebx |
657 | mov dword[esp + 20], ebx |
658 | .return_a: |
658 | .return_a: |
659 | mov dword[esp + 32], eax |
659 | mov dword[esp + 32], eax |
660 | ret |
660 | ret |