vserver 1.9.3
[linux-2.6.git] / drivers / scsi / fdomain.c
index 7b53d00..a78b6f2 100644 (file)
 #include <linux/pci.h>
 #include <linux/stat.h>
 #include <linux/delay.h>
+#include <scsi/scsicam.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include "scsi.h"
-#include "hosts.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_ioctl.h>
+#include "fdomain.h"
 
 MODULE_AUTHOR("Rickard E. Faith");
 MODULE_DESCRIPTION("Future domain SCSI driver");
@@ -385,7 +390,7 @@ static int               PCI_bus;
 static int               Quantum;      /* Quantum board variant */
 static int               interrupt_level;
 static volatile int      in_command;
-static Scsi_Cmnd         *current_SC;
+static struct scsi_cmnd  *current_SC;
 static enum chip_type    chip              = unknown;
 static int               adapter_mask;
 static int               this_id;
@@ -414,8 +419,6 @@ static int               FIFO_Size = 0x2000; /* 8k FIFO for
 
 static irqreturn_t       do_fdomain_16x0_intr( int irq, void *dev_id,
                                            struct pt_regs * regs );
-int                    fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt);
-
 /* Allow insmod parameters to be like LILO parameters.  For example:
    insmod fdomain fdomain=0x140,11 */
 static char * fdomain = NULL;
@@ -551,7 +554,7 @@ static void print_banner( struct Scsi_Host *shpnt )
    printk( "\n" );
 }
 
