uboot/arch/i386/lib/bios_pci.S
<<
>>
Prefs
   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