blob: 47c478b27d515b4cdb0e96fdc2f32183a03676d8 [file] [log] [blame]
wdenk7a8e9bed2003-05-31 18:35:21 +00001/*
2 * (C) Copyright 2002
Albert ARIBAUDfa82f872011-08-04 18:45:45 +02003 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
wdenk8bde7f72003-06-27 21:31:46 +00004 *
wdenk7a8e9bed2003-05-31 18:35:21 +00005 * 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
wdenk8bde7f72003-06-27 21:31:46 +000026 * for platforms that use one PCI hose and configuration
wdenk7a8e9bed2003-05-31 18:35:21 +000027 * access type 1. (The common case for low-end PC's)
28 */
wdenk8bde7f72003-06-27 21:31:46 +000029
wdenk7a8e9bed2003-05-31 18:35:21 +000030#include "bios.h"
31
32#define PCI_BIOS_DEBUG
33
34.section .bios, "ax"
35.code16
36.globl realmode_pci_bios_call_entry
Graeme Russ0fc1b492009-11-24 20:04:19 +110037.hidden realmode_pci_bios_call_entry
38.type realmode_pci_bios_call_entry, @function
wdenk7a8e9bed2003-05-31 18:35:21 +000039realmode_pci_bios_call_entry:
40 MAKE_BIOS_STACK
41 call realmode_pci_bios
42 RESTORE_CALLERS_STACK
43 ret
wdenk8bde7f72003-06-27 21:31:46 +000044
45
wdenk7a8e9bed2003-05-31 18:35:21 +000046.globl realmode_pci_bios
47realmode_pci_bios:
48gs 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
wdenk8bde7f72003-06-27 21:31:46 +000074
wdenk7a8e9bed2003-05-31 18:35:21 +000075/*****************************************************************************/
76
77pci_bios_present:
78#ifdef PCI_BIOS_DEBUG
79cs incl num_pci_bios_present
80#endif
81 movl $0x20494350, %eax
wdenk8bde7f72003-06-27 21:31:46 +000082gs movl %eax, OFFS_EDX(%bp)
Graeme Russ83088af2011-11-08 02:33:15 +000083
84 /* We support cfg type 1 version 2.10 */
wdenk7a8e9bed2003-05-31 18:35:21 +000085 movb $0x01, %al
Graeme Russ83088af2011-11-08 02:33:15 +000086gs movb %al, OFFS_AL(%bp)
87 movw $0x0210, %ax
wdenk8bde7f72003-06-27 21:31:46 +000088gs movw %ax, OFFS_BX(%bp)
Graeme Russ83088af2011-11-08 02:33:15 +000089
90 /* last bus number */
91cs movb pci_last_bus, %al
wdenk8bde7f72003-06-27 21:31:46 +000092gs movb %al, OFFS_CL(%bp)
Wolfgang Denk53677ef2008-05-20 16:00:29 +020093 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +000094
95/*****************************************************************************/
96
97/* device 0-31, function 0-7 */
wdenk8bde7f72003-06-27 21:31:46 +000098pci_bios_find_device:
wdenk7a8e9bed2003-05-31 18:35:21 +000099#ifdef PCI_BIOS_DEBUG
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200100cs incl num_pci_bios_find_device
wdenk7a8e9bed2003-05-31 18:35:21 +0000101#endif
wdenk8bde7f72003-06-27 21:31:46 +0000102gs movw OFFS_CX(%bp), %di
wdenk7a8e9bed2003-05-31 18:35:21 +0000103 shll $16, %edi
Graeme Russ83088af2011-11-08 02:33:15 +0000104gs movw OFFS_DX(%bp), %di
105 /* edi now holds device in upper 16 bits and vendor in lower 16 bits */
106
wdenk8bde7f72003-06-27 21:31:46 +0000107gs movw OFFS_SI(%bp), %si
Graeme Russ83088af2011-11-08 02:33:15 +0000108
109 /* start at bus 0 dev 0 function 0 */
110 xorw %bx, %bx
wdenk8bde7f72003-06-27 21:31:46 +0000111pfd_loop:
Graeme Russ83088af2011-11-08 02:33:15 +0000112 /* dword 0 is vendor/device */
113 xorw %ax, %ax
wdenk8bde7f72003-06-27 21:31:46 +0000114 call __pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000115 movw $0xcfc, %dx
116 inl %dx, %eax
Graeme Russ83088af2011-11-08 02:33:15 +0000117
118 /* our device ? */
119 cmpl %edi, %eax
wdenk7a8e9bed2003-05-31 18:35:21 +0000120 je pfd_found_one
121pfd_next_dev:
122 /* check for multi function devices */
123 movw %bx, %ax
124 andw $3, %ax
125 jnz pfd_function_not_zero
wdenk8bde7f72003-06-27 21:31:46 +0000126 movw $0x000c, %ax
127 call __pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000128 movw $0xcfe, %dx
129 inb %dx, %al
130 andb $0x80, %al
131 jz pfd_not_multi_function
132pfd_function_not_zero:
Graeme Russ83088af2011-11-08 02:33:15 +0000133 /* next function, overflows in to device number, then bus number */
134 incw %bx
wdenk7a8e9bed2003-05-31 18:35:21 +0000135 jmp pfd_check_bus
wdenk8bde7f72003-06-27 21:31:46 +0000136
wdenk7a8e9bed2003-05-31 18:35:21 +0000137pfd_not_multi_function:
Graeme Russ83088af2011-11-08 02:33:15 +0000138 /* remove function bits */
139 andw $0xfff8, %bx
140
141 /* next device, overflows in to bus number */
142 addw $0x0008, %bx
wdenk8bde7f72003-06-27 21:31:46 +0000143pfd_check_bus:
wdenk7a8e9bed2003-05-31 18:35:21 +0000144cs movb pci_last_bus, %ah
145 cmpb %ah, %bh
146 ja pfd_not_found
147 jmp pfd_loop
148pfd_found_one:
149 decw %si
150 js pfd_done
151 jmp pfd_next_dev
152
153pfd_done:
wdenk8bde7f72003-06-27 21:31:46 +0000154gs movw %bx, OFFS_BX(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +0000155 jmp clear_carry
156
157pfd_not_found:
Graeme Russ83088af2011-11-08 02:33:15 +0000158 /* device not found */
159 movb $0x86, %ah
wdenk7a8e9bed2003-05-31 18:35:21 +0000160 jmp set_carry
161
162/*****************************************************************************/
163
164pci_bios_find_class:
165#ifdef PCI_BIOS_DEBUG
166cs incl num_pci_bios_find_class
167#endif
wdenk8bde7f72003-06-27 21:31:46 +0000168gs movl OFFS_ECX(%bp), %edi
Graeme Russ83088af2011-11-08 02:33:15 +0000169
170 /* edi now holds class-code in lower 24 bits */
171 andl $0x00ffffff, %edi
wdenk8bde7f72003-06-27 21:31:46 +0000172gs movw OFFS_SI(%bp), %si
Graeme Russ83088af2011-11-08 02:33:15 +0000173
174 /* start at bus 0 dev 0 function 0 */
175 xorw %bx, %bx
wdenk8bde7f72003-06-27 21:31:46 +0000176pfc_loop:
Graeme Russ83088af2011-11-08 02:33:15 +0000177 /* dword 8 is class-code high 24bits */
178 movw $8, %ax
wdenk8bde7f72003-06-27 21:31:46 +0000179 call __pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000180 movw $0xcfc, %dx
181 inl %dx, %eax
182 shrl $8, %eax
183 andl $0x00ffffff, %eax
Graeme Russ83088af2011-11-08 02:33:15 +0000184
185 /* our device ? */
186 cmpl %edi, %eax
wdenk7a8e9bed2003-05-31 18:35:21 +0000187 je pfc_found_one
188pfc_next_dev:
189 /* check for multi function devices */
190 andw $3, %bx
191 jnz pfc_function_not_zero
wdenk8bde7f72003-06-27 21:31:46 +0000192 movw $0x000c, %ax
193 call __pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000194 movw $0xcfe, %dx
195 inb %dx, %al
196 andb $0x80, %al
197 jz pfc_not_multi_function
198pfc_function_not_zero:
Graeme Russ83088af2011-11-08 02:33:15 +0000199 /* next function, overflows in to device number, then bus number */
200 incw %bx
wdenk7a8e9bed2003-05-31 18:35:21 +0000201 jmp pfc_check_bus
wdenk8bde7f72003-06-27 21:31:46 +0000202
wdenk7a8e9bed2003-05-31 18:35:21 +0000203pfc_not_multi_function:
Graeme Russ83088af2011-11-08 02:33:15 +0000204 /* remove function bits */
205 andw $0xfff8, %bx
206
207 /* next device, overflows in to bus number */
208 addw $0x0008, %bx
wdenk8bde7f72003-06-27 21:31:46 +0000209pfc_check_bus:
wdenk7a8e9bed2003-05-31 18:35:21 +0000210cs movb pci_last_bus, %ah
211 cmpb %ah, %bh
212 ja pfc_not_found
213 jmp pfc_loop
214pfc_found_one:
215 decw %si
216 js pfc_done
217 jmp pfc_next_dev
218
219pfc_done:
wdenk8bde7f72003-06-27 21:31:46 +0000220gs movw %bx, OFFS_BX(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +0000221 jmp clear_carry
222
223pfc_not_found:
Graeme Russ83088af2011-11-08 02:33:15 +0000224 /* device not found */
225 movb $0x86, %ah
wdenk7a8e9bed2003-05-31 18:35:21 +0000226 jmp set_carry
227
228/*****************************************************************************/
229
230pci_bios_generate_special_cycle:
231#ifdef PCI_BIOS_DEBUG
232cs incl num_pci_bios_generate_special_cycle
233#endif
Graeme Russ83088af2011-11-08 02:33:15 +0000234 /* function not supported */
235 movb $0x81, %ah
wdenk7a8e9bed2003-05-31 18:35:21 +0000236 jmp set_carry
wdenk8bde7f72003-06-27 21:31:46 +0000237
wdenk7a8e9bed2003-05-31 18:35:21 +0000238/*****************************************************************************/
239
wdenk8bde7f72003-06-27 21:31:46 +0000240pci_bios_read_cfg_byte:
wdenk7a8e9bed2003-05-31 18:35:21 +0000241#ifdef PCI_BIOS_DEBUG
242cs incl num_pci_bios_read_cfg_byte
243#endif
wdenk8bde7f72003-06-27 21:31:46 +0000244 call pci_bios_select_register
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200245gs movw OFFS_DI(%bp), %dx
wdenk7a8e9bed2003-05-31 18:35:21 +0000246 andw $3, %dx
247 addw $0xcfc, %dx
248 inb %dx, %al
wdenk8bde7f72003-06-27 21:31:46 +0000249gs movb %al, OFFS_CL(%bp)
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200250 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +0000251
252/*****************************************************************************/
253
wdenk8bde7f72003-06-27 21:31:46 +0000254pci_bios_read_cfg_word:
wdenk7a8e9bed2003-05-31 18:35:21 +0000255#ifdef PCI_BIOS_DEBUG
256cs incl num_pci_bios_read_cfg_word
257#endif
258 call pci_bios_select_register
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200259gs movw OFFS_DI(%bp), %dx
wdenk7a8e9bed2003-05-31 18:35:21 +0000260 andw $2, %dx
261 addw $0xcfc, %dx
262 inw %dx, %ax
wdenk8bde7f72003-06-27 21:31:46 +0000263gs movw %ax, OFFS_CX(%bp)
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200264 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +0000265
266
267/*****************************************************************************/
268
wdenk8bde7f72003-06-27 21:31:46 +0000269pci_bios_read_cfg_dword:
wdenk7a8e9bed2003-05-31 18:35:21 +0000270#ifdef PCI_BIOS_DEBUG
271cs incl num_pci_bios_read_cfg_dword
272#endif
273 call pci_bios_select_register
274 movw $0xcfc, %dx
275 inl %dx, %eax
wdenk8bde7f72003-06-27 21:31:46 +0000276gs movl %eax, OFFS_ECX(%bp)
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200277 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +0000278
279/*****************************************************************************/
280
281pci_bios_write_cfg_byte:
282#ifdef PCI_BIOS_DEBUG
283cs incl num_pci_bios_write_cfg_byte
284#endif
wdenk8bde7f72003-06-27 21:31:46 +0000285 call pci_bios_select_register
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200286gs movw OFFS_DI(%bp), %dx
wdenk7a8e9bed2003-05-31 18:35:21 +0000287gs movb OFFS_CL(%bp), %al
288 andw $3, %dx
289 addw $0xcfc, %dx
290 outb %al, %dx
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200291 jmp clear_carry
wdenk8bde7f72003-06-27 21:31:46 +0000292
wdenk7a8e9bed2003-05-31 18:35:21 +0000293/*****************************************************************************/
294
295pci_bios_write_cfg_word:
296#ifdef PCI_BIOS_DEBUG
297cs incl num_pci_bios_write_cfg_word
298#endif
wdenk8bde7f72003-06-27 21:31:46 +0000299 call pci_bios_select_register
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200300gs movw OFFS_DI(%bp), %dx
wdenk7a8e9bed2003-05-31 18:35:21 +0000301gs movw OFFS_CX(%bp), %ax
302 andw $2, %dx
303 addw $0xcfc, %dx
304 outw %ax, %dx
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200305 jmp clear_carry
wdenk8bde7f72003-06-27 21:31:46 +0000306
wdenk7a8e9bed2003-05-31 18:35:21 +0000307/*****************************************************************************/
308
309pci_bios_write_cfg_dword:
310#ifdef PCI_BIOS_DEBUG
311cs incl num_pci_bios_write_cfg_dword
312#endif
wdenk8bde7f72003-06-27 21:31:46 +0000313 call pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000314gs movl OFFS_ECX(%bp), %eax
315 movw $0xcfc, %dx
316 outl %eax, %dx
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200317 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +0000318
319/*****************************************************************************/
320
321pci_bios_get_irq_routing:
322#ifdef PCI_BIOS_DEBUG
323cs incl num_pci_bios_get_irq_routing
324#endif
Graeme Russ83088af2011-11-08 02:33:15 +0000325 /* function not supported */
326 movb $0x81, %ah
wdenk7a8e9bed2003-05-31 18:35:21 +0000327 jmp set_carry
wdenk8bde7f72003-06-27 21:31:46 +0000328
wdenk7a8e9bed2003-05-31 18:35:21 +0000329/*****************************************************************************/
330
331pci_bios_set_irq:
332#ifdef PCI_BIOS_DEBUG
333cs incl num_pci_bios_set_irq
334#endif
Graeme Russ83088af2011-11-08 02:33:15 +0000335 /* function not supported */
336 movb $0x81, %ah
wdenk7a8e9bed2003-05-31 18:35:21 +0000337 jmp set_carry
338
339/*****************************************************************************/
340
341unknown_function:
342#ifdef PCI_BIOS_DEBUG
343cs incl num_pci_bios_unknown_function
344#endif
Graeme Russ83088af2011-11-08 02:33:15 +0000345 /* function not supported */
346 movb $0x81, %ah
wdenk7a8e9bed2003-05-31 18:35:21 +0000347 jmp set_carry
348
349/*****************************************************************************/
wdenk8bde7f72003-06-27 21:31:46 +0000350
wdenk7a8e9bed2003-05-31 18:35:21 +0000351pci_bios_select_register:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200352gs movw OFFS_BX(%bp), %bx
353gs movw OFFS_DI(%bp), %ax
wdenk7a8e9bed2003-05-31 18:35:21 +0000354/* destroys eax, dx */
Graeme Russ83088af2011-11-08 02:33:15 +0000355__pci_bios_select_register:
356 /* BX holds device id, AX holds register index */
wdenk7a8e9bed2003-05-31 18:35:21 +0000357 pushl %ebx
358 andl $0xfc, %eax
359 andl $0xffff, %ebx
360 shll $8, %ebx
361 orl %ebx, %eax
362 orl $0x80000000, %eax
363 movw $0xcf8, %dx
364 outl %eax, %dx
365 popl %ebx
366 ret
367
368
369clear_carry:
370gs movw OFFS_FLAGS(%bp), %ax
Graeme Russ83088af2011-11-08 02:33:15 +0000371
372 /* clear carry -- function succeeded */
373 andw $0xfffe, %ax
wdenk7a8e9bed2003-05-31 18:35:21 +0000374gs movw %ax, OFFS_FLAGS(%bp)
375 xorw %ax, %ax
wdenk8bde7f72003-06-27 21:31:46 +0000376gs movb %ah, OFFS_AH(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +0000377 ret
378
379set_carry:
wdenk8bde7f72003-06-27 21:31:46 +0000380gs movb %ah, OFFS_AH(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +0000381gs movw OFFS_FLAGS(%bp), %ax
Graeme Russ83088af2011-11-08 02:33:15 +0000382
383 /* return carry -- function not supported */
384 orw $1, %ax
wdenk7a8e9bed2003-05-31 18:35:21 +0000385gs movw %ax, OFFS_FLAGS(%bp)
386 movw $-1, %ax
387 ret
388
389/*****************************************************************************/
390
391.globl pci_last_bus
392pci_last_bus:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200393 .byte 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000394
395#ifdef PCI_BIOS_DEBUG
396.globl num_pci_bios_present
397num_pci_bios_present:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200398 .long 0
wdenk8bde7f72003-06-27 21:31:46 +0000399
wdenk7a8e9bed2003-05-31 18:35:21 +0000400.globl num_pci_bios_find_device
401num_pci_bios_find_device:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200402 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000403
404.globl num_pci_bios_find_class
405num_pci_bios_find_class:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200406 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000407
408.globl num_pci_bios_generate_special_cycle
wdenk8bde7f72003-06-27 21:31:46 +0000409num_pci_bios_generate_special_cycle:
wdenk7a8e9bed2003-05-31 18:35:21 +0000410 .long 0
wdenk8bde7f72003-06-27 21:31:46 +0000411
wdenk7a8e9bed2003-05-31 18:35:21 +0000412.globl num_pci_bios_read_cfg_byte
413num_pci_bios_read_cfg_byte:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200414 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000415
416.globl num_pci_bios_read_cfg_word
417num_pci_bios_read_cfg_word:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200418 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000419
420.globl num_pci_bios_read_cfg_dword
421num_pci_bios_read_cfg_dword:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200422 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000423
424.globl num_pci_bios_write_cfg_byte
425num_pci_bios_write_cfg_byte:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200426 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000427
428.globl num_pci_bios_write_cfg_word
429num_pci_bios_write_cfg_word:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200430 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000431
432.globl num_pci_bios_write_cfg_dword
433num_pci_bios_write_cfg_dword:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200434 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000435
436.globl num_pci_bios_get_irq_routing
437num_pci_bios_get_irq_routing:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200438 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000439
440.globl num_pci_bios_set_irq
441num_pci_bios_set_irq:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200442 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000443
444.globl num_pci_bios_unknown_function
445num_pci_bios_unknown_function:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200446 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000447#endif