-int __init fdomain_setup(char *str)
+int fdomain_setup(char *str)
 {
        int ints[4];
 
@@ -678,6 +681,7 @@ static int fdomain_get_irq( int base )
 
 static int fdomain_isa_detect( int *irq, int *iobase )
 {
+#ifndef PCMCIA
    int i, j;
    int base = 0xdeadbeef;
    int flag = 0;
@@ -729,17 +733,20 @@ static int fdomain_isa_detect( int *irq, int *iobase )
       printk( " %x,", base );
 #endif
 
-      for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
-        if (base == ports[i])
-              ++flag;
+      for (i = 0; i < PORT_COUNT; i++) {
+       if (base == ports[i]) {
+               if (!request_region(base, 0x10, "fdomain"))
+                       break;
+               if (!fdomain_is_valid_port(base)) {
+                       release_region(base, 0x10);
+                       break;
+               }
+               *irq    = fdomain_get_irq( base );
+               *iobase = base;
+               return 1;
+       }
       }
 
-      if (flag && fdomain_is_valid_port( base )) {
-        *irq    = fdomain_get_irq( base );
-        *iobase = base;
-        return 1;
-      }
-      
       /* This is a bad sign.  It usually means that someone patched the
         BIOS signature list (the signatures variable) to contain a BIOS
         signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */
@@ -760,7 +767,7 @@ static int fdomain_isa_detect( int *irq, int *iobase )
 
    for (i = 0; i < PORT_COUNT; i++) {
       base = ports[i];
-      if (check_region( base, 0x10 )) {
+      if (!request_region(base, 0x10, "fdomain")) {
 #if DEBUG_DETECT
         printk( " (%x inuse),", base );
 #endif
@@ -769,7 +776,10 @@ static int fdomain_isa_detect( int *irq, int *iobase )
 #if DEBUG_DETECT
       printk( " %x,", base );
 #endif
-      if ((flag = fdomain_is_valid_port( base ))) break;
+      flag = fdomain_is_valid_port(base);
+      if (flag)
+       break;
+      release_region(base, 0x10);
    }
 
 #if DEBUG_DETECT
@@ -783,6 +793,9 @@ static int fdomain_isa_detect( int *irq, int *iobase )
    *iobase = base;
 
    return 1;                   /* success */
+#else
+   return 0;
+#endif
 }
 
 /* PCI detection function: int fdomain_pci_bios_detect(int* irq, int*
@@ -825,6 +838,9 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_
    pci_base = pci_resource_start(pdev, 0);
    pci_irq = pdev->irq;
 
+   if (!request_region( pci_base, 0x10, "fdomain" ))
+       return 0;
+
    /* Now we have the I/O base address and interrupt from the PCI
       configuration registers. */
 
@@ -837,8 +853,9 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_
           " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );
 #endif
 
-   if (!fdomain_is_valid_port( *iobase )) {
+   if (!fdomain_is_valid_port(pci_base)) {
       printk(KERN_ERR "scsi: <fdomain> PCI card detected, but driver not loaded (invalid port)\n" );
+      release_region(pci_base, 0x10);
       return 0;
    }
 
@@ -852,7 +869,7 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_
 }
 #endif
 
-struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
 {
    int              retcode;
    struct Scsi_Host *shpnt;
@@ -863,10 +880,16 @@ struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
       printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
              port_base, interrupt_level );
 #endif
+      if (!request_region(port_base, 0x10, "fdomain")) {
+        printk( "scsi: <fdomain> port 0x%x is busy\n", port_base );
+        printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
+        return NULL;
+      }
       if (!fdomain_is_valid_port( 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;
       }
    } else {
@@ -901,13 +924,14 @@ struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
    Write_FIFO_port       = port_base + Write_FIFO;
    Write_SCSI_Data_port  = port_base + Write_SCSI_Data;
 
-   fdomain_16x0_bus_reset( NULL);
+   fdomain_16x0_bus_reset(NULL);
 
    if (fdomain_test_loopback()) {
       printk(KERN_ERR  "scsi: <fdomain> Detection failed (loopback test failed at port base 0x%x)\n", port_base);
       if (setup_called) {
         printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
       }
+      release_region(port_base, 0x10);
       return NULL;
    }
 
@@ -928,8 +952,10 @@ struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
    get resources.  */
 
    shpnt = scsi_register( tpnt, 0 );
-   if(shpnt == NULL)
+   if(shpnt == NULL) {
+       release_region(port_base, 0x10);
        return NULL;
+   }
    shpnt->irq = interrupt_level;
    shpnt->io_port = port_base;
    scsi_set_device(shpnt, &pdev->dev);
@@ -939,6 +965,7 @@ struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
    /* Log IRQ with kernel */   
    if (!interrupt_level) {
       printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
+      release_region(port_base, 0x10);
       return NULL;
    } else {
       /* Register the IRQ with the kernel */
@@ -960,17 +987,14 @@ struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt )
            printk(KERN_ERR "                Send mail to faith@acm.org\n" );
         }
         printk(KERN_ERR "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
+         release_region(port_base, 0x10);
         return NULL;
       }
    }
-
-   /* Log I/O ports with kernel */
-   request_region( port_base, 0x10, "fdomain" );
-
    return shpnt;
 }
 
-static int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
+static int fdomain_16x0_detect(struct scsi_host_template *tpnt)
 {
        if (fdomain)
                fdomain_setup(fdomain);
@@ -1254,7 +1278,7 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id,
    if (chip == tmc1800 && !current_SC->SCp.have_data_in
        && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
       
-      if(scsi_to_pci_dma_dir(current_SC->sc_data_direction)    == PCI_DMA_TODEVICE)
+      if(current_SC->sc_data_direction == DMA_TO_DEVICE)
       {
         current_SC->SCp.have_data_in = -1;
         outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
@@ -1387,7 +1411,8 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id,
    return IRQ_HANDLED;
 }
 
-static int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt,
+               void (*done)(struct scsi_cmnd *))
 {
    if (in_command) {
       panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
@@ -1439,7 +1464,7 @@ static int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 }
 
 #if DEBUG_ABORT
-static void print_info(Scsi_Cmnd *SCpnt)
+static void print_info(struct scsi_cmnd *SCpnt)
 {
    unsigned int imr;
    unsigned int irr;
@@ -1510,7 +1535,7 @@ static void print_info(Scsi_Cmnd *SCpnt)
 }
 #endif
 
-static int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
+static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt)
 {
 #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
    printk( "scsi: <fdomain> abort " );
@@ -1536,7 +1561,7 @@ static int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
    return SUCCESS;
 }
 
-int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt)
+int fdomain_16x0_bus_reset(struct scsi_cmnd *SCpnt)
 {
    outb( 1, SCSI_Cntl_port );
    do_pause( 2 );
@@ -1547,29 +1572,12 @@ int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt)
    return SUCCESS;
 }
 
