Skip to contentSkip to conversation

fdomain: Resurrect driver

RFC PATCH In review Ondrej Zary 3 participants 6 messages Apr 7, 2019 – Apr 9, 2019 SCSI

lore
Share & tools
lore
#1 lore raw

RFC PATCH 1/2 fdomain: Resurrect fdomain and fdomain_cs drivers

This reverts commit e184f2bf4d9f1a3c612a8c1d67e73e9cf8ab5ab9. It does not compile but following patches will fix that.

---
 MAINTAINERS                        |    6 +
 drivers/scsi/Kconfig               |   20 +
 drivers/scsi/Makefile              |    1 +
 drivers/scsi/fdomain.c             | 1783 ++++++++++++++++++++++++++++++++++++
 drivers/scsi/fdomain.h             |   24 +
 drivers/scsi/pcmcia/Kconfig        |    9 +
 drivers/scsi/pcmcia/Makefile       |    2 +
 drivers/scsi/pcmcia/fdomain_core.c |    2 +
 drivers/scsi/pcmcia/fdomain_stub.c |  209 +++++
 9 files changed, 2056 insertions(+)
 create mode 100644 drivers/scsi/fdomain.c
 create mode 100644 drivers/scsi/fdomain.h
 create mode 100644 drivers/scsi/pcmcia/fdomain_core.c
 create mode 100644 drivers/scsi/pcmcia/fdomain_stub.c
MAINTAINERS +6 -0
index 2359e12e4c41..4ff767f79454 100644
@@ -6416,6 +6416,12 @@ F:	tools/testing/selftests/futex/
 F:	tools/perf/bench/futex*
 F:	Documentation/*futex*
 
+FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit)
+M:	Rik Faith <[email protected]>
+L:	[email protected]
+S:	Odd Fixes (e.g., new signatures)
+F:	drivers/scsi/fdomain.*
+
 GCC PLUGINS
 M:	Kees Cook <[email protected]>
 R:	Emese Revfy <[email protected]>
drivers/scsi/Kconfig +20 -0
index d528018e6fa8..58690189c8cf 100644
@@ -663,6 +663,26 @@ config SCSI_DMX3191D
 	  To compile this driver as a module, choose M here: the
 	  module will be called dmx3191d.
 
+config SCSI_FUTURE_DOMAIN
+	tristate "Future Domain 16xx SCSI/AHA-2920A support"
+	depends on (ISA || PCI) && SCSI
+	select CHECK_SIGNATURE
+	---help---
+	  This is support for Future Domain's 16-bit SCSI host adapters
+	  (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and
+	  other adapters based on the Future Domain chipsets (Quantum
+	  ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board).
+	  It is explained in section 3.7 of the SCSI-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip
+	  and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI
+	  controller support"). This Future Domain driver works with the older
+	  Adaptec AHA-2920A boards with a Future Domain chip on them.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called fdomain.
+
 config SCSI_GDTH
 	tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support"
 	depends on PCI && SCSI
drivers/scsi/Makefile +1 -0
index 8826111fdf4a..a9f80770d989 100644
@@ -76,6 +76,7 @@ obj-$(CONFIG_SCSI_AIC94XX)	+= aic94xx/
 obj-$(CONFIG_SCSI_PM8001)	+= pm8001/
 obj-$(CONFIG_SCSI_ISCI)		+= isci/
 obj-$(CONFIG_SCSI_IPS)		+= ips.o
+obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
 obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o
 obj-$(CONFIG_SCSI_QLOGIC_FAS)	+= qlogicfas408.o	qlogicfas.o
 obj-$(CONFIG_PCMCIA_QLOGIC)	+= qlogicfas408.o
drivers/scsi/fdomain.c new file +1783 -0

1,783 lines not on this page · raw message

drivers/scsi/fdomain.h new file +24 -0
new file mode 100644
index 000000000000..5cbe86b573ae
@@ -0,0 +1,24 @@
+/*
+ * fdomain.c -- Future Domain TMC-16x0 SCSI driver
+ * Author: Rickard E. Faith, [email protected]
+ * Copyright 1992-1996, 1998 Rickard E. Faith ([email protected])
+ *
+ * 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
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+extern struct scsi_host_template fdomain_driver_template;
+extern int fdomain_setup(char *str);
+extern struct Scsi_Host *__fdomain_16x0_detect(struct  scsi_host_template *tpnt );
+extern int fdomain_16x0_host_reset(struct scsi_cmnd *SCpnt);
drivers/scsi/pcmcia/Kconfig +9 -0
index 2d435f105b16..ecc855c550aa 100644
@@ -19,6 +19,15 @@ config PCMCIA_AHA152X
 	  To compile this driver as a module, choose M here: the
 	  module will be called aha152x_cs.
 
+config PCMCIA_FDOMAIN
+	tristate "Future Domain PCMCIA support"
+	help
+	  Say Y here if you intend to attach this type of PCMCIA SCSI host
+	  adapter to your computer.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called fdomain_cs.
+
 config PCMCIA_NINJA_SCSI
 	tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
 	depends on !64BIT
drivers/scsi/pcmcia/Makefile +2 -0
index a5a24dd44e7e..ba1f126f9b17 100644
@@ -4,9 +4,11 @@ ccflags-y		:= -I $(srctree)/drivers/scsi
 
 # 16-bit client drivers
 obj-$(CONFIG_PCMCIA_QLOGIC)	+= qlogic_cs.o
+obj-$(CONFIG_PCMCIA_FDOMAIN)	+= fdomain_cs.o
 obj-$(CONFIG_PCMCIA_AHA152X)	+= aha152x_cs.o
 obj-$(CONFIG_PCMCIA_NINJA_SCSI)	+= nsp_cs.o
 obj-$(CONFIG_PCMCIA_SYM53C500)	+= sym53c500_cs.o
 
 aha152x_cs-objs	:= aha152x_stub.o aha152x_core.o
+fdomain_cs-objs	:= fdomain_stub.o fdomain_core.o
 qlogic_cs-objs	:= qlogic_stub.o
drivers/scsi/pcmcia/fdomain_core.c new file +2 -0
new file mode 100644
index 000000000000..a48913791868
@@ -0,0 +1,2 @@
+#define PCMCIA 1
+#include "fdomain.c"
drivers/scsi/pcmcia/fdomain_stub.c new file +209 -0

209 lines not on this page · raw message

Signature · 1 line
Ondrej Zary
#2 lore raw

Re: [RFC PATCH 1/2] fdomain: Resurrect fdomain and fdomain_cs drivers

Hi Ondrej,

Quoted 2 lines

This reverts commit e184f2bf4d9f1a3c612a8c1d67e73e9cf8ab5ab9. It does not compile but following patches will fix that.

I don't have any particular objections to reviving this driver if people are actually using it. However, breaking bisection is going to be a problem. So you'll have to squash the revert and the fixup patch and carefully annotate the resolutions in the commit description.

Thanks!

Signature · 1 line
Martin K. Petersen	Oracle Linux Engineering
#3 lore raw

Re: [RFC PATCH 1/2] fdomain: Resurrect fdomain and fdomain_cs drivers

In reply to Ondrej Zary
Quoted 2 lines · Ondrej Zary

This reverts commit e184f2bf4d9f1a3c612a8c1d67e73e9cf8ab5ab9. It does not compile but following patches will fix that.

Please just resurrect it as a proper driver that fits modern standards, including the coding style. To make your life much easier I'd suggest you do that for the PCI devices only and leave the rest behind.

#4 lore raw

RFC PATCH 2/2 fdomain: Fix compilation

In reply to Ondrej Zary

Remove usage of scsi_module.c, .use_clustering and scsi_(un)register. This allows the driver to compile and also work (tested with PCI card).

---
 drivers/scsi/fdomain.c             | 48 ++++++++++++++++++++++++++++----------
 drivers/scsi/pcmcia/fdomain_stub.c |  2 +-
 2 files changed, 37 insertions(+), 13 deletions(-)
drivers/scsi/fdomain.c +36 -12
index ebbe5a3e665d..fe9e373c27a8 100644
@@ -415,6 +415,7 @@ static char * fdomain = NULL;
 module_param(fdomain, charp, 0);
 
 #ifndef PCMCIA
+static struct Scsi_Host	*fdomain_shost;
 
 static unsigned long addresses[] = {
    0xc8000,
@@ -959,7 +960,7 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
 /* Print out a banner here in case we can't
    get resources.  */
 
-   shpnt = scsi_register( tpnt, 0 );
+   shpnt = scsi_host_alloc( tpnt, 0 );
    if(shpnt == NULL) {
 	release_region(port_base, 0x10);
    	return NULL;
@@ -1003,13 +1004,6 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
    return NULL;
 }
 
-static int fdomain_16x0_detect(struct scsi_host_template *tpnt)
-{
-	if (fdomain)
-		fdomain_setup(fdomain);
-	return (__fdomain_16x0_detect(tpnt) != NULL);
-}
-
 static const char *fdomain_16x0_info( struct Scsi_Host *ignore )
 {
    static char buffer[128];
@@ -1739,6 +1733,7 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev,
    return 0;
 }
 
+#ifndef PCMCIA
 static int fdomain_16x0_release(struct Scsi_Host *shpnt)
 {
 	if (shpnt->irq)
@@ -1749,22 +1744,21 @@ static int fdomain_16x0_release(struct Scsi_Host *shpnt)
 		pci_dev_put(PCI_dev);
 	return 0;
 }
+#endif
 
 struct scsi_host_template fdomain_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= "fdomain",
 	.proc_name		= "fdomain",
-	.detect			= fdomain_16x0_detect,
 	.info			= fdomain_16x0_info,
 	.queuecommand		= fdomain_16x0_queue,
 	.eh_abort_handler	= fdomain_16x0_abort,
 	.eh_host_reset_handler	= fdomain_16x0_host_reset,
 	.bios_param		= fdomain_16x0_biosparam,
-	.release		= fdomain_16x0_release,
 	.can_queue		= 1,
 	.this_id		= 6,
 	.sg_tablesize		= 64,
-	.use_clustering		= DISABLE_CLUSTERING,
+	.dma_boundary		= PAGE_SIZE - 1,
 };
 
 #ifndef PCMCIA
@@ -1778,6 +1772,36 @@ static struct pci_device_id fdomain_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl);
 #endif
 #define driver_template fdomain_driver_template
-#include "scsi_module.c"
+
+static int __init fdomain_16x0_init(void)
+{
+	int ret;
+
+	if (fdomain)
+		fdomain_setup(fdomain);
+	fdomain_shost = __fdomain_16x0_detect(&driver_template);
+	if (!fdomain_shost)
+		return -ENODEV;
+
+	ret = scsi_add_host(fdomain_shost, NULL);
+	if (ret)
+		goto fail;
+	scsi_scan_host(fdomain_shost);
+
+	return 0;
+fail:
+	scsi_remove_host(fdomain_shost);
+	return ret;
+}
+
+static void __exit fdomain_16x0_exit(void)
+{
+	scsi_remove_host(fdomain_shost);
+	fdomain_16x0_release(fdomain_shost);
+	scsi_host_put(fdomain_shost);
+}
+
+module_init(fdomain_16x0_init);
+module_exit(fdomain_16x0_exit);
 
 #endif
drivers/scsi/pcmcia/fdomain_stub.c +1 -1
index 953a792150ae..5febbb7d611b 100644
@@ -166,7 +166,7 @@ static void fdomain_release(struct pcmcia_device *link)
 
 	scsi_remove_host(info->host);
 	pcmcia_disable_device(link);
-	scsi_unregister(info->host);
+	scsi_host_put(info->host);
 }
 
 /*====================================================================*/
Signature · 1 line
Ondrej Zary
#5 lore raw

[RFC PATCH 3/2] fdomain: Use SCSI host private data instead of global variables

In reply to Ondrej Zary

Move global variables into SCSI host private data in order to support multiple cards.

---
 drivers/scsi/fdomain.c | 593 +++++++++++++++++++++++++------------------------
 1 file changed, 307 insertions(+), 286 deletions(-)
drivers/scsi/fdomain.c +307 -286
index fe9e373c27a8..83294cf6b668 100644
@@ -384,29 +384,32 @@ enum out_port_type {
 
 /* .bss will zero all the static variables below */
 static int               port_base;
-static unsigned long     bios_base;
-static void __iomem *    bios_mem;
-static int               bios_major;
-static int               bios_minor;
-static int               PCI_bus;
-#ifdef CONFIG_PCI
-static struct pci_dev	*PCI_dev;
-#endif
-static int               Quantum;	/* Quantum board variant */
 static int               interrupt_level;
-static volatile int      in_command;
-static struct scsi_cmnd  *current_SC;
-static enum chip_type    chip              = unknown;
-static int               adapter_mask;
 static int               this_id;
 static int               setup_called;
 
+struct fdomain {
+	int port_base;
+	unsigned long bios_base;
+	void __iomem *bios_mem;
+	int bios_major;
+	int bios_minor;
+	int PCI_bus;
+#ifdef CONFIG_PCI
+	struct pci_dev *PCI_dev;
+#endif
+	int Quantum;	/* Quantum board variant */
+	int interrupt_level;
+	volatile int in_command;
+	struct scsi_cmnd *current_SC;
+	enum chip_type chip;
+	int adapter_mask;
+	int this_id;
 #if DEBUG_RACE
-static volatile int      in_interrupt_flag;
+	volatile int in_interrupt_flag;
 #endif
-
-static int               FIFO_Size = 0x2000; /* 8k FIFO for
-						pre-tmc18c30 chips */
+	int FIFO_Size;
+};
 
 static irqreturn_t       do_fdomain_16x0_intr( int irq, void *dev_id );
 /* Allow insmod parameters to be like LILO parameters.  For example:
@@ -518,22 +521,22 @@ static struct signature {
 
 static void print_banner( struct Scsi_Host *shpnt )
 {
-   if (!shpnt) return;		/* This won't ever happen */
+	struct fdomain *fd = shost_priv(shpnt);
 
-   if (bios_major < 0 && bios_minor < 0) {
+   if (fd->bios_major < 0 && fd->bios_minor < 0) {
       printk(KERN_INFO "scsi%d: <fdomain> No BIOS; using scsi id %d\n",
 	      shpnt->host_no, shpnt->this_id);
    } else {
       printk(KERN_INFO "scsi%d: <fdomain> BIOS version ", shpnt->host_no);
 
-      if (bios_major >= 0) printk("%d.", bios_major);
+      if (fd->bios_major >= 0) printk("%d.", fd->bios_major);
       else                 printk("?.");
 
-      if (bios_minor >= 0) printk("%d", bios_minor);
+      if (fd->bios_minor >= 0) printk("%d", fd->bios_minor);
       else                 printk("?.");
 
       printk( " at 0x%lx using scsi id %d\n",
-	      bios_base, shpnt->this_id );
+	      fd->bios_base, shpnt->this_id );
    }
 
 				/* If this driver works for later FD PCI
@@ -542,11 +545,11 @@ static void print_banner( struct Scsi_Host *shpnt )
 				   it's PCI it's a TMC-3260 - JTM */
    printk(KERN_INFO "scsi%d: <fdomain> %s chip at 0x%x irq ",
 	   shpnt->host_no,
-	   chip == tmc1800 ? "TMC-1800" : (chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") : "Unknown")),
-	   port_base);
+	   fd->chip == tmc1800 ? "TMC-1800" : (fd->chip == tmc18c50 ? "TMC-18C50" : (fd->chip == tmc18c30 ? (fd->PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") : "Unknown")),
+	   fd->port_base);
 
-   if (interrupt_level)
-   	printk("%d", interrupt_level);
+   if (fd->interrupt_level)
+	printk("%d", fd->interrupt_level);
    else
         printk("<none>");
 
@@ -568,8 +571,7 @@ int fdomain_setup(char *str)
 	port_base       = ints[0] >= 1 ? ints[1] : 0;
 	interrupt_level = ints[0] >= 2 ? ints[2] : 0;
 	this_id         = ints[0] >= 3 ? ints[3] : 0;
-   
-	bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */
+
 	++setup_called;
 	return 1;
 }
@@ -582,22 +584,24 @@ static void do_pause(unsigned amount)	/* Pause for amount*10 milliseconds */
 	mdelay(10*amount);
 }
 
-static inline void fdomain_make_bus_idle( void )
+static inline void fdomain_make_bus_idle(struct fdomain *fd)
 {
-   outb(0, port_base + SCSI_Cntl);
-   outb(0, port_base + SCSI_Mode_Cntl);
-   if (chip == tmc18c50 || chip == tmc18c30)
-	 outb(0x21 | PARITY_MASK, port_base + TMC_Cntl); /* Clear forced intr. */
+   outb(0, fd->port_base + SCSI_Cntl);
+   outb(0, fd->port_base + SCSI_Mode_Cntl);
+   if (fd->chip == tmc18c50 || fd->chip == tmc18c30)
+	 outb(0x21 | PARITY_MASK, fd->port_base + TMC_Cntl); /* Clear forced intr. */
    else
-	 outb(0x01 | PARITY_MASK, port_base + TMC_Cntl);
+	 outb(0x01 | PARITY_MASK, fd->port_base + TMC_Cntl);
 }
 
-static int fdomain_is_valid_port( int port )
+static int fdomain_is_valid_port(struct fdomain *fd, int port)
 {
 #if DEBUG_DETECT 
    printk( " (%x%x),",
 	   inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
 #endif
+	fd->chip = unknown;
+	fd->FIFO_Size = 0x2000; /* 8k FIFO for pre-tmc18c30 chips */
 
    /* The MCA ID is a unique id for each MCA compatible board.  We
       are using ISA boards, but Future Domain provides the MCA ID
@@ -608,10 +612,10 @@ static int fdomain_is_valid_port( int port )
    if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */
       if (inb( port + LSB_ID_Code ) != 0x27) return 0;
       if (inb( port + MSB_ID_Code ) != 0x61) return 0;
-      chip = tmc1800;
+      fd->chip = tmc1800;
    } else {				    /* test for 0xe960 id */
       if (inb( port + MSB_ID_Code ) != 0x60) return 0;
-      chip = tmc18c50;
+      fd->chip = tmc18c50;
 
 				/* Try to toggle 32-bit mode.  This only
 				   works on an 18c30 chip.  (User reports
@@ -622,8 +626,8 @@ static int fdomain_is_valid_port( int port )
       if ((inb( port + Configuration2 ) & 0x80) == 0x80) {
 	 outb( 0x00, port + IO_Control );
 	 if ((inb( port + Configuration2 ) & 0x80) == 0x00) {
-	    chip = tmc18c30;
-	    FIFO_Size = 0x800;	/* 2k FIFO */
+	    fd->chip = tmc18c30;
+	    fd->FIFO_Size = 0x800;	/* 2k FIFO */
 	 }
       }
 				/* If that failed, we are an 18c50. */
@@ -632,14 +636,14 @@ static int fdomain_is_valid_port( int port )
    return 1;
 }
 
-static int fdomain_test_loopback( void )
+static int fdomain_test_loopback(int port_base)
 {
    int i;
    int result;
 
    for (i = 0; i < 255; i++) {
-      outb( i, port_base + Write_Loopback );
-      result = inb( port_base + Read_Loopback );
+      outb(i, port_base + Write_Loopback);
+      result = inb(port_base + Read_Loopback);
       if (i != result)
 	    return 1;
    }
@@ -662,7 +666,7 @@ static int fdomain_test_loopback( void )
    configure a PCI system so that one of these IRQs will be used by the
    Future Domain card. */
 
-static int fdomain_get_irq( int base )
+static int fdomain_get_irq(struct fdomain *fd, int base)
 {
    int options = inb(base + Configuration1);
 
@@ -675,12 +679,12 @@ static int fdomain_get_irq( int base )
       boards on the PCI bus, so just assume we
       have the right board. */
 
-   if (chip != tmc18c30 && !PCI_bus && addresses[(options & 0xc0) >> 6 ] != bios_base)
+   if (fd->chip != tmc18c30 && !fd->PCI_bus && addresses[(options & 0xc0) >> 6 ] != fd->bios_base)
    	return 0;
    return ints[(options & 0x0e) >> 1];
 }
 
-static int fdomain_isa_detect( int *irq, int *iobase )
+static int fdomain_isa_detect(struct fdomain *fd)
 {
    int i, j;
    int base = 0xdeadbeef;
@@ -695,18 +699,18 @@ static int fdomain_isa_detect( int *irq, int *iobase )
       if (!p)
 	continue;
 #if DEBUG_DETECT
-      printk( " %lx(%lx),", addresses[i], bios_base );
+      printk( " %lx(%lx),", addresses[i], fd->bios_base );
 #endif
       for (j = 0; j < SIGNATURE_COUNT; j++) {
 	 if (check_signature(p + signatures[j].sig_offset,
 			     signatures[j].signature,
 			     signatures[j].sig_length )) {
-	    bios_major = signatures[j].major_bios_version;
-	    bios_minor = signatures[j].minor_bios_version;
-	    PCI_bus    = (signatures[j].flag == 1);
-	    Quantum    = (signatures[j].flag > 1) ? signatures[j].flag : 0;
-	    bios_base  = addresses[i];
-	    bios_mem   = p;
+	    fd->bios_major = signatures[j].major_bios_version;
+	    fd->bios_minor = signatures[j].minor_bios_version;
+	    fd->PCI_bus    = (signatures[j].flag == 1);
+	    fd->Quantum    = (signatures[j].flag > 1) ? signatures[j].flag : 0;
+	    fd->bios_base  = addresses[i];
+	    fd->bios_mem   = p;
 	    goto found;
 	 }
       }
@@ -714,7 +718,7 @@ static int fdomain_isa_detect( int *irq, int *iobase )
    }
  
 found:
-   if (bios_major == 2) {
+   if (fd->bios_major == 2) {
       /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
 	 Assuming the ROM is enabled (otherwise we wouldn't have been
 	 able to read the ROM signature :-), then the ROM sets up the
@@ -723,16 +727,16 @@ static int fdomain_isa_detect( int *irq, int *iobase )
 	 DOS (this geometry has nothing to do with physical geometry).
        */
 
-      switch (Quantum) {
+      switch (fd->Quantum) {
       case 2:			/* ISA_200S */
       case 3:			/* ISA_250MG */
-	 base = readb(bios_mem + 0x1fa2) + (readb(bios_mem + 0x1fa3) << 8);
+	 base = readb(fd->bios_mem + 0x1fa2) + (readb(fd->bios_mem + 0x1fa3) << 8);
 	 break;
       case 4:			/* ISA_200S (another one) */
-	 base = readb(bios_mem + 0x1fa3) + (readb(bios_mem + 0x1fa4) << 8);
+	 base = readb(fd->bios_mem + 0x1fa3) + (readb(fd->bios_mem + 0x1fa4) << 8);
 	 break;
       default:
-	 base = readb(bios_mem + 0x1fcc) + (readb(bios_mem + 0x1fcd) << 8);
+	 base = readb(fd->bios_mem + 0x1fcc) + (readb(fd->bios_mem + 0x1fcd) << 8);
 	 break;
       }
    
@@ -744,12 +748,12 @@ static int fdomain_isa_detect( int *irq, int *iobase )
 	if (base == ports[i]) {
 		if (!request_region(base, 0x10, "fdomain"))
 			break;
-		if (!fdomain_is_valid_port(base)) {
+		if (!fdomain_is_valid_port(fd, base)) {
 			release_region(base, 0x10);
 			break;
 		}
-		*irq    = fdomain_get_irq( base );
-		*iobase = base;
+		fd->interrupt_level    = fdomain_get_irq(fd, base);
+		fd->port_base = base;
 		return 1;
 	}
       }
@@ -783,7 +787,7 @@ static int fdomain_isa_detect( int *irq, int *iobase )
 #if DEBUG_DETECT
       printk( " %x,", base );
 #endif
-      flag = fdomain_is_valid_port(base);
+      flag = fdomain_is_valid_port(fd, base);
       if (flag)
 	break;
       release_region(base, 0x10);
@@ -796,20 +800,18 @@ static int fdomain_isa_detect( int *irq, int *iobase )
 
    if (!flag) return 0;		/* iobase not found */
 
-   *irq    = fdomain_get_irq( base );
-   *iobase = base;
+   fd->interrupt_level    = fdomain_get_irq(fd, base);
+   fd->port_base = base;
 
    return 1;			/* success */
 }
 
 #else /* PCMCIA */
 
-static int fdomain_isa_detect( int *irq, int *iobase )
+static int fdomain_isa_detect(struct fdomain *fd)
 {
-	if (irq)
-		*irq = 0;
-	if (iobase)
-		*iobase = 0;
+	fd->interrupt_level = 0;
+	fd->port_base = 0;
 	return 0;
 }
 
@@ -821,7 +823,7 @@ static int fdomain_isa_detect( int *irq, int *iobase )
    the PCI configuration registers. */
 
 #ifdef CONFIG_PCI
-static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_pdev )
+static int fdomain_pci_bios_detect(struct fdomain *fd)
 {
    unsigned int     pci_irq;                /* PCI interrupt line */
    unsigned long    pci_base;               /* PCI I/O base address */
@@ -863,27 +865,26 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_
    /* Now we have the I/O base address and interrupt from the PCI
       configuration registers. */
 
-   *irq    = pci_irq;
-   *iobase = pci_base;
-   *ret_pdev = pdev;
+   fd->interrupt_level    = pci_irq;
+   fd->port_base = pci_base;
 
 #if DEBUG_DETECT
    printk( "scsi: <fdomain> TMC-3260 detect:"
-	   " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );
+	   " IRQ = %d, I/O base = 0x%x [0x%lx]\n", fd->interrupt_level, fd->port_base, pci_base );
 #endif
 
-   if (!fdomain_is_valid_port(pci_base)) {
+   if (!fdomain_is_valid_port(fd, pci_base)) {
       printk(KERN_ERR "scsi: <fdomain> PCI card detected, but driver not loaded (invalid port)\n" );
       release_region(pci_base, 0x10);
       goto fail;
    }
 
 				/* Fill in a few global variables.  Ugh. */
-   bios_major = bios_minor = -1;
-   PCI_bus    = 1;
-   PCI_dev    = pdev;
-   Quantum    = 0;
-   bios_base  = 0;
+   fd->bios_major = fd->bios_minor = -1;
+   fd->PCI_bus    = 1;
+   fd->PCI_dev    = pdev;
+   fd->Quantum    = 0;
+   fd->bios_base  = 0;
    
    return 1;
 fail:
@@ -893,12 +894,24 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_
 
 #endif
 
+void fdomain_16x0_reset(int port_base)
+{
+   outb(1, port_base + SCSI_Cntl);
+   do_pause( 2 );
+   outb(0, port_base + SCSI_Cntl);
+   do_pause( 115 );
+   outb(0, port_base + SCSI_Mode_Cntl);
+   outb(PARITY_MASK, port_base + TMC_Cntl);
+}
+
 struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
 {
    int              retcode;
    struct Scsi_Host *shpnt;
-   struct pci_dev *pdev = NULL;
+   struct fdomain fd_tmp;
+   struct fdomain *fd;
 
+   memset(&fd_tmp, 0, sizeof(struct fdomain));
    if (setup_called) {
 #if DEBUG_DETECT
       printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
@@ -909,23 +922,27 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
 	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
 	 return NULL;
       }
-      if (!fdomain_is_valid_port( port_base )) {
+      if (!fdomain_is_valid_port(&fd_tmp, port_base)) {
 	 printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
 		 port_base );
 	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
 	 release_region(port_base, 0x10);
 	 return NULL;
       }
+      fd_tmp.port_base = port_base;
+      fd_tmp.interrupt_level = interrupt_level;
+      fd_tmp.this_id = this_id;
+      fd_tmp.bios_major = fd_tmp.bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */
    } else {
       int flag = 0;
 
 #ifdef CONFIG_PCI
 				/* Try PCI detection first */
-      flag = fdomain_pci_bios_detect( &interrupt_level, &port_base, &pdev );
+      flag = fdomain_pci_bios_detect(&fd_tmp);
 #endif
       if (!flag) {
 				/* Then try ISA bus detection */
-	 flag = fdomain_isa_detect( &interrupt_level, &port_base );
+	 flag = fdomain_isa_detect(&fd_tmp);
 
 	 if (!flag) {
 	    printk( "scsi: <fdomain> Detection failed (no card)\n" );
@@ -934,62 +951,64 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
       }
    }
 
-   fdomain_16x0_host_reset(NULL);
+   fdomain_16x0_reset(fd_tmp.port_base);
 
-   if (fdomain_test_loopback()) {
-      printk(KERN_ERR  "scsi: <fdomain> Detection failed (loopback test failed at port base 0x%x)\n", port_base);
+   if (fdomain_test_loopback(fd_tmp.port_base)) {
+      printk(KERN_ERR  "scsi: <fdomain> Detection failed (loopback test failed at port base 0x%x)\n", fd_tmp.port_base);
       if (setup_called) {
 	 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
       }
       goto fail;
    }
 
-   if (this_id) {
-      tpnt->this_id = (this_id & 0x07);
-      adapter_mask  = (1 << tpnt->this_id);
+   if (fd_tmp.this_id) {
+      tpnt->this_id = (fd_tmp.this_id & 0x07);
+      fd_tmp.adapter_mask  = (1 << tpnt->this_id);
    } else {
-      if (PCI_bus || (bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
+      if (fd_tmp.PCI_bus || (fd_tmp.bios_major == 3 && fd_tmp.bios_minor >= 2) || fd_tmp.bios_major < 0) {
 	 tpnt->this_id = 7;
-	 adapter_mask  = 0x80;
+	 fd_tmp.adapter_mask  = 0x80;
       } else {
 	 tpnt->this_id = 6;
-	 adapter_mask  = 0x40;
+	 fd_tmp.adapter_mask  = 0x40;
       }
    }
 
 /* Print out a banner here in case we can't
    get resources.  */
 
-   shpnt = scsi_host_alloc( tpnt, 0 );
+   shpnt = scsi_host_alloc(tpnt, sizeof(struct fdomain));
    if(shpnt == NULL) {
-	release_region(port_base, 0x10);
+	release_region(fd_tmp.port_base, 0x10);
    	return NULL;
    }
-   shpnt->irq = interrupt_level;
-   shpnt->io_port = port_base;
+   fd = shost_priv(shpnt);
+   memcpy(fd, &fd_tmp, sizeof(struct fdomain));
+   shpnt->irq = fd->interrupt_level;
+   shpnt->io_port = fd->port_base;
    shpnt->n_io_port = 0x10;
    print_banner( shpnt );
 
    /* Log IRQ with kernel */   
-   if (!interrupt_level) {
+   if (!fd->interrupt_level) {
       printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
       goto fail;
    } else {
       /* Register the IRQ with the kernel */
 
-      retcode = request_irq( interrupt_level,
-			     do_fdomain_16x0_intr, pdev?IRQF_SHARED:0, "fdomain", shpnt);
+      retcode = request_irq(fd->interrupt_level,
+			     do_fdomain_16x0_intr, fd->PCI_dev?IRQF_SHARED:0, "fdomain", fd);
 
       if (retcode < 0) {
 	 if (retcode == -EINVAL) {
-	    printk(KERN_ERR "scsi: <fdomain> IRQ %d is bad!\n", interrupt_level );
+	    printk(KERN_ERR "scsi: <fdomain> IRQ %d is bad!\n", fd->interrupt_level);
 	    printk(KERN_ERR "                This shouldn't happen!\n" );
 	    printk(KERN_ERR "                Send mail to [email protected]\n" );
 	 } else if (retcode == -EBUSY) {
-	    printk(KERN_ERR "scsi: <fdomain> IRQ %d is already in use!\n", interrupt_level );
+	    printk(KERN_ERR "scsi: <fdomain> IRQ %d is already in use!\n", fd->interrupt_level);
 	    printk(KERN_ERR "                Please use another IRQ!\n" );
 	 } else {
-	    printk(KERN_ERR "scsi: <fdomain> Error getting IRQ %d\n", interrupt_level );
+	    printk(KERN_ERR "scsi: <fdomain> Error getting IRQ %d\n", fd->interrupt_level);
 	    printk(KERN_ERR "                This shouldn't happen!\n" );
 	    printk(KERN_ERR "                Send mail to [email protected]\n" );
 	 }
@@ -999,8 +1018,8 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
    }
    return shpnt;
 fail:
-   pci_dev_put(pdev);
-   release_region(port_base, 0x10);
+   pci_dev_put(fd->PCI_dev);
+   release_region(fd->port_base, 0x10);
    return NULL;
 }
 
@@ -1036,7 +1055,7 @@ static int fdomain_arbitrate( void )
 #endif
    
    outb(0x00, port_base + SCSI_Cntl);              /* Disable data drivers */
-   outb(adapter_mask, port_base + SCSI_Data_NoACK); /* Set our id bit */
+   outb(fd->adapter_mask, port_base + SCSI_Data_NoACK); /* Set our id bit */
    outb(0x04 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */
 
    timeout = 500;
@@ -1048,7 +1067,7 @@ static int fdomain_arbitrate( void )
    } while (--timeout);
 
    /* Make bus idle */
-   fdomain_make_bus_idle();
+   fdomain_make_bus_idle(fd);
 
 #if EVERY_ACCESS
    printk( "Arbitration failed, status = %x\n", status );
@@ -1060,7 +1079,7 @@ static int fdomain_arbitrate( void )
 }
 #endif
 
-static int fdomain_select( int target )
+static int fdomain_select(struct fdomain *fd, int target)
 {
    int           status;
    unsigned long timeout;
@@ -1068,25 +1087,25 @@ static int fdomain_select( int target )
    static int    flag = 0;
 #endif
 
-   outb(0x82, port_base + SCSI_Cntl); /* Bus Enable + Select */
-   outb(adapter_mask | (1 << target), port_base + SCSI_Data_NoACK);
+   outb(0x82, fd->port_base + SCSI_Cntl); /* Bus Enable + Select */
+   outb(fd->adapter_mask | (1 << target), fd->port_base + SCSI_Data_NoACK);
 
    /* Stop arbitration and enable parity */
-   outb(PARITY_MASK, port_base + TMC_Cntl); 
+   outb(PARITY_MASK, fd->port_base + TMC_Cntl); 
 
    timeout = 350;			/* 350 msec */
 
    do {
-      status = inb(port_base + SCSI_Status); /* Read adapter status */
+      status = inb(fd->port_base + SCSI_Status); /* Read adapter status */
       if (status & 1) {			/* Busy asserted */
 	 /* Enable SCSI Bus (on error, should make bus idle with 0) */
-	 outb(0x80, port_base + SCSI_Cntl);
+	 outb(0x80,fd-> port_base + SCSI_Cntl);
 	 return 0;
       }
       mdelay(1);			/* wait one msec */
    } while (--timeout);
    /* Make bus idle */
-   fdomain_make_bus_idle();
+   fdomain_make_bus_idle(fd);
 #if EVERY_ACCESS
    if (!target) printk( "Selection failed\n" );
 #endif
@@ -1101,26 +1120,27 @@ static int fdomain_select( int target )
    return 1;
 }
 
-static void my_done(int error)
+static void my_done(struct fdomain *fd, int error)
 {
-   if (in_command) {
-      in_command = 0;
-      outb(0x00, port_base + Interrupt_Cntl);
-      fdomain_make_bus_idle();
-      current_SC->result = error;
-      if (current_SC->scsi_done)
-	    current_SC->scsi_done( current_SC );
+   if (fd->in_command) {
+      fd->in_command = 0;
+      outb(0x00, fd->port_base + Interrupt_Cntl);
+      fdomain_make_bus_idle(fd);
+      fd->current_SC->result = error;
+      if (fd->current_SC->scsi_done)
+	    fd->current_SC->scsi_done(fd->current_SC);
       else panic( "scsi: <fdomain> current_SC->scsi_done() == NULL" );
    } else {
       panic( "scsi: <fdomain> my_done() called outside of command\n" );
    }
 #if DEBUG_RACE
-   in_interrupt_flag = 0;
+   fd->in_interrupt_flag = 0;
 #endif
 }
 
 static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
 {
+   struct fdomain *fd = dev_id;
    unsigned long flags;
    int      status;
    int      done = 0;
@@ -1133,23 +1153,23 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
 				   running. */
 
    /* Check for other IRQ sources */
-   if ((inb(port_base + TMC_Status) & 0x01) == 0)
+   if ((inb(fd->port_base + TMC_Status) & 0x01) == 0)
    	return IRQ_NONE;
 
    /* It is our IRQ */   	
-   outb(0x00, port_base + Interrupt_Cntl);
+   outb(0x00, fd->port_base + Interrupt_Cntl);
 
    /* We usually have one spurious interrupt after each command.  Ignore it. */
-   if (!in_command || !current_SC) {	/* Spurious interrupt */
+   if (!fd->in_command || !fd->current_SC) {	/* Spurious interrupt */
 #if EVERY_ACCESS
       printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
-	      in_command, current_SC );
+	      fd->in_command, fd->current_SC);
 #endif
       return IRQ_NONE;
    }
 
    /* Abort calls my_done, so we do nothing here. */
-   if (current_SC->SCp.phase & aborted) {
+   if (fd->current_SC->SCp.phase & aborted) {
 #if DEBUG_ABORT
       printk( "scsi: <fdomain> Interrupt after abort, ignoring\n" );
 #endif
@@ -1158,212 +1178,212 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
    }
 
 #if DEBUG_RACE
-   ++in_interrupt_flag;
+   ++fd->in_interrupt_flag;
 #endif
 
-   if (current_SC->SCp.phase & in_arbitration) {
-      status = inb(port_base + TMC_Status);        /* Read adapter status */
+   if (fd->current_SC->SCp.phase & in_arbitration) {
+      status = inb(fd->port_base + TMC_Status);        /* Read adapter status */
       if (!(status & 0x02)) {
 #if EVERY_ACCESS
 	 printk( " AFAIL " );
 #endif
-         spin_lock_irqsave(current_SC->device->host->host_lock, flags);
-	 my_done( DID_BUS_BUSY << 16 );
-         spin_unlock_irqrestore(current_SC->device->host->host_lock, flags);
+         spin_lock_irqsave(fd->current_SC->device->host->host_lock, flags);
+	 my_done(fd, DID_BUS_BUSY << 16);
+         spin_unlock_irqrestore(fd->current_SC->device->host->host_lock, flags);
 	 return IRQ_HANDLED;
       }
-      current_SC->SCp.phase = in_selection;
+      fd->current_SC->SCp.phase = in_selection;
       
-      outb(0x40 | FIFO_COUNT, port_base + Interrupt_Cntl);
+      outb(0x40 | FIFO_COUNT, fd->port_base + Interrupt_Cntl);
 
-      outb(0x82, port_base + SCSI_Cntl); /* Bus Enable + Select */
-      outb(adapter_mask | (1 << scmd_id(current_SC)), port_base + SCSI_Data_NoACK);
+      outb(0x82, fd->port_base + SCSI_Cntl); /* Bus Enable + Select */
+      outb(fd->adapter_mask | (1 << scmd_id(fd->current_SC)), fd->port_base + SCSI_Data_NoACK);
       
       /* Stop arbitration and enable parity */
-      outb(0x10 | PARITY_MASK, port_base + TMC_Cntl);
+      outb(0x10 | PARITY_MASK, fd->port_base + TMC_Cntl);
 #if DEBUG_RACE
-      in_interrupt_flag = 0;
+      fd->in_interrupt_flag = 0;
 #endif
       return IRQ_HANDLED;
-   } else if (current_SC->SCp.phase & in_selection) {
-      status = inb(port_base + SCSI_Status);
+   } else if (fd->current_SC->SCp.phase & in_selection) {
+      status = inb(fd->port_base + SCSI_Status);
       if (!(status & 0x01)) {
 	 /* Try again, for slow devices */
-	 if (fdomain_select( scmd_id(current_SC) )) {
+	 if (fdomain_select(fd,scmd_id(fd->current_SC))) {
 #if EVERY_ACCESS
 	    printk( " SFAIL " );
 #endif
-            spin_lock_irqsave(current_SC->device->host->host_lock, flags);
-	    my_done( DID_NO_CONNECT << 16 );
-            spin_unlock_irqrestore(current_SC->device->host->host_lock, flags);
+            spin_lock_irqsave(fd->current_SC->device->host->host_lock, flags);
+	    my_done(fd, DID_NO_CONNECT << 16);
+            spin_unlock_irqrestore(fd->current_SC->device->host->host_lock, flags);
 	    return IRQ_HANDLED;
 	 } else {
 #if EVERY_ACCESS
 	    printk( " AltSel " );
 #endif
 	    /* Stop arbitration and enable parity */
-	    outb(0x10 | PARITY_MASK, port_base + TMC_Cntl);
+	    outb(0x10 | PARITY_MASK, fd->port_base + TMC_Cntl);
 	 }
       }
-      current_SC->SCp.phase = in_other;
-      outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl);
-      outb(0x80, port_base + SCSI_Cntl);
+      fd->current_SC->SCp.phase = in_other;
+      outb(0x90 | FIFO_COUNT, fd->port_base + Interrupt_Cntl);
+      outb(0x80, fd->port_base + SCSI_Cntl);
 #if DEBUG_RACE
-      in_interrupt_flag = 0;
+      fd->in_interrupt_flag = 0;
 #endif
       return IRQ_HANDLED;
    }
    
    /* current_SC->SCp.phase == in_other: this is the body of the routine */
    
-   status = inb(port_base + SCSI_Status);
+   status = inb(fd->port_base + SCSI_Status);
    
    if (status & 0x10) {	/* REQ */
       
       switch (status & 0x0e) {
        
       case 0x08:		/* COMMAND OUT */
-	 outb(current_SC->cmnd[current_SC->SCp.sent_command++],
-	      port_base + Write_SCSI_Data);
+	 outb(fd->current_SC->cmnd[fd->current_SC->SCp.sent_command++],
+	      fd->port_base + Write_SCSI_Data);
 #if EVERY_ACCESS
 	 printk( "CMD = %x,",
-		 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
+		 fd->current_SC->cmnd[fd->current_SC->SCp.sent_command - 1]);
 #endif
 	 break;
       case 0x00:		/* DATA OUT -- tmc18c50/tmc18c30 only */
-	 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
-	    current_SC->SCp.have_data_in = -1;
-	    outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl);
+	 if (fd->chip != tmc1800 && !fd->current_SC->SCp.have_data_in) {
+	    fd->current_SC->SCp.have_data_in = -1;
+	    outb(0xd0 | PARITY_MASK, fd->port_base + TMC_Cntl);
 	 }
 	 break;
       case 0x04:		/* DATA IN -- tmc18c50/tmc18c30 only */
-	 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
-	    current_SC->SCp.have_data_in = 1;
-	    outb(0x90 | PARITY_MASK, port_base + TMC_Cntl);
+	 if (fd->chip != tmc1800 && !fd->current_SC->SCp.have_data_in) {
+	    fd->current_SC->SCp.have_data_in = 1;
+	    outb(0x90 | PARITY_MASK, fd->port_base + TMC_Cntl);
 	 }
 	 break;
       case 0x0c:		/* STATUS IN */
-	 current_SC->SCp.Status = inb(port_base + Read_SCSI_Data);
+	 fd->current_SC->SCp.Status = inb(fd->port_base + Read_SCSI_Data);
 #if EVERY_ACCESS
-	 printk( "Status = %x, ", current_SC->SCp.Status );
+	 printk( "Status = %x, ", fd->current_SC->SCp.Status );
 #endif
 #if ERRORS_ONLY
-	 if (current_SC->SCp.Status
-	     && current_SC->SCp.Status != 2
-	     && current_SC->SCp.Status != 8) {
+	 if (fd->current_SC->SCp.Status
+	     && fd->current_SC->SCp.Status != 2
+	     && fd->current_SC->SCp.Status != 8) {
 	    printk( "scsi: <fdomain> target = %d, command = %x, status = %x\n",
-		    current_SC->device->id,
-		    current_SC->cmnd[0],
-		    current_SC->SCp.Status );
+		    fd->current_SC->device->id,
+		    fd->current_SC->cmnd[0],
+		    fd->current_SC->SCp.Status );
 	 }
 #endif
 	       break;
       case 0x0a:		/* MESSAGE OUT */
-	 outb(MESSAGE_REJECT, port_base + Write_SCSI_Data); /* Reject */
+	 outb(MESSAGE_REJECT, fd->port_base + Write_SCSI_Data); /* Reject */
 	 break;
       case 0x0e:		/* MESSAGE IN */
-	 current_SC->SCp.Message = inb(port_base + Read_SCSI_Data);
+	 fd->current_SC->SCp.Message = inb(fd->port_base + Read_SCSI_Data);
 #if EVERY_ACCESS
-	 printk( "Message = %x, ", current_SC->SCp.Message );
+	 printk( "Message = %x, ", fd->current_SC->SCp.Message );
 #endif
-	 if (!current_SC->SCp.Message) ++done;
+	 if (!fd->current_SC->SCp.Message) ++done;
 #if DEBUG_MESSAGES || EVERY_ACCESS
-	 if (current_SC->SCp.Message) {
+	 if (fd->current_SC->SCp.Message) {
 	    printk( "scsi: <fdomain> message = %x\n",
-		    current_SC->SCp.Message );
+		    fd->current_SC->SCp.Message );
 	 }
 #endif
 	 break;
       }
    }
 
-   if (chip == tmc1800 && !current_SC->SCp.have_data_in
-       && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
+   if (fd->chip == tmc1800 && !fd->current_SC->SCp.have_data_in
+       && (fd->current_SC->SCp.sent_command >= fd->current_SC->cmd_len)) {
       
-      if(current_SC->sc_data_direction == DMA_TO_DEVICE)
+      if (fd->current_SC->sc_data_direction == DMA_TO_DEVICE)
       {
-	 current_SC->SCp.have_data_in = -1;
-	 outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl);
+	 fd->current_SC->SCp.have_data_in = -1;
+	 outb(0xd0 | PARITY_MASK, fd->port_base + TMC_Cntl);
       }
       else
       {
-	 current_SC->SCp.have_data_in = 1;
-	 outb(0x90 | PARITY_MASK, port_base + TMC_Cntl);
+	 fd->current_SC->SCp.have_data_in = 1;
+	 outb(0x90 | PARITY_MASK, fd->port_base + TMC_Cntl);
       }
    }
 
-   if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
-      while ((data_count = FIFO_Size - inw(port_base + FIFO_Data_Count)) > 512) {
+   if (fd->current_SC->SCp.have_data_in == -1) { /* DATA OUT */
+      while ((data_count = fd->FIFO_Size - inw(fd->port_base + FIFO_Data_Count)) > 512) {
 #if EVERY_ACCESS
 	 printk( "DC=%d, ", data_count ) ;
 #endif
-	 if (data_count > current_SC->SCp.this_residual)
-	       data_count = current_SC->SCp.this_residual;
+	 if (data_count > fd->current_SC->SCp.this_residual)
+	       data_count = fd->current_SC->SCp.this_residual;
 	 if (data_count > 0) {
 #if EVERY_ACCESS
 	    printk( "%d OUT, ", data_count );
 #endif
 	    if (data_count == 1) {
-	       outb(*current_SC->SCp.ptr++, port_base + Write_FIFO);
-	       --current_SC->SCp.this_residual;
+	       outb(*fd->current_SC->SCp.ptr++, fd->port_base + Write_FIFO);
+	       --fd->current_SC->SCp.this_residual;
 	    } else {
 	       data_count >>= 1;
-	       outsw(port_base + Write_FIFO, current_SC->SCp.ptr, data_count);
-	       current_SC->SCp.ptr += 2 * data_count;
-	       current_SC->SCp.this_residual -= 2 * data_count;
+	       outsw(fd->port_base + Write_FIFO, fd->current_SC->SCp.ptr, data_count);
+	       fd->current_SC->SCp.ptr += 2 * data_count;
+	       fd->current_SC->SCp.this_residual -= 2 * data_count;
 	    }
 	 }
-	 if (!current_SC->SCp.this_residual) {
-	    if (current_SC->SCp.buffers_residual) {
-	       --current_SC->SCp.buffers_residual;
-	       ++current_SC->SCp.buffer;
-	       current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
-	       current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
+	 if (!fd->current_SC->SCp.this_residual) {
+	    if (fd->current_SC->SCp.buffers_residual) {
+	       --fd->current_SC->SCp.buffers_residual;
+	       ++fd->current_SC->SCp.buffer;
+	       fd->current_SC->SCp.ptr = sg_virt(fd->current_SC->SCp.buffer);
+	       fd->current_SC->SCp.this_residual = fd->current_SC->SCp.buffer->length;
 	    } else
 		  break;
 	 }
       }
    }
    
-   if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
-      while ((data_count = inw(port_base + FIFO_Data_Count)) > 0) {
+   if (fd->current_SC->SCp.have_data_in == 1) { /* DATA IN */
+      while ((data_count = inw(fd->port_base + FIFO_Data_Count)) > 0) {
 #if EVERY_ACCESS
 	 printk( "DC=%d, ", data_count );
 #endif
-	 if (data_count > current_SC->SCp.this_residual)
-	       data_count = current_SC->SCp.this_residual;
+	 if (data_count > fd->current_SC->SCp.this_residual)
+	       data_count = fd->current_SC->SCp.this_residual;
 	 if (data_count) {
 #if EVERY_ACCESS
 	    printk( "%d IN, ", data_count );
 #endif
 	    if (data_count == 1) {
-	       *current_SC->SCp.ptr++ = inb(port_base + Read_FIFO);
-	       --current_SC->SCp.this_residual;
+	       *fd->current_SC->SCp.ptr++ = inb(fd->port_base + Read_FIFO);
+	       --fd->current_SC->SCp.this_residual;
 	    } else {
 	       data_count >>= 1; /* Number of words */
-	       insw(port_base + Read_FIFO, current_SC->SCp.ptr, data_count);
-	       current_SC->SCp.ptr += 2 * data_count;
-	       current_SC->SCp.this_residual -= 2 * data_count;
+	       insw(fd->port_base + Read_FIFO, fd->current_SC->SCp.ptr, data_count);
+	       fd->current_SC->SCp.ptr += 2 * data_count;
+	       fd->current_SC->SCp.this_residual -= 2 * data_count;
 	    }
 	 }
-	 if (!current_SC->SCp.this_residual
-	     && current_SC->SCp.buffers_residual) {
-	    --current_SC->SCp.buffers_residual;
-	    ++current_SC->SCp.buffer;
-	    current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
-	    current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
+	 if (!fd->current_SC->SCp.this_residual
+	     && fd->current_SC->SCp.buffers_residual) {
+	    --fd->current_SC->SCp.buffers_residual;
+	    ++fd->current_SC->SCp.buffer;
+	    fd->current_SC->SCp.ptr = sg_virt(fd->current_SC->SCp.buffer);
+	    fd->current_SC->SCp.this_residual = fd->current_SC->SCp.buffer->length;
 	 }
       }
    }
    
    if (done) {
 #if EVERY_ACCESS
-      printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
+      printk( " ** IN DONE %d ** ", fd->current_SC->SCp.have_data_in );
 #endif
 
 #if ERRORS_ONLY
-      if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
-	      char *buf = scsi_sglist(current_SC);
+      if (fd->current_SC->cmnd[0] == REQUEST_SENSE && !fd->current_SC->SCp.Status) {
+	      char *buf = scsi_sglist(fd->current_SC);
 	 if ((unsigned char)(*(buf + 2)) & 0x0f) {
 	    unsigned char key;
 	    unsigned char code;
@@ -1390,24 +1410,24 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
 #if EVERY_ACCESS
       printk( "BEFORE MY_DONE. . ." );
 #endif
-      spin_lock_irqsave(current_SC->device->host->host_lock, flags);
-      my_done( (current_SC->SCp.Status & 0xff)
-	       | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
-      spin_unlock_irqrestore(current_SC->device->host->host_lock, flags);
+      spin_lock_irqsave(fd->current_SC->device->host->host_lock, flags);
+      my_done(fd, (fd->current_SC->SCp.Status & 0xff)
+	       | ((fd->current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
+      spin_unlock_irqrestore(fd->current_SC->device->host->host_lock, flags);
 #if EVERY_ACCESS
       printk( "RETURNING.\n" );
 #endif
       
    } else {
-      if (current_SC->SCp.phase & disconnect) {
-	 outb(0xd0 | FIFO_COUNT, port_base + Interrupt_Cntl);
-	 outb(0x00, port_base + SCSI_Cntl);
+      if (fd->current_SC->SCp.phase & disconnect) {
+	 outb(0xd0 | FIFO_COUNT, fd->port_base + Interrupt_Cntl);
+	 outb(0x00, fd->port_base + SCSI_Cntl);
       } else {
-	 outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl);
+	 outb(0x90 | FIFO_COUNT, fd->port_base + Interrupt_Cntl);
       }
    }
 #if DEBUG_RACE
-   in_interrupt_flag = 0;
+   fd->in_interrupt_flag = 0;
 #endif
    return IRQ_HANDLED;
 }
@@ -1415,7 +1435,9 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
 static int fdomain_16x0_queue_lck(struct scsi_cmnd *SCpnt,
 		void (*done)(struct scsi_cmnd *))
 {
-   if (in_command) {
+	struct fdomain *fd = shost_priv(SCpnt->device->host);
+
+   if (fd->in_command) {
       panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
    }
 #if EVERY_ACCESS
@@ -1426,38 +1448,38 @@ static int fdomain_16x0_queue_lck(struct scsi_cmnd *SCpnt,
 	   scsi_bufflen(SCpnt));
 #endif
 
-   fdomain_make_bus_idle();
+   fdomain_make_bus_idle(fd);
 
-   current_SC            = SCpnt; /* Save this for the done function */
-   current_SC->scsi_done = done;
+   fd->current_SC            = SCpnt; /* Save this for the done function */
+   fd->current_SC->scsi_done = done;
 
    /* Initialize static data */
 
-   if (scsi_sg_count(current_SC)) {
-	   current_SC->SCp.buffer = scsi_sglist(current_SC);
-	   current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
-	   current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;
-	   current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
+   if (scsi_sg_count(fd->current_SC)) {
+	   fd->current_SC->SCp.buffer = scsi_sglist(fd->current_SC);
+	   fd->current_SC->SCp.ptr = sg_virt(fd->current_SC->SCp.buffer);
+	   fd->current_SC->SCp.this_residual    = fd->current_SC->SCp.buffer->length;
+	   fd->current_SC->SCp.buffers_residual = scsi_sg_count(fd->current_SC) - 1;
    } else {
-	   current_SC->SCp.ptr              = NULL;
-	   current_SC->SCp.this_residual    = 0;
-	   current_SC->SCp.buffer           = NULL;
-	   current_SC->SCp.buffers_residual = 0;
+	   fd->current_SC->SCp.ptr              = NULL;
+	   fd->current_SC->SCp.this_residual    = 0;
+	   fd->current_SC->SCp.buffer           = NULL;
+	   fd->current_SC->SCp.buffers_residual = 0;
    }
 
-   current_SC->SCp.Status              = 0;
-   current_SC->SCp.Message             = 0;
-   current_SC->SCp.have_data_in        = 0;
-   current_SC->SCp.sent_command        = 0;
-   current_SC->SCp.phase               = in_arbitration;
+   fd->current_SC->SCp.Status              = 0;
+   fd->current_SC->SCp.Message             = 0;
+   fd->current_SC->SCp.have_data_in        = 0;
+   fd->current_SC->SCp.sent_command        = 0;
+   fd->current_SC->SCp.phase               = in_arbitration;
 
    /* Start arbitration */
-   outb(0x00, port_base + Interrupt_Cntl);
-   outb(0x00, port_base + SCSI_Cntl);              /* Disable data drivers */
-   outb(adapter_mask, port_base + SCSI_Data_NoACK); /* Set our id bit */
-   ++in_command;
-   outb(0x20, port_base + Interrupt_Cntl);
-   outb(0x14 | PARITY_MASK, port_base + TMC_Cntl); /* Start arbitration */
+   outb(0x00, fd->port_base + Interrupt_Cntl);
+   outb(0x00, fd->port_base + SCSI_Cntl);              /* Disable data drivers */
+   outb(fd->adapter_mask, fd->port_base + SCSI_Data_NoACK); /* Set our id bit */
+   ++fd->in_command;
+   outb(0x20, fd->port_base + Interrupt_Cntl);
+   outb(0x14 | PARITY_MASK, fd->port_base + TMC_Cntl); /* Start arbitration */
 
    return 0;
 }
@@ -1470,18 +1492,20 @@ static void print_info(struct scsi_cmnd *SCpnt)
    unsigned int imr;
    unsigned int irr;
    unsigned int isr;
+	struct fdomain *fd;
 
    if (!SCpnt || !SCpnt->device || !SCpnt->device->host) {
       printk(KERN_WARNING "scsi: <fdomain> Cannot provide detailed information\n");
       return;
    }
+   fd = shost_priv(SCpnt->device->host);
    
    printk(KERN_INFO "%s\n", fdomain_16x0_info( SCpnt->device->host ) );
    print_banner(SCpnt->device->host);
    switch (SCpnt->SCp.phase) {
-   case in_arbitration: printk("arbitration"); break;
-   case in_selection:   printk("selection");   break;
-   case in_other:       printk("other");       break;
+   case fd->in_arbitration: printk("arbitration"); break;
+   case fd->in_selection:   printk("selection");   break;
+   case fd->in_other:       printk("other");       break;
    default:             printk("unknown");     break;
    }
 
@@ -1496,7 +1520,7 @@ static void print_info(struct scsi_cmnd *SCpnt)
 	   SCpnt->SCp.have_data_in,
 	   SCpnt->timeout );
 #if DEBUG_RACE
-   printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
+   printk( "in_interrupt_flag = %d\n", fd->in_interrupt_flag );
 #endif
 
    imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
@@ -1511,38 +1535,39 @@ static void print_info(struct scsi_cmnd *SCpnt)
 
 				/* Print out interesting information */
    printk( "IMR = 0x%04x", imr );
-   if (imr & (1 << interrupt_level))
+   if (imr & (1 << fd->interrupt_level))
 	 printk( " (masked)" );
    printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
 
-   printk( "SCSI Status      = 0x%02x\n", inb(port_base + SCSI_Status));
-   printk( "TMC Status       = 0x%02x", inb(port_base + TMC_Status));
-   if (inb((port_base + TMC_Status) & 1))
+   printk( "SCSI Status      = 0x%02x\n", inb(fd->port_base + SCSI_Status));
+   printk( "TMC Status       = 0x%02x", inb(fd->port_base + TMC_Status));
+   if (inb((fd->port_base + TMC_Status) & 1))
 	 printk( " (interrupt)" );
    printk( "\n" );
-   printk("Interrupt Status = 0x%02x", inb(port_base + Interrupt_Status));
-   if (inb(port_base + Interrupt_Status) & 0x08)
+   printk("Interrupt Status = 0x%02x", inb(fd->port_base + Interrupt_Status));
+   if (inb(fd->port_base + Interrupt_Status) & 0x08)
 	 printk( " (enabled)" );
    printk( "\n" );
-   if (chip == tmc18c50 || chip == tmc18c30) {
-      printk("FIFO Status      = 0x%02x\n", inb(port_base + FIFO_Status));
+   if (fd->chip == tmc18c50 || fd->chip == tmc18c30) {
+      printk("FIFO Status      = 0x%02x\n", inb(fd->port_base + FIFO_Status));
       printk( "Int. Condition   = 0x%02x\n",
-	      inb( port_base + Interrupt_Cond ) );
+	      inb(fd->port_base + Interrupt_Cond));
    }
-   printk( "Configuration 1  = 0x%02x\n", inb( port_base + Configuration1 ) );
-   if (chip == tmc18c50 || chip == tmc18c30)
+   printk("Configuration 1  = 0x%02x\n", inb(fd->port_base + Configuration1));
+   if (fd->chip == tmc18c50 || fd->chip == tmc18c30)
 	 printk( "Configuration 2  = 0x%02x\n",
-		 inb( port_base + Configuration2 ) );
+		 inb(fd->port_base + Configuration2));
 }
 #endif
 
 static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt)
 {
+	struct fdomain *fd = shost_priv(SCpnt->device->host);
 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
    printk( "scsi: <fdomain> abort " );
 #endif
 
-   if (!in_command) {
+   if (!fd->in_command) {
 #if EVERY_ACCESS || ERRORS_ONLY
       printk( " (not in command)\n" );
 #endif
@@ -1553,28 +1578,22 @@ static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt)
    print_info( SCpnt );
 #endif
 
-   fdomain_make_bus_idle();
-   current_SC->SCp.phase |= aborted;
-   current_SC->result = DID_ABORT << 16;
+   fdomain_make_bus_idle(fd);
+   fd->current_SC->SCp.phase |= aborted;
+   fd->current_SC->result = DID_ABORT << 16;
    
    /* Aborts are not done well. . . */
-   my_done(DID_ABORT << 16);
+   my_done(fd, DID_ABORT << 16);
    return SUCCESS;
 }
 
 int fdomain_16x0_host_reset(struct scsi_cmnd *SCpnt)
 {
+	struct fdomain *fd = shost_priv(SCpnt->device->host);
    unsigned long flags;
 
    local_irq_save(flags);
-
-   outb(1, port_base + SCSI_Cntl);
-   do_pause( 2 );
-   outb(0, port_base + SCSI_Cntl);
-   do_pause( 115 );
-   outb(0, port_base + SCSI_Mode_Cntl);
-   outb(PARITY_MASK, port_base + TMC_Cntl);
-
+   fdomain_16x0_reset(fd->port_base);
    local_irq_restore(flags);
    return SUCCESS;
 }
@@ -1591,6 +1610,7 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev,
       unsigned char  heads;
       unsigned char  sectors;
    } i;
+	struct fdomain *fd = shost_priv(sdev->host);
    
    /* NOTES:
       The RAM area starts at 0x1f00 from the bios_base address.
@@ -1641,8 +1661,8 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev,
    }
    drive = MINOR(bdev->bd_dev) >> 4;
 
-   if (bios_major == 2) {
-      switch (Quantum) {
+   if (fd->bios_major == 2) {
+      switch (fd->Quantum) {
       case 2:			/* ISA_200S */
 				/* The value of 25 has never been verified.
 				   It should probably be 15. */
@@ -1658,14 +1678,14 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev,
 	 offset = 0x1f31 + drive * 25;
 	 break;
       }
-      memcpy_fromio( &i, bios_mem + offset, sizeof( struct drive_info ) );
+      memcpy_fromio( &i, fd->bios_mem + offset, sizeof( struct drive_info ) );
       info_array[0] = i.heads;
       info_array[1] = i.sectors;
       info_array[2] = i.cylinders;
-   } else if (bios_major == 3
-	      && bios_minor >= 0
-	      && bios_minor < 4) { /* 3.0 and 3.2 BIOS */
-      memcpy_fromio( &i, bios_mem + 0x1f71 + drive * 10,
+   } else if (fd->bios_major == 3
+	      && fd->bios_minor >= 0
+	      && fd->bios_minor < 4) { /* 3.0 and 3.2 BIOS */
+      memcpy_fromio( &i, fd->bios_mem + 0x1f71 + drive * 10,
 		     sizeof( struct drive_info ) );
       info_array[0] = i.heads + 1;
       info_array[1] = i.sectors;
@@ -1736,12 +1756,13 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev,
 #ifndef PCMCIA
 static int fdomain_16x0_release(struct Scsi_Host *shpnt)
 {
+	struct fdomain *fd = shost_priv(shpnt);
 	if (shpnt->irq)
-		free_irq(shpnt->irq, shpnt);
+		free_irq(shpnt->irq, fd);
 	if (shpnt->io_port && shpnt->n_io_port)
 		release_region(shpnt->io_port, shpnt->n_io_port);
-	if (PCI_bus)
-		pci_dev_put(PCI_dev);
+	if (fd->PCI_bus)
+		pci_dev_put(fd->PCI_dev);
 	return 0;
 }
 #endif
Signature · 1 line
Ondrej Zary