]> git.sur5r.net Git - u-boot/blob - arch/i386/lib/bios_pci.S
x86: Fix support for booting bzImage
[u-boot] / arch / i386 / lib / bios_pci.S
1 /*
2  * (C) Copyright 2002
3  * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * x86 realmode assembly implementation of a PCI BIOS
26  * for platforms that use one PCI hose and configuration
27  * access type 1. (The common case for low-end PC's)
28  */
29
30 #include "bios.h"
31
32 #define PCI_BIOS_DEBUG
33
34 .section .bios, "ax"
35 .code16
36 .globl realmode_pci_bios_call_entry
37 .hidden realmode_pci_bios_call_entry
38 .type realmode_pci_bios_call_entry, @function
39 realmode_pci_bios_call_entry:
40         MAKE_BIOS_STACK
41         call realmode_pci_bios
42         RESTORE_CALLERS_STACK
43         ret
44
45
46 .globl realmode_pci_bios
47 realmode_pci_bios:
48 gs      movw    OFFS_AX(%bp), %ax
49         cmpb    $1, %al
50         je      pci_bios_present
51         cmpb    $2, %al
52         je      pci_bios_find_device
53         cmpb    $3, %al
54         je      pci_bios_find_class
55         cmpb    $6, %al
56         je      pci_bios_generate_special_cycle
57         cmpb    $8, %al
58         je      pci_bios_read_cfg_byte
59         cmpb    $9, %al
60         je      pci_bios_read_cfg_word
61         cmpb    $10, %al
62         je      pci_bios_read_cfg_dword
63         cmpb    $11, %al
64         je      pci_bios_write_cfg_byte
65         cmpb    $12, %al
66         je      pci_bios_write_cfg_word
67         cmpb    $13, %al
68         je      pci_bios_write_cfg_dword
69         cmpb    $14, %al
70         je      pci_bios_get_irq_routing
71         cmpb    $15, %al
72         je      pci_bios_set_irq
73         jmp     unknown_function
74
75 /*****************************************************************************/
76
77 pci_bios_present:
78 #ifdef PCI_BIOS_DEBUG
79 cs      incl    num_pci_bios_present
80 #endif
81         movl    $0x20494350, %eax
82 gs      movl    %eax, OFFS_EDX(%bp)
83         movb    $0x01, %al
84 gs      movb    %al, OFFS_AL(%bp)       /* We support cfg type 1 */
85         movw    $0x0210, %ax            /* version 2.10 */
86 gs      movw    %ax, OFFS_BX(%bp)
87 cs      movb    pci_last_bus, %al       /* last bus number */
88 gs      movb    %al, OFFS_CL(%bp)
89         jmp     clear_carry
90
91 /*****************************************************************************/
92
93 /* device 0-31, function 0-7 */
94 pci_bios_find_device:
95 #ifdef PCI_BIOS_DEBUG
96 cs      incl    num_pci_bios_find_device
97 #endif
98 gs      movw    OFFS_CX(%bp), %di
99         shll    $16, %edi
100 gs      movw    OFFS_DX(%bp), %di       /* edi now holds device in upper 16
101                                          * bits and vendor in lower 16 bits */
102 gs      movw    OFFS_SI(%bp), %si
103         xorw    %bx, %bx                /* start at bus 0 dev 0 function 0 */
104 pfd_loop:
105         xorw    %ax, %ax                /* dword 0 is vendor/device */
106         call    __pci_bios_select_register
107         movw    $0xcfc, %dx
108         inl     %dx, %eax
109         cmpl    %edi, %eax              /* our device ? */
110         je      pfd_found_one
111 pfd_next_dev:
112         /* check for multi function devices */
113         movw    %bx, %ax
114         andw    $3, %ax
115         jnz     pfd_function_not_zero
116         movw    $0x000c, %ax
117         call    __pci_bios_select_register
118         movw    $0xcfe, %dx
119         inb     %dx, %al
120         andb    $0x80, %al
121         jz      pfd_not_multi_function
122 pfd_function_not_zero:
123         incw    %bx                     /* next function, overflows in to
124                                          * device number, then bus number */
125         jmp     pfd_check_bus
126
127 pfd_not_multi_function:
128         andw    $0xfff8, %bx            /* remove function bits */
129         addw    $0x0008, %bx            /* next device, overflows in to bus number */
130 pfd_check_bus:
131 cs      movb    pci_last_bus, %ah
132         cmpb    %ah, %bh
133         ja      pfd_not_found
134         jmp     pfd_loop
135 pfd_found_one:
136         decw    %si
137         js      pfd_done
138         jmp     pfd_next_dev
139
140 pfd_done:
141 gs      movw    %bx, OFFS_BX(%bp)
142         jmp     clear_carry
143
144 pfd_not_found:
145         movb    $0x86, %ah              /* device not found */
146         jmp     set_carry
147
148 /*****************************************************************************/
149
150 pci_bios_find_class:
151 #ifdef PCI_BIOS_DEBUG
152 cs      incl    num_pci_bios_find_class
153 #endif
154 gs      movl    OFFS_ECX(%bp), %edi
155         andl    $0x00ffffff, %edi       /* edi now holds class-code in lower 24 bits */
156 gs      movw    OFFS_SI(%bp), %si
157         xorw    %bx, %bx                /* start at bus 0 dev 0 function 0 */
158 pfc_loop:
159         movw    $8, %ax                 /* dword 8 is class-code high 24bits */
160         call    __pci_bios_select_register
161         movw    $0xcfc, %dx
162         inl     %dx, %eax
163         shrl    $8, %eax
164         andl    $0x00ffffff, %eax
165         cmpl    %edi, %eax              /* our device ? */
166         je      pfc_found_one
167 pfc_next_dev:
168         /* check for multi function devices */
169         andw    $3, %bx
170         jnz     pfc_function_not_zero
171         movw    $0x000c, %ax
172         call    __pci_bios_select_register
173         movw    $0xcfe, %dx
174         inb     %dx, %al
175         andb    $0x80, %al
176         jz      pfc_not_multi_function
177 pfc_function_not_zero:
178         incw    %bx                     /* next function, overflows in to
179                                          * device number, then bus number */
180         jmp     pfc_check_bus
181
182 pfc_not_multi_function:
183         andw    $0xfff8, %bx            /* remove function bits */
184         addw    $0x0008, %bx            /* next device, overflows in to bus number */
185 pfc_check_bus:
186 cs      movb    pci_last_bus, %ah
187         cmpb    %ah, %bh
188         ja      pfc_not_found
189         jmp     pfc_loop
190 pfc_found_one:
191         decw    %si
192         js      pfc_done
193         jmp     pfc_next_dev
194
195 pfc_done:
196 gs      movw    %bx, OFFS_BX(%bp)
197         jmp     clear_carry
198
199 pfc_not_found:
200         movb    $0x86, %ah              /* device not found */
201         jmp     set_carry
202
203 /*****************************************************************************/
204
205 pci_bios_generate_special_cycle:
206 #ifdef PCI_BIOS_DEBUG
207 cs      incl    num_pci_bios_generate_special_cycle
208 #endif
209         movb    $0x81, %ah              /* function not supported */
210         jmp     set_carry
211
212 /*****************************************************************************/
213
214 pci_bios_read_cfg_byte:
215 #ifdef PCI_BIOS_DEBUG
216 cs      incl    num_pci_bios_read_cfg_byte
217 #endif
218         call    pci_bios_select_register
219 gs      movw    OFFS_DI(%bp), %dx
220         andw    $3, %dx
221         addw    $0xcfc, %dx
222         inb     %dx, %al
223 gs      movb    %al, OFFS_CL(%bp)
224         jmp     clear_carry
225
226 /*****************************************************************************/
227
228 pci_bios_read_cfg_word:
229 #ifdef PCI_BIOS_DEBUG
230 cs      incl    num_pci_bios_read_cfg_word
231 #endif
232         call    pci_bios_select_register
233 gs      movw    OFFS_DI(%bp), %dx
234         andw    $2, %dx
235         addw    $0xcfc, %dx
236         inw     %dx, %ax
237 gs      movw    %ax, OFFS_CX(%bp)
238         jmp     clear_carry
239
240
241 /*****************************************************************************/
242
243 pci_bios_read_cfg_dword:
244 #ifdef PCI_BIOS_DEBUG
245 cs      incl    num_pci_bios_read_cfg_dword
246 #endif
247         call    pci_bios_select_register
248         movw    $0xcfc, %dx
249         inl     %dx, %eax
250 gs      movl    %eax, OFFS_ECX(%bp)
251         jmp     clear_carry
252
253 /*****************************************************************************/
254
255 pci_bios_write_cfg_byte:
256 #ifdef PCI_BIOS_DEBUG
257 cs      incl    num_pci_bios_write_cfg_byte
258 #endif
259         call    pci_bios_select_register
260 gs      movw    OFFS_DI(%bp), %dx
261 gs      movb    OFFS_CL(%bp), %al
262         andw    $3, %dx
263         addw    $0xcfc, %dx
264         outb    %al, %dx
265         jmp     clear_carry
266
267 /*****************************************************************************/
268
269 pci_bios_write_cfg_word:
270 #ifdef PCI_BIOS_DEBUG
271 cs      incl    num_pci_bios_write_cfg_word
272 #endif
273         call    pci_bios_select_register
274 gs      movw    OFFS_DI(%bp), %dx
275 gs      movw    OFFS_CX(%bp), %ax
276         andw    $2, %dx
277         addw    $0xcfc, %dx
278         outw    %ax, %dx
279         jmp     clear_carry
280
281 /*****************************************************************************/
282
283 pci_bios_write_cfg_dword:
284 #ifdef PCI_BIOS_DEBUG
285 cs      incl    num_pci_bios_write_cfg_dword
286 #endif
287         call    pci_bios_select_register
288 gs      movl    OFFS_ECX(%bp), %eax
289         movw    $0xcfc, %dx
290         outl    %eax, %dx
291         jmp     clear_carry
292
293 /*****************************************************************************/
294
295 pci_bios_get_irq_routing:
296 #ifdef PCI_BIOS_DEBUG
297 cs      incl    num_pci_bios_get_irq_routing
298 #endif
299         movb    $0x81, %ah              /* function not supported */
300         jmp     set_carry
301
302 /*****************************************************************************/
303
304 pci_bios_set_irq:
305 #ifdef PCI_BIOS_DEBUG
306 cs      incl    num_pci_bios_set_irq
307 #endif
308         movb    $0x81, %ah              /* function not supported */
309         jmp     set_carry
310
311 /*****************************************************************************/
312
313 unknown_function:
314 #ifdef PCI_BIOS_DEBUG
315 cs      incl    num_pci_bios_unknown_function
316 #endif
317         movb    $0x81, %ah              /* function not supported */
318         jmp     set_carry
319
320 /*****************************************************************************/
321
322 pci_bios_select_register:
323 gs      movw    OFFS_BX(%bp), %bx
324 gs      movw    OFFS_DI(%bp), %ax
325 /* destroys eax, dx */
326 __pci_bios_select_register:               /* BX holds device id, AX holds register index */
327         pushl   %ebx
328         andl    $0xfc, %eax
329         andl    $0xffff, %ebx
330         shll    $8, %ebx
331         orl     %ebx, %eax
332         orl     $0x80000000, %eax
333         movw    $0xcf8, %dx
334         outl    %eax, %dx
335         popl    %ebx
336         ret
337
338
339 clear_carry:
340 gs      movw    OFFS_FLAGS(%bp), %ax
341         andw    $0xfffe, %ax                    /* clear carry -- function succeeded */
342 gs      movw    %ax, OFFS_FLAGS(%bp)
343         xorw    %ax, %ax
344 gs      movb    %ah, OFFS_AH(%bp)
345         ret
346
347 set_carry:
348 gs      movb    %ah, OFFS_AH(%bp)
349 gs      movw    OFFS_FLAGS(%bp), %ax
350         orw     $1, %ax                         /* return carry -- function not supported */
351 gs      movw    %ax, OFFS_FLAGS(%bp)
352         movw    $-1, %ax
353         ret
354
355 /*****************************************************************************/
356
357 .globl pci_last_bus
358 pci_last_bus:
359         .byte   0
360
361 #ifdef PCI_BIOS_DEBUG
362 .globl num_pci_bios_present
363 num_pci_bios_present:
364         .long   0
365
366 .globl num_pci_bios_find_device
367 num_pci_bios_find_device:
368         .long   0
369
370 .globl num_pci_bios_find_class
371 num_pci_bios_find_class:
372         .long   0
373
374 .globl num_pci_bios_generate_special_cycle
375 num_pci_bios_generate_special_cycle:
376         .long 0
377
378 .globl num_pci_bios_read_cfg_byte
379 num_pci_bios_read_cfg_byte:
380         .long   0
381
382 .globl num_pci_bios_read_cfg_word
383 num_pci_bios_read_cfg_word:
384         .long   0
385
386 .globl num_pci_bios_read_cfg_dword
387 num_pci_bios_read_cfg_dword:
388         .long   0
389
390 .globl num_pci_bios_write_cfg_byte
391 num_pci_bios_write_cfg_byte:
392         .long   0
393
394 .globl num_pci_bios_write_cfg_word
395 num_pci_bios_write_cfg_word:
396         .long   0
397
398 .globl num_pci_bios_write_cfg_dword
399 num_pci_bios_write_cfg_dword:
400         .long   0
401
402 .globl num_pci_bios_get_irq_routing
403 num_pci_bios_get_irq_routing:
404         .long   0
405
406 .globl num_pci_bios_set_irq
407 num_pci_bios_set_irq:
408         .long   0
409
410 .globl num_pci_bios_unknown_function
411 num_pci_bios_unknown_function:
412         .long   0
413 #endif