3 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
5 * See file CREDITS for list of people who contributed to this
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.
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.
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,
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)
32 #define PCI_BIOS_DEBUG
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:
41 call realmode_pci_bios
46 .globl realmode_pci_bios
48 gs movw OFFS_AX(%bp), %ax
52 je pci_bios_find_device
54 je pci_bios_find_class
56 je pci_bios_generate_special_cycle
58 je pci_bios_read_cfg_byte
60 je pci_bios_read_cfg_word
62 je pci_bios_read_cfg_dword
64 je pci_bios_write_cfg_byte
66 je pci_bios_write_cfg_word
68 je pci_bios_write_cfg_dword
70 je pci_bios_get_irq_routing
75 /*****************************************************************************/
79 cs incl num_pci_bios_present
81 movl $0x20494350, %eax
82 gs movl %eax, OFFS_EDX(%bp)
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)
91 /*****************************************************************************/
93 /* device 0-31, function 0-7 */
96 cs incl num_pci_bios_find_device
98 gs movw OFFS_CX(%bp), %di
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 */
105 xorw %ax, %ax /* dword 0 is vendor/device */
106 call __pci_bios_select_register
109 cmpl %edi, %eax /* our device ? */
112 /* check for multi function devices */
115 jnz pfd_function_not_zero
117 call __pci_bios_select_register
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 */
127 pfd_not_multi_function:
128 andw $0xfff8, %bx /* remove function bits */
129 addw $0x0008, %bx /* next device, overflows in to bus number */
131 cs movb pci_last_bus, %ah
141 gs movw %bx, OFFS_BX(%bp)
145 movb $0x86, %ah /* device not found */
148 /*****************************************************************************/
151 #ifdef PCI_BIOS_DEBUG
152 cs incl num_pci_bios_find_class
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 */
159 movw $8, %ax /* dword 8 is class-code high 24bits */
160 call __pci_bios_select_register
164 andl $0x00ffffff, %eax
165 cmpl %edi, %eax /* our device ? */
168 /* check for multi function devices */
170 jnz pfc_function_not_zero
172 call __pci_bios_select_register
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 */
182 pfc_not_multi_function:
183 andw $0xfff8, %bx /* remove function bits */
184 addw $0x0008, %bx /* next device, overflows in to bus number */
186 cs movb pci_last_bus, %ah
196 gs movw %bx, OFFS_BX(%bp)
200 movb $0x86, %ah /* device not found */
203 /*****************************************************************************/
205 pci_bios_generate_special_cycle:
206 #ifdef PCI_BIOS_DEBUG
207 cs incl num_pci_bios_generate_special_cycle
209 movb $0x81, %ah /* function not supported */
212 /*****************************************************************************/
214 pci_bios_read_cfg_byte:
215 #ifdef PCI_BIOS_DEBUG
216 cs incl num_pci_bios_read_cfg_byte
218 call pci_bios_select_register
219 gs movw OFFS_DI(%bp), %dx
223 gs movb %al, OFFS_CL(%bp)
226 /*****************************************************************************/
228 pci_bios_read_cfg_word:
229 #ifdef PCI_BIOS_DEBUG
230 cs incl num_pci_bios_read_cfg_word
232 call pci_bios_select_register
233 gs movw OFFS_DI(%bp), %dx
237 gs movw %ax, OFFS_CX(%bp)
241 /*****************************************************************************/
243 pci_bios_read_cfg_dword:
244 #ifdef PCI_BIOS_DEBUG
245 cs incl num_pci_bios_read_cfg_dword
247 call pci_bios_select_register
250 gs movl %eax, OFFS_ECX(%bp)
253 /*****************************************************************************/
255 pci_bios_write_cfg_byte:
256 #ifdef PCI_BIOS_DEBUG
257 cs incl num_pci_bios_write_cfg_byte
259 call pci_bios_select_register
260 gs movw OFFS_DI(%bp), %dx
261 gs movb OFFS_CL(%bp), %al
267 /*****************************************************************************/
269 pci_bios_write_cfg_word:
270 #ifdef PCI_BIOS_DEBUG
271 cs incl num_pci_bios_write_cfg_word
273 call pci_bios_select_register
274 gs movw OFFS_DI(%bp), %dx
275 gs movw OFFS_CX(%bp), %ax
281 /*****************************************************************************/
283 pci_bios_write_cfg_dword:
284 #ifdef PCI_BIOS_DEBUG
285 cs incl num_pci_bios_write_cfg_dword
287 call pci_bios_select_register
288 gs movl OFFS_ECX(%bp), %eax
293 /*****************************************************************************/
295 pci_bios_get_irq_routing:
296 #ifdef PCI_BIOS_DEBUG
297 cs incl num_pci_bios_get_irq_routing
299 movb $0x81, %ah /* function not supported */
302 /*****************************************************************************/
305 #ifdef PCI_BIOS_DEBUG
306 cs incl num_pci_bios_set_irq
308 movb $0x81, %ah /* function not supported */
311 /*****************************************************************************/
314 #ifdef PCI_BIOS_DEBUG
315 cs incl num_pci_bios_unknown_function
317 movb $0x81, %ah /* function not supported */
320 /*****************************************************************************/
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 */
332 orl $0x80000000, %eax
340 gs movw OFFS_FLAGS(%bp), %ax
341 andw $0xfffe, %ax /* clear carry -- function succeeded */
342 gs movw %ax, OFFS_FLAGS(%bp)
344 gs movb %ah, OFFS_AH(%bp)
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)
355 /*****************************************************************************/
361 #ifdef PCI_BIOS_DEBUG
362 .globl num_pci_bios_present
363 num_pci_bios_present:
366 .globl num_pci_bios_find_device
367 num_pci_bios_find_device:
370 .globl num_pci_bios_find_class
371 num_pci_bios_find_class:
374 .globl num_pci_bios_generate_special_cycle
375 num_pci_bios_generate_special_cycle:
378 .globl num_pci_bios_read_cfg_byte
379 num_pci_bios_read_cfg_byte:
382 .globl num_pci_bios_read_cfg_word
383 num_pci_bios_read_cfg_word:
386 .globl num_pci_bios_read_cfg_dword
387 num_pci_bios_read_cfg_dword:
390 .globl num_pci_bios_write_cfg_byte
391 num_pci_bios_write_cfg_byte:
394 .globl num_pci_bios_write_cfg_word
395 num_pci_bios_write_cfg_word:
398 .globl num_pci_bios_write_cfg_dword
399 num_pci_bios_write_cfg_dword:
402 .globl num_pci_bios_get_irq_routing
403 num_pci_bios_get_irq_routing:
406 .globl num_pci_bios_set_irq
407 num_pci_bios_set_irq:
410 .globl num_pci_bios_unknown_function
411 num_pci_bios_unknown_function: