Fix for PCI detection in fdomain.c

Brian Beaudoin (baddog@darkknight.net)
Sun, 19 Apr 1998 18:48:28 -0400


This is a multi-part message in MIME format.
--------------B5272FD39EC06E00B7231D01
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Martin,

Here is the patch to correct the PCI autodetection in the Future Domain
driver (fdomain.c). It should be applied against the version
distributed with kernel 2.1.96.

Although your routines seem to be implemented correctly, there is a
hardware problem with the Future Domain PCI cards that was documented by
one of the original authors, James McKinley:

"This should probably be done by a call to [pci_find_device]
but I can't get it to work... Also the device ID reported
from the PCI config registers does not match the device ID
quoted in the tech manual or available from offset 5 from
the I/O base address. It should be 0x60E9, but it is 0x0
if read from the PCI config registers."

The patch restores the original comments and the loop to detect the IRQ
and I/O base address for the adaptor. I've only touched what was
necessary to get the driver to function properly, all of your
modifications to the code are still intact.

Testing was done on an Intel i586 (Pentium MMX) architecture with an
Adaptec 2920 (Future Domain TMC-18C30/36C70). The device now
initializes properly and appears to function normally.

Please evaluate the changes and submit them to Linus for the next
release (maybe 2.1.98?)

Brian Beaudoin
baddog@darkknight.net

dmesg outout:

scsi0 <fdomain>: BIOS version 3.?. at 0xc8000 using scsi id 7
scsi0 <fdomain>: TMC-36C70 (PCI bus) chip at 0x6100 irq 11
scsi0 : Future Domain TMC-16x0 SCSI driver, version 5.47
scsi : 1 host.
[...]
scsi : detected 2 SCSI disks total.

Output from 'lspci -vvx'

00:0a.0 SCSI storage controller: Future Domain Corp. TMC-18C30 [36C70]
Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop-
ParErr- Stepping- SERR- FastB2B-
Status: 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort-
<TAbort- <MAbort- >SERR- <PERR-
Interrupt: pin A routed to IRQ 11
Region 0: I/O ports at 6100
00: 36 10 00 00 03 00 80 02 00 00 00 01 00 00 00 00
10: 01 61 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30: 00 00 00 00 00 00 00 00 00 00 00 00 0b 01 00 00
--------------B5272FD39EC06E00B7231D01
Content-Type: text/plain; charset=us-ascii; name="fdomain.c.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="fdomain.c.diff"

--- fdomain.c.old Sat Apr 11 14:13:25 1998
+++ fdomain.c Sun Apr 19 18:24:27 1998
@@ -4,7 +4,7 @@
* Author: Rickard E. Faith, faith@cs.unc.edu
* Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
*
- * $Id: fdomain.c,v 5.45 1996/10/02 15:13:06 root Exp $
+ * $Id: fdomain.c,v 5.47 1998/04/19 15:13:06 root Exp $

* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -108,6 +108,8 @@
1.3.85 5.41 4 Apr 1996
2.0.12 5.44 8 Aug 1996 Use ID 7 for all PCI cards
2.1.1 5.45 2 Oct 1996 Update ROM accesses for 2.1.x
+ 2.1.96 5.46 11 Apr 1998 Update PCI detection routines
+ 2.1.96 5.47 19 Apr 1998 Restore old detection loop



@@ -279,7 +281,7 @@
S_IFDIR | S_IRUGO | S_IXUGO, 2
};

-#define VERSION "$Revision: 5.45 $"
+#define VERSION "$Revision: 5.47 $"

/* START OF USER DEFINABLE OPTIONS */

@@ -403,6 +405,9 @@
extern void fdomain_16x0_intr( int irq, void *dev_id,
struct pt_regs * regs );