-static int fdomain_16x0_host_reset(Scsi_Cmnd *SCpnt)
-{
-  return FAILED;
-}
-
-static int fdomain_16x0_device_reset(Scsi_Cmnd *SCpnt)
-{
-  return FAILED;
-}
-
-#include <scsi/scsi_ioctl.h>
-
 static int fdomain_16x0_biosparam(struct scsi_device *sdev,
                struct block_device *bdev,
                sector_t capacity, int *info_array)
 {
    int              drive;
-   unsigned char    buf[512 + sizeof (Scsi_Ioctl_Command)];
-   Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;
    int             size      = capacity;
-   unsigned char    *data     = sic->data;
-   unsigned char    do_read[] = { READ_6, 0, 0, 0, 1, 0 };
-   int              retcode;
    unsigned long    offset;
    struct drive_info {
       unsigned short cylinders;
@@ -1657,16 +1665,10 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev,
       info_array[2] = i.cylinders;
    } else {                    /* 3.4 BIOS (and up?) */
       /* This algorithm was provided by Future Domain (much thanks!). */
+      unsigned char *p = scsi_bios_ptable(bdev);
 
-      sic->inlen  = 0;         /* zero bytes out */
-      sic->outlen = 512;               /* one sector in */
-      memcpy( data, do_read, sizeof( do_read ) );
-      retcode = kernel_scsi_ioctl( sdev,
-                                  SCSI_IOCTL_SEND_COMMAND,
-                                  sic );
-      if (!retcode                                 /* SCSI command ok */
-         && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
-         && data[0x1c2]) {                         /* Partition type */
+      if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */
+         && p[4]) {                        /* Partition type */
 
         /* The partition table layout is as follows:
 
@@ -1697,8 +1699,8 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev,
            Future Domain algorithm, but it seemed to be a reasonable thing
            to do, especially in the Linux and BSD worlds. */
 
-        info_array[0] = data[0x1c3] + 1;           /* heads */
-        info_array[1] = data[0x1c4] & 0x3f;        /* sectors */
+        info_array[0] = p[5] + 1;          /* heads */
+        info_array[1] = p[6] & 0x3f;       /* sectors */
       } else {
 
         /* Note that this new method guarantees that there will always be
@@ -1718,6 +1720,7 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev,
       }
                                /* For both methods, compute the cylinders */
       info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
+      kfree(p);
    }
    
    return 0;
@@ -1732,7 +1735,7 @@ static int fdomain_16x0_release(struct Scsi_Host *shpnt)
        return 0;
 }
 
-Scsi_Host_Template fdomain_driver_template = {
+struct scsi_host_template fdomain_driver_template = {
        .module                 = THIS_MODULE,
        .name                   = "fdomain",
        .proc_name              = "fdomain",
@@ -1741,8 +1744,6 @@ Scsi_Host_Template fdomain_driver_template = {
        .queuecommand           = fdomain_16x0_queue,
        .eh_abort_handler       = fdomain_16x0_abort,
        .eh_bus_reset_handler   = fdomain_16x0_bus_reset,
-       .eh_device_reset_handler = fdomain_16x0_device_reset,
-       .eh_host_reset_handler  = fdomain_16x0_host_reset,
        .bios_param             = fdomain_16x0_biosparam,
        .release                = fdomain_16x0_release,
        .can_queue              = 1,