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 realmode_pci_bios_call_entry:
39 call realmode_pci_bios
44 .globl realmode_pci_bios
46 gs movw OFFS_AX(%bp), %ax
50 je pci_bios_find_device
52 je pci_bios_find_class
54 je pci_bios_generate_special_cycle
56 je pci_bios_read_cfg_byte
58 je pci_bios_read_cfg_word
60 je pci_bios_read_cfg_dword
62 je pci_bios_write_cfg_byte
64 je pci_bios_write_cfg_word
66 je pci_bios_write_cfg_dword
68 je pci_bios_get_irq_routing
73 /*****************************************************************************/
77 cs incl num_pci_bios_present
79 movl $0x20494350, %eax
80 gs movl %eax, OFFS_EDX(%bp)
82 gs movb %al, OFFS_AL(%bp) /* We support cfg type 1 */
83 movw $0x0210, %ax /* version 2.10 */
84 gs movw %ax, OFFS_BX(%bp)
85 cs movb pci_last_bus, %al /* last bus number */
86 gs movb %al, OFFS_CL(%bp)
89 /*****************************************************************************/
91 /* device 0-31, function 0-7 */
94 cs incl num_pci_bios_find_device
96 gs movw OFFS_CX(%bp), %di
98 gs movw OFFS_DX(%bp), %di /* edi now holds device in upper 16
99 * bits and vendor in lower 16 bits */
100 gs movw OFFS_SI(%bp), %si
101 xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
103 xorw %ax, %ax /* dword 0 is vendor/device */
104 call __pci_bios_select_register
107 cmpl %edi, %eax /* our device ? */
110 /* check for multi function devices */
113 jnz pfd_function_not_zero
115 call __pci_bios_select_register
119 jz pfd_not_multi_function
120 pfd_function_not_zero:
121 incw %bx /* next function, overflows in to
122 * device number, then bus number */
125 pfd_not_multi_function:
126 andw $0xfff8, %bx /* remove function bits */
127 addw $0x0008, %bx /* next device, overflows in to bus number */
129 cs movb pci_last_bus, %ah
139 gs movw %bx, OFFS_BX(%bp)
143 movb $0x86, %ah /* device not found */
146 /*****************************************************************************/
149 #ifdef PCI_BIOS_DEBUG
150 cs incl num_pci_bios_find_class
152 gs movl OFFS_ECX(%bp), %edi
153 andl $0x00ffffff, %edi /* edi now holds class-code in lower 24 bits */
154 gs movw OFFS_SI(%bp), %si
155 xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
157 movw $8, %ax /* dword 8 is class-code high 24bits */
158 call __pci_bios_select_register
162 andl $0x00ffffff, %eax
163 cmpl %edi, %eax /* our device ? */
166 /* check for multi function devices */
168 jnz pfc_function_not_zero
170 call __pci_bios_select_register
174 jz pfc_not_multi_function
175 pfc_function_not_zero:
176 incw %bx /* next function, overflows in to
177 * device number, then bus number */
180 pfc_not_multi_function:
181 andw $0xfff8, %bx /* remove function bits */
182 addw $0x0008, %bx /* next device, overflows in to bus number */
184 cs movb pci_last_bus, %ah
194 gs movw %bx, OFFS_BX(%bp)
198 movb $0x86, %ah /* device not found */
201 /*****************************************************************************/
203 pci_bios_generate_special_cycle:
204 #ifdef PCI_BIOS_DEBUG
205 cs incl num_pci_bios_generate_special_cycle
207 movb $0x81, %ah /* function not supported */
210 /*****************************************************************************/
212 pci_bios_read_cfg_byte:
213 #ifdef PCI_BIOS_DEBUG
214 cs incl num_pci_bios_read_cfg_byte
216 call pci_bios_select_register
217 gs movw OFFS_DI(%bp), %dx
221 gs movb %al, OFFS_CL(%bp)
224 /*****************************************************************************/
226 pci_bios_read_cfg_word:
227 #ifdef PCI_BIOS_DEBUG
228 cs incl num_pci_bios_read_cfg_word
230 call pci_bios_select_register
231 gs movw OFFS_DI(%bp), %dx
235 gs movw %ax, OFFS_CX(%bp)
239 /*****************************************************************************/
241 pci_bios_read_cfg_dword:
242 #ifdef PCI_BIOS_DEBUG
243 cs incl num_pci_bios_read_cfg_dword
245 call pci_bios_select_register
248 gs movl %eax, OFFS_ECX(%bp)
251 /*****************************************************************************/
253 pci_bios_write_cfg_byte:
254 #ifdef PCI_BIOS_DEBUG
255 cs incl num_pci_bios_write_cfg_byte
257 call pci_bios_select_register
258 gs movw OFFS_DI(%bp), %dx
259 gs movb OFFS_CL(%bp), %al
265 /*****************************************************************************/
267 pci_bios_write_cfg_word:
268 #ifdef PCI_BIOS_DEBUG
269 cs incl num_pci_bios_write_cfg_word
271 call pci_bios_select_register
272 gs movw OFFS_DI(%bp), %dx
273 gs movw OFFS_CX(%bp), %ax
279 /*****************************************************************************/
281 pci_bios_write_cfg_dword:
282 #ifdef PCI_BIOS_DEBUG
283 cs incl num_pci_bios_write_cfg_dword
285 call pci_bios_select_register
286 gs movl OFFS_ECX(%bp), %eax
291 /*****************************************************************************/
293 pci_bios_get_irq_routing:
294 #ifdef PCI_BIOS_DEBUG
295 cs incl num_pci_bios_get_irq_routing
297 movb $0x81, %ah /* function not supported */
300 /*****************************************************************************/
303 #ifdef PCI_BIOS_DEBUG
304 cs incl num_pci_bios_set_irq
306 movb $0x81, %ah /* function not supported */
309 /*****************************************************************************/
312 #ifdef PCI_BIOS_DEBUG
313 cs incl num_pci_bios_unknown_function
315 movb $0x81, %ah /* function not supported */
318 /*****************************************************************************/
320 pci_bios_select_register:
321 gs movw OFFS_BX(%bp), %bx
322 gs movw OFFS_DI(%bp), %ax
323 /* destroys eax, dx */
324 __pci_bios_select_register: /* BX holds device id, AX holds register index */
330 orl $0x80000000, %eax
338 gs movw OFFS_FLAGS(%bp), %ax
339 andw $0xfffe, %ax /* clear carry -- function succeeded */
340 gs movw %ax, OFFS_FLAGS(%bp)
342 gs movb %ah, OFFS_AH(%bp)
346 gs movb %ah, OFFS_AH(%bp)
347 gs movw OFFS_FLAGS(%bp), %ax
348 orw $1, %ax /* return carry -- function not supported */
349 gs movw %ax, OFFS_FLAGS(%bp)
353 /*****************************************************************************/
359 #ifdef PCI_BIOS_DEBUG
360 .globl num_pci_bios_present
361 num_pci_bios_present:
364 .globl num_pci_bios_find_device
365 num_pci_bios_find_device:
368 .globl num_pci_bios_find_class
369 num_pci_bios_find_class:
372 .globl num_pci_bios_generate_special_cycle
373 num_pci_bios_generate_special_cycle:
376 .globl num_pci_bios_read_cfg_byte
377 num_pci_bios_read_cfg_byte:
380 .globl num_pci_bios_read_cfg_word
381 num_pci_bios_read_cfg_word:
384 .globl num_pci_bios_read_cfg_dword
385 num_pci_bios_read_cfg_dword:
388 .globl num_pci_bios_write_cfg_byte
389 num_pci_bios_write_cfg_byte:
392 .globl num_pci_bios_write_cfg_word
393 num_pci_bios_write_cfg_word:
396 .globl num_pci_bios_write_cfg_dword
397 num_pci_bios_write_cfg_dword:
400 .globl num_pci_bios_get_irq_routing
401 num_pci_bios_get_irq_routing:
404 .globl num_pci_bios_set_irq
405 num_pci_bios_set_irq:
408 .globl num_pci_bios_unknown_function
409 num_pci_bios_unknown_function: