lkml.org 
[lkml]   [1997]   [Feb]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Date
From
SubjectRe: Compaq PCI probs
> 
> Hi all
>
> I wonder if there is anyone that has managed to use the
> built-in PCI devices (ie Netflex/3 network adapter) on the
> newer kernels. I have tried to hardcode IRQ's and I/O space
> addresses, but there is not even a "probing..." message=20
> during startup.
>
> I have an Compaq Deskpro 4000 that I really would like to
> have working. During startup there is 3 lines of PCI32 bios
> messages that looks normal (directory entries found etc),
> but then it goes on abount "unknown PCI device at xxx:yyy".
> There is no problem with the CL5446 PCI/Video adapter though.
> It works like a charm.
>
> I did try the (old) Compaq boot image from redhat's ftp site, but
> I get the same problems with that one as with the newer kernels.
> =20
> ANy clues ?
>
> /Anders
>


Try one of following of two patches. You should know how to build a kernel
(see /usr/src/linux/Documentation/Changes).

First patch should work on 2.1.2x.
Second patch adapted from 2.1.2x is against 2.0.29.

First:
---------------------------* 2.1.2x *---------------------------------------
diff -urN linux-clean/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- linux-clean/arch/i386/kernel/bios32.c Mon Dec 23 18:25:31 1996
+++ linux/arch/i386/kernel/bios32.c Wed Feb 12 19:00:07 1997
@@ -49,6 +49,9 @@
* Dec 7, 1996 : Added support for direct configuration access of boards
* with Intel compatible access schemes (tsbogend@alpha.franken.de)
*
+ * Feb 3, 1997 : Set internal functions to static, save/restore flags
+ * avoid dead locks reading broken PCI BIOS, werner@suse.de
+ *
*/

#include <linux/config.h>
@@ -137,7 +140,7 @@
/*
* pointer to selected PCI access function table
*/
-struct pci_access *access_pci = NULL;
+static struct pci_access *access_pci = NULL;



@@ -151,7 +154,9 @@
unsigned long address; /* %ebx */
unsigned long length; /* %ecx */
unsigned long entry; /* %edx */
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%edi)"
: "=a" (return_code),
"=b" (address),
@@ -160,6 +165,7 @@
: "0" (service),
"1" (0),
"D" (&bios32_indirect));
+ restore_flags(flags);

switch (return_code) {
case 0:
@@ -187,11 +193,13 @@
unsigned char present_status;
unsigned char major_revision;
unsigned char minor_revision;
+ unsigned long flags;
int pack;

if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
pci_indirect.address = pcibios_entry | PAGE_OFFSET;

+ save_flags(flags);
__asm__("lcall (%%edi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -202,6 +210,7 @@
: "1" (PCIBIOS_PCI_BIOS_PRESENT),
"D" (&pci_indirect)
: "bx", "cx");
+ restore_flags(flags);

present_status = (pack >> 16) & 0xff;
major_revision = (pack >> 8) & 0xff;
@@ -227,12 +236,14 @@
}


-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 long bx;
unsigned long ret;
+ unsigned long flags;

+ save_flags(flags);
__asm__ ("lcall (%%edi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -243,18 +254,21 @@
"c" (class_code),
"S" ((int) index),
"D" (&pci_indirect));
+ restore_flags(flags);
*bus = (bx >> 8) & 0xff;
*device_fn = bx & 0xff;
return (int) (ret & 0xff00) >> 8;
}


-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 bx;
unsigned short ret;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%edi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -266,17 +280,20 @@
"d" (vendor),
"S" ((int) index),
"D" (&pci_indirect));
+ restore_flags(flags);
*bus = (bx >> 8) & 0xff;
*device_fn = bx & 0xff;
return (int) (ret & 0xff00) >> 8;
}

-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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -287,15 +304,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -306,15 +326,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -325,15 +348,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -344,15 +370,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -363,15 +392,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -382,13 +414,14 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

/*
* function table for BIOS32 access
*/
-struct pci_access pci_bios_access = {
+static struct pci_access pci_bios_access = {
pci_bios_find_device,
pci_bios_find_class,
pci_bios_read_config_byte,
@@ -405,23 +438,27 @@
* Given the vendor and device ids, find the n'th instance of that device
* in the system.
*/
-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 char *devfn)
{
unsigned int curr = 0;
struct pci_dev *dev;
+ unsigned long flags;

+ save_flags(flags);
for (dev = pci_devices; dev; dev = dev->next) {
if (dev->vendor == vendor && dev->device == device_id) {
if (curr == index) {
*devfn = dev->devfn;
*bus = dev->bus->number;
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}
++curr;
}
}
+ restore_flags(flags);
return PCIBIOS_DEVICE_NOT_FOUND;
}

@@ -430,22 +467,26 @@
* Given the class, find the n'th instance of that device
* in the system.
*/
-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 int curr = 0;
struct pci_dev *dev;
+ unsigned long flags;

+ save_flags(flags);
for (dev = pci_devices; dev; dev = dev->next) {
if (dev->class == class_code) {
if (curr == index) {
*devfn = dev->devfn;
*bus = dev->bus->number;
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}
++curr;
}
}
+ restore_flags(flags);
return PCIBIOS_DEVICE_NOT_FOUND;
}

@@ -454,9 +495,12 @@
*/
#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))

-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 long flags;
+
+ save_flags(flags);
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
switch (where & 3) {
case 0: *value = inb(0xCFC);
@@ -468,49 +512,70 @@
case 3: *value = inb(0xCFF);
break;
}
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
+ save_flags(flags);
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
if (where & 2)
*value = inw(0xCFE);
else
*value = inw(0xCFC);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
+ save_flags(flags);
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
*value = inl(0xCFC);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
+ save_flags(flags);
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
outb(value, 0xCFC);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
+ save_flags(flags);
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
outw(value, 0xCFC);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
+ save_flags(flags);
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
outl(value, 0xCFC);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