+extern void do_fdomain_16x0_intr( int irq, void *dev_id,
+ struct pt_regs * regs );
+
static unsigned long addresses[] = {
0xc8000,
0xca000,
@@ -758,8 +763,12 @@
#ifdef CONFIG_PCI
static int fdomain_pci_bios_detect( int *irq, int *iobase )
{
- unsigned int pci_irq; /* PCI interrupt line */
- unsigned long pci_base; /* PCI I/O base address */
+ int error;
+ unsigned char pci_bus, pci_dev_fn; /* PCI bus & device function */
+ unsigned short pci_vendor, pci_device; /* PCI vendor & device IDs */
+
+ unsigned char pci_irq; /* PCI interrupt line */
+ unsigned int pci_base; /* PCI I/O base address */
struct pci_dev *pdev = NULL;

if (!pci_present()) return 0;
@@ -775,21 +784,83 @@
PCI_DEVICE_ID_FD_36C70 );
#endif

- if ((pdev = pci_find_device(PCI_VENDOR_ID, PCI_DEVICE_ID, pdev)) == NULL)
- return 0;
-
+ /* We will have to change this if more than 1 PCI bus is present and the
+ FD scsi host is not on the first bus (i.e., a PCI to PCI bridge,
+ which is not supported by bios32 right now anyway). This should
+ probably be done by a call to pcibios_find_device but I can't get it
+ to work... Also the device ID reported from the PCI config registers
+ does not match the device ID quoted in the tech manual or available
+ from offset 5 from the I/O base address. It should be 0x60E9, but it
+ is 0x0 if read from the PCI config registers. I guess the FD folks
+ neglected to write it to the PCI registers... This loop is necessary
+ to get the device function (at least until someone can get
+ pcibios_find_device to work, I cannot but 53c7,8xx.c uses it...).
+
+ *** 19 Apr 1998: As James T. McKinley wrote above, there is a problem
+ with the Future Domain hardware that prevents pcibios_find_device
+ (now pci_find_device) from operating properly. Following is the
+ device call properly implemented by Martin Mares:
+
+ if ((pdev = pci_find_device(PCI_VENDOR_ID, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL)
+ return 0;
+
+ Unfortunately, it always returns NULL on my Adaptec 2920 SCSI host
+ adaptor. James reported to me that several people have written him
+ about the problem with the new driver, so here is the original loop
+ routine that he wrote to detect the PCI adaptors properly.
+
+ Brian Beaudoin <baddog@darkknight.net>
+ */
+
+ pci_bus = 0;
+
+ for (pci_dev_fn = 0x0; pci_dev_fn < 0xff; pci_dev_fn++) {
+ pcibios_read_config_word( pci_bus,
+ pci_dev_fn,
+ PCI_VENDOR_ID,
+ &pci_vendor );
+
+ if (pci_vendor == PCI_VENDOR_ID_FD) {
+ pcibios_read_config_word( pci_bus,
+ pci_dev_fn,
+ PCI_DEVICE_ID,
+ &pci_device );
+
+ if (pci_device == PCI_DEVICE_ID_FD_36C70) {
+ /* Break out once we have the correct device. If other FD
+ PCI devices are added to this driver we will need to add
+ an or of the other PCI_DEVICE_ID_FD_XXXXX's here. */
+ break;
+ } else {
+ /* If we can't find an FD scsi card we give up. */
+ return 0;
+ }
+ }
+ }
+
#if DEBUG_DETECT
printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
- pdev->bus->number,
- PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn));
+ pci_bus,
+ (pci_dev_fn & 0xf8) >> 3,
+ pci_dev_fn & 7 );
#endif

/* We now have the appropriate device function for the FD board so we
just read the PCI config info from the registers. */

- pci_base = pdev->base_address[0];
- pci_irq = pdev->irq;
+ if ((error = pcibios_read_config_dword( pci_bus,
+ pci_dev_fn,
+ PCI_BASE_ADDRESS_0,
+ &pci_base ))
+ || (error = pcibios_read_config_byte( pci_bus,
+ pci_dev_fn,
+ PCI_INTERRUPT_LINE,
+ &pci_irq ))) {
+ printk ( "PCI ERROR: Future Domain 36C70 not initializing"
+ " due to error reading configuration space\n" );
+ return 0;
+ } else {
+
#if DEBUG_DETECT
printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n",
pci_irq, pci_base );
@@ -798,16 +869,18 @@
/* Now we have the I/O base address and interrupt from the PCI
configuration registers. */

- *irq = pci_irq;
- *iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK);
+ *irq = pci_irq;
+ *iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK);

#if DEBUG_DETECT
- printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" );
- printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
+ printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" );
+ printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
#endif

- if (!fdomain_is_valid_port( *iobase )) return 0;
- return 1;
+ if (!fdomain_is_valid_port( *iobase )) return 0;
+ return 1;
+ }
+ return 0;
}
#endif

@@ -886,7 +959,7 @@
#endif
#ifdef CONFIG_PCI
printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" );
- printk( "Send mail to mckinley@msupa.pa.msu.edu.\n" );
+ printk( "Send mail to Martin Mares <mj@atrey.karlin.mff.cuni.cz>.\n" );
#endif
return 0; /* Cannot find valid set of ports */
}

--------------B5272FD39EC06E00B7231D01--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu