OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [i386/] [kernel/] [bios32.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 * bios32.c - BIOS32, PCI BIOS functions.
 * bios32.c - BIOS32, PCI BIOS functions.
 *
 *
 * $Id: bios32.c,v 1.1 2005-12-20 09:42:23 jcastillo Exp $
 * $Id: bios32.c,v 1.1 2005-12-20 09:42:23 jcastillo Exp $
 *
 *
 * Sponsored by
 * Sponsored by
 *      iX Multiuser Multitasking Magazine
 *      iX Multiuser Multitasking Magazine
 *      Hannover, Germany
 *      Hannover, Germany
 *      hm@ix.de
 *      hm@ix.de
 *
 *
 * Copyright 1993, 1994 Drew Eckhardt
 * Copyright 1993, 1994 Drew Eckhardt
 *      Visionary Computing
 *      Visionary Computing
 *      (Unix and Linux consulting and custom programming)
 *      (Unix and Linux consulting and custom programming)
 *      Drew@Colorado.EDU
 *      Drew@Colorado.EDU
 *      +1 (303) 786-7975
 *      +1 (303) 786-7975
 *
 *
 * For more information, please consult
 * For more information, please consult
 *
 *
 * PCI BIOS Specification Revision
 * PCI BIOS Specification Revision
 * PCI Local Bus Specification
 * PCI Local Bus Specification
 * PCI System Design Guide
 * PCI System Design Guide
 *
 *
 * PCI Special Interest Group
 * PCI Special Interest Group
 * M/S HF3-15A
 * M/S HF3-15A
 * 5200 N.E. Elam Young Parkway
 * 5200 N.E. Elam Young Parkway
 * Hillsboro, Oregon 97124-6497
 * Hillsboro, Oregon 97124-6497
 * +1 (503) 696-2000
 * +1 (503) 696-2000
 * +1 (800) 433-5177
 * +1 (800) 433-5177
 *
 *
 * Manuals are $25 each or $50 for all three, plus $7 shipping
 * Manuals are $25 each or $50 for all three, plus $7 shipping
 * within the United States, $35 abroad.
 * within the United States, $35 abroad.
 *
 *
 *
 *
 * CHANGELOG :
 * CHANGELOG :
 * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
 * Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
 *      Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
 *      Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
 *
 *
 * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic
 * Jan 5,  1995 : Modified to probe PCI hardware at boot time by Frederic
 *     Potter, potter@cao-vlsi.ibp.fr
 *     Potter, potter@cao-vlsi.ibp.fr
 *
 *
 * Jan 10, 1995 : Modified to store the information about configured pci
 * Jan 10, 1995 : Modified to store the information about configured pci
 *      devices into a list, which can be accessed via /proc/pci by
 *      devices into a list, which can be accessed via /proc/pci by
 *      Curtis Varner, cvarner@cs.ucr.edu
 *      Curtis Varner, cvarner@cs.ucr.edu
 *
 *
 * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
 * Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
 *      Alpha version. Intel & UMC chipset support only.
 *      Alpha version. Intel & UMC chipset support only.
 *
 *
 * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
 * Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
 *      moved to drivers/pci/pci.c.
 *      moved to drivers/pci/pci.c.
 *
 *
 * Dec 7, 1996  : Added support for direct configuration access of boards
 * Dec 7, 1996  : Added support for direct configuration access of boards
 *      with Intel compatible access schemes (tsbogend@alpha.franken.de)
 *      with Intel compatible access schemes (tsbogend@alpha.franken.de)
 *
 *
 * Feb 3, 1997  : Set internal functions to static, save/restore flags
 * Feb 3, 1997  : Set internal functions to static, save/restore flags
 *      avoid dead locks reading broken PCI BIOS, werner@suse.de
 *      avoid dead locks reading broken PCI BIOS, werner@suse.de
 *
 *
 * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
 * Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
 *      (mj@atrey.karlin.mff.cuni.cz)
 *      (mj@atrey.karlin.mff.cuni.cz)
 *
 *
 * May 7,  1997 : Added some missing cli()'s. [mj]
 * May 7,  1997 : Added some missing cli()'s. [mj]
 *
 *
 * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
 * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
 *      (paubert@iram.es)
 *      (paubert@iram.es)
 */
 */
 
 
#include <linux/config.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/bios32.h>
#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/pci.h>
 
 
#include <asm/segment.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/io.h>
 
 
#define PCIBIOS_PCI_FUNCTION_ID         0xb1XX
#define PCIBIOS_PCI_FUNCTION_ID         0xb1XX
#define PCIBIOS_PCI_BIOS_PRESENT        0xb101
#define PCIBIOS_PCI_BIOS_PRESENT        0xb101
#define PCIBIOS_FIND_PCI_DEVICE         0xb102
#define PCIBIOS_FIND_PCI_DEVICE         0xb102
#define PCIBIOS_FIND_PCI_CLASS_CODE     0xb103
#define PCIBIOS_FIND_PCI_CLASS_CODE     0xb103
#define PCIBIOS_GENERATE_SPECIAL_CYCLE  0xb106
#define PCIBIOS_GENERATE_SPECIAL_CYCLE  0xb106
#define PCIBIOS_READ_CONFIG_BYTE        0xb108
#define PCIBIOS_READ_CONFIG_BYTE        0xb108
#define PCIBIOS_READ_CONFIG_WORD        0xb109
#define PCIBIOS_READ_CONFIG_WORD        0xb109
#define PCIBIOS_READ_CONFIG_DWORD       0xb10a
#define PCIBIOS_READ_CONFIG_DWORD       0xb10a
#define PCIBIOS_WRITE_CONFIG_BYTE       0xb10b
#define PCIBIOS_WRITE_CONFIG_BYTE       0xb10b
#define PCIBIOS_WRITE_CONFIG_WORD       0xb10c
#define PCIBIOS_WRITE_CONFIG_WORD       0xb10c
#define PCIBIOS_WRITE_CONFIG_DWORD      0xb10d
#define PCIBIOS_WRITE_CONFIG_DWORD      0xb10d
 
 
 
 
/* BIOS32 signature: "_32_" */
/* BIOS32 signature: "_32_" */
#define BIOS32_SIGNATURE        (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
#define BIOS32_SIGNATURE        (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
 
 
/* PCI signature: "PCI " */
/* PCI signature: "PCI " */
#define PCI_SIGNATURE           (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
#define PCI_SIGNATURE           (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
 
 
/* PCI service signature: "$PCI" */
/* PCI service signature: "$PCI" */
#define PCI_SERVICE             (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
#define PCI_SERVICE             (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
 
 
/*
/*
 * This is the standard structure used to identify the entry point
 * This is the standard structure used to identify the entry point
 * to the BIOS32 Service Directory, as documented in
 * to the BIOS32 Service Directory, as documented in
 *      Standard BIOS 32-bit Service Directory Proposal
 *      Standard BIOS 32-bit Service Directory Proposal
 *      Revision 0.4 May 24, 1993
 *      Revision 0.4 May 24, 1993
 *      Phoenix Technologies Ltd.
 *      Phoenix Technologies Ltd.
 *      Norwood, MA
 *      Norwood, MA
 * and the PCI BIOS specification.
 * and the PCI BIOS specification.
 */
 */
 
 
union bios32 {
union bios32 {
        struct {
        struct {
                unsigned long signature;        /* _32_ */
                unsigned long signature;        /* _32_ */
                unsigned long entry;            /* 32 bit physical address */
                unsigned long entry;            /* 32 bit physical address */
                unsigned char revision;         /* Revision level, 0 */
                unsigned char revision;         /* Revision level, 0 */
                unsigned char length;           /* Length in paragraphs should be 01 */
                unsigned char length;           /* Length in paragraphs should be 01 */
                unsigned char checksum;         /* All bytes must add up to zero */
                unsigned char checksum;         /* All bytes must add up to zero */
                unsigned char reserved[5];      /* Must be zero */
                unsigned char reserved[5];      /* Must be zero */
        } fields;
        } fields;
        char chars[16];
        char chars[16];
};
};
 
 
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
/*
/*
 * Physical address of the service directory.  I don't know if we're
 * Physical address of the service directory.  I don't know if we're
 * allowed to have more than one of these or not, so just in case
 * allowed to have more than one of these or not, so just in case
 * we'll make pcibios_present() take a memory start parameter and store
 * we'll make pcibios_present() take a memory start parameter and store
 * the array there.
 * the array there.
 */
 */
 
 
static unsigned long bios32_entry = 0;
static unsigned long bios32_entry = 0;
static struct {
static struct {
        unsigned long address;
        unsigned long address;
        unsigned short segment;
        unsigned short segment;
} bios32_indirect = { 0, KERNEL_CS };
} bios32_indirect = { 0, KERNEL_CS };
 
 
 
 
/*
/*
 * function table for accessing PCI configuration space
 * function table for accessing PCI configuration space
 */
 */
struct pci_access {
struct pci_access {
    int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *);
    int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *);
    int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *);
    int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *);
    int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);
    int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);
    int (*read_config_word)(unsigned char, unsigned char, unsigned char, unsigned short *);
    int (*read_config_word)(unsigned char, unsigned char, unsigned char, unsigned short *);
    int (*read_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int *);
    int (*read_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int *);
    int (*write_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char);
    int (*write_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char);
    int (*write_config_word)(unsigned char, unsigned char, unsigned char, unsigned short);
    int (*write_config_word)(unsigned char, unsigned char, unsigned char, unsigned short);
    int (*write_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int);
    int (*write_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int);
};
};
 
 
/*
/*
 * pointer to selected PCI access function table
 * pointer to selected PCI access function table
 */
 */
static struct pci_access *access_pci = NULL;
static struct pci_access *access_pci = NULL;
 
 
 
 
 
 
/*
/*
 * Returns the entry point for the given service, NULL on error
 * Returns the entry point for the given service, NULL on error
 */
 */
 
 
static unsigned long bios32_service(unsigned long service)
static unsigned long bios32_service(unsigned long service)
{
{
        unsigned char return_code;      /* %al */
        unsigned char return_code;      /* %al */
        unsigned long address;          /* %ebx */
        unsigned long address;          /* %ebx */
        unsigned long length;           /* %ecx */
        unsigned long length;           /* %ecx */
        unsigned long entry;            /* %edx */
        unsigned long entry;            /* %edx */
        unsigned long flags;
        unsigned long flags;
 
 
        save_flags(flags); cli();
        save_flags(flags); cli();
        __asm__("lcall (%%edi)"
        __asm__("lcall (%%edi)"
                : "=a" (return_code),
                : "=a" (return_code),
                  "=b" (address),
                  "=b" (address),
                  "=c" (length),
                  "=c" (length),
                  "=d" (entry)
                  "=d" (entry)
                : "0" (service),
                : "0" (service),
                  "1" (0),
                  "1" (0),
                  "D" (&bios32_indirect));
                  "D" (&bios32_indirect));
        restore_flags(flags);
        restore_flags(flags);
 
 
        switch (return_code) {
        switch (return_code) {
                case 0:
                case 0:
                        return address + entry;
                        return address + entry;
                case 0x80:      /* Not present */
                case 0x80:      /* Not present */
                        printk("bios32_service(0x%lx) : not present\n", service);
                        printk("bios32_service(0x%lx) : not present\n", service);
                        return 0;
                        return 0;
                default: /* Shouldn't happen */
                default: /* Shouldn't happen */
                        printk("bios32_service(0x%lx) : returned 0x%x, mail drew@colorado.edu\n",
                        printk("bios32_service(0x%lx) : returned 0x%x, mail drew@colorado.edu\n",
                                service, return_code);
                                service, return_code);
                        return 0;
                        return 0;
        }
        }
}
}
 
 
static long pcibios_entry = 0;
static long pcibios_entry = 0;
static struct {
static struct {
        unsigned long address;
        unsigned long address;
        unsigned short segment;
        unsigned short segment;
} pci_indirect = { 0, KERNEL_CS };
} pci_indirect = { 0, KERNEL_CS };
 
 
 
 
static int check_pcibios(void)
static int check_pcibios(void)
{
{
        unsigned long signature;
        unsigned long signature;
        unsigned char present_status;
        unsigned char present_status;
        unsigned char major_revision;
        unsigned char major_revision;
        unsigned char minor_revision;
        unsigned char minor_revision;
        unsigned long flags;
        unsigned long flags;
        int pack;
        int pack;
 
 
        if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
        if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
                pci_indirect.address = pcibios_entry;
                pci_indirect.address = pcibios_entry;
 
 
                save_flags(flags); cli();
                save_flags(flags); cli();
                __asm__("lcall (%%edi)\n\t"
                __asm__("lcall (%%edi)\n\t"
                        "jc 1f\n\t"
                        "jc 1f\n\t"
                        "xor %%ah, %%ah\n"
                        "xor %%ah, %%ah\n"
                        "1:\tshl $8, %%eax\n\t"
                        "1:\tshl $8, %%eax\n\t"
                        "movw %%bx, %%ax"
                        "movw %%bx, %%ax"
                        : "=d" (signature),
                        : "=d" (signature),
                          "=a" (pack)
                          "=a" (pack)
                        : "1" (PCIBIOS_PCI_BIOS_PRESENT),
                        : "1" (PCIBIOS_PCI_BIOS_PRESENT),
                          "D" (&pci_indirect)
                          "D" (&pci_indirect)
                        : "bx", "cx");
                        : "bx", "cx");
                restore_flags(flags);
                restore_flags(flags);
 
 
                present_status = (pack >> 16) & 0xff;
                present_status = (pack >> 16) & 0xff;
                major_revision = (pack >> 8) & 0xff;
                major_revision = (pack >> 8) & 0xff;
                minor_revision = pack & 0xff;
                minor_revision = pack & 0xff;
                if (present_status || (signature != PCI_SIGNATURE)) {
                if (present_status || (signature != PCI_SIGNATURE)) {
                        printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
                        printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
                                "       but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
                                "       but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
                                "       and signature of 0x%08lx (%c%c%c%c).  mail drew@Colorado.EDU\n",
                                "       and signature of 0x%08lx (%c%c%c%c).  mail drew@Colorado.EDU\n",
                                (signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
                                (signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
                                present_status, signature,
                                present_status, signature,
                                (char) (signature >>  0), (char) (signature >>  8),
                                (char) (signature >>  0), (char) (signature >>  8),
                                (char) (signature >> 16), (char) (signature >> 24));
                                (char) (signature >> 16), (char) (signature >> 24));
 
 
                        if (signature != PCI_SIGNATURE)
                        if (signature != PCI_SIGNATURE)
                                pcibios_entry = 0;
                                pcibios_entry = 0;
                }
                }
                if (pcibios_entry) {
                if (pcibios_entry) {
                        printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
                        printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
                                major_revision, minor_revision, pcibios_entry);
                                major_revision, minor_revision, pcibios_entry);
                        return 1;
                        return 1;
                }
                }
        }
        }
        return 0;
        return 0;
}
}
 
 
 
 
static int pci_bios_find_class (unsigned int class_code, unsigned short index,
static int pci_bios_find_class (unsigned int class_code, unsigned short index,
        unsigned char *bus, unsigned char *device_fn)
        unsigned char *bus, unsigned char *device_fn)
{
{
        unsigned long bx;
        unsigned long bx;
        unsigned long ret;
        unsigned long ret;
        unsigned long flags;
        unsigned long flags;
 
 
        save_flags(flags); cli();
        save_flags(flags); cli();
        __asm__ ("lcall (%%edi)\n\t"
        __asm__ ("lcall (%%edi)\n\t"
                "jc 1f\n\t"
                "jc 1f\n\t"
                "xor %%ah, %%ah\n"
                "xor %%ah, %%ah\n"
                "1:"
                "1:"
                : "=b" (bx),
                : "=b" (bx),
                  "=a" (ret)
                  "=a" (ret)
                : "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
                : "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
                  "c" (class_code),
                  "c" (class_code),
                  "S" ((int) index),
                  "S" ((int) index),
                  "D" (&pci_indirect));
                  "D" (&pci_indirect));
        restore_flags(flags);
        restore_flags(flags);
        *bus = (bx >> 8) & 0xff;
        *bus = (bx >> 8) & 0xff;
        *device_fn = bx & 0xff;
        *device_fn = bx & 0xff;
        return (int) (ret & 0xff00) >> 8;
        return (int) (ret & 0xff00) >> 8;
}
}
 
 
 
 
static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
        unsigned short index, unsigned char *bus, unsigned char *device_fn)
        unsigned short index, unsigned char *bus, unsigned char *device_fn)
{
{
        unsigned short bx;
        unsigned short bx;
        unsigned short ret;
        unsigned short ret;
        unsigned long flags;
        unsigned long flags;
 
 
        save_flags(flags); cli();
        save_flags(flags); cli();
        __asm__("lcall (%%edi)\n\t"
        __asm__("lcall (%%edi)\n\t"
                "jc 1f\n\t"
                "jc 1f\n\t"
                "xor %%ah, %%ah\n"
                "xor %%ah, %%ah\n"
                "1:"
                "1:"
                : "=b" (bx),
                : "=b" (bx),
                  "=a" (ret)
                  "=a" (ret)
                : "1" (PCIBIOS_FIND_PCI_DEVICE),
                : "1" (PCIBIOS_FIND_PCI_DEVICE),
                  "c" (device_id),
                  "c" (device_id),
                  "d" (vendor),
                  "d" (vendor),
                  "S" ((int) index),
                  "S" ((int) index),
                  "D" (&pci_indirect));
                  "D" (&pci_indirect));
        restore_flags(flags);
        restore_flags(flags);
        *bus = (bx >> 8) & 0xff;
        *bus = (bx >> 8) & 0xff;
        *device_fn = bx & 0xff;
        *device_fn = bx & 0xff;
        return (int) (ret & 0xff00) >> 8;
        return (int) (ret & 0xff00) >> 8;
}
}
 
 
static int pci_bios_read_config_byte(unsigned char bus,
static int pci_bios_read_config_byte(unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char *value)
        unsigned char device_fn, unsigned char where, unsigned char *value)
{
{
        unsigned long ret;
        unsigned long ret;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long flags;
        unsigned long flags;
 
 
        save_flags(flags); cli();
        save_flags(flags); cli();
        __asm__("lcall (%%esi)\n\t"
        __asm__("lcall (%%esi)\n\t"
                "jc 1f\n\t"
                "jc 1f\n\t"
                "xor %%ah, %%ah\n"
                "xor %%ah, %%ah\n"
                "1:"
                "1:"
                : "=c" (*value),
                : "=c" (*value),
                  "=a" (ret)
                  "=a" (ret)
                : "1" (PCIBIOS_READ_CONFIG_BYTE),
                : "1" (PCIBIOS_READ_CONFIG_BYTE),
                  "b" (bx),
                  "b" (bx),
                  "D" ((long) where),
                  "D" ((long) where),
                  "S" (&pci_indirect));
                  "S" (&pci_indirect));
        restore_flags(flags);
        restore_flags(flags);
        return (int) (ret & 0xff00) >> 8;
        return (int) (ret & 0xff00) >> 8;
}
}
 
 
static int pci_bios_read_config_word (unsigned char bus,
static int pci_bios_read_config_word (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned short *value)
        unsigned char device_fn, unsigned char where, unsigned short *value)
{
{
        unsigned long ret;
        unsigned long ret;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long flags;
        unsigned long flags;
 
 
        save_flags(flags); cli();
        save_flags(flags); cli();
        __asm__("lcall (%%esi)\n\t"
        __asm__("lcall (%%esi)\n\t"
                "jc 1f\n\t"
                "jc 1f\n\t"
                "xor %%ah, %%ah\n"
                "xor %%ah, %%ah\n"
                "1:"
                "1:"
                : "=c" (*value),
                : "=c" (*value),
                  "=a" (ret)
                  "=a" (ret)
                : "1" (PCIBIOS_READ_CONFIG_WORD),
                : "1" (PCIBIOS_READ_CONFIG_WORD),
                  "b" (bx),
                  "b" (bx),
                  "D" ((long) where),
                  "D" ((long) where),
                  "S" (&pci_indirect));
                  "S" (&pci_indirect));
        restore_flags(flags);
        restore_flags(flags);
        return (int) (ret & 0xff00) >> 8;
        return (int) (ret & 0xff00) >> 8;
}
}
 
 
static int pci_bios_read_config_dword (unsigned char bus,
static int pci_bios_read_config_dword (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned int *value)
        unsigned char device_fn, unsigned char where, unsigned int *value)
{
{
        unsigned long ret;
        unsigned long ret;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long flags;
        unsigned long flags;
 
 
        save_flags(flags); cli();
        save_flags(flags); cli();
        __asm__("lcall (%%esi)\n\t"
        __asm__("lcall (%%esi)\n\t"
                "jc 1f\n\t"
                "jc 1f\n\t"
                "xor %%ah, %%ah\n"
                "xor %%ah, %%ah\n"
                "1:"
                "1:"
                : "=c" (*value),
                : "=c" (*value),
                  "=a" (ret)
                  "=a" (ret)
                : "1" (PCIBIOS_READ_CONFIG_DWORD),
                : "1" (PCIBIOS_READ_CONFIG_DWORD),
                  "b" (bx),
                  "b" (bx),
                  "D" ((long) where),
                  "D" ((long) where),
                  "S" (&pci_indirect));
                  "S" (&pci_indirect));
        restore_flags(flags);
        restore_flags(flags);
        return (int) (ret & 0xff00) >> 8;
        return (int) (ret & 0xff00) >> 8;
}
}
 
 
static int pci_bios_write_config_byte (unsigned char bus,
static int pci_bios_write_config_byte (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char value)
        unsigned char device_fn, unsigned char where, unsigned char value)
{
{
        unsigned long ret;
        unsigned long ret;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long flags;
        unsigned long flags;
 
 
        save_flags(flags); cli();
        save_flags(flags); cli();
        __asm__("lcall (%%esi)\n\t"
        __asm__("lcall (%%esi)\n\t"
                "jc 1f\n\t"
                "jc 1f\n\t"
                "xor %%ah, %%ah\n"
                "xor %%ah, %%ah\n"
                "1:"
                "1:"
                : "=a" (ret)
                : "=a" (ret)
                : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
                : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
                  "c" (value),
                  "c" (value),
                  "b" (bx),
                  "b" (bx),
                  "D" ((long) where),
                  "D" ((long) where),
                  "S" (&pci_indirect));
                  "S" (&pci_indirect));
        restore_flags(flags);
        restore_flags(flags);
        return (int) (ret & 0xff00) >> 8;
        return (int) (ret & 0xff00) >> 8;
}
}
 
 
static int pci_bios_write_config_word (unsigned char bus,
static int pci_bios_write_config_word (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned short value)
        unsigned char device_fn, unsigned char where, unsigned short value)
{
{
        unsigned long ret;
        unsigned long ret;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long flags;
        unsigned long flags;
 
 
        save_flags(flags); cli();
        save_flags(flags); cli();
        __asm__("lcall (%%esi)\n\t"
        __asm__("lcall (%%esi)\n\t"
                "jc 1f\n\t"
                "jc 1f\n\t"
                "xor %%ah, %%ah\n"
                "xor %%ah, %%ah\n"
                "1:"
                "1:"
                : "=a" (ret)
                : "=a" (ret)
                : "0" (PCIBIOS_WRITE_CONFIG_WORD),
                : "0" (PCIBIOS_WRITE_CONFIG_WORD),
                  "c" (value),
                  "c" (value),
                  "b" (bx),
                  "b" (bx),
                  "D" ((long) where),
                  "D" ((long) where),
                  "S" (&pci_indirect));
                  "S" (&pci_indirect));
        restore_flags(flags);
        restore_flags(flags);
        return (int) (ret & 0xff00) >> 8;
        return (int) (ret & 0xff00) >> 8;
}
}
 
 
static int pci_bios_write_config_dword (unsigned char bus,
static int pci_bios_write_config_dword (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned int value)
        unsigned char device_fn, unsigned char where, unsigned int value)
{
{
        unsigned long ret;
        unsigned long ret;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long bx = (bus << 8) | device_fn;
        unsigned long flags;
        unsigned long flags;
 
 
        save_flags(flags); cli();
        save_flags(flags); cli();
        __asm__("lcall (%%esi)\n\t"
        __asm__("lcall (%%esi)\n\t"
                "jc 1f\n\t"
                "jc 1f\n\t"
                "xor %%ah, %%ah\n"
                "xor %%ah, %%ah\n"
                "1:"
                "1:"
                : "=a" (ret)
                : "=a" (ret)
                : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
                : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
                  "c" (value),
                  "c" (value),
                  "b" (bx),
                  "b" (bx),
                  "D" ((long) where),
                  "D" ((long) where),
                  "S" (&pci_indirect));
                  "S" (&pci_indirect));
        restore_flags(flags);
        restore_flags(flags);
        return (int) (ret & 0xff00) >> 8;
        return (int) (ret & 0xff00) >> 8;
}
}
 
 
/*
/*
 * function table for BIOS32 access
 * function table for BIOS32 access
 */
 */