@@ -519,7 +584,7 @@
/*
* functiontable for type 1
*/
-struct pci_access pci_direct_conf1 = {
+static struct pci_access pci_direct_conf1 = {
pci_direct_find_device,
pci_direct_find_class,
pci_conf1_read_config_byte,
@@ -536,69 +601,93 @@
#define IOADDR(devfn, where) ((0xC000 | ((devfn & 0x78) << 5)) + where)
#define FUNC(devfn) (((devfn & 7) << 1) | 0xf0)

-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 long flags;
+
if (device_fn & 0x80)
return PCIBIOS_DEVICE_NOT_FOUND;
+ save_flags(flags);
outb (FUNC(device_fn), 0xCF8);
outb (bus, 0xCFA);
*value = inb(IOADDR(device_fn,where));
outb (0, 0xCF8);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
if (device_fn & 0x80)
return PCIBIOS_DEVICE_NOT_FOUND;
+ save_flags(flags);
outb (FUNC(device_fn), 0xCF8);
outb (bus, 0xCFA);
*value = inw(IOADDR(device_fn,where));
- outb (0, 0xCF8);
+ outb (0, 0xCF8);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
if (device_fn & 0x80)
return PCIBIOS_DEVICE_NOT_FOUND;
+ save_flags(flags);
outb (FUNC(device_fn), 0xCF8);
outb (bus, 0xCFA);
*value = inl (IOADDR(device_fn,where));
outb (0, 0xCF8);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
+ save_flags(flags);
outb (FUNC(device_fn), 0xCF8);
outb (bus, 0xCFA);
outb (value, IOADDR(device_fn,where));
outb (0, 0xCF8);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
+ save_flags(flags);
outb (FUNC(device_fn), 0xCF8);
outb (bus, 0xCFA);
outw (value, IOADDR(device_fn,where));
outb (0, 0xCF8);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

-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 long flags;
+
+ save_flags(flags);
outb (FUNC(device_fn), 0xCF8);
outb (bus, 0xCFA);
outl (value, IOADDR(device_fn,where));
outb (0, 0xCF8);
+ restore_flags(flags);
return PCIBIOS_SUCCESSFUL;
}

@@ -608,7 +697,7 @@
/*
* functiontable for type 2
*/
-struct pci_access pci_direct_conf2 = {
+static struct pci_access pci_direct_conf2 = {
pci_direct_find_device,
pci_direct_find_class,
pci_conf2_read_config_byte,
@@ -620,9 +709,12 @@
};


-struct pci_access *check_direct_pci(void)
+static struct pci_access *check_direct_pci(void)
{
unsigned int tmp;
+ unsigned long flags;
+
+ save_flags(flags);

/*
* check if configuration type 1 works
@@ -632,6 +724,7 @@
outl (0x80000000, 0xCF8);
if (inl (0xCF8) == 0x80000000) {
outl (tmp, 0xCF8);
+ restore_flags(flags);
printk("pcibios_init: Using configuration type 1\n");
return &pci_direct_conf1;
}
@@ -644,9 +737,11 @@
outb (0x00, 0xCF8);
outb (0x00, 0xCFA);
if (inb (0xCF8) == 0x00 && inb (0xCFC) == 0x00) {
+ restore_flags(flags);
printk("pcibios_init: Using configuration type 2\n");
return &pci_direct_conf2;
}
+ restore_flags(flags);
printk("pcibios_init: Not supported chipset for direct PCI access !\n");
return NULL;
}
---------------------------* 2.1.2x *---------------------------------------
Second:
---------------------------* 2.0.29 *---------------------------------------
--- linux/arch/i386/kernel/bios32.c.orig Sat Jun 8 10:10:49 1996
+++ linux/arch/i386/kernel/bios32.c Mon Feb 3 13:16:37 1997
@@ -46,6 +46,11 @@
* Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
* moved to drivers/pci/pci.c.
*
+ * Dec 7, 1996 : Added support for direct configuration access of boards
+ * with Intel compatible access schemes (tsbogend@alpha.franken.de)
+ *
+ * Feb 3, 1997 : Set internal functions to static, save/restore flags
+ * avoid dead locks reading broken PCI BIOS, werner@suse.de
*
*/

@@ -56,6 +61,8 @@
#include <linux/pci.h>

#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/io.h>

#define PCIBIOS_PCI_FUNCTION_ID 0xb1XX
#define PCIBIOS_PCI_BIOS_PRESENT 0xb101
@@ -101,6 +108,7 @@
char chars[16];
};

+#ifdef CONFIG_PCI
/*
* 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
@@ -114,7 +122,28 @@
unsigned short segment;
} bios32_indirect = { 0, KERNEL_CS };

-#ifdef CONFIG_PCI
+
+/*
+ * function table for accessing PCI configuration space
+ */
+struct pci_access {
+ 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 (*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_dword)(unsigned char, unsigned char, unsigned char, unsigned int *);
+ 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_dword)(unsigned char, unsigned char, unsigned char, unsigned int);
+};
+
+/*
+ * pointer to selected PCI access function table
+ */
+static struct pci_access *access_pci = NULL;
+
+
+
/*
* Returns the entry point for the given service, NULL on error
*/
@@ -125,7 +154,9 @@
unsigned long address; /* %ebx */
unsigned long length; /* %ecx */
unsigned long entry; /* %edx */
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%edi)"
: "=a" (return_code),
"=b" (address),
@@ -134,6 +165,7 @@
: "0" (service),
"1" (0),
"D" (&bios32_indirect));
+ restore_flags(flags);

switch (return_code) {
case 0:
@@ -161,11 +193,13 @@
unsigned char present_status;
unsigned char major_revision;
unsigned char minor_revision;
+ unsigned long flags;
int pack;

if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
pci_indirect.address = pcibios_entry;

+ save_flags(flags);
__asm__("lcall (%%edi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -176,6 +210,7 @@
: "1" (PCIBIOS_PCI_BIOS_PRESENT),
"D" (&pci_indirect)
: "bx", "cx");
+ restore_flags(flags);

present_status = (pack >> 16) & 0xff;
major_revision = (pack >> 8) & 0xff;
@@ -200,17 +235,15 @@
return memory_start;
}

-int pcibios_present(void)
-{
- return pcibios_entry ? 1 : 0;
-}

-int pcibios_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 long bx;
unsigned long ret;
+ unsigned long flags;

+ save_flags(flags);
__asm__ ("lcall (%%edi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -221,18 +254,21 @@
"c" (class_code),
"S" ((int) index),
"D" (&pci_indirect));
+ restore_flags(flags);
*bus = (bx >> 8) & 0xff;
*device_fn = bx & 0xff;
return (int) (ret & 0xff00) >> 8;
}


-int pcibios_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 bx;
unsigned short ret;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%edi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -244,17 +280,20 @@
"d" (vendor),
"S" ((int) index),
"D" (&pci_indirect));
+ restore_flags(flags);
*bus = (bx >> 8) & 0xff;
*device_fn = bx & 0xff;
return (int) (ret & 0xff00) >> 8;
}

-int pcibios_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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -265,15 +304,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-int pcibios_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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -284,15 +326,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-int pcibios_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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -303,15 +348,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-int pcibios_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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -322,15 +370,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-int pcibios_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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -341,15 +392,18 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

-int pcibios_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 long ret;
unsigned long bx = (bus << 8) | device_fn;
+ unsigned long flags;

+ save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@@ -360,9 +414,421 @@
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
+ restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}

+/*
+ * function table for BIOS32 access
+ */
+static struct pci_access pci_bios_access = {
+ pci_bios_find_device,
+ pci_bios_find_class,
+ pci_bios_read_config_byte,
+ pci_bios_read_config_word,
+ pci_bios_read_config_dword,
+ pci_bios_write_config_byte,
+ pci_bios_write_config_word,
+ pci_bios_write_config_dword
+};
+
+
+
+/*
+ * Given the vendor and device ids, find the n'th instance of that device
+ * in the system.
+ */
+static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,
+ unsigned short index, unsigned char *bus,
+ unsigned char *devfn)
+{
+ unsigned int curr = 0;
+ struct pci_dev *dev;
+ unsigned long flags;
+
+ save_flags(flags);
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if (dev->vendor == vendor && dev->device == device_id) {
+ if (curr == index) {
+ *devfn = dev->devfn;
+ *bus = dev->bus->number;
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ ++curr;
+ }
+ }
+ restore_flags(flags);
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+
+/*
+ * Given the class, find the n'th instance of that device
+ * in the system.
+ */
+static int pci_direct_find_class (unsigned int class_code, unsigned short index,
+ unsigned char *bus, unsigned char *devfn)
+{
+ unsigned int curr = 0;
+ struct pci_dev *dev;
+ unsigned long flags;
+
+ save_flags(flags);
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if (dev->class == class_code) {
+ if (curr == index) {
+ *devfn = dev->devfn;
+ *bus = dev->bus->number;
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+ }
+ ++curr;
+ }
+ }
+ restore_flags(flags);
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+/*
+ * 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))
+
+static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned char *value)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ switch (where & 3) {
+ case 0: *value = inb(0xCFC);
+ break;
+ case 1: *value = inb(0xCFD);
+ break;
+ case 2: *value = inb(0xCFE);
+ break;
+ case 3: *value = inb(0xCFF);
+ break;
+ }
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_read_config_word (unsigned char bus,
+ unsigned char device_fn, unsigned char where, unsigned short *value)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ if (where & 2)
+ *value = inw(0xCFE);
+ else
+ *value = inw(0xCFC);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_read_config_dword (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned int *value)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ *value = inl(0xCFC);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_write_config_byte (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned char value)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ outb(value, 0xCFC);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_write_config_word (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned short value)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ outw(value, 0xCFC);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_write_config_dword (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned int value)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
+ outl(value, 0xCFC);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+#undef CONFIG_CMD
+
+/*
+ * functiontable for type 1
+ */
+static struct pci_access pci_direct_conf1 = {
+ pci_direct_find_device,
+ pci_direct_find_class,
+ pci_conf1_read_config_byte,
+ pci_conf1_read_config_word,
+ pci_conf1_read_config_dword,
+ pci_conf1_write_config_byte,
+ pci_conf1_write_config_word,
+ pci_conf1_write_config_dword
+};
+
+/*
+ * Functions for accessing PCI configuration space with type 2 accesses
+ */
+#define IOADDR(devfn, where) ((0xC000 | ((devfn & 0x78) << 5)) + where)
+#define FUNC(devfn) (((devfn & 7) << 1) | 0xf0)
+
+static int pci_conf2_read_config_byte(unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned char *value)
+{
+ unsigned long flags;
+
+ if (device_fn & 0x80)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ save_flags(flags);
+ outb (FUNC(device_fn), 0xCF8);
+ outb (bus, 0xCFA);
+ *value = inb(IOADDR(device_fn,where));
+ outb (0, 0xCF8);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf2_read_config_word (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned short *value)
+{
+ unsigned long flags;
+
+ if (device_fn & 0x80)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ save_flags(flags);
+ outb (FUNC(device_fn), 0xCF8);
+ outb (bus, 0xCFA);
+ *value = inw(IOADDR(device_fn,where));
+ outb (0, 0xCF8);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf2_read_config_dword (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned int *value)
+{
+ unsigned long flags;
+
+ if (device_fn & 0x80)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ save_flags(flags);
+ outb (FUNC(device_fn), 0xCF8);
+ outb (bus, 0xCFA);
+ *value = inl (IOADDR(device_fn,where));
+ outb (0, 0xCF8);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf2_write_config_byte (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned char value)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ outb (FUNC(device_fn), 0xCF8);
+ outb (bus, 0xCFA);
+ outb (value, IOADDR(device_fn,where));
+ outb (0, 0xCF8);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf2_write_config_word (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned short value)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ outb (FUNC(device_fn), 0xCF8);
+ outb (bus, 0xCFA);
+ outw (value, IOADDR(device_fn,where));
+ outb (0, 0xCF8);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf2_write_config_dword (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned int value)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ outb (FUNC(device_fn), 0xCF8);
+ outb (bus, 0xCFA);
+ outl (value, IOADDR(device_fn,where));
+ outb (0, 0xCF8);
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+#undef IOADDR
+#undef FUNC
+
+/*
+ * functiontable for type 2
+ */
+static struct pci_access pci_direct_conf2 = {
+ pci_direct_find_device,
+ pci_direct_find_class,
+ pci_conf2_read_config_byte,
+ pci_conf2_read_config_word,
+ pci_conf2_read_config_dword,
+ pci_conf2_write_config_byte,
+ pci_conf2_write_config_word,
+ pci_conf2_write_config_dword
+};
+
+
+static struct pci_access *check_direct_pci(void)
+{
+ unsigned int tmp;
+ unsigned long flags;
+
+ save_flags(flags);
+
+ /*
+ * check if configuration type 1 works
+ */
+ outb (0x01, 0xCFB);
+ tmp = inl (0xCF8);
+ outl (0x80000000, 0xCF8);
+ if (inl (0xCF8) == 0x80000000) {
+ outl (tmp, 0xCF8);
+ restore_flags(flags);
+ printk("pcibios_init: Using configuration type 1\n");
+ return &pci_direct_conf1;
+ }
+ outl (tmp, 0xCF8);
+
+ /*
+ * check if configuration type 2 works
+ */
+ outb (0x00, 0xCFB);
+ outb (0x00, 0xCF8);
+ outb (0x00, 0xCFA);
+ if (inb (0xCF8) == 0x00 && inb (0xCFC) == 0x00) {
+ restore_flags(flags);
+ printk("pcibios_init: Using configuration type 2\n");
+ return &pci_direct_conf2;
+ }
+ restore_flags(flags);
+ printk("pcibios_init: Not supported chipset for direct PCI access !\n");
+ return NULL;
+}
+
+
+/*
+ * access defined pcibios functions via
+ * the function table
+ */
+
+int pcibios_present(void)
+{
+ return access_pci ? 1 : 0;
+}
+
+int pcibios_find_class (unsigned int class_code, unsigned short index,
+ unsigned char *bus, unsigned char *device_fn)
+{
+ if (access_pci && access_pci->find_class)
+ return access_pci->find_class(class_code, index, bus, device_fn);
+
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+int pcibios_find_device (unsigned short vendor, unsigned short device_id,
+ unsigned short index, unsigned char *bus, unsigned char *device_fn)
+{
+ if (access_pci && access_pci->find_device)
+ return access_pci->find_device(vendor, device_id, index, bus, device_fn);
+
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+int pcibios_read_config_byte (unsigned char bus,
+ unsigned char device_fn, unsigned char where, unsigned char *value)
+{
+ if (access_pci && access_pci->read_config_byte)
+ return access_pci->read_config_byte(bus, device_fn, where, value);
+
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+int pcibios_read_config_word (unsigned char bus,
+ unsigned char device_fn, unsigned char where, unsigned short *value)
+{
+ if (access_pci && access_pci->read_config_word)
+ return access_pci->read_config_word(bus, device_fn, where, value);
+
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+int pcibios_read_config_dword (unsigned char bus,
+ unsigned char device_fn, unsigned char where, unsigned int *value)
+{
+ if (access_pci && access_pci->read_config_dword)
+ return access_pci->read_config_dword(bus, device_fn, where, value);
+
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+int pcibios_write_config_byte (unsigned char bus,
+ unsigned char device_fn, unsigned char where, unsigned char value)
+{
+ if (access_pci && access_pci->write_config_byte)
+ return access_pci->write_config_byte(bus, device_fn, where, value);
+
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+int pcibios_write_config_word (unsigned char bus,
+ unsigned char device_fn, unsigned char where, unsigned short value)
+{
+ if (access_pci && access_pci->write_config_word)
+ return access_pci->write_config_word(bus, device_fn, where, value);
+
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
+int pcibios_write_config_dword (unsigned char bus,
+ unsigned char device_fn, unsigned char where, unsigned int value)
+{
+ if (access_pci && access_pci->write_config_dword)
+ return access_pci->write_config_dword(bus, device_fn, where, value);
+
+ return PCIBIOS_FUNC_NOT_SUPPORTED;
+}
+
const char *pcibios_strerror (int error)
{
static char buf[80];
@@ -398,14 +864,14 @@

unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
{
-return mem_start;
+ return mem_start;
}

-
#endif

unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
{
+#ifdef CONFIG_PCI
union bios32 *check;
unsigned char sum;
int i, length;
@@ -436,14 +902,16 @@
printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check);
if (!bios32_entry) {
if (check->fields.entry >= 0x100000) {
- printk("pcibios_init: entry in high memory, unable to access\n");
+ printk("pcibios_init: entry in high memory, trying direct PCI access\n");
+ access_pci = check_direct_pci();
} else {
- bios32_indirect.address = bios32_entry = check->fields.entry;
+ bios32_entry = check->fields.entry;
printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
+ bios32_indirect.address = bios32_entry;
+ access_pci = &pci_bios_access;
}
}
}
-#ifdef CONFIG_PCI
if (bios32_entry) {
memory_start = check_pcibios (memory_start, memory_end);
}
---------------------------* 2.0.29 *---------------------------------------



Hope it helps

Werner

\
 
 \ /
  Last update: 2005-03-22 13:38    [W:0.066 / U:0.192 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site