vserver 1.9.3
[linux-2.6.git] / drivers / scsi / wd7000.c
index 4dca4c1..553a5f1 100644 (file)
  * Removed now obsolete wd7000.h
  */
 
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <asm/dma.h>
 #include <asm/io.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/scsicam.h>
 
 
-#define ANY2SCSI_INLINE                /* undef this to use old macros */
 #undef  WD7000_DEBUG           /* general debug                */
 #ifdef WD7000_DEBUG
 #define dprintk printk
  *  In this version, sg_tablesize now defaults to WD7000_SG, and will
  *  be set to SG_NONE for older boards.  This is the reverse of the
  *  previous default, and was changed so that the driver-level
- *  Scsi_Host_Template would reflect the driver's support for scatter/
+ *  scsi_host_template would reflect the driver's support for scatter/
  *  gather.
  *
  *  Also, it has been reported that boards at Revision 6 support scatter/
@@ -434,8 +436,8 @@ typedef struct initCmd {
  *  carrying SCB addresses to/from the 7000-FASST2.
  *
  *  Note also since SCBs are not "permanently" associated with mailboxes,
- *  there is no need to keep a global list of Scsi_Cmnd pointers indexed
- *  by OGMB.   Again, SCBs reference their Scsi_Cmnds directly, so mailbox
+ *  there is no need to keep a global list of scsi_cmnd pointers indexed
+ *  by OGMB.   Again, SCBs reference their scsi_cmnds directly, so mailbox
  *  indices need not be involved.
  */
 
@@ -462,7 +464,7 @@ typedef struct scb {                /* Command Control Block 5.4.1               */
        unchar direc;           /* Transfer Direction                        */
        unchar reserved2[6];    /* SCSI Command Descriptor Block             */
        /* end of hardware SCB                       */
-       Scsi_Cmnd *SCpnt;       /* Scsi_Cmnd using this SCB                  */
+       struct scsi_cmnd *SCpnt;/* scsi_cmnd using this SCB                  */
        Sgb sgb[WD7000_SG];     /* Scatter/gather list for this SCB          */
        Adapter *host;          /* host adapter                              */
        struct scb *next;       /* for lists of scbs                         */
@@ -723,55 +725,17 @@ static int __init wd7000_setup(char *str)
 
 __setup("wd7000=", wd7000_setup);
 
-#ifdef ANY2SCSI_INLINE
-/*
- * Since they're used a lot, I've redone the following from the macros
- * formerly in wd7000.h, hopefully to speed them up by getting rid of
- * all the shifting (it may not matter; GCC might have done as well anyway).
- *
- * xany2scsi and xscsi2int were not being used, and are no longer defined.
- * (They were simply 4-byte versions of these routines).
- */
-typedef union {                        /* let's cheat... */
-       int i;
-       unchar u[sizeof(int)];  /* the sizeof(int) makes it more portable */
-} i_u;
-
-
 static inline void any2scsi(unchar * scsi, int any)
 {
-       *scsi++ = ((i_u) any).u[2];
-       *scsi++ = ((i_u) any).u[1];
-       *scsi++ = ((i_u) any).u[0];
+       *scsi++ = (unsigned)any >> 16;
+       *scsi++ = (unsigned)any >> 8;
+       *scsi++ = any;
 }
 
-
 static inline int scsi2int(unchar * scsi)
 {
-       i_u result;
-
-       result.i = 0;           /* clears unused bytes */
-       result.u[2] = *scsi++;
-       result.u[1] = *scsi++;
-       result.u[0] = *scsi++;
-
-       return (result.i);
+       return (scsi[0] << 16) | (scsi[1] << 8) | scsi[2];
 }
-#else
-/*
- * These are the old ones - I've just moved them here...
- */
-#undef any2scsi
-#define any2scsi(up, p)   (up)[0] = (((unsigned long) (p)) >> 16);     \
-                         (up)[1] = ((unsigned long) (p)) >> 8;         \
-                         (up)[2] = ((unsigned long) (p));
-
-#undef scsi2int
-#define scsi2int(up)   ( (((unsigned long) *(up)) << 16) +     \
-                        (((unsigned long) (up)[1]) << 8) +     \
-                        ((unsigned long) (up)[2]) )
-#endif
-
 
 static inline void wd7000_enable_intr(Adapter * host)
 {
@@ -798,8 +762,8 @@ static inline void wd7000_enable_dma(Adapter * host)
 
 static inline short WAIT(unsigned port, unsigned mask, unsigned allof, unsigned noneof)
 {
-       register unsigned WAITbits;
-       register unsigned long WAITtimeout = jiffies + WAITnexttimeout;
+       unsigned WAITbits;
+       unsigned long WAITtimeout = jiffies + WAITnexttimeout;
 
        while (time_before_eq(jiffies, WAITtimeout)) {
                WAITbits = inb(port) & mask;
@@ -845,10 +809,10 @@ static inline int command_out(Adapter * host, unchar * cmd, int len)
  */
 static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed)
 {
-       register Scb *scb, *p = NULL;
-       register unsigned long flags;
-       register unsigned long timeout = jiffies + WAITnexttimeout;
-       register unsigned long now;
+       Scb *scb, *p = NULL;
+       unsigned long flags;
+       unsigned long timeout = jiffies + WAITnexttimeout;
+       unsigned long now;
        int i;
 
        if (needed <= 0)
@@ -898,7 +862,7 @@ static inline Scb *alloc_scbs(struct Scsi_Host *host, int needed)
 
 static inline void free_scb(Scb * scb)
 {
-       register unsigned long flags;
+       unsigned long flags;
 
        spin_lock_irqsave(&scbpool_lock, flags);
 
@@ -935,8 +899,8 @@ static int mail_out(Adapter * host, Scb * scbptr)
  *  Note: this can also be used for ICBs; just cast to the parm type.
  */
 {
-       register int i, ogmb;
-       register unsigned long flags;
+       int i, ogmb;
+       unsigned long flags;
        unchar start_ogmb;
        Mailbox *ogmbs = host->mb.ogmb;
        int *next_ogmb = &(host->next_ogmb);
@@ -1033,23 +997,26 @@ static int make_code(unsigned hosterr, unsigned scsierr)
 
 #define wd7000_intr_ack(host)   outb (0, host->iobase + ASC_INTR_ACK)
 
-static void wd7000_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
+
+static irqreturn_t wd7000_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-       register int flag, icmb, errstatus, icmb_status;
-       register int host_error, scsi_error;
-       register Scb *scb;      /* for SCSI commands */
-       register IcbAny *icb;   /* for host commands */
-       register Scsi_Cmnd *SCpnt;
        Adapter *host = (Adapter *) dev_id;
+       int flag, icmb, errstatus, icmb_status;
+       int host_error, scsi_error;
+       Scb *scb;       /* for SCSI commands */
+       IcbAny *icb;    /* for host commands */
+       struct scsi_cmnd *SCpnt;
        Mailbox *icmbs = host->mb.icmb;
+       unsigned long flags;
 
+       spin_lock_irqsave(host->sh->host_lock, flags);
        host->int_counter++;
 
-       dprintk("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host);
+       dprintk("wd7000_intr: irq = %d, host = 0x%06lx\n", irq, (long) host);
 
        flag = inb(host->iobase + ASC_INTR_STAT);
 
-       dprintk("wd7000_intr_handle: intr stat = 0x%02x\n", flag);
+       dprintk("wd7000_intr: intr stat = 0x%02x\n", flag);
 
        if (!(inb(host->iobase + ASC_STAT) & INT_IM)) {
                /* NB: these are _very_ possible if IRQ 15 is being used, since
@@ -1060,79 +1027,70 @@ static void wd7000_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
                 * can sort these out.  Otherwise, electrical noise and other such
                 * problems would be indistinguishable from valid interrupts...
                 */
-               dprintk("wd7000_intr_handle: phantom interrupt...\n");
-               wd7000_intr_ack(host);
-               return;
+               dprintk("wd7000_intr: phantom interrupt...\n");
+               goto ack;
        }
 
-       if (flag & MB_INTR) {
-               /* The interrupt is for a mailbox */
-               if (!(flag & IMB_INTR)) {
-                       dprintk("wd7000_intr_handle: free outgoing mailbox\n");
-                       /*
-                        * If sleep_on() and the "interrupt on free OGMB" command are
-                        * used in mail_out(), wake_up() should correspondingly be called
-                        * here.  For now, we don't need to do anything special.
-                        */
-                       wd7000_intr_ack(host);
-                       return;
-               } else {
-                       /* The interrupt is for an incoming mailbox */
-                       icmb = flag & MB_MASK;
-                       icmb_status = icmbs[icmb].status;
-                       if (icmb_status & 0x80) {       /* unsolicited - result in ICMB */
-                               dprintk("wd7000_intr_handle: unsolicited interrupt 0x%02x\n", icmb_status);
-                               wd7000_intr_ack(host);
-                               return;
-                       }
-                       /* Aaaargh! (Zaga) */
-                       scb = isa_bus_to_virt(scsi2int((unchar *) icmbs[icmb].scbptr));
-                       icmbs[icmb].status = 0;
-                       if (!(scb->op & ICB_OP_MASK)) { /* an SCB is done */
-                               SCpnt = scb->SCpnt;
-                               if (--(SCpnt->SCp.phase) <= 0) {        /* all scbs are done */
-                                       host_error = scb->vue | (icmb_status << 8);
-                                       scsi_error = scb->status;
-                                       errstatus = make_code(host_error, scsi_error);
-                                       SCpnt->result = errstatus;
-
-                                       free_scb(scb);
-
-                                       SCpnt->scsi_done(SCpnt);
-                               }
-                       } else {        /* an ICB is done */
-                               icb = (IcbAny *) scb;
-                               icb->status = icmb_status;
-                               icb->phase = 0;
-                       }
-               }               /* incoming mailbox */
+       if (!(flag & MB_INTR))
+               goto ack;
+
+       /* The interrupt is for a mailbox */
+       if (!(flag & IMB_INTR)) {
+               dprintk("wd7000_intr: free outgoing mailbox\n");
+               /*
+                * If sleep_on() and the "interrupt on free OGMB" command are
+                * used in mail_out(), wake_up() should correspondingly be called
+                * here.  For now, we don't need to do anything special.
+                */
+               goto ack;
        }
 
-       wd7000_intr_ack(host);
+       /* The interrupt is for an incoming mailbox */
+       icmb = flag & MB_MASK;
+       icmb_status = icmbs[icmb].status;
+       if (icmb_status & 0x80) {       /* unsolicited - result in ICMB */
+               dprintk("wd7000_intr: unsolicited interrupt 0x%02x\n", icmb_status);
+               goto ack;
+       }
 
-       dprintk("wd7000_intr_handle: return from interrupt handler\n");
-}
+       /* Aaaargh! (Zaga) */
+       scb = isa_bus_to_virt(scsi2int((unchar *) icmbs[icmb].scbptr));
+       icmbs[icmb].status = 0;
+       if (scb->op & ICB_OP_MASK) {    /* an SCB is done */
+               icb = (IcbAny *) scb;
+               icb->status = icmb_status;
+               icb->phase = 0;
+               goto ack;
+       }
 
-static irqreturn_t do_wd7000_intr_handle(int irq, void *dev_id,
-                                       struct pt_regs *regs)
-{
-       unsigned long flags;
-       struct Scsi_Host *host = dev_id;
+       SCpnt = scb->SCpnt;
+       if (--(SCpnt->SCp.phase) <= 0) {        /* all scbs are done */
+               host_error = scb->vue | (icmb_status << 8);
+               scsi_error = scb->status;
+               errstatus = make_code(host_error, scsi_error);
+               SCpnt->result = errstatus;
 
-       spin_lock_irqsave(host->host_lock, flags);
-       wd7000_intr_handle(irq, dev_id, regs);
-       spin_unlock_irqrestore(host->host_lock, flags);
+               free_scb(scb);
+
+               SCpnt->scsi_done(SCpnt);
+       }
+
+ ack:
+       dprintk("wd7000_intr: return from interrupt handler\n");
+       wd7000_intr_ack(host);
+
+       spin_unlock_irqrestore(host->sh->host_lock, flags);
        return IRQ_HANDLED;
 }
 
-
-static int wd7000_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
+static int wd7000_queuecommand(struct scsi_cmnd *SCpnt,
+               void (*done)(struct scsi_cmnd *))
 {
-       register Scb *scb;
-       register Sgb *sgb;
-       register unchar *cdb = (unchar *) SCpnt->cmnd;
-       register unchar idlun;
-       register short cdblen;
+       Scb *scb;
+       Sgb *sgb;
+       unchar *cdb = (unchar *) SCpnt->cmnd;
+       unchar idlun;
+       short cdblen;
        Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
 
        cdblen = SCpnt->cmd_len;
@@ -1292,7 +1250,7 @@ static int wd7000_init(Adapter * host)
                return 0;
 
 
-       if (request_irq(host->irq, do_wd7000_intr_handle, SA_INTERRUPT, "wd7000", host)) {
+       if (request_irq(host->irq, wd7000_intr, SA_INTERRUPT, "wd7000", host)) {
                printk("wd7000_init: can't get IRQ %d.\n", host->irq);
                return (0);
        }
@@ -1433,7 +1391,7 @@ static int wd7000_proc_info(struct Scsi_Host *host, char *buffer, char **start,
  *
  */
 
-static int wd7000_detect(Scsi_Host_Template * tpnt)
+static int wd7000_detect(struct scsi_host_template *tpnt)
 {
        short present = 0, biosaddr_ptr, sig_ptr, i, pass;
        short biosptr[NUM_CONFIGS];
@@ -1604,6 +1562,7 @@ static int wd7000_release(struct Scsi_Host *shost)
        return 0;
 }
 
+#if 0
 /*
  *  I have absolutely NO idea how to do an abort with the WD7000...
  */
@@ -1618,27 +1577,13 @@ static int wd7000_abort(Scsi_Cmnd * SCpnt)
        }
        return FAILED;
 }
-
-
-/*
- *  I also have no idea how to do a reset...
- */
-
-static int wd7000_bus_reset(Scsi_Cmnd * SCpnt)
-{
-       return FAILED;
-}
-
-static int wd7000_device_reset(Scsi_Cmnd * SCpnt)
-{
-       return FAILED;
-}
+#endif
 
 /*
  *  Last resort. Reinitialize the board.
  */
 
-static int wd7000_host_reset(Scsi_Cmnd * SCpnt)
+static int wd7000_host_reset(struct scsi_cmnd *SCpnt)
 {
        Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
 
@@ -1648,7 +1593,6 @@ static int wd7000_host_reset(Scsi_Cmnd * SCpnt)
        return SUCCESS;
 }
 
-
 /*
  *  This was borrowed directly from aha1542.c. (Zaga)
  */
@@ -1704,15 +1648,13 @@ MODULE_AUTHOR("Thomas Wuensche, John Boyd, Miroslav Zagorac");
 MODULE_DESCRIPTION("Driver for the WD7000 series ISA controllers");
 MODULE_LICENSE("GPL");
 
-static Scsi_Host_Template driver_template = {
+static struct scsi_host_template driver_template = {
        .proc_name              = "wd7000",
        .proc_info              = wd7000_proc_info,
        .name                   = "Western Digital WD-7000",
        .detect                 = wd7000_detect,
        .release                = wd7000_release,
        .queuecommand           = wd7000_queuecommand,
-       .eh_bus_reset_handler   = wd7000_bus_reset,
-       .eh_device_reset_handler = wd7000_device_reset,
        .eh_host_reset_handler  = wd7000_host_reset,
        .bios_param             = wd7000_biosparam,
        .can_queue              = WD7000_Q,