static struct pci_access pci_bios_access = {
static struct pci_access pci_bios_access = {
      pci_bios_find_device,
      pci_bios_find_device,
      pci_bios_find_class,
      pci_bios_find_class,
      pci_bios_read_config_byte,
      pci_bios_read_config_byte,
      pci_bios_read_config_word,
      pci_bios_read_config_word,
      pci_bios_read_config_dword,
      pci_bios_read_config_dword,
      pci_bios_write_config_byte,
      pci_bios_write_config_byte,
      pci_bios_write_config_word,
      pci_bios_write_config_word,
      pci_bios_write_config_dword
      pci_bios_write_config_dword
};
};
 
 
 
 
 
 
/*
/*
 * Given the vendor and device ids, find the n'th instance of that device
 * Given the vendor and device ids, find the n'th instance of that device
 * in the system.
 * in the system.
 */
 */
static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,
static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,
                           unsigned short index, unsigned char *bus,
                           unsigned short index, unsigned char *bus,
                           unsigned char *devfn)
                           unsigned char *devfn)
{
{
    unsigned int curr = 0;
    unsigned int curr = 0;
    struct pci_dev *dev;
    struct pci_dev *dev;
 
 
    for (dev = pci_devices; dev; dev = dev->next) {
    for (dev = pci_devices; dev; dev = dev->next) {
        if (dev->vendor == vendor && dev->device == device_id) {
        if (dev->vendor == vendor && dev->device == device_id) {
            if (curr == index) {
            if (curr == index) {
                *devfn = dev->devfn;
                *devfn = dev->devfn;
                *bus = dev->bus->number;
                *bus = dev->bus->number;
                return PCIBIOS_SUCCESSFUL;
                return PCIBIOS_SUCCESSFUL;
            }
            }
            ++curr;
            ++curr;
        }
        }
    }
    }
    return PCIBIOS_DEVICE_NOT_FOUND;
    return PCIBIOS_DEVICE_NOT_FOUND;
}
}
 
 
 
 
/*
/*
 * Given the class, find the n'th instance of that device
 * Given the class, find the n'th instance of that device
 * in the system.
 * in the system.
 */
 */
