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 39realmode_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 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 74 75/*****************************************************************************/ 76 77pci_bios_present: 78#ifdef PCI_BIOS_DEBUG 79cs incl num_pci_bios_present 80#endif 81 movl $0x20494350, %eax 82gs movl %eax, OFFS_EDX(%bp) 83 movb $0x01, %al 84gs movb %al, OFFS_AL(%bp) /* We support cfg type 1 */ 85 movw $0x0210, %ax /* version 2.10 */ 86gs movw %ax, OFFS_BX(%bp) 87cs movb pci_last_bus, %al /* last bus number */ 88gs movb %al, OFFS_CL(%bp) 89 jmp clear_carry 90 91/*****************************************************************************/ 92 93/* device 0-31, function 0-7 */ 94pci_bios_find_device: 95#ifdef PCI_BIOS_DEBUG 96cs incl num_pci_bios_find_device 97#endif 98gs movw OFFS_CX(%bp), %di 99 shll $16, %edi 100gs movw OFFS_DX(%bp), %di /* edi now holds device in upper 16 101 * bits and vendor in lower 16 bits */ 102gs movw OFFS_SI(%bp), %si 103 xorw %bx, %bx /* start at bus 0 dev 0 function 0 */ 104pfd_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 111pfd_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 122pfd_function_not_zero: 123 incw %bx /* next function, overflows in to 124 * device number, then bus number */ 125 jmp pfd_check_bus 126 127pfd_not_multi_function: 128 andw $0xfff8, %bx /* remove function bits */ 129 addw $0x0008, %bx /* next device, overflows in to bus number */ 130pfd_check_bus: 131cs movb pci_last_bus, %ah 132 cmpb %ah, %bh 133 ja pfd_not_found 134 jmp pfd_loop 135pfd_found_one: 136 decw %si 137 js pfd_done 138 jmp pfd_next_dev 139 140pfd_done: 141gs movw %bx, OFFS_BX(%bp) 142 jmp clear_carry 143 144pfd_not_found: 145 movb $0x86, %ah /* device not found */ 146 jmp set_carry 147 148/*****************************************************************************/ 149 150pci_bios_find_class: 151#ifdef PCI_BIOS_DEBUG 152cs incl num_pci_bios_find_class 153#endif 154gs movl OFFS_ECX(%bp), %edi 155 andl $0x00ffffff, %edi /* edi now holds class-code in lower 24 bits */ 156gs movw OFFS_SI(%bp), %si 157 xorw %bx, %bx /* start at bus 0 dev 0 function 0 */ 158pfc_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 167pfc_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 177pfc_function_not_zero: 178 incw %bx /* next function, overflows in to 179 * device number, then bus number */ 180 jmp pfc_check_bus 181 182pfc_not_multi_function: 183 andw $0xfff8, %bx /* remove function bits */ 184 addw $0x0008, %bx /* next device, overflows in to bus number */ 185pfc_check_bus: 186cs movb pci_last_bus, %ah 187 cmpb %ah, %bh 188 ja pfc_not_found 189 jmp pfc_loop 190pfc_found_one: 191 decw %si 192 js pfc_done 193 jmp pfc_next_dev 194 195pfc_done: 196gs movw %bx, OFFS_BX(%bp) 197 jmp clear_carry 198 199pfc_not_found: 200 movb $0x86, %ah /* device not found */ 201 jmp set_carry 202 203/*****************************************************************************/ 204 205pci_bios_generate_special_cycle: 206#ifdef PCI_BIOS_DEBUG 207cs incl num_pci_bios_generate_special_cycle 208#endif 209 movb $0x81, %ah /* function not supported */ 210 jmp set_carry 211 212/*****************************************************************************/ 213 214pci_bios_read_cfg_byte: 215#ifdef PCI_BIOS_DEBUG 216cs incl num_pci_bios_read_cfg_byte 217#endif 218 call pci_bios_select_register 219gs movw OFFS_DI(%bp), %dx 220 andw $3, %dx 221 addw $0xcfc, %dx 222 inb %dx, %al 223gs movb %al, OFFS_CL(%bp) 224 jmp clear_carry 225 226/*****************************************************************************/ 227 228pci_bios_read_cfg_word: 229#ifdef PCI_BIOS_DEBUG 230cs incl num_pci_bios_read_cfg_word 231#endif 232 call pci_bios_select_register 233gs movw OFFS_DI(%bp), %dx 234 andw $2, %dx 235 addw $0xcfc, %dx 236 inw %dx, %ax 237gs movw %ax, OFFS_CX(%bp) 238 jmp clear_carry 239 240 241/*****************************************************************************/ 242 243pci_bios_read_cfg_dword: 244#ifdef PCI_BIOS_DEBUG 245cs incl num_pci_bios_read_cfg_dword 246#endif 247 call pci_bios_select_register 248 movw $0xcfc, %dx 249 inl %dx, %eax 250gs movl %eax, OFFS_ECX(%bp) 251 jmp clear_carry 252 253/*****************************************************************************/ 254 255pci_bios_write_cfg_byte: 256#ifdef PCI_BIOS_DEBUG 257cs incl num_pci_bios_write_cfg_byte 258#endif 259 call pci_bios_select_register 260gs movw OFFS_DI(%bp), %dx 261gs movb OFFS_CL(%bp), %al 262 andw $3, %dx 263 addw $0xcfc, %dx 264 outb %al, %dx 265 jmp clear_carry 266 267/*****************************************************************************/ 268 269pci_bios_write_cfg_word: 270#ifdef PCI_BIOS_DEBUG 271cs incl num_pci_bios_write_cfg_word 272#endif 273 call pci_bios_select_register 274gs movw OFFS_DI(%bp), %dx 275gs movw OFFS_CX(%bp), %ax 276 andw $2, %dx 277 addw $0xcfc, %dx 278 outw %ax, %dx 279 jmp clear_carry 280 281/*****************************************************************************/ 282 283pci_bios_write_cfg_dword: 284#ifdef PCI_BIOS_DEBUG 285cs incl num_pci_bios_write_cfg_dword 286#endif 287 call pci_bios_select_register 288gs movl OFFS_ECX(%bp), %eax 289 movw $0xcfc, %dx 290 outl %eax, %dx 291 jmp clear_carry 292 293/*****************************************************************************/ 294 295pci_bios_get_irq_routing: 296#ifdef PCI_BIOS_DEBUG 297cs incl num_pci_bios_get_irq_routing 298#endif 299 movb $0x81, %ah /* function not supported */ 300 jmp set_carry 301 302/*****************************************************************************/ 303 304pci_bios_set_irq: 305#ifdef PCI_BIOS_DEBUG 306cs incl num_pci_bios_set_irq 307#endif 308 movb $0x81, %ah /* function not supported */ 309 jmp set_carry 310 311/*****************************************************************************/ 312 313unknown_function: 314#ifdef PCI_BIOS_DEBUG 315cs incl num_pci_bios_unknown_function 316#endif 317 movb $0x81, %ah /* function not supported */ 318 jmp set_carry 319 320/*****************************************************************************/ 321 322pci_bios_select_register: 323gs movw OFFS_BX(%bp), %bx 324gs 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 339clear_carry: 340gs movw OFFS_FLAGS(%bp), %ax 341 andw $0xfffe, %ax /* clear carry -- function succeeded */ 342gs movw %ax, OFFS_FLAGS(%bp) 343 xorw %ax, %ax 344gs movb %ah, OFFS_AH(%bp) 345 ret 346 347set_carry: 348gs movb %ah, OFFS_AH(%bp) 349gs movw OFFS_FLAGS(%bp), %ax 350 orw $1, %ax /* return carry -- function not supported */ 351gs movw %ax, OFFS_FLAGS(%bp) 352 movw $-1, %ax 353 ret 354 355/*****************************************************************************/ 356 357.globl pci_last_bus 358pci_last_bus: 359 .byte 0 360 361#ifdef PCI_BIOS_DEBUG 362.globl num_pci_bios_present 363num_pci_bios_present: 364 .long 0 365 366.globl num_pci_bios_find_device 367num_pci_bios_find_device: 368 .long 0 369 370.globl num_pci_bios_find_class 371num_pci_bios_find_class: 372 .long 0 373 374.globl num_pci_bios_generate_special_cycle 375num_pci_bios_generate_special_cycle: 376 .long 0 377 378.globl num_pci_bios_read_cfg_byte 379num_pci_bios_read_cfg_byte: 380 .long 0 381 382.globl num_pci_bios_read_cfg_word 383num_pci_bios_read_cfg_word: 384 .long 0 385 386.globl num_pci_bios_read_cfg_dword 387num_pci_bios_read_cfg_dword: 388 .long 0 389 390.globl num_pci_bios_write_cfg_byte 391num_pci_bios_write_cfg_byte: 392 .long 0 393 394.globl num_pci_bios_write_cfg_word 395num_pci_bios_write_cfg_word: 396 .long 0 397 398.globl num_pci_bios_write_cfg_dword 399num_pci_bios_write_cfg_dword: 400 .long 0 401 402.globl num_pci_bios_get_irq_routing 403num_pci_bios_get_irq_routing: 404 .long 0 405 406.globl num_pci_bios_set_irq 407num_pci_bios_set_irq: 408 .long 0 409 410.globl num_pci_bios_unknown_function 411num_pci_bios_unknown_function: 412 .long 0 413#endif 414