static int pci_direct_find_class (unsigned int class_code, unsigned short index,
static int pci_direct_find_class (unsigned int class_code, unsigned short index,
                          unsigned char *bus, unsigned char *devfn)
                          unsigned char *bus, unsigned char *devfn)
{
{
    unsigned int curr = 0;
    unsigned int curr = 0;
    struct pci_dev *dev;
    struct pci_dev *dev;
 
 
    for (dev = pci_devices; dev; dev = dev->next) {
    for (dev = pci_devices; dev; dev = dev->next) {
        if (dev->class == class_code) {
        if (dev->class == class_code) {
            if (curr == index) {
            if (curr == index) {
                *devfn = dev->devfn;
                *devfn = dev->devfn;
                *bus = dev->bus->number;
                *bus = dev->bus->number;
                return PCIBIOS_SUCCESSFUL;
                return PCIBIOS_SUCCESSFUL;
            }
            }
            ++curr;
            ++curr;
        }
        }
    }
    }
    return PCIBIOS_DEVICE_NOT_FOUND;
    return PCIBIOS_DEVICE_NOT_FOUND;
}
}
 
 
/*
/*
 * Functions for accessing PCI configuration space with type 1 accesses
 * Functions for accessing PCI configuration space with type 1 accesses
 */
 */
#define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
#define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
 
 
static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn,
static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn,
                               unsigned char where, unsigned char *value)
                               unsigned char where, unsigned char *value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    save_flags(flags); cli();
    save_flags(flags); cli();
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    *value = inb(0xCFC + (where&3));
    *value = inb(0xCFC + (where&3));
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf1_read_config_word (unsigned char bus,
static int pci_conf1_read_config_word (unsigned char bus,
    unsigned char device_fn, unsigned char where, unsigned short *value)
    unsigned char device_fn, unsigned char where, unsigned short *value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
    if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
    save_flags(flags); cli();
    save_flags(flags); cli();
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    *value = inw(0xCFC + (where&2));
    *value = inw(0xCFC + (where&2));
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf1_read_config_dword (unsigned char bus, unsigned char device_fn,
static int pci_conf1_read_config_dword (unsigned char bus, unsigned char device_fn,
                                 unsigned char where, unsigned int *value)
                                 unsigned char where, unsigned int *value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
    if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
    save_flags(flags); cli();
    save_flags(flags); cli();
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    *value = inl(0xCFC);
    *value = inl(0xCFC);
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf1_write_config_byte (unsigned char bus, unsigned char device_fn,
static int pci_conf1_write_config_byte (unsigned char bus, unsigned char device_fn,
                                 unsigned char where, unsigned char value)
                                 unsigned char where, unsigned char value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    save_flags(flags); cli();
    save_flags(flags); cli();
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    outb(value, 0xCFC + (where&3));
    outb(value, 0xCFC + (where&3));
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf1_write_config_word (unsigned char bus, unsigned char device_fn,
static int pci_conf1_write_config_word (unsigned char bus, unsigned char device_fn,
                                 unsigned char where, unsigned short value)
                                 unsigned char where, unsigned short value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
    if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
    save_flags(flags); cli();
    save_flags(flags); cli();
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    outw(value, 0xCFC + (where&2));
    outw(value, 0xCFC + (where&2));
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf1_write_config_dword (unsigned char bus, unsigned char device_fn,
static int pci_conf1_write_config_dword (unsigned char bus, unsigned char device_fn,
                                  unsigned char where, unsigned int value)
                                  unsigned char where, unsigned int value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
    if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
    save_flags(flags); cli();
    save_flags(flags); cli();
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    outl(value, 0xCFC);
    outl(value, 0xCFC);
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
#undef CONFIG_CMD
#undef CONFIG_CMD
 
 
/*
/*
 * functiontable for type 1
 * functiontable for type 1
 */
 */
static struct pci_access pci_direct_conf1 = {
static struct pci_access pci_direct_conf1 = {
      pci_direct_find_device,
      pci_direct_find_device,
      pci_direct_find_class,
      pci_direct_find_class,
      pci_conf1_read_config_byte,
      pci_conf1_read_config_byte,
      pci_conf1_read_config_word,
      pci_conf1_read_config_word,
      pci_conf1_read_config_dword,
      pci_conf1_read_config_dword,
      pci_conf1_write_config_byte,
      pci_conf1_write_config_byte,
      pci_conf1_write_config_word,
      pci_conf1_write_config_word,
      pci_conf1_write_config_dword
      pci_conf1_write_config_dword
};
};
 
 
/*
/*
 * Functions for accessing PCI configuration space with type 2 accesses
 * Functions for accessing PCI configuration space with type 2 accesses
 */
 */
#define IOADDR(devfn, where)   ((0xC000 | ((devfn & 0x78) << 5)) + where)
#define IOADDR(devfn, where)   ((0xC000 | ((devfn & 0x78) << 5)) + where)
#define FUNC(devfn)            (((devfn & 7) << 1) | 0xf0)
#define FUNC(devfn)            (((devfn & 7) << 1) | 0xf0)
 
 
static int pci_conf2_read_config_byte(unsigned char bus, unsigned char device_fn,
static int pci_conf2_read_config_byte(unsigned char bus, unsigned char device_fn,
                               unsigned char where, unsigned char *value)
                               unsigned char where, unsigned char *value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    if (device_fn & 0x80)
    if (device_fn & 0x80)
        return PCIBIOS_DEVICE_NOT_FOUND;
        return PCIBIOS_DEVICE_NOT_FOUND;
    save_flags(flags); cli();
    save_flags(flags); cli();
    outb (FUNC(device_fn), 0xCF8);
    outb (FUNC(device_fn), 0xCF8);
    outb (bus, 0xCFA);
    outb (bus, 0xCFA);
    *value = inb(IOADDR(device_fn,where));
    *value = inb(IOADDR(device_fn,where));
    outb (0, 0xCF8);
    outb (0, 0xCF8);
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf2_read_config_word (unsigned char bus, unsigned char device_fn,
static int pci_conf2_read_config_word (unsigned char bus, unsigned char device_fn,
                                unsigned char where, unsigned short *value)
                                unsigned char where, unsigned short *value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    if (device_fn & 0x80)
    if (device_fn & 0x80)
        return PCIBIOS_DEVICE_NOT_FOUND;
        return PCIBIOS_DEVICE_NOT_FOUND;
    save_flags(flags); cli();
    save_flags(flags); cli();
    outb (FUNC(device_fn), 0xCF8);
    outb (FUNC(device_fn), 0xCF8);
    outb (bus, 0xCFA);
    outb (bus, 0xCFA);
    *value = inw(IOADDR(device_fn,where));
    *value = inw(IOADDR(device_fn,where));
    outb (0, 0xCF8);
    outb (0, 0xCF8);
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf2_read_config_dword (unsigned char bus, unsigned char device_fn,
static int pci_conf2_read_config_dword (unsigned char bus, unsigned char device_fn,
                                 unsigned char where, unsigned int *value)
                                 unsigned char where, unsigned int *value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    if (device_fn & 0x80)
    if (device_fn & 0x80)
        return PCIBIOS_DEVICE_NOT_FOUND;
        return PCIBIOS_DEVICE_NOT_FOUND;
    save_flags(flags); cli();
    save_flags(flags); cli();
    outb (FUNC(device_fn), 0xCF8);
    outb (FUNC(device_fn), 0xCF8);
    outb (bus, 0xCFA);
    outb (bus, 0xCFA);
    *value = inl (IOADDR(device_fn,where));
    *value = inl (IOADDR(device_fn,where));
    outb (0, 0xCF8);
    outb (0, 0xCF8);
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf2_write_config_byte (unsigned char bus, unsigned char device_fn,
static int pci_conf2_write_config_byte (unsigned char bus, unsigned char device_fn,
                                 unsigned char where, unsigned char value)
                                 unsigned char where, unsigned char value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    save_flags(flags); cli();
    save_flags(flags); cli();
    outb (FUNC(device_fn), 0xCF8);
    outb (FUNC(device_fn), 0xCF8);
    outb (bus, 0xCFA);
    outb (bus, 0xCFA);
    outb (value, IOADDR(device_fn,where));
    outb (value, IOADDR(device_fn,where));
    outb (0, 0xCF8);
    outb (0, 0xCF8);
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf2_write_config_word (unsigned char bus, unsigned char device_fn,
static int pci_conf2_write_config_word (unsigned char bus, unsigned char device_fn,
                                 unsigned char where, unsigned short value)
                                 unsigned char where, unsigned short value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    save_flags(flags); cli();
    save_flags(flags); cli();
    outb (FUNC(device_fn), 0xCF8);
    outb (FUNC(device_fn), 0xCF8);
    outb (bus, 0xCFA);
    outb (bus, 0xCFA);
    outw (value, IOADDR(device_fn,where));
    outw (value, IOADDR(device_fn,where));
    outb (0, 0xCF8);
    outb (0, 0xCF8);
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
static int pci_conf2_write_config_dword (unsigned char bus, unsigned char device_fn,
static int pci_conf2_write_config_dword (unsigned char bus, unsigned char device_fn,
                                  unsigned char where, unsigned int value)
                                  unsigned char where, unsigned int value)
{
{
    unsigned long flags;
    unsigned long flags;
 
 
    save_flags(flags); cli();
    save_flags(flags); cli();
    outb (FUNC(device_fn), 0xCF8);
    outb (FUNC(device_fn), 0xCF8);
    outb (bus, 0xCFA);
    outb (bus, 0xCFA);
    outl (value, IOADDR(device_fn,where));
    outl (value, IOADDR(device_fn,where));
    outb (0, 0xCF8);
    outb (0, 0xCF8);
    restore_flags(flags);
    restore_flags(flags);
    return PCIBIOS_SUCCESSFUL;
    return PCIBIOS_SUCCESSFUL;
}
}
 
 
#undef IOADDR
#undef IOADDR
#undef FUNC
#undef FUNC
 
 
/*
/*
 * functiontable for type 2
 * functiontable for type 2
 */
 */
static struct pci_access pci_direct_conf2 = {
static struct pci_access pci_direct_conf2 = {
      pci_direct_find_device,
      pci_direct_find_device,
      pci_direct_find_class,
      pci_direct_find_class,
      pci_conf2_read_config_byte,
      pci_conf2_read_config_byte,
      pci_conf2_read_config_word,
      pci_conf2_read_config_word,
      pci_conf2_read_config_dword,
      pci_conf2_read_config_dword,
      pci_conf2_write_config_byte,
      pci_conf2_write_config_byte,
      pci_conf2_write_config_word,
      pci_conf2_write_config_word,
      pci_conf2_write_config_dword
      pci_conf2_write_config_dword
};
};
 
 
 
 
static struct pci_access *check_direct_pci(void)
static struct pci_access *check_direct_pci(void)
{
{
    unsigned int tmp;
    unsigned int tmp;
    unsigned long flags;
    unsigned long flags;
 
 
    save_flags(flags); cli();
    save_flags(flags); cli();
 
 
    /*
    /*
     * check if configuration type 1 works
     * check if configuration type 1 works
     */
     */
    outb (0x01, 0xCFB);
    outb (0x01, 0xCFB);
    tmp = inl (0xCF8);
    tmp = inl (0xCF8);
    outl (0x80000000, 0xCF8);
    outl (0x80000000, 0xCF8);
    if (inl (0xCF8) == 0x80000000) {
    if (inl (0xCF8) == 0x80000000) {
        outl (tmp, 0xCF8);
        outl (tmp, 0xCF8);
        restore_flags(flags);
        restore_flags(flags);
        printk("pcibios_init: Using configuration type 1\n");
        printk("pcibios_init: Using configuration type 1\n");
        return &pci_direct_conf1;
        return &pci_direct_conf1;
    }
    }
    outl (tmp, 0xCF8);
    outl (tmp, 0xCF8);
 
 
    /*
    /*
     * check if configuration type 2 works
     * check if configuration type 2 works
     */
     */
    outb (0x00, 0xCFB);
    outb (0x00, 0xCFB);
    outb (0x00, 0xCF8);
    outb (0x00, 0xCF8);
    outb (0x00, 0xCFA);
    outb (0x00, 0xCFA);
    if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) {
    if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00) {
        restore_flags(flags);
        restore_flags(flags);
        printk("pcibios_init: Using configuration type 2\n");
        printk("pcibios_init: Using configuration type 2\n");
        return &pci_direct_conf2;
        return &pci_direct_conf2;
    }
    }
    restore_flags(flags);
    restore_flags(flags);
    printk("pcibios_init: Not supported chipset for direct PCI access !\n");
    printk("pcibios_init: Not supported chipset for direct PCI access !\n");
    return NULL;
    return NULL;
}
}
 
 
 
 
/*
/*
 * access defined pcibios functions via
 * access defined pcibios functions via
 * the function table
 * the function table
 */
 */
 
 
int pcibios_present(void)
int pcibios_present(void)
{
{
        return access_pci ? 1 : 0;
        return access_pci ? 1 : 0;
}
}
 
 
int pcibios_find_class (unsigned int class_code, unsigned short index,
int pcibios_find_class (unsigned int class_code, unsigned short index,
        unsigned char *bus, unsigned char *device_fn)
        unsigned char *bus, unsigned char *device_fn)
{
{
   if (access_pci && access_pci->find_class)
   if (access_pci && access_pci->find_class)
      return access_pci->find_class(class_code, index, bus, device_fn);
      return access_pci->find_class(class_code, index, bus, device_fn);
 
 
    return PCIBIOS_FUNC_NOT_SUPPORTED;
    return PCIBIOS_FUNC_NOT_SUPPORTED;
}
}
 
 
int pcibios_find_device (unsigned short vendor, unsigned short device_id,
int pcibios_find_device (unsigned short vendor, unsigned short device_id,
        unsigned short index, unsigned char *bus, unsigned char *device_fn)
        unsigned short index, unsigned char *bus, unsigned char *device_fn)
{
{
    if (access_pci && access_pci->find_device)
    if (access_pci && access_pci->find_device)
      return access_pci->find_device(vendor, device_id, index, bus, device_fn);
      return access_pci->find_device(vendor, device_id, index, bus, device_fn);
 
 
    return PCIBIOS_FUNC_NOT_SUPPORTED;
    return PCIBIOS_FUNC_NOT_SUPPORTED;
}
}
 
 
int pcibios_read_config_byte (unsigned char bus,
int pcibios_read_config_byte (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char *value)
        unsigned char device_fn, unsigned char where, unsigned char *value)
{
{
    if (access_pci && access_pci->read_config_byte)
    if (access_pci && access_pci->read_config_byte)
      return access_pci->read_config_byte(bus, device_fn, where, value);
      return access_pci->read_config_byte(bus, device_fn, where, value);
 
 
    return PCIBIOS_FUNC_NOT_SUPPORTED;
    return PCIBIOS_FUNC_NOT_SUPPORTED;
}
}
 
 
int pcibios_read_config_word (unsigned char bus,
int pcibios_read_config_word (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned short *value)
        unsigned char device_fn, unsigned char where, unsigned short *value)
{
{
    if (access_pci && access_pci->read_config_word)
    if (access_pci && access_pci->read_config_word)
      return access_pci->read_config_word(bus, device_fn, where, value);
      return access_pci->read_config_word(bus, device_fn, where, value);
 
 
    return PCIBIOS_FUNC_NOT_SUPPORTED;
    return PCIBIOS_FUNC_NOT_SUPPORTED;
}
}
 
 
int pcibios_read_config_dword (unsigned char bus,
int pcibios_read_config_dword (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned int *value)
        unsigned char device_fn, unsigned char where, unsigned int *value)
{
{
    if (access_pci && access_pci->read_config_dword)
    if (access_pci && access_pci->read_config_dword)
      return access_pci->read_config_dword(bus, device_fn, where, value);
      return access_pci->read_config_dword(bus, device_fn, where, value);
 
 
    return PCIBIOS_FUNC_NOT_SUPPORTED;
    return PCIBIOS_FUNC_NOT_SUPPORTED;
}
}
 
 
int pcibios_write_config_byte (unsigned char bus,
int pcibios_write_config_byte (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char value)
        unsigned char device_fn, unsigned char where, unsigned char value)
{
{
    if (access_pci && access_pci->write_config_byte)
    if (access_pci && access_pci->write_config_byte)
      return access_pci->write_config_byte(bus, device_fn, where, value);
      return access_pci->write_config_byte(bus, device_fn, where, value);
 
 
    return PCIBIOS_FUNC_NOT_SUPPORTED;
    return PCIBIOS_FUNC_NOT_SUPPORTED;
}
}
 
 
int pcibios_write_config_word (unsigned char bus,
int pcibios_write_config_word (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned short value)
        unsigned char device_fn, unsigned char where, unsigned short value)
{
{
    if (access_pci && access_pci->write_config_word)
    if (access_pci && access_pci->write_config_word)
      return access_pci->write_config_word(bus, device_fn, where, value);
      return access_pci->write_config_word(bus, device_fn, where, value);
 
 
    return PCIBIOS_FUNC_NOT_SUPPORTED;
    return PCIBIOS_FUNC_NOT_SUPPORTED;
}
}
 
 
int pcibios_write_config_dword (unsigned char bus,
int pcibios_write_config_dword (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned int value)
        unsigned char device_fn, unsigned char where, unsigned int value)
{
{
    if (access_pci && access_pci->write_config_dword)
    if (access_pci && access_pci->write_config_dword)
      return access_pci->write_config_dword(bus, device_fn, where, value);
      return access_pci->write_config_dword(bus, device_fn, where, value);
 
 
    return PCIBIOS_FUNC_NOT_SUPPORTED;
    return PCIBIOS_FUNC_NOT_SUPPORTED;
}
}
 
 
const char *pcibios_strerror (int error)
const char *pcibios_strerror (int error)
{
{
        static char buf[80];
        static char buf[80];
 
 
        switch (error) {
        switch (error) {
                case PCIBIOS_SUCCESSFUL:
                case PCIBIOS_SUCCESSFUL:
                        return "SUCCESSFUL";
                        return "SUCCESSFUL";
 
 
                case PCIBIOS_FUNC_NOT_SUPPORTED:
                case PCIBIOS_FUNC_NOT_SUPPORTED:
                        return "FUNC_NOT_SUPPORTED";
                        return "FUNC_NOT_SUPPORTED";
 
 
                case PCIBIOS_BAD_VENDOR_ID:
                case PCIBIOS_BAD_VENDOR_ID:
                        return "SUCCESSFUL";
                        return "SUCCESSFUL";
 
 
                case PCIBIOS_DEVICE_NOT_FOUND:
                case PCIBIOS_DEVICE_NOT_FOUND:
                        return "DEVICE_NOT_FOUND";
                        return "DEVICE_NOT_FOUND";
 
 
                case PCIBIOS_BAD_REGISTER_NUMBER:
                case PCIBIOS_BAD_REGISTER_NUMBER:
                        return "BAD_REGISTER_NUMBER";
                        return "BAD_REGISTER_NUMBER";
 
 
                case PCIBIOS_SET_FAILED:
                case PCIBIOS_SET_FAILED:
                        return "SET_FAILED";
                        return "SET_FAILED";
 
 
                case PCIBIOS_BUFFER_TOO_SMALL:
                case PCIBIOS_BUFFER_TOO_SMALL:
                        return "BUFFER_TOO_SMALL";
                        return "BUFFER_TOO_SMALL";
 
 
                default:
                default:
                        sprintf (buf, "UNKNOWN RETURN 0x%x", error);
                        sprintf (buf, "UNKNOWN RETURN 0x%x", error);
                        return buf;
                        return buf;
        }
        }
}
}
 
 
 
 
unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
{
{
    return mem_start;
    return mem_start;
}
}
 
 
#endif
#endif
 
 
unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
{
{
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
        union bios32 *check;
        union bios32 *check;
        unsigned char sum;
        unsigned char sum;
        int i, length;
        int i, length;
 
 
        /*
        /*
         * Follow the standard procedure for locating the BIOS32 Service
         * Follow the standard procedure for locating the BIOS32 Service
         * directory by scanning the permissible address range from
         * directory by scanning the permissible address range from
         * 0xe0000 through 0xfffff for a valid BIOS32 structure.
         * 0xe0000 through 0xfffff for a valid BIOS32 structure.
         *
         *
         */
         */
 
 
        for (check = (union bios32 *) 0xe0000;
        for (check = (union bios32 *) 0xe0000;
             check <= (union bios32 *) 0xffff0;
             check <= (union bios32 *) 0xffff0;
             ++check) {
             ++check) {
                if (check->fields.signature != BIOS32_SIGNATURE)
                if (check->fields.signature != BIOS32_SIGNATURE)
                        continue;
                        continue;
                length = check->fields.length * 16;
                length = check->fields.length * 16;
                if (!length)
                if (!length)
                        continue;
                        continue;
                sum = 0;
                sum = 0;
                for (i = 0; i < length ; ++i)
                for (i = 0; i < length ; ++i)
                        sum += check->chars[i];
                        sum += check->chars[i];
                if (sum != 0)
                if (sum != 0)
                        continue;
                        continue;
                if (check->fields.revision != 0) {
                if (check->fields.revision != 0) {
                        printk("pcibios_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n",
                        printk("pcibios_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n",
                                check->fields.revision, check);
                                check->fields.revision, check);
                        continue;
                        continue;
                }
                }
                printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check);
                printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check);
                if (!bios32_entry) {
                if (!bios32_entry) {
                        if (check->fields.entry >= 0x100000) {
                        if (check->fields.entry >= 0x100000) {
                                printk("pcibios_init: entry in high memory, trying direct PCI access\n");
                                printk("pcibios_init: entry in high memory, trying direct PCI access\n");
                                access_pci = check_direct_pci();
                                access_pci = check_direct_pci();
                        } else {
                        } else {
                                bios32_entry = check->fields.entry;
                                bios32_entry = check->fields.entry;
                                printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
                                printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
                                bios32_indirect.address = bios32_entry;
                                bios32_indirect.address = bios32_entry;
                        }
                        }
                }
                }
        }
        }
        if (bios32_entry && check_pcibios())
        if (bios32_entry && check_pcibios())
                access_pci = &pci_bios_access;
                access_pci = &pci_bios_access;
#endif
#endif
        return memory_start;
        return memory_start;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.