]> git.neil.brown.name Git - history.git/commitdiff
Update the 32-bit Ninja SCSI driver from YOKOTA Hiroshi.
authorLinus Torvalds <torvalds@home.osdl.org>
Tue, 19 Aug 2003 05:35:48 +0000 (22:35 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Tue, 19 Aug 2003 05:35:48 +0000 (22:35 -0700)
MAINTAINERS
drivers/scsi/nsp32.c
drivers/scsi/nsp32.h
drivers/scsi/nsp32_debug.c
drivers/scsi/nsp32_io.h

index 77762a2248fae90479b04839b6df4b080fc8dd79..8f3121ec7d77f6cd41538f0d7d0391ffae93333e 100644 (file)
@@ -1348,7 +1348,7 @@ M:        Andreas Mohr <100.30936@germany.net>
 L:     linux-net@vger.kernel.org
 S:     Maintained
 
-NINJA SCSI-3 / NINJA SCSI-32Bi PCMCIA SCSI HOST ADAPTER DRIVER
+NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER
 P:     YOKOTA Hiroshi
 M:     yokota@netlab.is.tsukuba.ac.jp
 W:     http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
index 6b3dfedcd0319cab28745628026a03569ac1045d..d8d59abb6bc86dfa734e615752c129352d306499 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * NinjaSCSI-32Bi Cardbus, NinjaSCSI-32UDE PCI/CardBus SCSI driver
- * Copyright (C) 2001, 2002
+ * Copyright (C) 2001, 2002, 2003
  *      YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
- *      GOTO Masanori <gotom@debian.or.jp>
+ *      GOTO Masanori <gotom@debian.or.jp>, <gotom@debian.org>
  *
  * 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
  * 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.
+ *
+ *
+ * Revision History:
+ *   1.0: Initial Release.
+ *   1.1: Add /proc SDTR status.
+ *        Remove obsolete error handler nsp32_reset.
+ *        Some clean up.
+ *   1.2: PowerPC (big endian) support.
  */
 
 #include <linux/version.h>
@@ -30,6 +38,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ctype.h>
+#include <linux/interrupt.h>
 
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi.h>
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+# include <linux/blk.h>
+#endif
+
 #include "nsp32.h"
 
 
-static int trans_mode = 0;     /* default: BIOS */
-static int auto_param = 0;     /* default: ON */
-MODULE_PARM(trans_mode, "i");
-MODULE_PARM(auto_param, "i");
-MODULE_PARM_DESC(trans_mode, "transfer mode (0: BIOS 1: Async 2: Ultra20M");
-MODULE_PARM_DESC(auto_param, "AutoParameter mode (0: ON 1: OFF)");
+/***********************************************************************
+ * Module parameters
+ */
+static int       trans_mode = 0;       /* default: BIOS */
+MODULE_PARM     (trans_mode, "i");
+MODULE_PARM_DESC(trans_mode, "transfer mode (0: BIOS(default) 1: Async 2: Ultra20M");
 #define ASYNC_MODE    1
 #define ULTRA20M_MODE 2
 
-MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>, GOTO Masanori <gotom@debian.or.jp>");
-MODULE_DESCRIPTION("Workbit NinjaSCSI-32Bi/UDE PCI/CardBus SCSI host bus adapter module");
-MODULE_LICENSE("GPL");
-
-static const char *nsp32_release_version = "1.0";
-
-
-/*
- * structure for DMA/Scatter Gather list
- */
-#define AUTOPARAM_SIZE         (sizeof(int)*0x15)      /* 4x15H = 0x60 */
-#define NSP_SG_SIZE            SG_ALL
-#define NSP32_SG_END_SGT       0x80000000              /* Last SGT marker */
-#define NSP32_SG_CNT_MASK      0x1FFFF
-
-struct nsp32_sgtable {
-       unsigned long           addr;           /* transfer address */
-       unsigned long           len;            /* transfer length.
-                                                  Bit (24-32) is for SGT_END */
-};
-
-struct nsp32_sglun {
-       struct nsp32_sgtable sgt[NSP_SG_SIZE+1];        /* SG table */
-};
-
-
-/*
- * host data structure
- */
-/* message in/out buffer */
-#define MSGOUTBUF_MAX  13  /* 13 is ok ? */
-#define MSGINBUF_MAX   13
-
-/* flag for trans_method */
-#define NSP32_TRANSFER_BUSMASTER       BIT(0)
-#define NSP32_TRANSFER_MMIO            BIT(1)  /* Not supported yet */
-#define NSP32_TRANSFER_PIO             BIT(2)  /* Not supported yet */
-
+static int       auto_param = 0;       /* default: ON */
+MODULE_PARM     (auto_param, "i");
+MODULE_PARM_DESC(auto_param, "AutoParameter mode (0: ON(default) 1: OFF)");
 
-/*
- * SCSI TARGET/LUN definition
- */
-#define NSP32_HOST_SCSIID      7       /* SCSI initiator is everytime defined as 7 */
-#define MAX_TARGET             8
-#define MAX_LUN                        8       /* XXX: In SPI3, max number of LUN is 64. */
+static int       disc_priv  = 1;       /* default: OFF */
+MODULE_PARM     (disc_priv,  "i");
+MODULE_PARM_DESC(disc_priv,  "disconnection privilege mode (0: ON 1: OFF(default))");
 
+MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>, GOTO Masanori <gotom@debian.or.jp>");
+MODULE_DESCRIPTION("Workbit NinjaSCSI-32Bi/UDE CardBus/PCI SCSI host bus adapter module");
+MODULE_LICENSE("GPL");
 
-/*
- * structure for synchronous transfer negotiation data
- */
-#define SYNC_NOT_YET   0
-#define SYNC_OK                1
-#define SYNC_NG                2
-
-struct nsp32_sync_table {
-       unsigned char   period_num;     /* period number */
-       unsigned char   ackwidth;       /* ack width designated by period */
-       unsigned char   start_period;   /* search range - start period */
-       unsigned char   end_period;     /* search range - end period */
-};
+static const char *nsp32_release_version = "1.2";
 
 
-/*
- * structure for target device static data
+/****************************************************************************
+ * Supported hardware
  */
-/* flag for nsp32_target.sync_flag */
-#define SDTR_INITIATOR         BIT(0)  /* sending SDTR from initiator */
-#define SDTR_TARGET            BIT(1)  /* sending SDTR from target */
-#define SDTR_DONE              BIT(2)  /* exchanging SDTR has been processed */
-
-/* syncronous period value for nsp32_target.config_max */
-#define FAST5M                 0x32
-#define FAST10M                        0x19
-#define ULTRA20M               0x0c
-
-/* flag for nsp32_target.{sync_offset}, period */
-#define ASYNC_OFFSET           0       /* asynchronous transfer */
-#define SYNC_OFFSET            0xf     /* synchronous transfer max offset */
-
-/* syncreg:
-      07 06 05 04 03 02 01 00
-      ---PERIOD-- ---OFFSET--   */
-#define TO_SYNCREG(period, offset)     (period << 4 | offset)
-
-struct nsp32_target {
-       unsigned char   syncreg;        /* value for SYNCREG  */
-       unsigned char   ackwidth;       /* value for ACKWIDTH */
-       unsigned char   offset;         /* sync offset (0-15) */
-       int             sync_flag;      /* SDTR_*, 0 */
-       int             limit_entry;    /* max speed limit entry designated
-                                          by EEPROM configuration */
+static struct pci_device_id nsp32_pci_table[] __devinitdata = {
+       {
+               .vendor      = PCI_VENDOR_ID_IODATA,
+               .device      = PCI_DEVICE_ID_NINJASCSI_32BI_CBSC_II,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = MODEL_IODATA,
+       },
+       {
+               .vendor      = PCI_VENDOR_ID_WORKBIT,
+               .device      = PCI_DEVICE_ID_NINJASCSI_32BI_KME,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = MODEL_KME,
+       },
+       {
+               .vendor      = PCI_VENDOR_ID_WORKBIT,
+               .device      = PCI_DEVICE_ID_NINJASCSI_32BI_WBT,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = MODEL_WORKBIT,
+       },
+       {
+               .vendor      = PCI_VENDOR_ID_WORKBIT,
+               .device      = PCI_DEVICE_ID_WORKBIT_STANDARD,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = MODEL_PCI_WORKBIT,
+       },
+       {
+               .vendor      = PCI_VENDOR_ID_WORKBIT,
+               .device      = PCI_DEVICE_ID_NINJASCSI_32BI_LOGITEC,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = MODEL_LOGITEC,
+       },
+       {
+               .vendor      = PCI_VENDOR_ID_WORKBIT,
+               .device      = PCI_DEVICE_ID_NINJASCSI_32BIB_LOGITEC,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = MODEL_PCI_LOGITEC,
+       },
+       {
+               .vendor      = PCI_VENDOR_ID_WORKBIT,
+               .device      = PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = MODEL_PCI_MELCO,
+       },
+       {
+               .vendor      = PCI_VENDOR_ID_WORKBIT,
+               .device      = PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO_II,
+               .subvendor   = PCI_ANY_ID,
+               .subdevice   = PCI_ANY_ID,
+               .driver_data = MODEL_PCI_MELCO,
+       },
+       {0,0,},
 };
+MODULE_DEVICE_TABLE(pci, nsp32_pci_table);
 
-typedef struct _nsp32_hw_data {
-       int IrqNumber;
-       int BaseAddress;
-       int NumAddress;
-#define NSP32_MMIO_OFFSET 0x0800
-       unsigned long MmioAddress;
-       unsigned long length;
-
-       Scsi_Cmnd *CurrentSC;
-
-       struct pci_dev *Pci;
-       const struct pci_device_id *pci_devid;
-       struct Scsi_Host *Host;
-       spinlock_t Lock;
-
-       char info_str[100];
-
-       /* allocated memory region */
-       struct nsp32_lunt       *lunt_list;     /* kmalloc region for lunt */
-       struct nsp32_sglun      *sg_list;       /* sglist virtual address */
-       dma_addr_t              sgaddr;         /* physical address of hw_sg_table */
-       unsigned char           *autoparam;     /* auto parameter transfer region */
-       dma_addr_t              apaddr;         /* physical address of autoparam */
-       int                     cur_entry;      /* current sgt entry */
-
-       /* target/LUN */
-       struct nsp32_lunt       *curlunt;       /* Current connected LUN table */
-       struct nsp32_lunt       *lunt[MAX_TARGET][MAX_LUN];  /* All LUN table */
-       struct nsp32_target     *curtarget;     /* Current connected SCSI ID */
-       struct nsp32_target     target[MAX_TARGET];          /* SCSI ID */
-       int                     pid;            /* Current connected target ID */
-       int                     plun;           /* Current connected target LUN */
-
-       /* behavior setting parameters */
-       int                     trans_method;   /* transfer method flag */
-       int                     resettime;      /* Reset time */
-       int                     clock;          /* clock dividing flag */
-       struct nsp32_sync_table *synct;         /* sync_table determined by clock */
-       int                     syncnum;        /* the max number of synct element */
-
-       /* message buffer */
-        unsigned char  msgoutbuf[MSGOUTBUF_MAX]; /* msgout buffer */
-       char            msgoutlen;                /* msgoutbuf length */
-       unsigned char   msginbuf[MSGINBUF_MAX];   /* megin buffer */
-       char            msginlen;                 /* msginbuf length */
-
-
-} nsp32_hw_data;
 static nsp32_hw_data nsp32_data_base;  /* probe <-> detect glue */
 
 
-/*
- * TIME definition
- */
-#define RESET_HOLD_TIME                10000   /* reset time in us (SCSI-2 says the
-                                          minimum is 25us) */
-#define SEL_TIMEOUT_TIME       10000   /* 250ms defined in SCSI specification
-                                          (25.6us/1unit) */
-#define ARBIT_TIMEOUT_TIME     100     /* 100us */
-#define REQSACK_TIMEOUT_TIME   10000   /* max wait time for REQ/SACK assertion
-                                          or negation, 10000us == 10ms */
-
-/*
- * structure for connected LUN dynamic data
- *
- * Note: Currently tagged queuing is disabled, each nsp32_lunt holds
- *       one SCSI command and one state.
- */
-#define DISCPRIV_OK            BIT(0)          /* DISCPRIV Enable mode */
-#define MSGIN03                        BIT(1)          /* Auto Msg In 03 Flag */
-
-struct nsp32_lunt {
-       Scsi_Cmnd               *SCpnt;         /* Current Handling Scsi_Cmnd */
-       unsigned long           save_datp;      /* Save Data Pointer - saved position from initial address */
-       int                     msgin03;        /* auto msg in 03 flag */
-       unsigned int            sg_num;         /* Total number of SG entries */
-       int                     cur_entry;      /* Current SG entry number */
-       struct nsp32_sglun      *sglun;         /* sg table per lun */
-       long                    sglun_paddr;    /* sglun physical address */
-};
-
-
 /*
  * Period/AckWidth speed conversion table
  *
  * Note: This period/ackwidth speed table must be in descending order.
  */
-static struct nsp32_sync_table nsp32_sync_table_40M[] = {
-     /* {PNo, AW,  SP,   EP}  Speed(MB/s) Period AckWidth */
-       {0x1, 0, 0x0c, 0x0c},   /*  20.0 :  50ns,  25ns */
-       {0x2, 0, 0x0d, 0x18},   /*  13.3 :  75ns,  25ns */
-       {0x3, 1, 0x19, 0x19},   /*  10.0 : 100ns,  50ns */
-       {0x4, 1, 0x1a, 0x1f},   /*   8.0 : 125ns,  50ns */
-       {0x5, 2, 0x20, 0x25},   /*   6.7 : 150ns,  75ns */
-       {0x6, 2, 0x26, 0x31},   /*   5.7 : 175ns,  75ns */
-       {0x7, 3, 0x32, 0x32},   /*   5.0 : 200ns, 100ns */
-       {0x8, 3, 0x33, 0x38},   /*   4.4 : 225ns, 100ns */
-       {0x9, 3, 0x39, 0x3e},   /*   4.0 : 250ns, 100ns */
+static nsp32_sync_table nsp32_sync_table_40M[] = {
+     /* {PNo, AW,   SP,   EP, SREQ smpl}  Speed(MB/s) Period AckWidth */
+       {0x1,  0, 0x0c, 0x0c, SMPL_40M},  /*  20.0 :  50ns,  25ns */
+       {0x2,  0, 0x0d, 0x18, SMPL_40M},  /*  13.3 :  75ns,  25ns */
+       {0x3,  1, 0x19, 0x19, SMPL_40M},  /*  10.0 : 100ns,  50ns */
+       {0x4,  1, 0x1a, 0x1f, SMPL_20M},  /*   8.0 : 125ns,  50ns */
+       {0x5,  2, 0x20, 0x25, SMPL_20M},  /*   6.7 : 150ns,  75ns */
+       {0x6,  2, 0x26, 0x31, SMPL_20M},  /*   5.7 : 175ns,  75ns */
+       {0x7,  3, 0x32, 0x32, SMPL_20M},  /*   5.0 : 200ns, 100ns */
+       {0x8,  3, 0x33, 0x38, SMPL_10M},  /*   4.4 : 225ns, 100ns */
+       {0x9,  3, 0x39, 0x3e, SMPL_10M},  /*   4.0 : 250ns, 100ns */
 };
-static const int nsp32_table_40M_num =
-               sizeof(nsp32_sync_table_40M)/sizeof(struct nsp32_sync_table);
-
-static struct nsp32_sync_table nsp32_sync_table_20M[] = {
-       {0x1, 0, 0x19, 0x19},   /* 10.0 : 100ns,  50ns */
-       {0x2, 0, 0x1a, 0x25},   /*  6.7 : 150ns,  50ns */
-       {0x3, 1, 0x26, 0x32},   /*  5.0 : 200ns, 100ns */
-       {0x4, 1, 0x33, 0x3e},   /*  4.0 : 250ns, 100ns */
-       {0x5, 2, 0x3f, 0x4b},   /*  3.3 : 300ns, 150ns */
-       {0x6, 2, 0x4c, 0x57},   /*  2.8 : 350ns, 150ns */
-       {0x7, 3, 0x58, 0x64},   /*  2.5 : 400ns, 200ns */
-       {0x8, 3, 0x65, 0x70},   /*  2.2 : 450ns, 200ns */
-       {0x9, 3, 0x71, 0x7d},   /*  2.0 : 500ns, 200ns */
+
+static nsp32_sync_table nsp32_sync_table_20M[] = {
+       {0x1,  0, 0x19, 0x19, SMPL_40M},  /* 10.0 : 100ns,  50ns */
+       {0x2,  0, 0x1a, 0x25, SMPL_20M},  /*  6.7 : 150ns,  50ns */
+       {0x3,  1, 0x26, 0x32, SMPL_20M},  /*  5.0 : 200ns, 100ns */
+       {0x4,  1, 0x33, 0x3e, SMPL_10M},  /*  4.0 : 250ns, 100ns */
+       {0x5,  2, 0x3f, 0x4b, SMPL_10M},  /*  3.3 : 300ns, 150ns */
+       {0x6,  2, 0x4c, 0x57, SMPL_10M},  /*  2.8 : 350ns, 150ns */
+       {0x7,  3, 0x58, 0x64, SMPL_10M},  /*  2.5 : 400ns, 200ns */
+       {0x8,  3, 0x65, 0x70, SMPL_10M},  /*  2.2 : 450ns, 200ns */
+       {0x9,  3, 0x71, 0x7d, SMPL_10M},  /*  2.0 : 500ns, 200ns */
 };
-static const int nsp32_table_20M_num =
-               sizeof(nsp32_sync_table_20M)/sizeof(struct nsp32_sync_table);
-
-static struct nsp32_sync_table nsp32_sync_table_pci[] = {
-       {0x1, 0, 0x0c, 0x0f},   /* 16.6 :  60ns,  30ns */
-       {0x2, 0, 0x10, 0x16},   /* 11.1 :  90ns,  30ns */
-       {0x3, 1, 0x17, 0x1e},   /*  8.3 : 120ns,  60ns */
-       {0x4, 1, 0x1f, 0x25},   /*  6.7 : 150ns,  60ns */
-       {0x5, 2, 0x26, 0x2d},   /*  5.6 : 180ns,  90ns */
-       {0x6, 2, 0x2e, 0x34},   /*  4.8 : 210ns,  90ns */
-       {0x7, 3, 0x35, 0x3c},   /*  4.2 : 240ns, 120ns */
-       {0x8, 3, 0x3d, 0x43},   /*  3.7 : 270ns, 120ns */
-       {0x9, 3, 0x44, 0x4b},   /*  3.3 : 300ns, 120ns */
+
+static nsp32_sync_table nsp32_sync_table_pci[] = {
+       {0x1,  0, 0x0c, 0x0f, SMPL_40M},  /* 16.6 :  60ns,  30ns */
+       {0x2,  0, 0x10, 0x16, SMPL_40M},  /* 11.1 :  90ns,  30ns */
+       {0x3,  1, 0x17, 0x1e, SMPL_20M},  /*  8.3 : 120ns,  60ns */
+       {0x4,  1, 0x1f, 0x25, SMPL_20M},  /*  6.7 : 150ns,  60ns */
+       {0x5,  2, 0x26, 0x2d, SMPL_20M},  /*  5.6 : 180ns,  90ns */
+       {0x6,  2, 0x2e, 0x34, SMPL_10M},  /*  4.8 : 210ns,  90ns */
+       {0x7,  3, 0x35, 0x3c, SMPL_10M},  /*  4.2 : 240ns, 120ns */
+       {0x8,  3, 0x3d, 0x43, SMPL_10M},  /*  3.7 : 270ns, 120ns */
+       {0x9,  3, 0x44, 0x4b, SMPL_10M},  /*  3.3 : 300ns, 120ns */
 };
-static const int nsp32_table_pci_num =
-               sizeof(nsp32_sync_table_pci)/sizeof(struct nsp32_sync_table);
 
 /*
  * function declaration
  */
-static int nsp32_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static const char *nsp32_info(struct Scsi_Host *);
-static int nsp32_eh_abort(Scsi_Cmnd *);
-static int nsp32_eh_bus_reset(Scsi_Cmnd *);
-static int nsp32_eh_host_reset(Scsi_Cmnd *);
-static int nsp32_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-static int __devinit nsp32_probe(struct pci_dev *, const struct pci_device_id *);
+/* module entry point */
+static int  __devinit nsp32_probe (struct pci_dev *, const struct pci_device_id *);
 static void __devexit nsp32_remove(struct pci_dev *);
-static int __init init_nsp32(void);
-static void __exit exit_nsp32(void);
-
-static void nsp32_message(const char *, int, char *, char *, ...);
-static void nsp32_dmessage(const char *, int, int, char *, ...);
-static void nsp32_build_identify(nsp32_hw_data *, Scsi_Cmnd *);
-static void nsp32_build_sdtr(nsp32_hw_data *, unsigned char, unsigned char);
-static void nsp32_build_nop(nsp32_hw_data *);
-static void nsp32_build_reject(nsp32_hw_data *);
-static int nsp32hw_start_selection(Scsi_Cmnd *, nsp32_hw_data *);
-static int nsp32_selection_autoscsi(Scsi_Cmnd *, nsp32_hw_data *);
-static int nsp32_reselection(nsp32_hw_data *, unsigned char);
-static int nsp32hw_setup_sg_table(Scsi_Cmnd *, nsp32_hw_data *);
-static int nsp32hw_init(struct Scsi_Host *);
-static void nsp32_scsi_done(nsp32_hw_data *, Scsi_Cmnd *);
-static int nsp32_busfree_occur(nsp32_hw_data *, unsigned short);
-static void nsp32_adjust_busfree(nsp32_hw_data *, unsigned int);
-static void nsp32_msgout_occur(nsp32_hw_data *);
-static void nsp32_restart_autoscsi(nsp32_hw_data *, unsigned short);
-static void nsp32_msgin_occur(nsp32_hw_data *, unsigned long, unsigned short);
-static void nsp32_analyze_sdtr(nsp32_hw_data *);
-static int nsp32_search_period_entry(nsp32_hw_data *,struct nsp32_target *, unsigned char);
-static void nsp32_set_async(nsp32_hw_data *, struct nsp32_target *);
-static void nsp32_set_max_sync(nsp32_hw_data *, struct nsp32_target *, unsigned char *, unsigned char *);
-static void nsp32_set_sync_entry(nsp32_hw_data *, struct nsp32_target *, int, unsigned char);
-static void nsp32_wait_req(nsp32_hw_data *, int);
-static void nsp32_wait_sack(nsp32_hw_data *, int);
-static void nsp32_sack_assert(nsp32_hw_data *);
-static void nsp32_sack_negate(nsp32_hw_data *);
-static void nsp32_do_bus_reset(nsp32_hw_data *);
+static int  __init    init_nsp32  (void);
+static void __exit    exit_nsp32  (void);
+
+/* struct Scsi_Host_Template */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+static int         nsp32_proc_info   (struct Scsi_Host *, char *, char **, off_t, int, int);
+#else
+static int         nsp32_proc_info   (char *, char **, off_t, int, int, int);
+#endif
 
-static int nsp32_getprom_param(nsp32_hw_data *);
-static int nsp32_getprom_new(nsp32_hw_data *);
-static int nsp32_getprom_standard(nsp32_hw_data *);
-static int nsp32_prom_read(nsp32_hw_data *, int);
-static void nsp32_prom_start(nsp32_hw_data *);
-static void nsp32_prom_stop(nsp32_hw_data *);
-static void nsp32_prom_write(nsp32_hw_data *, int);
-static int nsp32_prom_fetch(nsp32_hw_data *);
-static inline void nsp32_prom_set(nsp32_hw_data *, int, int);
-static inline int nsp32_prom_get(nsp32_hw_data *, int);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+static int         nsp32_detect      (struct pci_dev *pdev);
+#else
+static int         nsp32_detect      (Scsi_Host_Template *);
+#endif
+static int         nsp32_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+static const char *nsp32_info        (struct Scsi_Host *);
+static int         nsp32_release     (struct Scsi_Host *);
+
+/* SCSI error handler */
+static int         nsp32_eh_abort     (Scsi_Cmnd *);
+static int         nsp32_eh_bus_reset (Scsi_Cmnd *);
+static int         nsp32_eh_host_reset(Scsi_Cmnd *);
+
+/* generate SCSI message */
+static void nsp32_build_identify(Scsi_Cmnd *);
+static void nsp32_build_nop     (Scsi_Cmnd *);
+static void nsp32_build_reject  (Scsi_Cmnd *);
+static void nsp32_build_sdtr    (Scsi_Cmnd *, unsigned char, unsigned char);
+
+/* SCSI message handler */
+static int  nsp32_busfree_occur(Scsi_Cmnd *, unsigned short);
+static void nsp32_msgout_occur (Scsi_Cmnd *);
+static void nsp32_msgin_occur  (Scsi_Cmnd *, unsigned long, unsigned short);
+
+static int  nsp32_setup_sg_table    (Scsi_Cmnd *);
+static int  nsp32_selection_autopara(Scsi_Cmnd *);
+static int  nsp32_selection_autoscsi(Scsi_Cmnd *);
+static void nsp32_scsi_done         (Scsi_Cmnd *);
+static int  nsp32_arbitration       (Scsi_Cmnd *, unsigned int);
+static int  nsp32_reselection       (Scsi_Cmnd *, unsigned char);
+static void nsp32_adjust_busfree    (Scsi_Cmnd *, unsigned int);
+static void nsp32_restart_autoscsi  (Scsi_Cmnd *, unsigned short);
+
+/* SCSI SDTR */
+static void nsp32_analyze_sdtr       (Scsi_Cmnd *);
+static int  nsp32_search_period_entry(nsp32_hw_data *, nsp32_target *, unsigned char);
+static void nsp32_set_async          (nsp32_hw_data *, nsp32_target *);
+static void nsp32_set_max_sync       (nsp32_hw_data *, nsp32_target *, unsigned char *, unsigned char *);
+static void nsp32_set_sync_entry     (nsp32_hw_data *, nsp32_target *, int, unsigned char);
+
+/* SCSI bus status handler */
+static void nsp32_wait_req    (nsp32_hw_data *, int);
+static void nsp32_wait_sack   (nsp32_hw_data *, int);
+static void nsp32_sack_assert (nsp32_hw_data *);
+static void nsp32_sack_negate (nsp32_hw_data *);
+static void nsp32_do_bus_reset(nsp32_hw_data *);
 
+/* hardware interrupt handler */
+static irqreturn_t do_nsp32_isr(int, void *, struct pt_regs *);
+
+/* initialize hardware */
+static int  nsp32hw_init(nsp32_hw_data *);
+
+/* EEPROM handler */
+static        int  nsp32_getprom_param (nsp32_hw_data *);
+static        int  nsp32_getprom_at24  (nsp32_hw_data *);
+static        int  nsp32_getprom_c16   (nsp32_hw_data *);
+static        void nsp32_prom_start    (nsp32_hw_data *);
+static        void nsp32_prom_stop     (nsp32_hw_data *);
+static        int  nsp32_prom_read     (nsp32_hw_data *, int);
+static        int  nsp32_prom_read_bit (nsp32_hw_data *);
+static        void nsp32_prom_write_bit(nsp32_hw_data *, int);
+static inline void nsp32_prom_set      (nsp32_hw_data *, int, int);
+static inline int  nsp32_prom_get      (nsp32_hw_data *, int);
+
+/* debug/warning/info message */
+static void nsp32_message (const char *, int, char *, char *, ...);
+#ifdef NSP32_DEBUG
+static void nsp32_dmessage(const char *, int, int,    char *, ...);
+#endif
 
 /*
  * max_sectors is currently limited up to 128.
  */
 static Scsi_Host_Template nsp32_template = {
-       .name =                         "Workbit NinjaSCSI-32Bi/UDE",
-       .proc_name =                    "nsp32",
-       .proc_info =                    nsp32_proc_info,
-       .info =                         nsp32_info,
-       .queuecommand =                 nsp32_queuecommand,
-       .can_queue =                    1,
-       .sg_tablesize =                 NSP_SG_SIZE,
-       .max_sectors =                  128,
-       .cmd_per_lun =                  1,
-       .this_id =                      7,
-       .use_clustering =               DISABLE_CLUSTERING,
-       .eh_abort_handler =             nsp32_eh_abort,
-       .eh_device_reset_handler =      NULL,
-       .eh_bus_reset_handler =         nsp32_eh_bus_reset,
-       .eh_host_reset_handler =        nsp32_eh_host_reset,
+       .proc_name                      = "nsp32",
+       .name                           = "Workbit NinjaSCSI-32Bi/UDE",
+       .proc_info                      = nsp32_proc_info,
+       .info                           = nsp32_info,
+       .queuecommand                   = nsp32_queuecommand,
+       .can_queue                      = 1,
+       .sg_tablesize                   = NSP32_SG_SIZE,
+       .max_sectors                    = 128,
+       .cmd_per_lun                    = 1,
+       .this_id                        = NSP32_HOST_SCSIID,
+       .use_clustering                 = DISABLE_CLUSTERING,
+       .eh_abort_handler               = nsp32_eh_abort,
+/*     .eh_device_reset_handler        = NULL, */
+       .eh_bus_reset_handler           = nsp32_eh_bus_reset,
+       .eh_host_reset_handler          = nsp32_eh_host_reset,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74))
+       .detect                         = nsp32_detect,
+       .release                        = nsp32_release,
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
+       .use_new_eh_code                = 1,
+#else
+/*     .highmem_io                     = 1, */
+#endif
 };
 
 #include "nsp32_io.h"
 
-/*
+/***********************************************************************
  * debug, error print
  */
-#define nsp32_msg(type, args...) \
-       nsp32_message(__FUNCTION__, __LINE__, (type), ## args)
-#define nsp32_dbg(mask, args...) \
-       nsp32_dmessage(__FUNCTION__, __LINE__, (mask), ## args)
-
 #ifndef NSP32_DEBUG
-# define NSP32_DEBUG_MASK              0x000000
+# define NSP32_DEBUG_MASK            0x000000
+# define nsp32_msg(type, args...)     nsp32_message ("", 0, (type), args)
+# define nsp32_dbg(mask, args...)     /* */
 #else
-# define NSP32_DEBUG_MASK              0xffffff
+# define NSP32_DEBUG_MASK            0xffffff
+# define nsp32_msg(type, args...) \
+       nsp32_message (__FUNCTION__, __LINE__, (type), args)
+# define nsp32_dbg(mask, args...) \
+       nsp32_dmessage(__FUNCTION__, __LINE__, (mask), args)
 #endif
 
-#define NSP32_DEBUG_QUEUECOMMAND       0x000001
-#define NSP32_DEBUG_REGISTER           0x000002
-#define NSP32_DEBUG_AUTOSCSI           0x000004
-#define NSP32_DEBUG_INTR               0x000008
-#define NSP32_DEBUG_SGLIST             0x000010
-#define NSP32_DEBUG_BUSFREE            0x000020
-#define NSP32_DEBUG_CDB_CONTENTS       0x000040
-#define NSP32_DEBUG_RESELECTION                0x000080
-#define NSP32_DEBUG_MSGINOCCUR         0x000100
-#define NSP32_DEBUG_EEPROM             0x000200
-#define NSP32_DEBUG_MSGOUTOCCUR                0x000400
-#define NSP32_DEBUG_BUSRESET           0x000800
-#define NSP32_DEBUG_RESTART            0x001000
-#define NSP32_DEBUG_SYNC               0x002000
-#define NSP32_DEBUG_WAIT               0x004000
-#define NSP32_DEBUG_TARGETFLAG         0x008000
-#define NSP32_DEBUG_PROC               0x010000
-#define NSP32_DEBUG_INIT               0x020000
-#define NSP32_SPECIAL_PRINT_REGISTER   0x100000
+#define NSP32_DEBUG_QUEUECOMMAND       BIT(0)
+#define NSP32_DEBUG_REGISTER           BIT(1)
+#define NSP32_DEBUG_AUTOSCSI           BIT(2)
+#define NSP32_DEBUG_INTR               BIT(3)
+#define NSP32_DEBUG_SGLIST             BIT(4)
+#define NSP32_DEBUG_BUSFREE            BIT(5)
+#define NSP32_DEBUG_CDB_CONTENTS       BIT(6)
+#define NSP32_DEBUG_RESELECTION                BIT(7)
+#define NSP32_DEBUG_MSGINOCCUR         BIT(8)
+#define NSP32_DEBUG_EEPROM             BIT(9)
+#define NSP32_DEBUG_MSGOUTOCCUR                BIT(10)
+#define NSP32_DEBUG_BUSRESET           BIT(11)
+#define NSP32_DEBUG_RESTART            BIT(12)
+#define NSP32_DEBUG_SYNC               BIT(13)
+#define NSP32_DEBUG_WAIT               BIT(14)
+#define NSP32_DEBUG_TARGETFLAG         BIT(15)
+#define NSP32_DEBUG_PROC               BIT(16)
+#define NSP32_DEBUG_INIT               BIT(17)
+#define NSP32_SPECIAL_PRINT_REGISTER   BIT(20)
 
 #define NSP32_DEBUG_BUF_LEN            100
 
@@ -394,7 +352,7 @@ static void nsp32_message(const char *func, int line, char *type, char *fmt, ...
        char buf[NSP32_DEBUG_BUF_LEN];
 
        va_start(args, fmt);
-       vsprintf(buf, fmt, args);
+       vsnprintf(buf, sizeof(buf), fmt, args);
        va_end(args);
 
 #ifndef NSP32_DEBUG
@@ -404,19 +362,21 @@ static void nsp32_message(const char *func, int line, char *type, char *fmt, ...
 #endif
 }
 
+#ifdef NSP32_DEBUG
 static void nsp32_dmessage(const char *func, int line, int mask, char *fmt, ...)
 {
        va_list args;
        char buf[NSP32_DEBUG_BUF_LEN];
 
        va_start(args, fmt);
-       vsprintf(buf, fmt, args);
+       vsnprintf(buf, sizeof(buf), fmt, args);
        va_end(args);
 
        if (mask & NSP32_DEBUG_MASK) {
-               printk("Ninja: %d %s (%d): %s\n", mask, func, line, buf);
+               printk("nsp32-debug: 0x%x %s (%d): %s\n", mask, func, line, buf);
        }
 }
+#endif
 
 #ifdef NSP32_DEBUG
 # include "nsp32_debug.c"
@@ -426,56 +386,51 @@ static void nsp32_dmessage(const char *func, int line, int mask, char *fmt, ...)
 # define show_autophase(arg) /* */
 #endif
 
-#ifdef NSP32_DEBUG
-static int pc_debug = NSP32_DEBUG;
-MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(/*KERN_DEBUG*/ args)
-#else
-#define DEBUG(n, args...)
-#endif
-
-
 /*
  * IDENTIFY Message
  */
-static void nsp32_build_identify(nsp32_hw_data *data, Scsi_Cmnd *SCpnt)
+static void nsp32_build_identify(Scsi_Cmnd *SCpnt)
 {
-       int pos = data->msgoutlen;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       int pos             = data->msgout_len;
+       int mode            = FALSE;
 
-       data->msgoutbuf[pos++] =
-               0x80 |          /* Identify */
-#if 0
-               /* XXX: Auto DiscPriv detection is progressing... */
-               0x40 |          /* DiscPriv */
-#endif
-               SCpnt->device->lun;     /* LUNTRN */
+       /* XXX: Auto DiscPriv detection is progressing... */
+       if (disc_priv == 0) {
+               /* mode = TRUE; */
+       }
 
-       data->msgoutlen = pos;
+       data->msgoutbuf[pos] = IDENTIFY(mode, SCpnt->device->lun); pos++;
+
+       data->msgout_len = pos;
 }
 
 /*
  * SDTR Message Routine
  */
-static void nsp32_build_sdtr(nsp32_hw_data *data,
-                            unsigned char period, unsigned char offset)
+static void nsp32_build_sdtr(Scsi_Cmnd    *SCpnt,
+                            unsigned char period,
+                            unsigned char offset)
 {
-       int pos = data->msgoutlen;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       int pos             = data->msgout_len;
 
-       data->msgoutbuf[pos++] = EXTENDED_MESSAGE;
-       data->msgoutbuf[pos++] = EXTENDED_SDTR_LEN;
-       data->msgoutbuf[pos++] = EXTENDED_SDTR;
-       data->msgoutbuf[pos++] = period;
-       data->msgoutbuf[pos++] = offset;
+       data->msgoutbuf[pos] = EXTENDED_MESSAGE;  pos++;
+       data->msgoutbuf[pos] = EXTENDED_SDTR_LEN; pos++;
+       data->msgoutbuf[pos] = EXTENDED_SDTR;     pos++;
+       data->msgoutbuf[pos] = period;            pos++;
+       data->msgoutbuf[pos] = offset;            pos++;
 
-       data->msgoutlen = pos;
+       data->msgout_len = pos;
 }
 
 /*
  * No Operation Message
  */
-static void nsp32_build_nop(nsp32_hw_data *data)
+static void nsp32_build_nop(Scsi_Cmnd *SCpnt)
 {
-       int pos = data->msgoutlen;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       int            pos  = data->msgout_len;
 
        if (pos != 0) {
                nsp32_msg(KERN_WARNING,
@@ -483,19 +438,20 @@ static void nsp32_build_nop(nsp32_hw_data *data)
                return;
        }
 
-       data->msgoutbuf[pos++] = NOP;
-       data->msgoutlen = pos;
+       data->msgoutbuf[pos] = NOP; pos++;
+       data->msgout_len = pos;
 }
 
 /*
  * Reject Message
  */
-static void nsp32_build_reject(nsp32_hw_data *data)
+static void nsp32_build_reject(Scsi_Cmnd *SCpnt)
 {
-       int pos = data->msgoutlen;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       int            pos  = data->msgout_len;
 
-       data->msgoutbuf[pos++] = MESSAGE_REJECT;
-       data->msgoutlen = pos;
+       data->msgoutbuf[pos] = MESSAGE_REJECT; pos++;
+       data->msgout_len = pos;
 }
        
 /*
@@ -506,10 +462,10 @@ static void nsp32_start_timer(Scsi_Cmnd *SCpnt, int time)
 {
        unsigned int base = SCpnt->host->io_port;
 
-       DEBUG(0, __func__ " time=%d\n", time);
+       nsp32_dbg(NSP32_DEBUG_INTR, "timer=%d", time);
 
        if (time & (~TIMER_CNT_MASK)) {
-               printk("timer set overflow\n");
+               nsp32_dbg(NSP32_DEBUG_INTR, "timer set overflow");
        }
 
        nsp32_write2(base, TIMER_SET, time & TIMER_CNT_MASK);
@@ -520,17 +476,19 @@ static void nsp32_start_timer(Scsi_Cmnd *SCpnt, int time)
 /*
  * set SCSI command and other parameter to asic, and start selection phase
  */
-static int nsp32hw_start_selection(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
+static int nsp32_selection_autopara(Scsi_Cmnd *SCpnt)
 {
-       unsigned int   host_id = SCpnt->device->host->this_id;
-       unsigned int   base    = SCpnt->device->host->io_port;
-       unsigned char  target  = SCpnt->device->id;
-       unsigned char  *param  = data->autoparam;
-       unsigned char  phase, arbit;
-       int            i, time;
-       unsigned int   msgout;
-       unsigned long  l;
-       unsigned short s;
+       nsp32_hw_data  *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int    base    = SCpnt->device->host->io_port;
+       unsigned int    host_id = SCpnt->device->host->this_id;
+       unsigned char   target  = SCpnt->device->id;
+       nsp32_autoparam *param  = data->autoparam;
+       unsigned char   phase;
+       int             i, ret;
+       unsigned int    msgout;
+       u16_le          s;
+
+       nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "in");
 
        /*
         * check bus free
@@ -546,16 +504,16 @@ static int nsp32hw_start_selection(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
        /*
         * message out
         *
-        * Note: If the range of msgoutlen is 1 - 3, fill scsi_msgout.
+        * Note: If the range of msgout_len is 1 - 3, fill scsi_msgout.
         *       over 3 messages needs another routine.
         */
-       if (data->msgoutlen == 0) {
+       if (data->msgout_len == 0) {
                nsp32_msg(KERN_ERR, "SCSI MsgOut without any message!");
                SCpnt->result = DID_ERROR << 16;
                return FALSE;
-       } else if (data->msgoutlen > 0 && data->msgoutlen <= 3) {
+       } else if (data->msgout_len > 0 && data->msgout_len <= 3) {
                msgout = 0;
-               for (i=0; i<data->msgoutlen; i++) {
+               for (i = 0; i < data->msgout_len; i++) {
                        /*
                         * the sending order of the message is:
                         *  MCNT 3: MSG#0 -> MSG#1 -> MSG#2
@@ -563,42 +521,46 @@ static int nsp32hw_start_selection(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
                         *  MCNT 1:                   MSG#2    
                         */
                        msgout >>= 8;
-                       msgout |= (unsigned int)(data->msgoutbuf[i] << 24);
+                       msgout |= ((unsigned int)(data->msgoutbuf[i]) << 24);
                }
                msgout |= MV_VALID;     /* MV valid */
-               msgout |= (unsigned int)data->msgoutlen; /* len */
+               msgout |= (unsigned int)data->msgout_len; /* len */
        } else {
-               /* data->msgoutlen > 3 */
+               /* data->msgout_len > 3 */
                msgout = 0;
        }
 
+       // nsp_dbg(NSP32_DEBUG_AUTOSCSI, "sel time out=0x%x\n", nsp32_read2(base, SEL_TIME_OUT));
+       // nsp32_write2(base, SEL_TIME_OUT,   SEL_TIMEOUT_TIME);
+
        /*
         * setup asic parameter
         */
-       memset(param, 0, AUTOPARAM_SIZE);
+       memset(param, 0, sizeof(nsp32_autoparam));
 
        /* cdb */
-       for (i=0; i<SCpnt->cmd_len; i++) {
-               param[4*i] = SCpnt->cmnd[i];
+       for (i = 0; i < SCpnt->cmd_len; i++) {
+               param->cdb[4 * i] = SCpnt->cmnd[i];
        }
 
-       /* message out */
-       param[4*0x10 +0] = (msgout & 0x000000ff) >> 0;
-       param[4*0x10 +1] = (msgout & 0x0000ff00) >> 8;
-       param[4*0x10 +2] = (msgout & 0x00ff0000) >> 16;
-       param[4*0x10 +3] = (msgout & 0xff000000) >> 24;
+       /* outgoing messages */
+       param->msgout = cpu_to_le32(msgout);
+
+       /* syncreg, ackwidth, target id, SREQ sampling rate */
+       param->syncreg    = data->cur_target->syncreg;
+       param->ackwidth   = data->cur_target->ackwidth;
+       param->target_id  = BIT(host_id) | BIT(target);
+       param->sample_reg = data->cur_target->sample_reg;
 
-       /* syncreg, ackwidth, target id, sampleing rate */
-       param[4*0x11 +0] = data->curtarget->syncreg;
-       param[4*0x11 +1] = data->curtarget->ackwidth;
-       param[4*0x11 +2] = BIT(host_id) | BIT(target);
-       param[4*0x11 +3] = 0;
+       // nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "sample rate=0x%x\n", data->cur_target->sample_reg);
 
        /* command control */
-       s = (CLEAR_CDB_FIFO_POINTER | AUTOSCSI_START |
-            AUTO_MSGIN_00_OR_04 | AUTO_MSGIN_02 | AUTO_ATN);
-       param[4*0x12 +0] = (s & 0x00ff) >> 0;
-       param[4*0x12 +1] = (s & 0xff00) >> 8;
+       param->command_control = cpu_to_le16(CLEAR_CDB_FIFO_POINTER |
+                                            AUTOSCSI_START         |
+                                            AUTO_MSGIN_00_OR_04    |
+                                            AUTO_MSGIN_02          |
+                                            AUTO_ATN               );
+
 
        /* transfer control */
        s = 0;
@@ -614,86 +576,51 @@ static int nsp32hw_start_selection(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
                break;
        default:
                nsp32_msg(KERN_ERR, "unknown trans_method");
+               break;
        }
        /*
-        * ORed BLIEND_MODE, FIFO intr is decreased, instead of PCI bus waits.
+        * OR-ed BLIEND_MODE, FIFO intr is decreased, instead of PCI bus waits.
         * For bus master transfer, it's taken off.
         */
        s |= (TRANSFER_GO | ALL_COUNTER_CLR);
-       param[4*0x12 +2] = (s & 0x00ff) >> 0;
-       param[4*0x12 +3] = (s & 0xff00) >> 8;
+       param->transfer_control = cpu_to_le16(s);
 
        /* sg table addr */
-       l = data->curlunt->sglun_paddr;
-       param[4*0x13 +0] = (l & 0x000000ff) >> 0;
-       param[4*0x13 +1] = (l & 0x0000ff00) >> 8;
-       param[4*0x13 +2] = (l & 0x00ff0000) >> 16;
-       param[4*0x13 +3] = (l & 0xff000000) >> 24;
+       param->sgt_pointer = cpu_to_le32(data->cur_lunt->sglun_paddr);
 
        /*
-        * transfer parameter to asic
+        * transfer parameter to ASIC
         */
-       nsp32_write4(base, SGT_ADR,         virt_to_bus(param));
+       nsp32_write4(base, SGT_ADR,         data->auto_paddr);
        nsp32_write2(base, COMMAND_CONTROL, CLEAR_CDB_FIFO_POINTER |
                                            AUTO_PARAMETER         );
 
        /*
-        * Arbitration Status Check
-        *      
-        * Note: Arbitration counter is wait during ARBIT_GO is not lifting.
-        *       Using udelay(1) consumes CPU time and system time, but 
-        *       arbitration delay time is defined minimal 2.4us in SCSI
-        *       specification, thus udelay works as coarse grained wait timer.
-        */
-       time = 0;
-       do {
-               arbit = nsp32_read1(base, ARBIT_STATUS);
-               nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "arbit=0x%x", arbit);
-       } while ((arbit & (ARBIT_WIN | ARBIT_FAIL)) == 0 &&
-                (time++ <= 1000));
-
-       nsp32_dbg(NSP32_DEBUG_AUTOSCSI,
-                 "arbit: 0x%x, delay time: %d", arbit, time);
-
-       if (arbit & ARBIT_WIN) {
-               SCpnt->result = DID_OK << 16;
-               /* PCI LED on! */
-               nsp32_index_write1(base, EXT_PORT, LED_ON);
-       } else if (arbit & ARBIT_FAIL) {
-               SCpnt->result = DID_BUS_BUSY << 16;
-               nsp32_write1(base, SET_ARBIT, ARBIT_CLEAR);
-               return FALSE;
-       } else {
-               /* unknown error or ARBIT_GO timeout */
-               nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "arbit fail");
-               SCpnt->result = DID_NO_CONNECT << 16;
-               nsp32_write1(base, SET_ARBIT, ARBIT_CLEAR);
-               return FALSE;
-        }
-
-       /*
-        * clear Arbit
+        * Check arbitration
         */
-       nsp32_write1(base, SET_ARBIT, ARBIT_CLEAR);
+       ret = nsp32_arbitration(SCpnt, base);
 
-       return TRUE;
+       return ret;
 }
 
 
 /*
  * Selection with AUTO SCSI (without AUTO PARAMETER)
  */
-static int nsp32_selection_autoscsi(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
+static int nsp32_selection_autoscsi(Scsi_Cmnd *SCpnt)
 {
+       nsp32_hw_data  *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int    base    = SCpnt->device->host->io_port;
+       unsigned int    host_id = SCpnt->device->host->this_id;
+       unsigned char   target  = SCpnt->device->id;
        unsigned char   phase;
-       unsigned char   arbit;
        int             status;
-       int             i;
        unsigned short  command = 0;
-       int             time = 0;
-       unsigned int    msgout = 0;
+       unsigned int    msgout  = 0;
        unsigned short  execph;
-       unsigned int    base = data->BaseAddress;
+       int             i;
+
+       nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "in");
 
        /*
         * IRQ disable
@@ -704,8 +631,7 @@ static int nsp32_selection_autoscsi(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
         * check bus line
         */
        phase = nsp32_read1(base, SCSI_BUS_MONITOR);
-       if(((phase & BUSMON_BSY) == 1) ||
-          (phase & BUSMON_SEL) == 1) {
+       if(((phase & BUSMON_BSY) == 1) || (phase & BUSMON_SEL) == 1) {
                nsp32_msg(KERN_WARNING, "bus busy");
                SCpnt->result = DID_BUS_BUSY << 16;
                status = 1;
@@ -725,32 +651,30 @@ static int nsp32_selection_autoscsi(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
        /*
         * set CDB0 - CDB15
         */
-       for (i=0; i<SCpnt->cmd_len; i++) {
+       for (i = 0; i < SCpnt->cmd_len; i++) {
                nsp32_write1(base, COMMAND_DATA, SCpnt->cmnd[i]);
         }
-       nsp32_dbg(NSP32_DEBUG_CDB_CONTENTS, "CDB[0]=[0x%x]", SCpnt->cmnd[i]);
+       nsp32_dbg(NSP32_DEBUG_CDB_CONTENTS, "CDB[0]=[0x%x]", SCpnt->cmnd[0]);
 
        /*
-        * set SCSIOUT LATCH(initiator)/TARGET(target) (ORed) ID
+        * set SCSIOUT LATCH(initiator)/TARGET(target) (OR-ed) ID
         */
-       nsp32_write1(base, SCSI_OUT_LATCH_TARGET_ID,
-               ((1 << NSP32_HOST_SCSIID) | (1 << SCpnt->device->id)));
+       nsp32_write1(base, SCSI_OUT_LATCH_TARGET_ID, BIT(host_id) | BIT(target));
 
        /*
         * set SCSI MSGOUT REG
         *
-        * Note: If the range of msgoutlen is 1 - 3, fill scsi_msgout.
+        * Note: If the range of msgout_len is 1 - 3, fill scsi_msgout.
         *       over 3 messages needs another routine.
         */
-       if (data->msgoutlen == 0) {
-               nsp32_msg(KERN_ERR, 
-                         "SCSI MsgOut without any message!");
+       if (data->msgout_len == 0) {
+               nsp32_msg(KERN_ERR, "SCSI MsgOut without any message!");
                SCpnt->result = DID_ERROR << 16;
                status = 1;
                goto out;
-       } else if (data->msgoutlen > 0 && data->msgoutlen <= 3) {
+       } else if (data->msgout_len > 0 && data->msgout_len <= 3) {
                msgout = 0;
-               for (i=0; i<data->msgoutlen; i++) {
+               for (i = 0; i < data->msgout_len; i++) {
                        /*
                         * the sending order of the message is:
                         *  MCNT 3: MSG#0 -> MSG#1 -> MSG#2
@@ -758,62 +682,62 @@ static int nsp32_selection_autoscsi(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
                         *  MCNT 1:                   MSG#2    
                         */
                        msgout >>= 8;
-                       msgout |= (unsigned int)(data->msgoutbuf[i] << 24);
+                       msgout |= ((unsigned int)(data->msgoutbuf[i]) << 24);
                }
                msgout |= MV_VALID;     /* MV valid */
-               msgout |= (unsigned int)data->msgoutlen; /* len */
+               msgout |= (unsigned int)data->msgout_len; /* len */
                nsp32_write4(base, SCSI_MSG_OUT, msgout);
        } else {
-               /* data->msgoutlen > 3 */
+               /* data->msgout_len > 3 */
                nsp32_write4(base, SCSI_MSG_OUT, 0);
        }
 
        /*
         * set selection timeout(= 250ms)
         */
-       nsp32_write2(base, SEL_TIME_OUT, SEL_TIMEOUT_TIME);
+       nsp32_write2(base, SEL_TIME_OUT,   SEL_TIMEOUT_TIME);
 
        /*
-        * set smpl rate
+        * set SREQ hazard killer sampling rate
         * 
-        * TODO: smpl_rate (BASE+0F) is 0 when internal clock = 40MHz.
+        * TODO: sample_rate (BASE+0F) is 0 when internal clock = 40MHz.
         *      check other internal clock!
         */
-       nsp32_write1(base, SREQ_SMPL_RATE, 0);
+       nsp32_write1(base, SREQ_SMPL_RATE, data->cur_target->sample_reg);
 
        /*
         * clear Arbit
         */
-       nsp32_write1(base, SET_ARBIT, ARBIT_CLEAR);
+       nsp32_write1(base, SET_ARBIT,      ARBIT_CLEAR);
 
        /*
         * set SYNCREG
         * Don't set BM_START_ADR before setting this register.
         */
-       nsp32_write1(base, SYNC_REG, data->curtarget->syncreg);
+       nsp32_write1(base, SYNC_REG,  data->cur_target->syncreg);
 
        /*
         * set ACKWIDTH
         */
-       nsp32_write1(base, ACK_WIDTH, data->curtarget->ackwidth);
+       nsp32_write1(base, ACK_WIDTH, data->cur_target->ackwidth);
 
        nsp32_dbg(NSP32_DEBUG_AUTOSCSI,
                  "syncreg=0x%x, ackwidth=0x%x, sgtpaddr=0x%x, id=0x%x",
                  nsp32_read1(base, SYNC_REG), nsp32_read1(base, ACK_WIDTH),
                  nsp32_read4(base, SGT_ADR), nsp32_read1(base, SCSI_OUT_LATCH_TARGET_ID));
-       nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "msgoutlen=%d, msgout=0x%x",
-                 data->msgoutlen, msgout);
+       nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "msgout_len=%d, msgout=0x%x",
+                 data->msgout_len, msgout);
 
        /*
         * set SGT ADDR (physical address)
         */
-       nsp32_write4(base, SGT_ADR, data->curlunt->sglun_paddr);
+       nsp32_write4(base, SGT_ADR, data->cur_lunt->sglun_paddr);
 
        /*
         * set TRANSFER CONTROL REG
         */
        command = 0;
-       command |= ( TRANSFER_GO | ALL_COUNTER_CLR);
+       command |= (TRANSFER_GO | ALL_COUNTER_CLR);
        if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
                if (SCpnt->request_bufflen > 0) {
                        command |= BM_START;
@@ -828,73 +752,75 @@ static int nsp32_selection_autoscsi(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
        /*
         * start AUTO SCSI, kick off arbitration
         */
-       command = 0;
-       command |= (CLEAR_CDB_FIFO_POINTER
-                   | AUTOSCSI_START
-                   | AUTO_MSGIN_00_OR_04
-                   | AUTO_MSGIN_02 
-                   | AUTO_ATN);
+       command = (CLEAR_CDB_FIFO_POINTER |
+                  AUTOSCSI_START         |
+                  AUTO_MSGIN_00_OR_04    |
+                  AUTO_MSGIN_02          |
+                  AUTO_ATN                );
        nsp32_write2(base, COMMAND_CONTROL, command);
 
        /*
-        * Arbitration Status Check
-        *      
-        * Note: Arbitration counter is wait during ARBIT_GO is not lifting.
-        *       Using udelay(1) consumes CPU time and system time, but 
-        *       arbitration delay time is defined minimal 2.4us in SCSI
-        *       specification, thus udelay works as coarse grained wait timer.
+        * Check arbitration
         */
-       time = 0;
-       while(1) {
-               arbit = nsp32_read1(base, ARBIT_STATUS);
-               if(arbit & ARBIT_GO) {
-                       udelay(1);
-                       time++;
-                       if ( time > ARBIT_TIMEOUT_TIME ) {
-                               /* something lock up! guess no connection */
-                               SCpnt->result = DID_NO_CONNECT << 16;
-                               status = FALSE;
-                               goto out;
-                       }
-               } else {
-                       break;
-               }
-       };
-
-       nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "arbit: 0x%x, delay time: %d", arbit, time);
+       status = nsp32_arbitration(SCpnt, base);
 
+ out:
        /*
-        * check Arbitration Status Result
+        * IRQ enable
         */
-       if(arbit & ARBIT_WIN) {
+       nsp32_write2(base, IRQ_CONTROL, 0);
+
+       return status;
+}
+
+
+/*
+ * Arbitration Status Check
+ *     
+ * Note: Arbitration counter is waited during ARBIT_GO is not lifting.
+ *      Using udelay(1) consumes CPU time and system time, but 
+ *      arbitration delay time is defined minimal 2.4us in SCSI
+ *      specification, thus udelay works as coarse grained wait timer.
+ */
+static int nsp32_arbitration(Scsi_Cmnd *SCpnt, unsigned int base)
+{
+       unsigned char arbit;
+       int           status = TRUE;
+       int           time   = 0;
+
+       do {
+               arbit = nsp32_read1(base, ARBIT_STATUS);
+               time++;
+       } while ((arbit & (ARBIT_WIN | ARBIT_FAIL)) == 0 &&
+                (time <= ARBIT_TIMEOUT_TIME));
+
+       nsp32_dbg(NSP32_DEBUG_AUTOSCSI,
+                 "arbit: 0x%x, delay time: %d", arbit, time);
+
+       if (arbit & ARBIT_WIN) {
                /* Arbitration succeeded */
-               status = TRUE;
                SCpnt->result = DID_OK << 16;
-               /* PCI LED on! */
-               nsp32_index_write1(base, EXT_PORT, LED_ON);
-       } else if(arbit & ARBIT_FAIL) {
+               nsp32_index_write1(base, EXT_PORT, LED_ON); /* PCI LED on */
+       } else if (arbit & ARBIT_FAIL) {
                /* Arbitration failed */
-               status = FALSE;
                SCpnt->result = DID_BUS_BUSY << 16;
-       } else {
-               /* unknown error? */
                status = FALSE;
-               SCpnt->result = DID_ERROR << 16;
+       } else {
+               /*
+                * unknown error or ARBIT_GO timeout,
+                * something lock up! guess no connection.
+                */
+               nsp32_dbg(NSP32_DEBUG_AUTOSCSI, "arbit timeout");
                SCpnt->result = DID_NO_CONNECT << 16;
-       }
+               status = FALSE;
+        }
 
        /*
         * clear Arbit
         */
        nsp32_write1(base, SET_ARBIT, ARBIT_CLEAR);
 
- out:
-       /*
-        * IRQ enable
-        */
-       nsp32_write2(base, IRQ_CONTROL, 0);
-
-       return(status);
+       return status;
 }
 
 
@@ -905,10 +831,12 @@ static int nsp32_selection_autoscsi(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
  *      reselection target id&lun must be already set.
  *      SCSI-2 says IDENTIFY implies RESTORE_POINTER operation.
  */
-static int nsp32_reselection(nsp32_hw_data *data, unsigned char newlun)
+static int nsp32_reselection(Scsi_Cmnd *SCpnt, unsigned char newlun)
 {
-       unsigned int base = data->BaseAddress;
-       unsigned char tmpid, newid;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int   host_id = SCpnt->device->host->this_id;
+       unsigned int   base    = SCpnt->device->host->io_port;
+       unsigned char  tmpid, newid;
 
        nsp32_dbg(NSP32_DEBUG_RESELECTION, "enter");
 
@@ -916,7 +844,7 @@ static int nsp32_reselection(nsp32_hw_data *data, unsigned char newlun)
         * calculate reselected SCSI ID
         */
        tmpid = nsp32_read1(base, RESELECT_ID);
-       tmpid &= 0x7f;
+       tmpid &= (~BIT(host_id));
        newid = 0;
        while (tmpid) {
                if (tmpid & 1) {
@@ -931,18 +859,18 @@ static int nsp32_reselection(nsp32_hw_data *data, unsigned char newlun)
         * or current nexus is not existed, unexpected
         * reselection is occurred. Send reject message.
         */
-       if (newid >= MAX_TARGET || newlun >= MAX_LUN) {
+       if (newid >= NUMBER(data->lunt) || newlun >= NUMBER(data->lunt[0])) {
                nsp32_msg(KERN_WARNING, "unknown id/lun");
                return FALSE;
-       } else if(data->lunt[newid][newlun]->SCpnt == NULL) {
+       } else if(data->lunt[newid][newlun].SCpnt == NULL) {
                nsp32_msg(KERN_WARNING, "no SCSI command is processing");
                return FALSE;
        }
 
-       data->pid       = newid;
-       data->plun      = newlun;
-       data->curtarget = &data->target[newid];
-       data->curlunt   = data->lunt[newid][newlun];
+       data->cur_id    = newid;
+       data->cur_lun   = newlun;
+       data->cur_target = &(data->target[newid]);
+       data->cur_lunt   = &(data->lunt[newid][newlun]);
 
        /* reset SACK/SavedACK counter (or ALL clear?) */
        nsp32_write4(base, CLR_COUNTER, CLRCOUNTER_ALLMASK);
@@ -952,16 +880,18 @@ static int nsp32_reselection(nsp32_hw_data *data, unsigned char newlun)
 
 
 /*
- * nsp32hw_setup_sg_table - build scatter gather list for transfer data
+ * nsp32_setup_sg_table - build scatter gather list for transfer data
  *                         with bus master.
  *
  * Note: NinjaSCSI-32Bi/UDE bus master can not transfer over 64KB at a time.
  */
-static int nsp32hw_setup_sg_table(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
+static int nsp32_setup_sg_table(Scsi_Cmnd *SCpnt)
 {
-       struct scatterlist *sgl;
-       struct nsp32_sgtable *sgt = data->curlunt->sglun->sgt;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       struct scatterlist   *sgl;
+       nsp32_sgtable *sgt = data->cur_lunt->sglun->sgt;
        int num, i;
+       u32_le l;
 
        if (SCpnt->request_bufflen == 0) {
                return TRUE;
@@ -976,7 +906,7 @@ static int nsp32hw_setup_sg_table(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
                sgl = (struct scatterlist *)SCpnt->request_buffer;
                num = pci_map_sg(data->Pci, sgl, SCpnt->use_sg,
                                 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-               for (i=0; i<num; i++) {
+               for (i = 0; i < num; i++) {
                        /*
                         * Build nsp32_sglist, substitute sg dma addresses.
                         */
@@ -984,26 +914,38 @@ static int nsp32hw_setup_sg_table(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
                        sgt[i].len  = cpu_to_le32(sg_dma_len(sgl));
                        sgl++;
 
-                       if (sgt[i].len > 65536) {
+                       if (le32_to_cpu(sgt[i].len) > 0x10000) {
                                nsp32_msg(KERN_ERR,
-                                       "can't transfer over 64KB at a time");
+                                       "can't transfer over 64KB at a time, size=0x%lx", le32_to_cpu(sgt[i].len));
                                return FALSE;
                        }
                        nsp32_dbg(NSP32_DEBUG_SGLIST,
-                                 "num 0x%x : addr 0x%lx len 0x%x",
-                                 i, sgt[i].addr, sgt[i].len);
+                                 "num 0x%x : addr 0x%lx len 0x%lx",
+                                 i,
+                                 le32_to_cpu(sgt[i].addr),
+                                 le32_to_cpu(sgt[i].len ));
                }
-               sgt[num-1].len |= NSP32_SG_END_SGT; /* set end mark */
+
+               /* set end mark */
+               l = le32_to_cpu(sgt[num-1].len);
+               sgt[num-1].len = cpu_to_le32(l | SGTEND);
+
        } else {
                SCpnt->SCp.have_data_in = pci_map_single(data->Pci,
                        SCpnt->request_buffer, SCpnt->request_bufflen,
                        scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+
                sgt[0].addr = cpu_to_le32(SCpnt->SCp.have_data_in);
-               sgt[0].len  = cpu_to_le32(SCpnt->request_bufflen);
-               sgt[0].len |= NSP32_SG_END_SGT; /* set end mark */
+               sgt[0].len  = cpu_to_le32(SCpnt->request_bufflen | SGTEND); /* set end mark */
 
-               nsp32_dbg(NSP32_DEBUG_SGLIST, "single : addr 0x%lx len=0x%x",
-                         sgt[0].addr, sgt[0].len);
+               if (SCpnt->request_bufflen > 0x10000) {
+                       nsp32_msg(KERN_ERR,
+                                 "can't transfer over 64KB at a time, size=0x%lx", SCpnt->request_bufflen);
+                       return FALSE;
+               }
+               nsp32_dbg(NSP32_DEBUG_SGLIST, "single : addr 0x%lx len=0x%lx",
+                         le32_to_cpu(sgt[0].addr),
+                         le32_to_cpu(sgt[0].len ));
        }
 
        return TRUE;
@@ -1012,8 +954,8 @@ static int nsp32hw_setup_sg_table(Scsi_Cmnd *SCpnt, nsp32_hw_data *data)
 static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
        nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
-       struct nsp32_target *target;
-       struct nsp32_lunt *curlunt;
+       nsp32_target *target;
+       nsp32_lunt   *cur_lunt;
        int ret;
 
        nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND,
@@ -1022,27 +964,29 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
                  SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len,
                  SCpnt->use_sg, SCpnt->request_buffer, SCpnt->request_bufflen);
 
-       if (data->CurrentSC != NULL ) {
+       if (data->CurrentSC != NULL) {
                nsp32_msg(KERN_ERR, "Currentsc != NULL. Cancel this command request");
                data->CurrentSC = NULL;
                SCpnt->result   = DID_NO_CONNECT << 16;
                done(SCpnt);
 
-               return 1;
+               return SCSI_MLQUEUE_HOST_BUSY;
        }
 
        /* check target ID is not same as this initiator ID */
-       if (SCpnt->device->id == NSP32_HOST_SCSIID) {
+       if (SCpnt->device->id == SCpnt->device->host->this_id) {
+               nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "terget==host???");
                SCpnt->result = DID_BAD_TARGET << 16;
                done(SCpnt);
-               return 1;
+               return SCSI_MLQUEUE_DEVICE_BUSY;
        }
 
        /* check target LUN is allowable value */
        if (SCpnt->device->lun >= MAX_LUN) {
+               nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "no more lun");
                SCpnt->result = DID_BAD_TARGET << 16;
                done(SCpnt);
-               return 1;
+               return SCSI_MLQUEUE_DEVICE_BUSY;
        }
 
        show_command(SCpnt);
@@ -1051,7 +995,7 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        data->CurrentSC      = SCpnt;
        SCpnt->SCp.Status    = CHECK_CONDITION;
        SCpnt->SCp.Message   = 0;
-       SCpnt->resid         = 0; //SCpnt->request_bufflen;
+       SCpnt->resid         = SCpnt->request_bufflen;
 
        SCpnt->SCp.ptr              = (char *) SCpnt->request_buffer;
        SCpnt->SCp.this_residual    = SCpnt->request_bufflen;
@@ -1059,24 +1003,26 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
        SCpnt->SCp.buffers_residual = 0;
 
        /* initialize data */
-       data->msgoutlen         = 0;
-       data->msginlen          = 0;
-       curlunt                 = data->lunt[SCpnt->device->id][SCpnt->device->lun];
-       curlunt->SCpnt          = SCpnt;
-       curlunt->save_datp      = 0;
-       curlunt->msgin03        = FALSE;
-       data->curlunt           = curlunt;
-       data->pid               = SCpnt->device->id;
-       data->plun              = SCpnt->device->lun;
-
-       ret = nsp32hw_setup_sg_table(SCpnt, data);
+       data->msgout_len        = 0;
+       data->msgin_len         = 0;
+       cur_lunt                = &(data->lunt[SCpnt->device->id][SCpnt->device->lun]);
+       cur_lunt->SCpnt         = SCpnt;
+       cur_lunt->save_datp     = 0;
+       cur_lunt->msgin03       = FALSE;
+       data->cur_lunt          = cur_lunt;
+       data->cur_id            = SCpnt->device->id;
+       data->cur_lun           = SCpnt->device->lun;
+
+       ret = nsp32_setup_sg_table(SCpnt);
        if (ret == FALSE) {
+               nsp32_msg(KERN_ERR, "SGT fail");
                SCpnt->result = DID_ERROR << 16;
-               nsp32_scsi_done(data, SCpnt);
+               nsp32_scsi_done(SCpnt);
+               return SCSI_MLQUEUE_HOST_BUSY;
        }
 
        /* Build IDENTIFY */
-       nsp32_build_identify(data, SCpnt);
+       nsp32_build_identify(SCpnt);
 
        /* 
         * If target is the first time to transfer after the reset
@@ -1084,14 +1030,14 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
         * message SDTR is needed to do synchronous transfer.
         */
        target = &data->target[SCpnt->device->id];
-       data->curtarget = target;
+       data->cur_target = target;
 
        if (!(target->sync_flag & (SDTR_DONE | SDTR_INITIATOR | SDTR_TARGET))) {
                unsigned char period, offset;
 
                if (trans_mode != ASYNC_MODE) {
                        nsp32_set_max_sync(data, target, &period, &offset);
-                       nsp32_build_sdtr(data, period, offset);
+                       nsp32_build_sdtr(SCpnt, period, offset);
                        target->sync_flag |= SDTR_INITIATOR;
                } else {
                        nsp32_set_async(data, target);
@@ -1134,27 +1080,27 @@ static int nsp32_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 
        /* Selection */
        if (auto_param == 0) {
-               ret = nsp32hw_start_selection(SCpnt, data);
+               ret = nsp32_selection_autopara(SCpnt);
        } else {
-               ret = nsp32_selection_autoscsi(SCpnt, data);
+               ret = nsp32_selection_autoscsi(SCpnt);
        }
 
        if (ret != TRUE) {
-               nsp32_scsi_done(data, SCpnt);
-               return 1;
+               nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, "selection fail");
+               nsp32_scsi_done(SCpnt);
+               return SCSI_MLQUEUE_DEVICE_BUSY;
        }
 
        return 0;
 }
 
 /* initialize asic */
-static int nsp32hw_init(struct Scsi_Host *host)
+static int nsp32hw_init(nsp32_hw_data *data)
 {
-       unsigned int  base = host->io_port;
+       unsigned int   base = data->BaseAddress;
        unsigned short irq_stat;
-       unsigned long lc_reg;
-       unsigned char power;
-       nsp32_hw_data *data = (nsp32_hw_data *)host->hostdata;
+       unsigned long  lc_reg;
+       unsigned char  power;
 
        lc_reg = nsp32_index_read4(base, CFG_LATE_CACHE);
        if ((lc_reg & 0xff00) == 0) {
@@ -1162,15 +1108,15 @@ static int nsp32hw_init(struct Scsi_Host *host)
                nsp32_index_write2(base, CFG_LATE_CACHE, lc_reg & 0xffff);
        }
 
-       nsp32_write2(base, IRQ_CONTROL,      IRQ_CONTROL_ALL_IRQ_MASK);
-       nsp32_write2(base, TRANSFER_CONTROL, 0);
-       nsp32_write4(base, BM_CNT,           0);
+       nsp32_write2(base, IRQ_CONTROL,        IRQ_CONTROL_ALL_IRQ_MASK);
+       nsp32_write2(base, TRANSFER_CONTROL,   0);
+       nsp32_write4(base, BM_CNT,             0);
        nsp32_write2(base, SCSI_EXECUTE_PHASE, 0);
 
        do {
                irq_stat = nsp32_read2(base, IRQ_STATUS);
+               nsp32_dbg(NSP32_DEBUG_INIT, "irq_stat 0x%x", irq_stat);
        } while (irq_stat & IRQSTATUS_ANY_IRQ);
-       nsp32_dbg(NSP32_DEBUG_INIT, "irq_stat 0x%x", irq_stat);
 
        /*
         * Fill FIFO_FULL_SHLD, FIFO_EMPTY_SHLD. Below parameter is
@@ -1178,22 +1124,25 @@ static int nsp32hw_init(struct Scsi_Host *host)
         */
        if ((data->trans_method & NSP32_TRANSFER_PIO) ||
            (data->trans_method & NSP32_TRANSFER_MMIO)) {
-               nsp32_index_write1(base, FIFO_FULL_SHLD_COUNT, 0x40);
+               nsp32_index_write1(base, FIFO_FULL_SHLD_COUNT,  0x40);
+               nsp32_index_write1(base, FIFO_EMPTY_SHLD_COUNT, 0x40);
        } else if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
-               nsp32_index_write1(base, FIFO_FULL_SHLD_COUNT, 0x10);
+               nsp32_index_write1(base, FIFO_FULL_SHLD_COUNT,  0x10);
+               nsp32_index_write1(base, FIFO_EMPTY_SHLD_COUNT, 0x60);
+       } else {
+               nsp32_dbg(NSP32_DEBUG_INIT, "unknown transfer mode");
        }
-       nsp32_index_write1(base, FIFO_EMPTY_SHLD_COUNT, 0x60);
 
        nsp32_dbg(NSP32_DEBUG_INIT, "full 0x%x emp 0x%x",
                  nsp32_index_read1(base, FIFO_FULL_SHLD_COUNT),
                  nsp32_index_read1(base, FIFO_EMPTY_SHLD_COUNT));
 
        nsp32_index_write1(base, CLOCK_DIV, data->clock);
-       nsp32_index_write1(base, BM_CYCLE, MEMRD_CMD1 | SGT_AUTO_PARA_MEMED_CMD);
+       nsp32_index_write1(base, BM_CYCLE,  MEMRD_CMD1 | SGT_AUTO_PARA_MEMED_CMD);
        nsp32_write1(base, PARITY_CONTROL, 0);  /* parity check is disable */
 
        /*
-        * initialize I_MISC_WRRD register
+        * initialize MISC_WRRD register
         * 
         * Note: Designated parameters is obeyed as following:
         *      MISC_SCSI_DIRECTION_DETECTOR_SELECT: It must be set.
@@ -1209,10 +1158,10 @@ static int nsp32hw_init(struct Scsi_Host *host)
         */
        nsp32_index_write2(base, MISC_WR,
                           (SCSI_DIRECTION_DETECTOR_SELECT |
-                           DELAYED_BMSTART |
-                           MASTER_TERMINATION_SELECT |
-                           BMREQ_NEGATE_TIMING_SEL |
-                           AUTOSEL_TIMING_SEL |
+                           DELAYED_BMSTART                |
+                           MASTER_TERMINATION_SELECT      |
+                           BMREQ_NEGATE_TIMING_SEL        |
+                           AUTOSEL_TIMING_SEL             |
                            BMSTOP_CHANGE2_NONDATA_PHASE));
 
        nsp32_index_write1(base, TERM_PWR_CONTROL, 0);
@@ -1223,11 +1172,11 @@ static int nsp32hw_init(struct Scsi_Host *host)
        }
 
        nsp32_write2(base, TIMER_SET, TIMER_STOP);
-       nsp32_write2(base, TIMER_SET, TIMER_STOP);
+       nsp32_write2(base, TIMER_SET, TIMER_STOP); /* Required 2 times */
 
-       nsp32_write1(base, SYNC_REG,  0);
-       nsp32_write1(base, ACK_WIDTH, 0);
-       nsp32_write2(base, SEL_TIME_OUT, 10000); /* 25us x10000 = 250ms defined in SCSI */
+       nsp32_write1(base, SYNC_REG,     0);
+       nsp32_write1(base, ACK_WIDTH,    0);
+       nsp32_write2(base, SEL_TIME_OUT, SEL_TIMEOUT_TIME);
 
        /*
         * enable to select designated IRQ (except for
@@ -1239,14 +1188,14 @@ static int nsp32hw_init(struct Scsi_Host *host)
                                             IRQSELECT_RESELECT_IRQ      |
                                             IRQSELECT_PHASE_CHANGE_IRQ  |
                                             IRQSELECT_AUTO_SCSI_SEQ_IRQ |
-                                            //IRQSELECT_BMCNTERR_IRQ    |
+                                         //   IRQSELECT_BMCNTERR_IRQ      |
                                             IRQSELECT_TARGET_ABORT_IRQ  |
                                             IRQSELECT_MASTER_ABORT_IRQ );
        nsp32_write2(base, IRQ_CONTROL, 0);
 
        /* PCI LED off */
        nsp32_index_write1(base, EXT_PORT_DDR, LED_OFF);
-       nsp32_index_write1(base, EXT_PORT, LED_OFF);
+       nsp32_index_write1(base, EXT_PORT,     LED_OFF);
 
        return TRUE;
 }
@@ -1264,7 +1213,7 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
        int ret;
        int handled = 0;
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
        struct Scsi_Host *host = data->Host;
        spin_lock_irqsave(host->host_lock, flags);
 #else
@@ -1279,7 +1228,7 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
                  "enter IRQ: %d, IRQstatus: 0x%x", irq, irq_stat);
        /* is this interrupt comes from Ninja asic? */
        if ((irq_stat & IRQSTATUS_ANY_IRQ) == 0) {
-               nsp32_msg(KERN_INFO, "spurious interrupt: irq other 0x%x", irq_stat);
+               nsp32_dbg(NSP32_DEBUG_INTR, "shared interrupt: irq other 0x%x", irq_stat);
                goto out2;
        }
        handled = 1;
@@ -1294,14 +1243,14 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
                if (data->CurrentSC != NULL) {
                        nsp32_msg(KERN_INFO, "clean up current SCSI command");
                        SCpnt->result = DID_BAD_TARGET << 16;
-                       nsp32_scsi_done(data, SCpnt);
+                       nsp32_scsi_done(SCpnt);
                }
                goto out;
        }
 
        /* Timer IRQ */
        if (irq_stat & IRQSTATUS_TIMER_IRQ) {
-               DEBUG(0, "timer stop\n");
+               nsp32_dbg(NSP32_DEBUG_INTR, "timer stop");
                nsp32_write2(base, TIMER_SET, TIMER_STOP);
                goto out;
        }
@@ -1312,14 +1261,14 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
                nsp32_do_bus_reset(data);
                if (SCpnt != NULL) {
                        SCpnt->result = DID_RESET << 16;
-                       nsp32_scsi_done(data, SCpnt);
+                       nsp32_scsi_done(SCpnt);
                }
                goto out;
        }
-       
+
        if (SCpnt == NULL) {
-               nsp32_msg(KERN_WARNING, "SCpnt==NULL this can't be happen\n");
-               nsp32_msg(KERN_WARNING, "irq_stat=0x%x trans_stat=0x%x\n", irq_stat, trans_stat);
+               nsp32_msg(KERN_WARNING, "SCpnt==NULL this can't be happened");
+               nsp32_msg(KERN_WARNING, "irq_stat=0x%x trans_stat=0x%x", irq_stat, trans_stat);
                goto out;
        }
 
@@ -1340,7 +1289,7 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
                                  "selection timeout occurred");
 
                        SCpnt->result = DID_TIME_OUT << 16;
-                       nsp32_scsi_done(data, SCpnt);
+                       nsp32_scsi_done(SCpnt);
                        goto out;
                }
 
@@ -1348,17 +1297,17 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
                        /*
                         * MsgOut phase was processed.
                         * If MSG_IN_OCCUER is not set, then MsgOut phase is
-                        * completed. Thus, msgoutlen must reset.  Otherwise,
+                        * completed. Thus, msgout_len must reset.  Otherwise,
                         * nothing to do here. If MSG_OUT_OCCUER is occurred,
                         * then we will encounter the condition and check.
                         */
                        if (!(auto_stat & MSG_IN_OCCUER) &&
-                            (data->msgoutlen <= 3)) {
+                            (data->msgout_len <= 3)) {
                                /*
-                                * !MSG_IN_OCCUER && msgoutlen <=3
+                                * !MSG_IN_OCCUER && msgout_len <=3
                                 *   ---> AutoSCSI with MSGOUTreg is processed.
                                 */
-                               data->msgoutlen = 0;
+                               data->msgout_len = 0;
                        };
 
                        nsp32_dbg(NSP32_DEBUG_INTR, "MsgOut phase processed");
@@ -1385,28 +1334,29 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
                                    nsp32_read4(base, SACK_CNT));
                        nsp32_dbg(NSP32_DEBUG_INTR, "SSACK=0x%lx", 
                                    nsp32_read4(base, SAVED_SACK_CNT));
-                       
+
+                       SCpnt->resid = 0; /* all data transfered! */
                }
 
                /*
                 * MsgIn Occur
                 */
                if (auto_stat & MSG_IN_OCCUER) {
-                       nsp32_msgin_occur(data, irq_stat, auto_stat);
+                       nsp32_msgin_occur(SCpnt, irq_stat, auto_stat);
                }
 
                /*
                 * MsgOut Occur
                 */
                if (auto_stat & MSG_OUT_OCCUER) {
-                       nsp32_msgout_occur(data);
+                       nsp32_msgout_occur(SCpnt);
                }
 
                /*
                 * Bus Free Occur
                 */
                if (auto_stat & BUS_FREE_OCCUER) {
-                       ret = nsp32_busfree_occur(data, auto_stat);
+                       ret = nsp32_busfree_occur(SCpnt, auto_stat);
                        if (ret == TRUE) {
                                goto out;
                        }
@@ -1457,28 +1407,28 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
 
                switch(busphase) {
                case BUSPHASE_DATA_OUT:
-                       printk( "write\n");
+                       nsp32_dbg(NSP32_DEBUG_INTR, "fifo/write");
 
                        //nsp32_pio_write(SCpnt);
 
                        break;
 
                case BUSPHASE_DATA_IN:
-                       printk( "read\n");
+                       nsp32_dbg(NSP32_DEBUG_INTR, "fifo/read");
 
                        //nsp32_pio_read(SCpnt);
 
                        break;
 
                case BUSPHASE_STATUS:
-                       //DEBUG(0, "fifo/status\n");
+                       nsp32_dbg(NSP32_DEBUG_INTR, "fifo/status");
 
                        SCpnt->SCp.Status = nsp32_read1(base, SCSI_CSB_IN);
 
                        break;
                default:
-                       printk("fifo/other phase?\n");
-                       printk("irq_stat=0x%x trans_stat=0x%x\n", irq_stat, trans_stat);
+                       nsp32_dbg(NSP32_DEBUG_INTR, "fifo/other phase");
+                       nsp32_dbg(NSP32_DEBUG_INTR, "irq_stat=0x%x trans_stat=0x%x", irq_stat, trans_stat);
                        show_busphase(busphase);
                        break;
                }
@@ -1493,7 +1443,7 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
                switch(busphase) {
                case BUSPHASE_MESSAGE_IN:
                        nsp32_dbg(NSP32_DEBUG_INTR, "phase chg/msg in");
-                       nsp32_msgin_occur(data, irq_stat, 0);
+                       nsp32_msgin_occur(SCpnt, irq_stat, 0);
                        break;
                default:
                        nsp32_msg(KERN_WARNING, "phase chg/other phase?");
@@ -1522,7 +1472,8 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
        }
 
 #if 0
-       printk("irq_stat=0x%x trans_stat=0x%x\n", irq_stat, trans_stat);
+       nsp32_dbg(NSP32_DEBUG_INTR,
+                 "irq_stat=0x%x trans_stat=0x%x", irq_stat, trans_stat);
        show_busphase(busphase);
 #endif
 
@@ -1531,10 +1482,10 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
        nsp32_write2(base, IRQ_CONTROL, 0);
 
  out2:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       spin_unlock_irqrestore(&io_request_lock, flags);
-#else
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
        spin_unlock_irqrestore(host->host_lock, flags);
+#else
+       spin_unlock_irqrestore(&io_request_lock, flags);
 #endif
 
        nsp32_dbg(NSP32_DEBUG_INTR, "exit");
@@ -1544,48 +1495,113 @@ static irqreturn_t do_nsp32_isr(int irq, void *dev_id, struct pt_regs *regs)
 
 #undef SPRINTF
 #define SPRINTF(args...) \
-        do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
-static int nsp32_proc_info(struct Scsi_Host *host, char  *buffer,
-                          char **start,
-                          off_t  offset,
-                          int    length,
-                          int    inout)
+       do { \
+               if(length > (pos - buffer)) { \
+                       pos += snprintf(pos, length - (pos - buffer) + 1, ## args); \
+                       nsp32_dbg(NSP32_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length,  length - (pos - buffer));\
+               } \
+       } while(0)
+static int nsp32_proc_info(
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
+       struct Scsi_Host *host,
+#endif
+       char             *buffer,
+       char            **start,
+       off_t             offset,
+       int               length,
+#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
+       int               hostno,
+#endif
+       int               inout)
 {
-       char *pos = buffer;
-       int thislength;
-       unsigned long flags;
-       nsp32_hw_data *data;
-       unsigned int base;
-       unsigned char mode_reg;
+       char             *pos = buffer;
+       int               thislength;
+       unsigned long     flags;
+       nsp32_hw_data    *data;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
+       int               hostno;
+#else
+       struct Scsi_Host *host;
+#endif
+       unsigned int      base;
+       unsigned char     mode_reg;
+       int               id, speed;
+       long              model;
 
        /* Write is not supported, just return. */
        if (inout == TRUE) {
                return -EINVAL;
        }
 
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) 
+       hostno = host->host_no;
+#else
+       /* search this HBA host */
+       host = scsi_host_hn_get(hostno);
+       if (host == NULL) {
+               return -ESRCH;
+       }
+#endif
        data = (nsp32_hw_data *)host->hostdata;
        base = host->io_port;
 
        SPRINTF("NinjaSCSI-32 status\n\n");
-       SPRINTF("Driver version:        %s\n",          nsp32_release_version);
-       SPRINTF("SCSI host No.:         %d\n",          host->host_no);
+       SPRINTF("Driver version:        %s, $Revision: 1.33 $\n", nsp32_release_version);
+       SPRINTF("SCSI host No.:         %d\n",          hostno);
        SPRINTF("IRQ:                   %d\n",          host->irq);
        SPRINTF("IO:                    0x%lx-0x%lx\n", host->io_port, host->io_port + host->n_io_port - 1);
-       SPRINTF("MMIO(virtual address): 0x%lx\n",       host->base);
+       SPRINTF("MMIO(virtual address): 0x%lx-0x%lx\n", host->base, host->base + data->MmioLength - 1);
        SPRINTF("sg_tablesize:          %d\n",          host->sg_tablesize);
-       SPRINTF("Chip revision:         %d\n",          (nsp32_read2(base, INDEX_REG) >> 8) - 0x4f);
+       SPRINTF("Chip revision:         0x%x\n",        (nsp32_read2(base, INDEX_REG) >> 8) & 0xff);
 
        mode_reg = nsp32_index_read1(base, CHIP_MODE);
+       model    = data->pci_devid->driver_data;
 
 #ifdef CONFIG_PM
-       //SPRINTF("Power Management:      %s\n",          (mode_reg & OPTF) ? "yes" : "no");
+       SPRINTF("Power Management:      %s\n",          (mode_reg & OPTF) ? "yes" : "no");
 #endif
-       SPRINTF("OEM:                   %s\n",          nsp32_model[mode_reg & (OEM0|OEM1)]);
+       SPRINTF("OEM:                   %ld, %s\n",     (mode_reg & (OEM0|OEM1)), nsp32_model[model]);
 
        spin_lock_irqsave(&(data->Lock), flags);
        SPRINTF("CurrentSC:             0x%p\n\n",      data->CurrentSC);
        spin_unlock_irqrestore(&(data->Lock), flags);
 
+
+       SPRINTF("SDTR status\n");
+       for(id = 0; id < NUMBER(data->target); id++) {
+
+                SPRINTF("id %d: ", id);
+
+               if (id == host->this_id) {
+                       SPRINTF("----- NinjaSCSI-32 host adapter\n");
+                       continue;
+               }
+
+               if (data->target[id].sync_flag == SDTR_DONE) {
+                       if (data->target[id].period == 0            &&
+                           data->target[id].offset == ASYNC_OFFSET ) {
+                               SPRINTF("async");
+                       } else {
+                               SPRINTF(" sync");
+                       }
+               } else {
+                       SPRINTF(" none");
+               }
+
+               if (data->target[id].period != 0) {
+
+                       speed = 1000000 / (data->target[id].period * 4);
+
+                       SPRINTF(" transfer %d.%dMB/s, offset %d",
+                               speed / 1000,
+                               speed % 1000,
+                               data->target[id].offset
+                               );
+               }
+               SPRINTF("\n");
+       }
+
+
        thislength = pos - (buffer + offset);
 
        if(thislength < 0) {
@@ -1601,1495 +1617,1452 @@ static int nsp32_proc_info(struct Scsi_Host *host, char  *buffer,
 }
 #undef SPRINTF
 
+
+
 /*
- * Note: n_io_port is defined as 0x7f because I/O register port is
- *      assigned as:
- *     0x800-0x8ff: memory mapped I/O port
- *     0x900-0xbff: (map same 0x800-0x8ff I/O port image repeatedly)
- *     0xc00-0xfff: CardBus status registers
+ * Reset parameters and call scsi_done for data->cur_lunt.
+ * Be careful setting SCpnt->result = DID_* before calling this function.
  */
-static int nsp32_detect(struct pci_dev *pdev)
+static void nsp32_scsi_done(Scsi_Cmnd *SCpnt)
 {
-       struct Scsi_Host *host; /* registered host structure */
-       int ret;
-       nsp32_hw_data *data;
-       int i, j;
-
-       nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int   base = SCpnt->device->host->io_port;
 
        /*
-        * register this HBA as SCSI device
+        * unmap pci
         */
-       host = scsi_host_alloc(&nsp32_template, sizeof(nsp32_hw_data));
-       if (host == NULL) {
-               nsp32_msg (KERN_ERR, "failed to scsi register");
-               goto err;
+       if (SCpnt->request_bufflen == 0) {
+               goto skip;
        }
 
-       /*
-        * set nsp32_hw_data
-        */
-       data = (nsp32_hw_data *)host->hostdata;
-       memset(data, 0, sizeof(nsp32_hw_data));
-
-       data->IrqNumber   = nsp32_data_base.IrqNumber;
-       data->BaseAddress = nsp32_data_base.BaseAddress;
-       data->NumAddress  = nsp32_data_base.NumAddress; 
-       data->MmioAddress = nsp32_data_base.MmioAddress;
-       data->Pci         = nsp32_data_base.Pci;
-       data->pci_devid   = nsp32_data_base.pci_devid;
-
-       host->irq         = data->IrqNumber;
-       host->io_port     = data->BaseAddress;
-       host->unique_id   = data->BaseAddress;
-       host->n_io_port   = data->NumAddress;
-       host->base        = data->MmioAddress;
-       scsi_set_device(host, &data->Pci->dev);
-
-       data->Host        = host;
-       spin_lock_init(&(data->Lock));
-
-       data->curlunt     = NULL;
-       data->curtarget   = NULL;
+       if (SCpnt->use_sg) {
+               pci_unmap_sg(data->Pci,
+                            (struct scatterlist *)SCpnt->buffer,
+                            SCpnt->use_sg,
+                            scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+       } else {
+               pci_unmap_single(data->Pci,
+                                (u32)SCpnt->SCp.have_data_in,
+                                SCpnt->request_bufflen,
+                                scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
+       }
 
+ skip:
        /*
-        * Bus master transfer mode is supported currently.
+        * clear TRANSFERCONTROL_BM_START
         */
-       data->trans_method      = NSP32_TRANSFER_BUSMASTER;
+       nsp32_write2(base, TRANSFER_CONTROL, 0);
+       nsp32_write4(base, BM_CNT,           0);
 
        /*
-        * Set clock div, CLOCK_4 (HBA has external clock, and
-        * dividing * 100ns/4).
-        * Currently CLOCK_4 has only tested, not for CLOCK_2/PCICLK yet.
+        * call scsi_done
         */
-       data->clock = CLOCK_4;
+       (*SCpnt->scsi_done)(SCpnt);
 
        /*
-        * Select appropriate nsp32_sync_table and set I_CLOCKDIV.
+        * reset parameters
         */
-       switch (data->clock) {
-       case CLOCK_4:
-               /* If data->clock is CLOCK_4, then select 40M sync table. */
-               data->synct = nsp32_sync_table_40M;
-               data->syncnum = nsp32_table_40M_num;
-               break;
-       case CLOCK_2:
-               /* If data->clock is CLOCK_2, then select 20M sync table. */
-               data->synct = nsp32_sync_table_20M;
-               data->syncnum = nsp32_table_20M_num;
-               break;
-       case PCICLK:
-               /* If data->clock is PCICLK, then select pci sync table. */
-               data->synct = nsp32_sync_table_pci;
-               data->syncnum = nsp32_table_pci_num;
-               break;
-       default:
-               nsp32_msg(KERN_WARNING,
-                         "Invalid clock div is selected, set CLOCK_4.");
-               /* Use default value CLOCK_4 */
-               data->clock = CLOCK_4;
-               data->synct = nsp32_sync_table_40M;
-               data->syncnum = nsp32_table_40M_num;
-       }
+       data->cur_lunt->SCpnt = NULL;
+       data->cur_lunt        = NULL;
+       data->cur_target      = NULL;
+       data->CurrentSC      = NULL;
+}
 
-       /*
-        * setup nsp32_lunt
-        */
-       data->lunt_list = (struct nsp32_lunt *)
-               kmalloc(sizeof(struct nsp32_lunt) * MAX_TARGET * MAX_LUN,
-                       GFP_KERNEL);
-       if (data->lunt_list == NULL) {
-               nsp32_msg(KERN_ERR, "cannot allocate LUN memory");
-               goto scsi_unregister;
-       }
-       nsp32_dbg(NSP32_DEBUG_REGISTER, "0x%x 0x%x",
-                 data->lunt_list, sizeof(struct nsp32_lunt)*MAX_TARGET*MAX_LUN);
 
-       /*
-        * setup DMA 
-        */
-       if (pci_set_dma_mask(data->Pci, 0xffffffffUL)) {
-               nsp32_msg (KERN_ERR, "failed to set PCI DMA mask");
-               goto kfree_lunt;
-       }
+/*
+ * Bus Free Occur
+ *
+ * Current Phase is BUSFREE. AutoSCSI is automatically execute BUSFREE phase
+ * with ACK reply when below condition is matched:
+ *     MsgIn 00: Command Complete.
+ *     MsgIn 02: Save Data Pointer.
+ *     MsgIn 04: Diconnect.
+ * In other case, unexpected BUSFREE is detected.
+ */
+static int nsp32_busfree_occur(Scsi_Cmnd *SCpnt, unsigned short execph)
+{
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int base   = SCpnt->device->host->io_port;
 
-       /*
-        * allocate autoparam DMA resource.
-        */
-       data->autoparam = pci_alloc_consistent(data->Pci, AUTOPARAM_SIZE, &data->apaddr);
-       if (data->autoparam == NULL) {
-               nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
-               goto kfree_lunt;
-       }
+       nsp32_dbg(NSP32_DEBUG_BUSFREE, "enter execph=0x%x", execph);
+       show_autophase(execph);
+
+       nsp32_write4(base, BM_CNT,           0);
+       nsp32_write2(base, TRANSFER_CONTROL, 0);
 
        /*
-        * allocate scatter-gather DMA resource.
+        * MsgIn 02: Save Data Pointer
+        *
+        * VALID:
+        *   Save Data Pointer is received. Adjust pointer.
+        *   
+        * NO-VALID:
+        *   SCSI-3 says if Save Data Pointer is not received, then we restart
+        *   processing and we can't adjust any SCSI data pointer in next data
+        *   phase.
         */
-       data->sg_list = pci_alloc_consistent(data->Pci, 
-                       (sizeof(struct nsp32_sgtable) * NSP_SG_SIZE * MAX_TARGET * MAX_LUN),
-                        &data->sgaddr);
-       if (data->sg_list == NULL) {
-               nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
-               goto free_autoparam;
-       }
+       if (execph & MSGIN_02_VALID) {
+               nsp32_dbg(NSP32_DEBUG_BUSFREE, "MsgIn02_Valid");
 
-       for (i=0; i<MAX_TARGET; i++) {
-               for (j=0; j<MAX_LUN; j++) {
-                       data->lunt[i][j] = data->lunt_list + (i * MAX_LUN + j);
-               }
-       }
+               /*
+                * Check sack_cnt/saved_sack_cnt, then adjust sg table if
+                * needed.
+                */
+               if (!(execph & MSGIN_00_VALID) && 
+                   ((execph & DATA_IN_PHASE) || (execph & DATA_OUT_PHASE))) {
+                       unsigned int sacklen, s_sacklen;
 
-       for (i=0; i<MAX_TARGET; i++) {
-               for (j=0; j<MAX_LUN; j++) {
-                       struct nsp32_lunt *lp = data->lunt[i][j];
-                       lp->sglun = (struct nsp32_sglun *)
-                               (data->sg_list + (i * MAX_LUN + j));
-                       lp->sglun_paddr = data->sgaddr +
-                               (long)((i * MAX_LUN + j) 
-                                      * sizeof(struct nsp32_sglun));
-                       lp->SCpnt = NULL;
-                       lp->save_datp = 0;
-                       lp->msgin03 = FALSE;
-                       lp->sg_num = 0;
-                       lp->cur_entry = 0;
-               }
-       }
+                       /*
+                        * Read SACK count and SAVEDSACK count, then compare.
+                        */
+                       sacklen   = nsp32_read4(base, SACK_CNT      );
+                       s_sacklen = nsp32_read4(base, SAVED_SACK_CNT);
 
-       /*
-        * setup target
-        */
-       for (i=0; i<MAX_TARGET; i++) {
-               struct nsp32_target *target = &data->target[i];
+                       /*
+                        * If SAVEDSACKCNT == 0, it means SavedDataPointer is
+                        * come after data transfering.
+                        */
+                       if (s_sacklen > 0) {
+                               /*
+                                * Comparing between sack and savedsack to
+                                * check the condition of AutoMsgIn03.
+                                *
+                                * If they are same, set msgin03 == TRUE,
+                                * COMMANDCONTROL_AUTO_MSGIN_03 is enabled at
+                                * reselection.  On the other hand, if they
+                                * aren't same, set msgin03 == FALSE, and
+                                * COMMANDCONTROL_AUTO_MSGIN_03 is disabled at
+                                * reselection.
+                                */
+                               if (sacklen != s_sacklen) {
+                                       data->cur_lunt->msgin03 = FALSE;
+                               } else {
+                                       data->cur_lunt->msgin03 = TRUE;
+                               }
 
-               target->limit_entry  = 0;
-               target->sync_flag    = 0;
-               nsp32_set_async(data, target);
+                               nsp32_adjust_busfree(SCpnt, s_sacklen);
+                       }
+               }
+
+               /* This value has not substitude with valid value yet... */
+               //data->cur_lunt->save_datp = data->cur_datp;
+       } else {
+               /*
+                * no processing.
+                */
+       }
+       
+       if (execph & MSGIN_03_VALID) {
+               /* MsgIn03 was valid to be processed. No need processing. */
        }
 
        /*
-        * EEPROM check
+        * target SDTR check
         */
-       ret = nsp32_getprom_param(data);
-       if (ret == FALSE) {
-               data->resettime = 3;    /* default 3 */
+       if (data->cur_target->sync_flag & SDTR_INITIATOR) {
+               /*
+                * SDTR negotiation pulled by the initiator has not
+                * finished yet. Fall back to ASYNC mode.
+                */
+               nsp32_set_async(data, data->cur_target);
+               data->cur_target->sync_flag &= ~SDTR_INITIATOR;
+               data->cur_target->sync_flag |= SDTR_DONE;
+       } else if (data->cur_target->sync_flag & SDTR_TARGET) {
+               /*
+                * SDTR negotiation pulled by the target has been
+                * negotiating.
+                */
+               if (execph & (MSGIN_00_VALID | MSGIN_04_VALID)) {
+                       /* 
+                        * If valid message is received, then
+                        * negotiation is succeeded.
+                        */
+               } else {
+                       /*
+                        * On the contrary, if unexpected bus free is
+                        * occurred, then negotiation is failed. Fall
+                        * back to ASYNC mode.
+                        */
+                       nsp32_set_async(data, data->cur_target);
+               }
+               data->cur_target->sync_flag &= ~SDTR_TARGET;
+               data->cur_target->sync_flag |= SDTR_DONE;
        }
 
        /*
-        * setup HBA
+        * It is always ensured by SCSI standard that initiator
+        * switches into Bus Free Phase after
+        * receiving message 00 (Command Complete), 04 (Disconnect).
+        * It's the reason that processing here is valid.
         */
-       nsp32hw_init(host);
-
-       snprintf(data->info_str, sizeof(data->info_str),
-                "NinjaSCSI-32Bi/UDE: irq %d, io 0x%lx+0x%x",
-                host->irq, host->io_port, host->n_io_port);
+       if (execph & MSGIN_00_VALID) {
+               /* MsgIn 00: Command Complete */
+               nsp32_dbg(NSP32_DEBUG_BUSFREE, "command complete");
 
-       /*
-        * SCSI bus reset
-        *
-        * Note: It's important to reset SCSI bus in initialization phase.
-        *     NinjaSCSI-32Bi/UDE HBA EEPROM seems to exchange SDTR when system is
-        *     coming up, so SCSI devices connected to HBA is set as
-        *     un-asynchronous mode.  It brings the merit that this HBA is
-        *     ready to start synchronous transfer without any preparation,
-        *     but we are difficult to control transfer speed.  In addition,
-        *     it prevents device transfer speed from effecting EEPROM start-up
-        *     SDTR.  NinjaSCSI-32Bi/UDE has the feature if EEPROM is set as Auto
-        *     Mode, then FAST-10M is selected when SCSI devices are connected
-        *     same or more than 4 devices.  It should be avoided depending on
-        *     this specification Thus, resetting the SCSI bus restores all
-        *     connected SCSI devices to asynchronous mode, then this driver
-        *     put SDTR safely later, and we can control all SCSI device
-        *     transfer mode.
-        */
-       nsp32_do_bus_reset(data);
+               SCpnt->SCp.Status  = nsp32_read1(base, SCSI_CSB_IN);
+               SCpnt->SCp.Message = 0;
+               nsp32_dbg(NSP32_DEBUG_BUSFREE, 
+                         "normal end stat=0x%x resid=0x%x\n",
+                         SCpnt->SCp.Status, SCpnt->resid);
+               SCpnt->result = (DID_OK             << 16) |
+                               (SCpnt->SCp.Message <<  8) |
+                               (SCpnt->SCp.Status  <<  0);
+               nsp32_scsi_done(SCpnt);
+               /* All operation is done */
+               return TRUE;
+       } else if (execph & MSGIN_04_VALID) {
+               /* MsgIn 04: Disconnect */
+               SCpnt->SCp.Status  = nsp32_read1(base, SCSI_CSB_IN);
+               SCpnt->SCp.Message = 4;
+               
+               nsp32_dbg(NSP32_DEBUG_BUSFREE, "disconnect");
+               return TRUE;
+       } else {
+               /* Unexpected bus free */
+               nsp32_msg(KERN_WARNING, "unexpected bus free occurred");
 
-       ret = request_irq(host->irq, do_nsp32_isr, SA_SHIRQ, "nsp32", data);
-       if (ret < 0) {
-               nsp32_msg(KERN_ERR, "Unable to allocate IRQ for NSP32 "
-                         "SCSI PCI controller. Interrupt: %d\n", host->irq);
-               goto free_sg_list;
+               /* DID_ERROR? */
+               //SCpnt->result   = (DID_OK << 16) | (SCpnt->SCp.Message << 8) | (SCpnt->SCp.Status << 0);
+               SCpnt->result = DID_ERROR << 16;
+               nsp32_scsi_done(SCpnt);
+               return TRUE;
        }
+       return FALSE;
+}
 
-        /*
-         * PCI IO register
-         */
-       if(!request_region(host->io_port, host->n_io_port, "nsp32")) {
-               nsp32_msg(KERN_ERR, 
-                         "I/O region 0x%lx+0x%lx is already used",
-                         data->BaseAddress, data->length);
-               goto free_irq;
-        }
 
-       scsi_add_host(host, &pdev->dev); /* XXX handle failure */
-       scsi_scan_host(host);
-       pci_set_drvdata(pdev, host);
-       return 0;
+/*
+ * nsp32_adjust_busfree - adjusting SG table
+ *
+ * Note: This driver adjust the SG table using SCSI ACK
+ *       counter instead of BMCNT counter!
+ */
+static void nsp32_adjust_busfree(Scsi_Cmnd *SCpnt, unsigned int s_sacklen)
+{
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       int                   old_entry = data->cur_entry;
+       int                   new_entry;
+       int                   sg_num = data->cur_lunt->sg_num;
+       nsp32_sgtable *sgt    = data->cur_lunt->sglun->sgt;
+       unsigned int          restlen, sentlen;
+       u32_le                len, addr;
 
- free_irq:
-       free_irq(host->irq, data);
+       nsp32_dbg(NSP32_DEBUG_SGLIST, "old resid=0x%x", SCpnt->resid);
 
- free_autoparam:
-       pci_free_consistent(data->Pci, AUTOPARAM_SIZE, data->autoparam, data->apaddr);
-       
- free_sg_list:
-       pci_free_consistent(data->Pci,
-               (sizeof(struct nsp32_sgtable) * NSP_SG_SIZE * MAX_TARGET * MAX_LUN),
-               data->sg_list, data->sgaddr);
-       
- kfree_lunt:
-       kfree(data->lunt_list);
+       /* adjust saved SACK count with 4 byte start address boundary */
+       s_sacklen -= le32_to_cpu(sgt[old_entry].addr) & 3;
 
- scsi_unregister:
-       scsi_host_put(host);
-
- err:
-       return 1;
-}
+       /*
+        * calculate new_entry from sack count and each sgt[].len 
+        * calculate the byte which is intent to send
+        */
+       sentlen = 0;
+       for (new_entry = old_entry; new_entry < sg_num; new_entry++) {
+               sentlen += (le32_to_cpu(sgt[new_entry].len) & ~SGTEND);
+               if (sentlen > s_sacklen) {
+                       break;
+               }
+       }
 
-static const char *nsp32_info(struct Scsi_Host *shpnt)
-{
-       nsp32_hw_data *data = (nsp32_hw_data *)shpnt->hostdata;
+       /* all sgt is processed */
+       if (new_entry == sg_num) {
+               goto last;
+       }
 
-       return data->info_str;
-}
+       if (sentlen == s_sacklen) {
+               /* XXX: confirm it's ok or not */
+               /* In this case, it's ok because we are at 
+                  the head element of the sg. restlen is correctly calculated. */
+       }
 
+       /* calculate the rest length for transfering */
+       restlen = sentlen - s_sacklen;
 
-static int nsp32_eh_abort(Scsi_Cmnd *SCpnt)
-{
-       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
-       unsigned int base = data->BaseAddress;
+       /* update adjusting current SG table entry */
+       len  = le32_to_cpu(sgt[new_entry].len);
+       addr = le32_to_cpu(sgt[new_entry].addr);
+       addr += (len - restlen);
+       sgt[new_entry].addr = cpu_to_le32(addr);
+       sgt[new_entry].len  = cpu_to_le32(restlen);
 
-       nsp32_msg(KERN_WARNING, "abort");
+       /* set cur_entry with new_entry */
+       data->cur_entry = new_entry;
+       return;
 
-       if (data->curlunt->SCpnt == NULL) {
-               return (FAILED);
+ last:
+       if (SCpnt->resid < sentlen) {
+               nsp32_msg(KERN_ERR, "resid underflow");
        }
 
-       if (data->curtarget->sync_flag & (SDTR_INITIATOR | SDTR_TARGET)) {
-               /* reset SDTR negotiation */
-               data->curtarget->sync_flag = 0;
-       }
+       SCpnt->resid -= sentlen;
+       nsp32_dbg(NSP32_DEBUG_SGLIST, "new resid=0x%x", SCpnt->resid);
 
-       nsp32_write2(base, TRANSFER_CONTROL, 0);
-       nsp32_write2(base, BM_CNT, 0);
+       /* update hostdata and lun */
 
-       return (FAILED);
+       return;
 }
 
-static int nsp32_eh_bus_reset(Scsi_Cmnd *SCpnt)
-{
-       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
-       unsigned int base = data->BaseAddress;
-
-       nsp32_msg(KERN_INFO, "Bus Reset");      
-       nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%x", SCpnt);
-
-       nsp32_write2(base, IRQ_CONTROL, IRQ_CONTROL_ALL_IRQ_MASK);
-       nsp32_do_bus_reset(data);
-       nsp32_write2(base, IRQ_CONTROL, 0);
-
-       return SUCCESS; /* SCSI bus reset is succeeded at any time. */
-}
 
-static void nsp32_do_bus_reset(nsp32_hw_data *data)
+/*
+ * It's called MsgOut phase occur.
+ * NinjaSCSI-32Bi/UDE automatically processes up to 3 messages in
+ * message out phase. It, however, has more than 3 messages,
+ * HBA creates the interrupt and we have to process by hand.
+ */
+static void nsp32_msgout_occur(Scsi_Cmnd *SCpnt)
 {
-       unsigned int base = data->BaseAddress;
-       unsigned short intrdat;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int base   = SCpnt->device->host->io_port;
+       //unsigned short command;
+       long new_sgtp;
        int i;
+       
+       nsp32_dbg(NSP32_DEBUG_MSGOUTOCCUR,
+                 "enter: msgout_len: 0x%x", data->msgout_len);
 
        /*
-        * stop all transfer
-        * clear TRANSFERCONTROL_BM_START
-        * clear counter
+        * If MsgOut phase is occurred without having any
+        * message, then No_Operation is sent (SCSI-2).
         */
-       nsp32_write2(base, TRANSFER_CONTROL, 0);
-       nsp32_write4(base, BM_CNT,           0);
-       nsp32_write4(base, CLR_COUNTER, CLRCOUNTER_ALLMASK);
+       if (data->msgout_len == 0) {
+               nsp32_build_nop(SCpnt);
+       }
 
        /*
-        * fall back to asynchronous transfer mode
-        * initialize SDTR negotiation flag
+        * Set SGTP ADDR current entry for restarting AUTOSCSI, 
+        * because SGTP is incremented next point.
+        * There is few statement in the specification...
         */
-       for (i=0; i<MAX_TARGET; i++) {
-               struct nsp32_target *target = &data->target[i];
-
-               target->sync_flag = 0;
-               nsp32_set_async(data, target);
-       }
+       new_sgtp = data->cur_lunt->sglun_paddr + 
+                  (data->cur_lunt->cur_entry * sizeof(nsp32_sgtable));
 
        /*
-        * reset SCSI bus
+        * send messages
         */
-       nsp32_write1(base, SCSI_BUS_CONTROL, BUSCTL_RST);
-       udelay(RESET_HOLD_TIME);
-       nsp32_write1(base, SCSI_BUS_CONTROL, 0);
-       for(i = 0; i < 5; i++) {
-               intrdat = nsp32_read2(base, IRQ_STATUS); /* dummy read */
-               nsp32_dbg(NSP32_DEBUG_BUSRESET, "irq:1: 0x%x", intrdat);
-        }
+       for (i = 0; i < data->msgout_len; i++) {
+               nsp32_dbg(NSP32_DEBUG_MSGOUTOCCUR,
+                         "%d : 0x%x", i, data->msgoutbuf[i]);
 
-       data->CurrentSC = NULL;
-}
+               /*
+                * Check REQ is asserted.
+                */
+               nsp32_wait_req(data, ASSERT);
 
-static int nsp32_eh_host_reset(Scsi_Cmnd *SCpnt)
-{
-       struct Scsi_Host *host = SCpnt->device->host;
-       nsp32_hw_data *data = (nsp32_hw_data *)host->hostdata;
-       unsigned int base = data->BaseAddress;
+               if (i == (data->msgout_len - 1)) {
+                       /*
+                        * If the last message, set the AutoSCSI restart
+                        * before send back the ack message. AutoSCSI
+                        * restart automatically negate ATN signal.
+                        */
+                       //command = (AUTO_MSGIN_00_OR_04 | AUTO_MSGIN_02);
+                       //nsp32_restart_autoscsi(SCpnt, command);
+                       nsp32_write2(base, COMMAND_CONTROL,
+                                        (CLEAR_CDB_FIFO_POINTER |
+                                         AUTO_COMMAND_PHASE     |
+                                         AUTOSCSI_RESTART       |
+                                         AUTO_MSGIN_00_OR_04    |
+                                         AUTO_MSGIN_02          ));
+               }
+               /*
+                * Write data with SACK, then wait sack is
+                * automatically negated.
+                */
+               nsp32_write1(base, SCSI_DATA_WITH_ACK, data->msgoutbuf[i]);
+               nsp32_wait_sack(data, NEGATE);
 
-       nsp32_msg(KERN_INFO, "Host Reset");     
-       nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%x", SCpnt);
+               nsp32_dbg(NSP32_DEBUG_MSGOUTOCCUR, "bus: 0x%x\n",
+                         nsp32_read1(base, SCSI_BUS_MONITOR));
+       };
 
-       nsp32hw_init(host);
-       nsp32_write2(base, IRQ_CONTROL, IRQ_CONTROL_ALL_IRQ_MASK);
-       nsp32_do_bus_reset(data);
-       nsp32_write2(base, IRQ_CONTROL, 0);
+       data->msgout_len = 0;
 
-       return SUCCESS; /* Host reset is succeeded at any time. */
+       nsp32_dbg(NSP32_DEBUG_MSGOUTOCCUR, "exit");
 }
 
 /*
- * PCI/Cardbus probe/remove routine
+ * Restart AutoSCSI
+ *
+ * Note: Restarting AutoSCSI needs set:
+ *             SYNC_REG, ACK_WIDTH, SGT_ADR, TRANSFER_CONTROL
  */
-static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static void nsp32_restart_autoscsi(Scsi_Cmnd *SCpnt, unsigned short command)
 {
-       int ret;
-       nsp32_hw_data *data = &nsp32_data_base;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int   base = data->BaseAddress;
+       unsigned short transfer = 0;
 
-       nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
+       nsp32_dbg(NSP32_DEBUG_RESTART, "enter");
 
-        ret = pci_enable_device(pdev);
-       if (ret) {
-               nsp32_msg(KERN_ERR, "failed to enable pci device");
-               return ret;
+       if (data->cur_target == NULL || data->cur_lunt == NULL) {
+               nsp32_msg(KERN_ERR, "Target or Lun is invalid");
        }
 
-       data->Pci = pdev;
-       data->pci_devid = id;
-       data->IrqNumber = pdev->irq;
-       data->BaseAddress = pci_resource_start(pdev, 0);
-       data->NumAddress = pci_resource_len(pdev, 0);
-       data->MmioAddress = (unsigned long)ioremap_nocache(
-               pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
+       /*
+        * set SYNC_REG
+        * Don't set BM_START_ADR before setting this register.
+        */
+       nsp32_write1(base, SYNC_REG, data->cur_target->syncreg);
 
-       pci_set_master(pdev);
+       /*
+        * set ACKWIDTH
+        */
+       nsp32_write1(base, ACK_WIDTH, data->cur_target->ackwidth);
 
-       ret = nsp32_detect(pdev);
+       /*
+        * set SREQ hazard killer sampling rate
+        */
+       nsp32_write1(base, SREQ_SMPL_RATE, data->cur_target->sample_reg);
 
-       nsp32_msg(KERN_INFO, "nsp32 irq: %i mmio: 0x%lx slot: %s model: %s",
-                 pdev->irq, data->MmioAddress, pci_name(pdev),
-                 nsp32_model[id->driver_data]);
+       /*
+        * set SGT ADDR (physical address)
+        */
+       nsp32_write4(base, SGT_ADR, data->cur_lunt->sglun_paddr);
 
-       nsp32_dbg(NSP32_DEBUG_REGISTER, "exit");
+       /*
+        * set TRANSFER CONTROL REG
+        */
+       transfer = 0;
+       transfer |= (TRANSFER_GO | ALL_COUNTER_CLR);
+       if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
+               if (SCpnt->request_bufflen > 0) {
+                       transfer |= BM_START;
+               }
+       } else if (data->trans_method & NSP32_TRANSFER_MMIO) {
+               transfer |= CB_MMIO_MODE;
+       } else if (data->trans_method & NSP32_TRANSFER_PIO) {
+               transfer |= CB_IO_MODE;
+       }
+       nsp32_write2(base, TRANSFER_CONTROL, transfer);
 
-       return ret;
+       /*
+        * restart AutoSCSI
+        *
+        * TODO: COMMANDCONTROL_AUTO_COMMAND_PHASE is needed ?
+        */
+       command |= (CLEAR_CDB_FIFO_POINTER |
+                   AUTO_COMMAND_PHASE     |
+                   AUTOSCSI_RESTART       );
+       nsp32_write2(base, COMMAND_CONTROL, command);
+
+       nsp32_dbg(NSP32_DEBUG_RESTART, "exit");
 }
 
-static void __devexit nsp32_remove(struct pci_dev *pdev)
+
+/*
+ * cannot run automatically message in occur
+ */
+static void nsp32_msgin_occur(Scsi_Cmnd     *SCpnt,
+                             unsigned long  irq_status,
+                             unsigned short execph)
 {
-       struct Scsi_Host *shpnt = pci_get_drvdata(pdev);
-       nsp32_hw_data *data = (nsp32_hw_data *)shpnt->hostdata;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int   base = SCpnt->device->host->io_port;
+       unsigned char  msg;
+       unsigned char  msgtype;
+       unsigned char  newlun;
+       unsigned short command  = 0;
+       int            msgclear = TRUE;
+       long           new_sgtp;
+       int            ret;
 
-       kfree(data->lunt_list);
-       pci_free_consistent(data->Pci, AUTOPARAM_SIZE,
-                       data->autoparam, data->apaddr);
-       pci_free_consistent(data->Pci, 
-               (sizeof(struct nsp32_sgtable) * NSP_SG_SIZE*MAX_TARGET*MAX_LUN),
-               data->sg_list, data->sgaddr);
-       free_irq(shpnt->irq, data);
-       release_region(shpnt->io_port, shpnt->n_io_port);
-       iounmap((void *)(data->MmioAddress));
-}
-
-static struct pci_device_id nsp32_pci_table[] = {
-       {
-               .vendor      = PCI_VENDOR_ID_IODATA,
-               .device      = PCI_DEVICE_ID_NINJASCSI_32BI_CBSC_II,
-               .subvendor   = PCI_ANY_ID,
-               .subdevice   = PCI_ANY_ID,
-               .driver_data = MODEL_IODATA,
-       },
-       {
-               .vendor      = PCI_VENDOR_ID_WORKBIT,
-               .device      = PCI_DEVICE_ID_NINJASCSI_32BI_KME,
-               .subvendor   = PCI_ANY_ID,
-               .subdevice   = PCI_ANY_ID,
-               .driver_data = MODEL_KME,
-       },
-       {
-               .vendor      = PCI_VENDOR_ID_WORKBIT,
-               .device      = PCI_DEVICE_ID_NINJASCSI_32BI_WBT,
-               .subvendor   = PCI_ANY_ID,
-               .subdevice   = PCI_ANY_ID,
-               .driver_data = MODEL_WORKBIT,
-       },
-       {
-               .vendor      = PCI_VENDOR_ID_WORKBIT,
-               .device      = PCI_DEVICE_ID_WORKBIT_STANDARD,
-               .subvendor   = PCI_ANY_ID,
-               .subdevice   = PCI_ANY_ID,
-               .driver_data = MODEL_PCI_WORKBIT,
-       },
-       {
-               .vendor      = PCI_VENDOR_ID_WORKBIT,
-               .device      = PCI_DEVICE_ID_NINJASCSI_32BI_LOGITEC,
-               .subvendor   = PCI_ANY_ID,
-               .subdevice   = PCI_ANY_ID,
-               .driver_data = MODEL_EXT_ROM,
-       },
-       {
-               .vendor      = PCI_VENDOR_ID_WORKBIT,
-               .device      = PCI_DEVICE_ID_NINJASCSI_32BIB_LOGITEC,
-               .subvendor   = PCI_ANY_ID,
-               .subdevice   = PCI_ANY_ID,
-               .driver_data = MODEL_PCI_LOGITEC,
-       },
-       {
-               .vendor      = PCI_VENDOR_ID_WORKBIT,
-               .device      = PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO,
-               .subvendor   = PCI_ANY_ID,
-               .subdevice   = PCI_ANY_ID,
-               .driver_data = MODEL_PCI_MELCO,
-       },
-       {0,0,},
-};
-MODULE_DEVICE_TABLE(pci, nsp32_pci_table);
-
-static struct pci_driver nsp32_driver = {
-       .name =         "nsp32",
-       .id_table =     nsp32_pci_table,
-       .probe =        nsp32_probe,
-       .remove =       nsp32_remove,
-#ifdef CONFIG_PM
-/*     .suspend =      nsp32_suspend,*/
-/*     .resume =       nsp32_resume,*/
-#endif
-};
-
-static int __init init_nsp32(void) {
-       return pci_module_init(&nsp32_driver);
-}
-
-static void __exit exit_nsp32(void) {
-       pci_unregister_driver(&nsp32_driver);
-}
-
-module_init(init_nsp32);
-module_exit(exit_nsp32);
-
-
-/*
- * Reset parameters and call scsi_done for data->curlunt.
- * Be careful setting SCpnt->result = DID_* before calling this function.
- */
-static void nsp32_scsi_done(nsp32_hw_data *data, Scsi_Cmnd *SCpnt)
-{
-       unsigned int base = data->BaseAddress;
+       /*
+        * read first message
+        *    Use SCSIDATA_W_ACK instead of SCSIDATAIN, because the procedure
+        *    of Message-In have to be processed before sending back SCSI ACK.
+        */
+       msg = nsp32_read1(base, SCSI_DATA_IN);
+       data->msginbuf[(unsigned char)data->msgin_len] = msg;
+       msgtype = data->msginbuf[0];
+       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR,
+                 "enter: msglen: 0x%x msgin: 0x%x msgtype: 0x%x",
+                 data->msgin_len, msg, msgtype);
 
        /*
-        * unmap pci
+        * TODO: We need checking whether bus phase is message in?
         */
-       if (SCpnt->request_bufflen == 0) {
-               goto skip;
-       }
-
-       if (SCpnt->use_sg) {
-               pci_unmap_sg(data->Pci,
-                       (struct scatterlist *)SCpnt->buffer,
-                       SCpnt->use_sg,
-                       scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-       } else {
-               pci_unmap_single(data->Pci,
-                       (u32)SCpnt->SCp.have_data_in,
-                       SCpnt->request_bufflen,
-                       scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
-       }
 
- skip:
        /*
-        * clear TRANSFERCONTROL_BM_START
+        * assert SCSI ACK
         */
-       nsp32_write2(base, TRANSFER_CONTROL, 0);
-       nsp32_write4(base, BM_CNT, 0);
+       nsp32_sack_assert(data);
 
        /*
-        * call scsi_done
+        * processing IDENTIFY
         */
-       (*SCpnt->scsi_done)(SCpnt);
+       if (msgtype & 0x80) {
+               if (!(irq_status & IRQSTATUS_RESELECT_OCCUER)) {
+                       /* Invalid (non reselect) phase */
+                       goto reject;
+               }
 
+               newlun = msgtype & 0x1f; /* TODO: SPI-3 compliant? */
+               ret = nsp32_reselection(SCpnt, newlun);
+               if (ret == TRUE) {
+                       goto restart;
+               } else {
+                       goto reject;
+               }
+       }
+       
        /*
-        * reset parameters
+        * processing messages except for IDENTIFY
+        *
+        * TODO: Messages are all SCSI-2 terminology. SCSI-3 compliance is TODO.
         */
-       data->curlunt->SCpnt = NULL;
-       data->curlunt = NULL;
-       data->curtarget = NULL;
-       data->CurrentSC = NULL;
-}
-
+       switch (msgtype) {
+       /*
+        * 1-byte message
+        */
+       case COMMAND_COMPLETE:
+       case DISCONNECT:
+               /*
+                * These messages should not be occurred.
+                * They should be processed on AutoSCSI sequencer.
+                */
+               nsp32_msg(KERN_WARNING, 
+                          "unexpected message of AutoSCSI MsgIn: 0x%x", msg);
+               break;
+               
+       case RESTORE_POINTERS:
+               /*
+                * AutoMsgIn03 is disabled, and HBA gets this message.
+                */
 
-/*
- * Bus Free Occur
- *
- * Current Phase is BUSFREE. AutoSCSI is automatically execute BUSFREE phase
- * with ACK reply when below condition is matched:
- *     MsgIn 00: Command Complete.
- *     MsgIn 02: Save Data Pointer.
- *     MsgIn 04: Diconnect.
- * In other case, unexpected BUSFREE is detected.
- */
-static int nsp32_busfree_occur(nsp32_hw_data *data, unsigned short execph)
-{
-       Scsi_Cmnd *SCpnt = data->curlunt->SCpnt;
-       unsigned int base = data->BaseAddress;
+               if ((execph & DATA_IN_PHASE) || (execph & DATA_OUT_PHASE)) {
+                       unsigned int s_sacklen;
 
-       nsp32_dbg(NSP32_DEBUG_BUSFREE, "enter");
+                       s_sacklen = nsp32_read4(base, SAVED_SACK_CNT);
+                       if ((execph & MSGIN_02_VALID) && (s_sacklen > 0)) {
+                               nsp32_adjust_busfree(SCpnt, s_sacklen);
+                       } else {
+                               /* No need to rewrite SGT */
+                       }
+               }
+               data->cur_lunt->msgin03 = FALSE;
 
-       nsp32_write4(base, BM_CNT, 0);
-       nsp32_write2(base, TRANSFER_CONTROL, 0);
+               /* Update with the new value */
 
-       /*
-        * MsgIn 02: Save Data Pointer
-        *
-        * VALID:
-        *   Save Data Pointer is received. Adjust pointer.
-        *   
-        * NO-VALID:
-        *   SCSI-3 says if Save Data Pointer is not received, then we restart
-        *   processing and we can't adjust any SCSI data pointer in next data
-        *   phase.
-        */
-       if (execph & MSGIN_02_VALID) {
-               nsp32_dbg(NSP32_DEBUG_BUSFREE, "MsgIn02_Valid");
+               /* reset SACK/SavedACK counter (or ALL clear?) */
+               nsp32_write4(base, CLR_COUNTER, CLRCOUNTER_ALLMASK);
 
                /*
-                * Check sack_cnt/saved_sack_cnt, then adjust sg table if
-                * needed.
+                * set new sg pointer
                 */
-               if (!(execph & MSGIN_00_VALID) && 
-                   ((execph & DATA_IN_PHASE) || (execph & DATA_OUT_PHASE))) {
-                       unsigned int sacklen, s_sacklen;
+               new_sgtp = data->cur_lunt->sglun_paddr + 
+                       (data->cur_lunt->cur_entry * sizeof(nsp32_sgtable));
+               nsp32_write4(base, SGT_ADR, new_sgtp);
 
-                       /*
-                        * Read SACK count and SAVEDSACK count, then compare.
-                        */
-                       sacklen   = nsp32_read4(base, SACK_CNT);
-                       s_sacklen = nsp32_read4(base, SAVED_SACK_CNT);
+               break;
 
+       case SAVE_POINTERS:
+               /*
+                * These messages should not be occurred.
+                * They should be processed on AutoSCSI sequencer.
+                */
+               nsp32_msg (KERN_WARNING, 
+                          "unexpected message of AutoSCSI MsgIn: SAVE_POINTERS");
+               
+               break;
+               
+       case MESSAGE_REJECT:
+               /* If previous message_out is sending SDTR, and get 
+                  message_reject from target, SDTR negotiation is failed */
+               if (data->cur_target->sync_flag &
+                               (SDTR_INITIATOR | SDTR_TARGET)) {
                        /*
-                        * If SAVEDSACKCNT == 0, it means SavedDataPointer is
-                        * come after data transfering.
+                        * Current target is negotiating SDTR, but it's
+                        * failed.  Fall back to async transfer mode, and set
+                        * SDTR_DONE.
                         */
-                       if (s_sacklen > 0) {
-                               /*
-                                * Comparing between sack and savedsack to
-                                * check the condition of AutoMsgIn03.
-                                *
-                                * If they are same, set msgin03 == TRUE,
-                                * COMMANDCONTROL_AUTO_MSGIN_03 is enabled at
-                                * reselection.  On the other hand, if they
-                                * aren't same, set msgin03 == FALSE, and
-                                * COMMANDCONTROL_AUTO_MSGIN_03 is disabled at
-                                * reselection.
-                                */
-                               if (sacklen != s_sacklen) {
-                                       data->curlunt->msgin03 = FALSE;
-                               } else {
-                                       data->curlunt->msgin03 = TRUE;
-                               }
+                       nsp32_set_async(data, data->cur_target);
+                       data->cur_target->sync_flag &= ~SDTR_INITIATOR;
+                       data->cur_target->sync_flag |= SDTR_DONE;
 
-                               nsp32_adjust_busfree(data, s_sacklen);
-                       }
                }
+               break;
 
-               /* This value has not substitude with valid value yet... */
-               //data->curlunt->save_datp = data->cur_datp;
-       } else {
-               /*
-                * no processing.
-                */
-       }
-       
-       if (execph & MSGIN_03_VALID) {
-               /* MsgIn03 was valid to be processed. No need processing. */
-       }
+       case LINKED_CMD_COMPLETE:
+       case LINKED_FLG_CMD_COMPLETE:
+               /* queue tag is not supported currently */
+               nsp32_msg (KERN_WARNING, 
+                          "unsupported message: 0x%x", msgtype);
+               break;
+
+       case INITIATE_RECOVERY:
+               /* staring ECA (Extended Contingent Allegiance) state. */
+               /* This message is declined in SPI2 or later. */
+
+               goto reject;
 
        /*
-        * target SDTR check
+        * 2-byte message
         */
-       if (data->curtarget->sync_flag & SDTR_INITIATOR) {
-               /*
-                * SDTR negotiation pulled by the initiator has not
-                * finished yet. Fall back to ASYNC mode.
-                */
-               nsp32_set_async(data, data->curtarget);
-               data->curtarget->sync_flag &= ~SDTR_INITIATOR;
-               data->curtarget->sync_flag |= SDTR_DONE;
-       } else if (data->curtarget->sync_flag & SDTR_TARGET) {
+       case SIMPLE_QUEUE_TAG:
+       case 0x23:
                /*
-                * SDTR negotiation pulled by the target has been
-                * negotiating.
+                * 0x23: Ignore_Wide_Residue is not declared in scsi.h.
+                * No support is needed.
                 */
-               if (execph & (MSGIN_00_VALID | MSGIN_04_VALID)) {
-                       /* 
-                        * If valid message is received, then
-                        * negotiation is succeeded.
+               if (data->msgin_len >= 1) {
+                       goto reject;
+               }
+
+               /* current position is 1-byte of 2 byte */
+               msgclear = FALSE;
+
+               break;
+
+       /*
+        * extended message
+        */
+       case EXTENDED_MESSAGE:
+               if (data->msgin_len < 1) {
+                       /*
+                        * Current position does not reach 2-byte
+                        * (2-byte is extended message length).
                         */
-               } else {
+                       msgclear = FALSE;
+                       break;
+               }
+
+               if ((data->msginbuf[1] + 1) > data->msgin_len) {
                        /*
-                        * On the contrary, if unexpected bus free is
-                        * occurred, then negotiation is failed. Fall
-                        * back to ASYNC mode.
+                        * Current extended message has msginbuf[1] + 2
+                        * (msgin_len starts counting from 0, so buf[1] + 1).
+                        * If current message position is not finished,
+                        * continue receiving message.
                         */
-                       nsp32_set_async(data, data->curtarget);
+                       msgclear = FALSE;
+                       break;
                }
-               data->curtarget->sync_flag &= ~SDTR_TARGET;
-               data->curtarget->sync_flag |= SDTR_DONE;
-       }
-       
-       /*
-        * It is always ensured by SCSI standard that initiator
-        * switches into Bus Free Phase after
-        * receiving message 00 (Command Complete), 04 (Disconnect).
-        * It's the reason that processing here is valid.
-        */
-       if (execph & MSGIN_00_VALID) {
-               /* MsgIn 00: Command Complete */
-               nsp32_dbg(NSP32_DEBUG_BUSFREE, "command complete");
 
-               SCpnt->SCp.Status  = nsp32_read1(base, SCSI_CSB_IN);
-               SCpnt->SCp.Message = 0;
-               nsp32_dbg(NSP32_DEBUG_BUSFREE, 
-                         "normal end stat=0x%x resid=0x%x\n",
-                         SCpnt->SCp.Status, SCpnt->resid);
-               SCpnt->result = 
-                       (DID_OK << 16) | (SCpnt->SCp.Message << 8) | (SCpnt->SCp.Status << 0);
-               nsp32_scsi_done(data, SCpnt);
-               /* All operation is done */
-               return (TRUE);
-       } else if (execph & MSGIN_04_VALID) {
-               /* MsgIn 04: Disconnect */
-               SCpnt->SCp.Status  = nsp32_read1(base, SCSI_CSB_IN);
-               SCpnt->SCp.Message = 4;
-               
-               nsp32_dbg(NSP32_DEBUG_BUSFREE, "disconnect");
-               return (TRUE);
-       } else {
-               /* Unexpected bus free */
-               nsp32_msg(KERN_WARNING, "unexpected bus free occurred");
-
-               /* DID_ERROR? */
-               //SCpnt->result   = (DID_OK << 16) | (SCpnt->SCp.Message << 8) | (SCpnt->SCp.Status << 0);
-               SCpnt->result = DID_ERROR << 16;
-               nsp32_scsi_done(data, SCpnt);
-               return (TRUE);
-       }
-       return (FALSE);
-}
-
-
-/*
- * nsp32_adjust_busfree - adjusting SG table
- *
- * Note: This driver adjust the SG table using SCSI ACK
- *       counter instead of BMCNT counter!
- */
-static void nsp32_adjust_busfree(nsp32_hw_data *data, unsigned int s_sacklen)
-{
-       int old_entry = data->cur_entry;
-       int new_entry;
-       struct nsp32_sgtable *sgt = data->curlunt->sglun->sgt;
-       unsigned int restlen, sentlen;
-       int sg_num = data->curlunt->sg_num;
-
-       /* adjust saved SACK count with 4 byte start address boundary */
-       s_sacklen -= sgt[old_entry].addr & 3;
-
-       /*
-        * calculate new_entry from sack count and each sgt[].len 
-        * calculate the byte which is intent to send
-        */
-       sentlen = 0;
-       for (new_entry = old_entry; new_entry < sg_num; new_entry++) {
-               sentlen += (sgt[new_entry].len & ~NSP32_SG_END_SGT);
-               if (sentlen > s_sacklen) {
+               /*
+                * Reach here means regular length of each type of 
+                * extended messages.
+                */
+               switch (data->msginbuf[2]) {
+               case EXTENDED_MODIFY_DATA_POINTER:
+                       /* TODO */
+                       goto reject; /* not implemented yet */
                        break;
-               }
-       }
-
-       /* all sgt is processed */
-       if (new_entry == sg_num) {
-               goto last;
-       }
-
-       if (sentlen == s_sacklen) {
-               /* XXX: confirm it's ok or not */
-               /* In this case, it's ok because we are at 
-                  the head element of the sg. restlen is correctly calculated. */
-       }
 
-       /* calculate the rest length for transfering */
-       restlen = sentlen - s_sacklen;
-       
-       /* update adjusting current SG table entry */
-       sgt[new_entry].addr += (sgt[new_entry].len - restlen);
-       sgt[new_entry].len = restlen;
+               case EXTENDED_SDTR:
+                       /*
+                        * Exchange this message between initiator and target.
+                        */
+                       if (data->msgin_len != EXTENDED_SDTR_LEN + 1) {
+                               /*
+                                * received inappropriate message.
+                                */
+                               goto reject;
+                               break;
+                       }
 
-       /* set cur_entry with new_entry */
-       data->cur_entry = new_entry;
-       
-       return;
+                       nsp32_analyze_sdtr(SCpnt);
 
- last:
-       /* update hostdata and lun */
+                       break;
 
-       return;
-}
+               case EXTENDED_EXTENDED_IDENTIFY:
+                       /* SCSI-I only, not supported. */
+                       goto reject; /* not implemented yet */
 
+                       break;
 
-/*
- * It's called MsgOut phase occur.
- * NinjaSCSI-32Bi/UDE automatically processes up to 3 messages in
- * message out phase. It, however, has more than 3 messages,
- * HBA creates the interrupt and we have to process by hand.
- */
-static void nsp32_msgout_occur(nsp32_hw_data *data)
-{
-       unsigned int base = data->BaseAddress;
-       long new_sgtp;
-       int i;
-       
-       nsp32_dbg(NSP32_DEBUG_MSGOUTOCCUR,
-                 "enter: msgoutlen: 0x%x", data->msgoutlen);
+               case EXTENDED_WDTR:
+                       goto reject; /* not implemented yet */
 
-       /*
-        * If MsgOut phase is occurred without having any
-        * message, then No_Operation is sent (SCSI-2).
-        */
-       if (data->msgoutlen == 0) {
-               nsp32_build_nop(data);
+                       break;
+                       
+               default:
+                       goto reject;
+               }
+               break;
+               
+       default:
+               goto reject;
        }
 
-       /*
-        * Set SGTP ADDR current entry for restarting AUTOSCSI, 
-        * because SGTP is incremented next point.
-        * There is few statement in the specification...
-        */
-       new_sgtp = data->curlunt->sglun_paddr
-               + data->curlunt->cur_entry * sizeof(struct nsp32_sgtable);
-
-       /*
-        * send messages
-        */
-       for (i=0; i<data->msgoutlen; i++) {
-               nsp32_dbg(NSP32_DEBUG_MSGOUTOCCUR,
-                         "%d : 0x%x", i, data->msgoutbuf[i]);
+ restart:
+       if (msgclear == TRUE) {
+               data->msgin_len = 0;
 
                /*
-                * Check REQ is asserted.
+                * If restarting AutoSCSI, but there are some message to out
+                * (msgout_len > 0), set AutoATN, and set SCSIMSGOUT as 0
+                * (MV_VALID = 0). When commandcontrol is written with
+                * AutoSCSI restart, at the same time MsgOutOccur should be
+                * happened (however, such situation is really possible...?).
                 */
-               nsp32_wait_req(data, ASSERT);
-
-               if (i == (data->msgoutlen - 1)) {
-                       /*
-                        * If the last message, set the AutoSCSI restart
-                        * before send back the ack message. AutoSCSI
-                        * restart automatically negate ATN signal.
-                        */
-                       //command = (AUTO_MSGIN_00_OR_04 | AUTO_MSGIN_02);
-                       //nsp32_restart_autoscsi(data, command);
-                       nsp32_write2(base, COMMAND_CONTROL,
-                                        (CLEAR_CDB_FIFO_POINTER |
-                                         AUTO_COMMAND_PHASE |
-                                         AUTOSCSI_RESTART |
-                                         AUTO_MSGIN_00_OR_04 |
-                                         AUTO_MSGIN_02 ));
+               if (data->msgout_len > 0) {     
+                       nsp32_write4(base, SCSI_MSG_OUT, 0);
+                       command |= AUTO_ATN;
                }
+
                /*
-                * Write data with SACK, then wait sack is
-                * automatically negated.
+                * restart AutoSCSI
+                * If it's failed, COMMANDCONTROL_AUTO_COMMAND_PHASE is needed.
                 */
-               nsp32_write1(base, SCSI_DATA_WITH_ACK, data->msgoutbuf[i]);
-               nsp32_wait_sack(data, NEGATE);
-
-               nsp32_dbg(NSP32_DEBUG_MSGOUTOCCUR, "bus: 0x%x\n",
-                         nsp32_read1(base, SCSI_BUS_MONITOR));
-       };
-
-       data->msgoutlen = 0;
-
-       nsp32_dbg(NSP32_DEBUG_MSGOUTOCCUR, "exit");
-}
-
-/*
- * Restart AutoSCSI
- *
- * Note: Restarting AutoSCSI needs set:
- *             SYNC_REG, ACK_WIDTH, SGT_ADR, TRANSFER_CONTROL
- */
-static void nsp32_restart_autoscsi(nsp32_hw_data *data, unsigned short command)
-{
-       unsigned int base = data->BaseAddress;
-       unsigned short transfer = 0;
-       Scsi_Cmnd *SCpnt = data->curlunt->SCpnt;
-
-       nsp32_dbg(NSP32_DEBUG_RESTART, "enter");
+               command |= (AUTO_MSGIN_00_OR_04 | AUTO_MSGIN_02);
 
-       if (data->curtarget == NULL || data->curlunt == NULL) {
-               nsp32_msg(KERN_ERR, "Target or Lun is invalid");
+               /*
+                * If current msgin03 is TRUE, then flag on.
+                */
+               if (data->cur_lunt->msgin03 == TRUE) {
+                       command |= AUTO_MSGIN_03;
+               }
+               data->cur_lunt->msgin03 = FALSE;
+       } else {
+               data->msgin_len++;
        }
 
        /*
-        * set SYNC_REG
-        * Don't set BM_START_ADR before setting this register.
+        * restart AutoSCSI
         */
-       nsp32_write1(base, SYNC_REG, data->curtarget->syncreg);
+       nsp32_restart_autoscsi(SCpnt, command);
 
        /*
-        * set ACKWIDTH
+        * wait SCSI REQ negate for REQ-ACK handshake
         */
-       nsp32_write1(base, ACK_WIDTH, data->curtarget->ackwidth);
+       nsp32_wait_req(data, NEGATE);
 
        /*
-        * set SGT ADDR (physical address)
+        * negate SCSI ACK
         */
-       nsp32_write4(base, SGT_ADR, data->curlunt->sglun_paddr);
+       nsp32_sack_negate(data);
 
-       /*
-        * set TRANSFER CONTROL REG
-        */
-       transfer = 0;
-       transfer |= (TRANSFER_GO | ALL_COUNTER_CLR);
-       if (data->trans_method & NSP32_TRANSFER_BUSMASTER) {
-               if (SCpnt->request_bufflen > 0) {
-                       transfer |= BM_START;
-               }
-       } else if (data->trans_method & NSP32_TRANSFER_MMIO) {
-               transfer |= CB_MMIO_MODE;
-       } else if (data->trans_method & NSP32_TRANSFER_PIO) {
-               transfer |= CB_IO_MODE;
-       }
-       nsp32_write2(base, TRANSFER_CONTROL, transfer);
+       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "exit");
 
-       /*
-        * restart AutoSCSI
-        *
-        * TODO: COMMANDCONTROL_AUTO_COMMAND_PHASE is needed ?
-        */
-       command |= (CLEAR_CDB_FIFO_POINTER |
-                   AUTO_COMMAND_PHASE |
-                   AUTOSCSI_RESTART);
-       nsp32_write2(base, COMMAND_CONTROL, command);
+       return;
 
-       nsp32_dbg(NSP32_DEBUG_RESTART, "exit");
-}
+ reject:
+       nsp32_msg(KERN_WARNING, 
+                 "invalid or unsupported MessageIn, rejected. "
+                 "current msg: 0x%x (len: 0x%x), processing msg: 0x%x",
+                 msg, data->msgin_len, msgtype);
+       nsp32_build_reject(SCpnt);
+       data->msgin_len = 0;
 
+       goto restart;
+}
 
 /*
- * cannot run automatically message in occur
+ * 
  */
-static void nsp32_msgin_occur(nsp32_hw_data *data, unsigned long irq_status,
-                       unsigned short execph)
+static void nsp32_analyze_sdtr(Scsi_Cmnd *SCpnt)
 {
-       unsigned int base = data->BaseAddress;
-       unsigned char msg;
-       unsigned char msgtype;
-       unsigned char newlun;
-       unsigned short command = 0;
-       int msgclear = TRUE;
-       long new_sgtp;
-       int ret;
+       nsp32_hw_data   *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       nsp32_target     *target     = data->cur_target;
+       nsp32_sync_table *synct;
+       unsigned char     get_period = data->msginbuf[3];
+       unsigned char     get_offset = data->msginbuf[4];
+       int               entry;
+       int               syncnum;
 
-       /*
-        * read first message
-        *    Use SCSIDATA_W_ACK instead of SCSIDATAIN, because the procedure
-        *    of Message-In have to be processed before sending back SCSI ACK.
-        */
-       msg = nsp32_read1(base, SCSI_DATA_IN);
-       data->msginbuf[(unsigned char)data->msginlen] = msg;
-       msgtype = data->msginbuf[0];
-       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR,
-                 "enter: msglen: 0x%x msgin: 0x%x msgtype: 0x%x",
-                 data->msginlen, msg, msgtype);
+       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "enter");
 
-       /*
-        * TODO: We need checking whether bus phase is message in?
-        */
+       synct   = data->synct;
+       syncnum = data->syncnum;
 
        /*
-        * assert SCSI ACK
-        */
-       nsp32_sack_assert(data);
+        * If this inititor sent the SDTR message, then target responds SDTR,
+        * initiator SYNCREG, ACKWIDTH from SDTR parameter.
+        * Messages are not appropriate, then send back reject message.
+        * If initiator did not send the SDTR, but target sends SDTR, 
+        * initiator calculator the appropriate parameter and send back SDTR.
+        */     
+       if (target->sync_flag & SDTR_INITIATOR) {
+               /*
+                * Initiator sent SDTR, the target responds and
+                * send back negotiation SDTR.
+                */
+               nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "target responds SDTR");
+       
+               target->sync_flag &= ~SDTR_INITIATOR;
+               target->sync_flag |= SDTR_DONE;
 
-       /*
-        * processing IDENTIFY
-        */
-       if (msgtype & 0x80) {
-               if (!(irq_status & IRQSTATUS_RESELECT_OCCUER)) {
-                       /* Invalid (non reselect) phase */
-                       goto reject;
-               }
-
-               newlun = msgtype & 0x1f; /* TODO: SPI-3 compliant? */
-               ret = nsp32_reselection(data, newlun);
-               if (ret == TRUE) {
-                       goto restart;
-               } else {
-                       goto reject;
-               }
-       }
-       
-       /*
-        * processing messages except for IDENTIFY
-        *
-        * TODO: Messages are all SCSI-2 terminology. SCSI-3 compliance is TODO.
-        */
-       switch (msgtype) {
-       /*
-        * 1-byte message
-        */
-       case COMMAND_COMPLETE:
-       case DISCONNECT:
                /*
-                * These messages should not be occurred.
-                * They should be processed on AutoSCSI sequencer.
+                * offset:
                 */
-               nsp32_msg(KERN_WARNING, 
-                          "unexpected message of AutoSCSI MsgIn: 0x%x", msg);
-               break;
+               if (get_offset > SYNC_OFFSET) {
+                       /*
+                        * Negotiation is failed, the target send back
+                        * unexpected offset value.
+                        */
+                       goto reject;
+               }
                
-       case RESTORE_POINTERS:
+               if (get_offset == ASYNC_OFFSET) {
+                       /*
+                        * Negotiation is succeeded, the target want
+                        * to fall back into asynchronous transfer mode.
+                        */
+                       goto async;
+               }
+
                /*
-                * AutoMsgIn03 is disabled, and HBA gets this message.
+                * period:
+                *    Check whether sync period is too short. If too short,
+                *    fall back to async mode. If it's ok, then investigate
+                *    the received sync period. If sync period is acceptable
+                *    between sync table start_period and end_period, then
+                *    set this I_T nexus as sent offset and period.
+                *    If it's not acceptable, send back reject and fall back
+                *    to async mode.
                 */
-
-               if ((execph & DATA_IN_PHASE) || (execph & DATA_OUT_PHASE)) {
-                       unsigned int s_sacklen;
-
-                       s_sacklen = nsp32_read4(base, SAVED_SACK_CNT);
-                       if ((execph & MSGIN_02_VALID) && (s_sacklen > 0)) {
-                               nsp32_adjust_busfree(data, s_sacklen);
-                       } else {
-                               /* No need to rewrite SGT */
-                       }
+               if (get_period < data->synct[0].period_num) {
+                       /*
+                        * Negotiation is failed, the target send back
+                        * unexpected period value.
+                        */
+                       goto reject;
                }
-               data->curlunt->msgin03 = FALSE;
 
-               /* Update with the new value */
+               entry = nsp32_search_period_entry(data, target, get_period);
 
-               /* reset SACK/SavedACK counter (or ALL clear?) */
-               nsp32_write4(base, CLR_COUNTER, CLRCOUNTER_ALLMASK);
+               if (entry < 0) {
+                       /*
+                        * Target want to use long period which is not 
+                        * acceptable NinjaSCSI-32Bi/UDE.
+                        */
+                       goto reject;
+               }
 
                /*
-                * set new sg pointer
+                * Set new sync table and offset in this I_T nexus.
                 */
-               new_sgtp = data->curlunt->sglun_paddr + 
-                       data->curlunt->cur_entry * sizeof(struct nsp32_sgtable);
-               nsp32_write4(base, SGT_ADR, new_sgtp);
-
-               break;
+               nsp32_set_sync_entry(data, target, entry, get_offset);
+       } else {
+               /* Target send SDTR to initiator. */
+               nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "target send SDTR");
+       
+               target->sync_flag |= SDTR_INITIATOR;
 
-       case SAVE_POINTERS:
-               /*
-                * These messages should not be occurred.
-                * They should be processed on AutoSCSI sequencer.
-                */
-               nsp32_msg (KERN_WARNING, 
-                          "unexpected message of AutoSCSI MsgIn: SAVE_POINTERS");
-               
-               break;
-               
-       case MESSAGE_REJECT:
-               /* If previous message_out is sending SDTR, and get 
-                  message_reject from target, SDTR negotiation is failed */
-               if (data->curtarget->sync_flag &
-                               (SDTR_INITIATOR | SDTR_TARGET)) {
-                       /*
-                        * Current target is negotiating SDTR, but it's
-                        * failed.  Fall back to async transfer mode, and set
-                        * SDTR_DONE.
-                        */
-                       nsp32_set_async(data, data->curtarget);
-                       data->curtarget->sync_flag &= ~SDTR_INITIATOR;
-                       data->curtarget->sync_flag |= SDTR_DONE;
+               /* offset: */
+               if (get_offset > SYNC_OFFSET) {
+                       /* send back as SYNC_OFFSET */
+                       get_offset = SYNC_OFFSET;
+               }
 
+               /* period: */
+               if (get_period < data->synct[0].period_num) {
+                       get_period = data->synct[0].period_num;
                }
-               break;
 
-       case LINKED_CMD_COMPLETE:
-       case LINKED_FLG_CMD_COMPLETE:
-               /* queue tag is not supported currently */
-               nsp32_msg (KERN_WARNING, 
-                          "unsupported message: 0x%x", msgtype);
-               break;
+               entry = nsp32_search_period_entry(data, target, get_period);
 
-       case INITIATE_RECOVERY:
-               /* staring ECA (Extended Contingent Allegiance) state. */
-               /* This message is declined in SPI2 or later. */
+               if (get_offset == ASYNC_OFFSET || entry < 0) {
+                       nsp32_set_async(data, target);
+                       nsp32_build_sdtr(SCpnt, 0, ASYNC_OFFSET);
+               } else {
+                       nsp32_set_sync_entry(data, target, entry, get_offset);
+                       nsp32_build_sdtr(SCpnt, get_period, get_offset);
+               }
+       }
 
-               goto reject;
+       target->period = get_period;
+       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "exit");
+       return;
 
+ reject:
        /*
-        * 2-byte message
+        * If the current message is unacceptable, send back to the target
+        * with reject message.
         */
-       case SIMPLE_QUEUE_TAG:
-       case 0x23:
-               /*
-                * 0x23: Ignore_Wide_Residue is not declared in scsi.h.
-                * No support is needed.
-                */
-               if (data->msginlen >= 1) {
-                       goto reject;
-               }
+       nsp32_build_reject(SCpnt);
 
-               /* current position is 1-byte of 2 byte */
-               msgclear = FALSE;
+ async:
+       nsp32_set_async(data, target);  /* set as ASYNC transfer mode */
 
-               break;
+       target->period = 0;
+       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "exit: set async");
+       return;
+}
+
+
+/*
+ * Search config entry number matched in sync_table from given
+ * target and speed period value. If failed to search, return negative value.
+ */
+static int nsp32_search_period_entry(nsp32_hw_data *data,
+                                    nsp32_target  *target,
+                                    unsigned char  period)
+{
+       int i;
+
+       if (target->limit_entry >= data->syncnum) {
+               nsp32_msg(KERN_ERR, "limit_entry exceeds syncnum!");
+               target->limit_entry = 0;
+       }
+
+       for (i = target->limit_entry; i < data->syncnum; i++) {
+               if (period >= data->synct[i].start_period &&
+                   period <= data->synct[i].end_period) {
+                               break;
+               }
+       }
 
        /*
-        * extended message
+        * Check given period value is over the sync_table value.
+        * If so, return max value.
         */
-       case EXTENDED_MESSAGE:
-               if (data->msginlen < 1) {
-                       /*
-                        * Current position does not reach 2-byte
-                        * (2-byte is extended message length).
-                        */
-                       msgclear = FALSE;
-                       break;
-               }
+       if (i == data->syncnum) {
+               i = -1;
+       }
 
-               if ((data->msginbuf[1] + 1) > data->msginlen) {
-                       /*
-                        * Current extended message has msginbuf[1] + 2
-                        * (msginlen starts counting from 0, so buf[1] + 1).
-                        * If current message position is not finished,
-                        * continue receiving message.
-                        */
-                       msgclear = FALSE;
-                       break;
-               }
+       return i;
+}
 
-               /*
-                * Reach here means regular length of each type of 
-                * extended messages.
-                */
-               switch (data->msginbuf[2]) {
-               case EXTENDED_MODIFY_DATA_POINTER:
-                       /* TODO */
-                       goto reject; /* not implemented yet */
-                       break;
 
-               case EXTENDED_SDTR:
-                       /*
-                        * Exchange this message between initiator and target.
-                        */
-                       if (data->msginlen != EXTENDED_SDTR_LEN + 1) {
-                               /*
-                                * received inappropriate message.
-                                */
-                               goto reject;
-                               break;
-                       }
+/*
+ * target <-> initiator use ASYNC transfer
+ */
+static void nsp32_set_async(nsp32_hw_data *data, nsp32_target *target)
+{
+       unsigned char period = data->synct[target->limit_entry].period_num;
 
-                       nsp32_analyze_sdtr(data);
+       target->offset     = ASYNC_OFFSET;
+       target->period     = 0;
+       target->syncreg    = TO_SYNCREG(period, ASYNC_OFFSET);
+       target->ackwidth   = 0;
+       target->sample_reg = 0;
 
-                       break;
+       nsp32_dbg(NSP32_DEBUG_SYNC, "set async");
+}
 
-               case EXTENDED_EXTENDED_IDENTIFY:
-                       /* SCSI-I only, not supported. */
-                       goto reject; /* not implemented yet */
 
-                       break;
+/*
+ * target <-> initiator use maximum SYNC transfer
+ */
+static void nsp32_set_max_sync(nsp32_hw_data *data,
+                              nsp32_target  *target,
+                              unsigned char *period,
+                              unsigned char *offset)
+{
+       unsigned char period_num, ackwidth;
 
-               case EXTENDED_WDTR:
-                       goto reject; /* not implemented yet */
+       period_num = data->synct[target->limit_entry].period_num;
+       *period    = data->synct[target->limit_entry].start_period;
+       ackwidth   = data->synct[target->limit_entry].ackwidth;
+       *offset    = SYNC_OFFSET;
 
-                       break;
-                       
-               default:
-                       goto reject;
-               }
-               break;
-               
-       default:
-               goto reject;
-       }
+       target->syncreg    = TO_SYNCREG(period_num, *offset);
+       target->ackwidth   = ackwidth;
+       target->offset     = *offset;
+       target->sample_reg = 0;       /* disable SREQ sampling */
+}
 
- restart:
-       if (msgclear == TRUE) {
-               data->msginlen = 0;
 
-               /*
-                * If restarting AutoSCSI, but there are some message to out
-                * (msgoutlen > 0), set AutoATN, and set SCSIMSGOUT as 0
-                * (MV_VALID = 0). When commandcontrol is written with
-                * AutoSCSI restart, at the same time MsgOutOccur should be
-                * happened (however, such situation is really possible...?).
-                */
-               if (data->msgoutlen > 0) {      
-                       nsp32_write4(base, SCSI_MSG_OUT, 0);
-                       command |= AUTO_ATN;
+/*
+ * target <-> initiator use entry number speed
+ */
+static void nsp32_set_sync_entry(nsp32_hw_data *data,
+                                nsp32_target  *target,
+                                int            entry,
+                                unsigned char  offset)
+{
+       unsigned char period, ackwidth, sample_rate;
+
+       period      = data->synct[entry].period_num;
+       ackwidth    = data->synct[entry].ackwidth;
+       offset      = offset;
+       sample_rate = data->synct[entry].sample_rate;
+
+       target->syncreg    = TO_SYNCREG(period, offset);
+       target->ackwidth   = ackwidth;
+       target->offset     = offset;
+       target->sample_reg = sample_rate | SAMPLING_ENABLE;
+
+       nsp32_dbg(NSP32_DEBUG_SYNC, "set sync");
+}
+
+
+/*
+ * It waits until SCSI REQ becomes assertion or negation state.
+ *
+ * Note: If nsp32_msgin_occur is called, we asserts SCSI ACK. Then
+ *     connected target responds SCSI REQ negation.  We have to wait
+ *     SCSI REQ becomes negation in order to negate SCSI ACK signal for
+ *     REQ-ACK handshake.
+ */
+static void nsp32_wait_req(nsp32_hw_data *data, int state)
+{
+       unsigned int  base      = data->BaseAddress;
+       int           wait_time = 0;
+       unsigned char bus, req_bit;
+
+       if (!((state == ASSERT) || (state == NEGATE))) {
+               nsp32_msg(KERN_ERR, "unknown state designation");
+       }
+       /* REQ is BIT(5) */
+       req_bit = (state == ASSERT ? BUSMON_REQ : 0);
+
+       do {
+               bus = nsp32_read1(base, SCSI_BUS_MONITOR);
+               if ((bus & BUSMON_REQ) == req_bit) {
+                       nsp32_dbg(NSP32_DEBUG_WAIT, 
+                                 "wait_time: %d", wait_time);
+                       return;
                }
+               udelay(1);
+               wait_time++;
+       } while (wait_time < REQSACK_TIMEOUT_TIME);
 
-               /*
-                * restart AutoSCSI
-                * If it's failed, COMMANDCONTROL_AUTO_COMMAND_PHASE is needed.
-                */
-               command |= (AUTO_MSGIN_00_OR_04 | AUTO_MSGIN_02);
+       nsp32_msg(KERN_WARNING, "wait REQ timeout, req_bit: 0x%x", req_bit);
+}
 
-               /*
-                * If current msgin03 is TRUE, then flag on.
-                */
-               if (data->curlunt->msgin03 == TRUE) {
-                       command |= AUTO_MSGIN_03;
+/*
+ * It waits until SCSI SACK becomes assertion or negation state.
+ */
+static void nsp32_wait_sack(nsp32_hw_data *data, int state)
+{
+       unsigned int  base      = data->BaseAddress;
+       int           wait_time = 0;
+       unsigned char bus, ack_bit;
+
+       if (!((state == ASSERT) || (state == NEGATE))) {
+               nsp32_msg(KERN_ERR, "unknown state designation");
+       }
+       /* ACK is BIT(4) */
+       ack_bit = (state == ASSERT ? BUSMON_ACK : 0);
+
+       do {
+               bus = nsp32_read1(base, SCSI_BUS_MONITOR);
+               if ((bus & BUSMON_ACK) == ack_bit) {
+                       nsp32_dbg(NSP32_DEBUG_WAIT,
+                                 "wait_time: %d", wait_time);
+                       return;
                }
-               data->curlunt->msgin03 = FALSE;
-       } else {
-               data->msginlen++;
+               udelay(1);
+               wait_time++;
+       } while (wait_time < REQSACK_TIMEOUT_TIME);
+
+       nsp32_msg(KERN_WARNING, "wait SACK timeout, ack_bit: 0x%x", ack_bit);
+}
+
+/*
+ * assert SCSI ACK
+ *
+ * Note: SCSI ACK assertion needs with ACKENB=1, AUTODIRECTION=1.
+ */
+static void nsp32_sack_assert(nsp32_hw_data *data)
+{
+       unsigned int  base = data->BaseAddress;
+       unsigned char busctrl;
+
+       busctrl  = nsp32_read1(base, SCSI_BUS_CONTROL);
+       busctrl |= (BUSCTL_ACK | AUTODIRECTION | ACKENB);
+       nsp32_write1(base, SCSI_BUS_CONTROL, busctrl);
+}
+
+/*
+ * negate SCSI ACK
+ */
+static void nsp32_sack_negate(nsp32_hw_data *data)
+{
+       unsigned int  base = data->BaseAddress;
+       unsigned char busctrl;
+
+       busctrl  = nsp32_read1(base, SCSI_BUS_CONTROL);
+       busctrl &= ~BUSCTL_ACK;
+       nsp32_write1(base, SCSI_BUS_CONTROL, busctrl);
+}
+
+
+
+/*
+ * Note: n_io_port is defined as 0x7f because I/O register port is
+ *      assigned as:
+ *     0x800-0x8ff: memory mapped I/O port
+ *     0x900-0xbff: (map same 0x800-0x8ff I/O port image repeatedly)
+ *     0xc00-0xfff: CardBus status registers
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+#define DETECT_OK 0
+#define DETECT_NG 1
+#define PCIDEV    pdev
+static int nsp32_detect(struct pci_dev *pdev)
+#else
+#define DETECT_OK 1
+#define DETECT_NG 0
+#define PCIDEV    (data->Pci)
+static int nsp32_detect(Scsi_Host_Template *sht)
+#endif
+{
+       struct Scsi_Host *host; /* registered host structure */
+       struct resource  *res;
+       nsp32_hw_data    *data;
+       int               ret;
+       int               i, j;
+
+       nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
+
+       /*
+        * register this HBA as SCSI device
+        */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+       host = scsi_host_alloc(&nsp32_template, sizeof(nsp32_hw_data));
+#else
+       host = scsi_register(sht, sizeof(nsp32_hw_data));
+#endif
+       if (host == NULL) {
+               nsp32_msg (KERN_ERR, "failed to scsi register");
+               goto err;
        }
 
        /*
-        * restart AutoSCSI
+        * set nsp32_hw_data
+        */
+       data = (nsp32_hw_data *)host->hostdata;
+
+       memcpy(data, &nsp32_data_base, sizeof(nsp32_hw_data));
+
+       host->irq       = data->IrqNumber;
+       host->io_port   = data->BaseAddress;
+       host->unique_id = data->BaseAddress;
+       host->n_io_port = data->NumAddress;
+       host->base      = data->MmioAddress;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,63))
+       scsi_set_device(host, &PCIDEV->dev);
+#else
+       scsi_set_pci_device(host, PCIDEV);
+#endif
+
+       data->Host      = host;
+       spin_lock_init(&(data->Lock));
+
+       data->cur_lunt   = NULL;
+       data->cur_target = NULL;
+
+       /*
+        * Bus master transfer mode is supported currently.
+        */
+       data->trans_method = NSP32_TRANSFER_BUSMASTER;
+
+       /*
+        * Set clock div, CLOCK_4 (HBA has own external clock, and
+        * dividing * 100ns/4).
+        * Currently CLOCK_4 has only tested, not for CLOCK_2/PCICLK yet.
         */
-       nsp32_restart_autoscsi(data, command);
+       data->clock = CLOCK_4;
 
        /*
-        * wait SCSI REQ negate for REQ-ACK handshake
+        * Select appropriate nsp32_sync_table and set I_CLOCKDIV.
         */
-       nsp32_wait_req(data, NEGATE);
+       switch (data->clock) {
+       case CLOCK_4:
+               /* If data->clock is CLOCK_4, then select 40M sync table. */
+               data->synct   = nsp32_sync_table_40M;
+               data->syncnum = NUMBER(nsp32_sync_table_40M);
+               break;
+       case CLOCK_2:
+               /* If data->clock is CLOCK_2, then select 20M sync table. */
+               data->synct   = nsp32_sync_table_20M;
+               data->syncnum = NUMBER(nsp32_sync_table_20M);
+               break;
+       case PCICLK:
+               /* If data->clock is PCICLK, then select pci sync table. */
+               data->synct   = nsp32_sync_table_pci;
+               data->syncnum = NUMBER(nsp32_sync_table_pci);
+               break;
+       default:
+               nsp32_msg(KERN_WARNING,
+                         "Invalid clock div is selected, set CLOCK_4.");
+               /* Use default value CLOCK_4 */
+               data->clock   = CLOCK_4;
+               data->synct   = nsp32_sync_table_40M;
+               data->syncnum = NUMBER(nsp32_sync_table_40M);
+       }
 
        /*
-        * negate SCSI ACK
+        * setup nsp32_lunt
         */
-       nsp32_sack_negate(data);
 
-       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "exit");
+       /*
+        * setup DMA 
+        */
+       if (pci_set_dma_mask(PCIDEV, 0xffffffffUL) != 0) {
+               nsp32_msg (KERN_ERR, "failed to set PCI DMA mask");
+               goto scsi_unregister;
+       }
 
-       return;
+       /*
+        * allocate autoparam DMA resource.
+        */
+       data->autoparam = pci_alloc_consistent(PCIDEV, sizeof(nsp32_autoparam), &(data->auto_paddr));
+       if (data->autoparam == NULL) {
+               nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
+               goto scsi_unregister;
+       }
 
- reject:
-       nsp32_msg(KERN_WARNING, 
-                 "invalid or unsupported MessageIn, rejected. "
-                 "current msg: 0x%x (len: 0x%x), processing msg: 0x%x",
-                 msg, data->msginlen, msgtype);
-       nsp32_build_reject(data);
-       data->msginlen = 0;
+       /*
+        * allocate scatter-gather DMA resource.
+        */
+       data->sg_list = pci_alloc_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+                                            &(data->sg_paddr));
+       if (data->sg_list == NULL) {
+               nsp32_msg(KERN_ERR, "failed to allocate DMA memory");
+               goto free_autoparam;
+       }
 
-       goto restart;
-}
+       for (i = 0; i < NUMBER(data->lunt); i++) {
+               for (j = 0; j < NUMBER(data->lunt[0]); j++) {
+                       int offset = i * NUMBER(data->lunt[0]) + j;
+                       nsp32_lunt tmp = {
+                               SCpnt:       NULL,
+                               save_datp:   0,
+                               msgin03:     FALSE,
+                               sg_num:      0,
+                               cur_entry:   0,
+                               sglun:       &(data->sg_list[offset]),
+                               sglun_paddr: data->sg_paddr + (offset * sizeof(nsp32_sglun)),
+                       };
 
-/*
- * 
- */
-static void nsp32_analyze_sdtr(nsp32_hw_data *data)
-{
-       struct nsp32_target *target = data->curtarget;
-       struct nsp32_sync_table *synct;
-       unsigned char get_period = data->msginbuf[3];
-       unsigned char get_offset = data->msginbuf[4];
-       int entry;
-       int syncnum;
+                       data->lunt[i][j] = tmp;
+               }
+       }
 
-       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "enter");
+       /*
+        * setup target
+        */
+       for (i = 0; i < NUMBER(data->target); i++) {
+               nsp32_target *target = &(data->target[i]);
 
-       synct = data->synct;
-       syncnum = data->syncnum;
+               target->limit_entry  = 0;
+               target->sync_flag    = 0;
+               nsp32_set_async(data, target);
+       }
 
        /*
-        * If this inititor sent the SDTR message, then target responds SDTR,
-        * initiator SYNCREG, ACKWIDTH from SDTR parameter.
-        * Messages are not appropriate, then send back reject message.
-        * If initiator did not send the SDTR, but target sends SDTR, 
-        * initiator calculator the appropriate parameter and send back SDTR.
-        */     
-       if (target->sync_flag & SDTR_INITIATOR) {
-               /*
-                * Initiator sent SDTR, the target responds and
-                * send back negotiation SDTR.
-                */
-               nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "target responds SDTR");
-       
-               target->sync_flag &= ~SDTR_INITIATOR;
-               target->sync_flag |= SDTR_DONE;
+        * EEPROM check
+        */
+       ret = nsp32_getprom_param(data);
+       if (ret == FALSE) {
+               data->resettime = 3;    /* default 3 */
+       }
 
-               /*
-                * offset:
-                */
-               if (get_offset > SYNC_OFFSET) {
-                       /*
-                        * Negotiation is failed, the target send back
-                        * unexpected offset value.
-                        */
-                       goto reject;
-               }
-               
-               if (get_offset == ASYNC_OFFSET) {
-                       /*
-                        * Negotiation is succeeded, the target want
-                        * to fall back into asynchronous transfer mode.
-                        */
-                       goto async;
-               }
+       /*
+        * setup HBA
+        */
+       nsp32hw_init(data);
 
-               /*
-                * period:
-                *    Check whether sync period is too short. If too short,
-                *    fall back to async mode. If it's ok, then investigate
-                *    the received sync period. If sync period is acceptable
-                *    between sync table start_period and end_period, then
-                *    set this I_T nexus as sent offset and period.
-                *    If it's not acceptable, send back reject and fall back
-                *    to async mode.
-                */
-               if (get_period < data->synct[0].period_num) {
-                       /*
-                        * Negotiation is failed, the target send back
-                        * unexpected period value.
-                        */
-                       goto reject;
-               }
+       snprintf(data->info_str, sizeof(data->info_str),
+                "NinjaSCSI-32Bi/UDE: irq %d, io 0x%lx+0x%x",
+                host->irq, host->io_port, host->n_io_port);
 
-               entry = nsp32_search_period_entry(data, target, get_period);
+       /*
+        * SCSI bus reset
+        *
+        * Note: It's important to reset SCSI bus in initialization phase.
+        *     NinjaSCSI-32Bi/UDE HBA EEPROM seems to exchange SDTR when
+        *     system is coming up, so SCSI devices connected to HBA is set as
+        *     un-asynchronous mode.  It brings the merit that this HBA is
+        *     ready to start synchronous transfer without any preparation,
+        *     but we are difficult to control transfer speed.  In addition,
+        *     it prevents device transfer speed from effecting EEPROM start-up
+        *     SDTR.  NinjaSCSI-32Bi/UDE has the feature if EEPROM is set as
+        *     Auto Mode, then FAST-10M is selected when SCSI devices are
+        *     connected same or more than 4 devices.  It should be avoided
+        *     depending on this specification. Thus, resetting the SCSI bus
+        *     restores all connected SCSI devices to asynchronous mode, then
+        *     this driver set SDTR safely later, and we can control all SCSI
+        *     device transfer mode.
+        */
+       nsp32_do_bus_reset(data);
 
-               if (entry < 0) {
-                       /*
-                        * Target want to use long period which is not 
-                        * acceptable NinjaSCSI-32Bi/UDE.
-                        */
-                       goto reject;
-               }
+       ret = request_irq(host->irq, do_nsp32_isr,
+                         SA_SHIRQ | SA_SAMPLE_RANDOM, "nsp32", data);
+       if (ret < 0) {
+               nsp32_msg(KERN_ERR, "Unable to allocate IRQ for NinjaSCSI32 "
+                         "SCSI PCI controller. Interrupt: %d", host->irq);
+               goto free_sg_list;
+       }
 
-               /*
-                * Set new sync table and offset in this I_T nexus.
-                */
-               nsp32_set_sync_entry(data, target, entry, get_offset);
-       } else {
-               /* Target send SDTR to initiator. */
-               nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "target send SDTR");
-       
-               target->sync_flag |= SDTR_INITIATOR;
+        /*
+         * PCI IO register
+         */
+       res = request_region(host->io_port, host->n_io_port, "nsp32");
+       if (res == NULL) {
+               nsp32_msg(KERN_ERR, 
+                         "I/O region 0x%lx+0x%lx is already used",
+                         data->BaseAddress, data->NumAddress);
+               goto free_irq;
+        }
 
-               /* offset: */
-               if (get_offset > SYNC_OFFSET) {
-                       /* send back as SYNC_OFFSET */
-                       get_offset = SYNC_OFFSET;
-               }
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+       scsi_add_host (host, &PCIDEV->dev);
+       scsi_scan_host(host);
+#endif
+       pci_set_drvdata(PCIDEV, host);
+       return DETECT_OK;
 
-               /* period: */
-               if (get_period < data->synct[0].period_num) {
-                       get_period = data->synct[0].period_num;
-               }
+ free_irq:
+       free_irq(host->irq, data);
 
-               entry = nsp32_search_period_entry(data, target, get_period);
+ free_sg_list:
+       pci_free_consistent(PCIDEV, NSP32_SG_TABLE_SIZE,
+                           data->sg_list, data->sg_paddr);
 
-               if (get_offset == ASYNC_OFFSET || entry < 0) {
-                       nsp32_set_async(data, target);
-                       nsp32_build_sdtr(data, 0, ASYNC_OFFSET);
-               } else {
-                       nsp32_set_sync_entry(data, target, entry, get_offset);
-                       nsp32_build_sdtr(data, get_period, get_offset);
-               }
-       }
+ free_autoparam:
+       pci_free_consistent(PCIDEV, sizeof(nsp32_autoparam),
+                           data->autoparam, data->auto_paddr);
        
-       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "exit");
-       return;
-
- reject:
-       /*
-        * If the current message is unacceptable, send back to the target
-        * with reject message.
-        */
-       nsp32_build_reject(data);
-
- async:
-       nsp32_set_async(data, target);  /* set as ASYNC transfer mode */
+ scsi_unregister:
+       scsi_host_put(host);
 
-       nsp32_dbg(NSP32_DEBUG_MSGINOCCUR, "exit: set async");
-       return;
+ err:
+       return DETECT_NG;
 }
+#undef DETECT_OK
+#undef DETECT_NG
+#undef PCIDEV
 
-
-/*
- * Search config entry number matched in sync_table from given
- * target and speed period value. If failed to search, return negative value.
- */
-static int nsp32_search_period_entry(nsp32_hw_data *data,
-                             struct nsp32_target *target,
-                             unsigned char period)
+static int nsp32_release(struct Scsi_Host *host)
 {
-       int i;
+       nsp32_hw_data *data = (nsp32_hw_data *)host->hostdata;
 
-       if (target->limit_entry >= data->syncnum) {
-               nsp32_msg(KERN_ERR, "limit_entry exceeds syncnum!");
-               target->limit_entry = 0;
+       if (data->autoparam) {
+               pci_free_consistent(data->Pci, sizeof(nsp32_autoparam),
+                                   data->autoparam, data->auto_paddr);
        }
 
-       for (i=target->limit_entry; i<data->syncnum; i++) {
-               if (period >= data->synct[i].start_period &&
-                   period <= data->synct[i].end_period) {
-                               break;
-               }
+       if (data->sg_list) {
+               pci_free_consistent(data->Pci, NSP32_SG_TABLE_SIZE,
+                                   data->sg_list, data->sg_paddr);
        }
 
-       /*
-        * Check given period value is over the sync_table value.
-        * If so, return max value.
-        */
-       if (i == data->syncnum) {
-               i = -1;
+       if (host->irq) {
+               free_irq(host->irq, data);
        }
 
-       return i;
-}
-
-
-/*
- * target <-> initiator use ASYNC transfer
- */
-static void nsp32_set_async(nsp32_hw_data *data, struct nsp32_target *target)
-{
-       unsigned char period = data->synct[target->limit_entry].period_num;
+       if (host->io_port && host->n_io_port) {
+               release_region(host->io_port, host->n_io_port);
+       }
 
-       target->offset   = ASYNC_OFFSET;
-       target->syncreg  = TO_SYNCREG(period, ASYNC_OFFSET);
-       target->ackwidth = 0;
+       if (data->MmioAddress != 0) {
+               iounmap((void *)(data->MmioAddress));
+       }
 
-       nsp32_dbg(NSP32_DEBUG_SYNC, "set async");
+       return 0;
 }
 
+static const char *nsp32_info(struct Scsi_Host *shpnt)
+{
+       nsp32_hw_data *data = (nsp32_hw_data *)shpnt->hostdata;
 
-/*
- * target <-> initiator use maximum SYNC transfer
- */
-static void nsp32_set_max_sync(nsp32_hw_data *data,
-                              struct nsp32_target *target,
-                              unsigned char *period, unsigned char *offset)
-{
-       unsigned char period_num, ackwidth;
-
-       period_num = data->synct[target->limit_entry].period_num;
-       *period    = data->synct[target->limit_entry].start_period;
-       ackwidth   = data->synct[target->limit_entry].ackwidth;
-       *offset    = SYNC_OFFSET;
-
-       target->syncreg  = TO_SYNCREG(period_num, *offset);
-       target->ackwidth = ackwidth;
-       target->offset   = *offset;
+       return data->info_str;
 }
 
 
-/*
- * target <-> initiator use entry number speed
+/****************************************************************************
+ * error handler
  */
-static void nsp32_set_sync_entry(nsp32_hw_data *data,
-                                struct nsp32_target *target,
-                                int entry, unsigned char offset)
+static int nsp32_eh_abort(Scsi_Cmnd *SCpnt)
 {
-       unsigned char period, ackwidth;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int   base = SCpnt->device->host->io_port;
 
-       period   = data->synct[entry].period_num;
-       ackwidth = data->synct[entry].ackwidth;
-       offset  = offset;
+       nsp32_msg(KERN_WARNING, "abort");
 
-       target->syncreg  = TO_SYNCREG(period, offset);
-       target->ackwidth = ackwidth;
-       target->offset   = offset;
+       if (data->cur_lunt->SCpnt == NULL) {
+               nsp32_dbg(NSP32_DEBUG_BUSRESET, "abort failed");
+               return FAILED;
+       }
 
-       nsp32_dbg(NSP32_DEBUG_SYNC, "set sync");
-}
+       if (data->cur_target->sync_flag & (SDTR_INITIATOR | SDTR_TARGET)) {
+               /* reset SDTR negotiation */
+               data->cur_target->sync_flag = 0;
+               nsp32_set_async(data, data->cur_target);
+       }
 
+       nsp32_write2(base, TRANSFER_CONTROL, 0);
+       nsp32_write2(base, BM_CNT,           0);
 
-/*
- * It waits until SCSI REQ becomes assertion or negation state.
- *
- * Note: If nsp32_msgin_occur is called, we asserts SCSI ACK. Then
- *     connected target responds SCSI REQ negation.  We have to wait
- *     SCSI REQ becomes negation in order to negate SCSI ACK signal for
- *     REQ-ACK handshake.
- */
-static void nsp32_wait_req(nsp32_hw_data *data, int state)
+       SCpnt->result = DID_ABORT << 16;
+       nsp32_scsi_done(SCpnt);
+
+       nsp32_dbg(NSP32_DEBUG_BUSRESET, "abort success");
+       return SUCCESS;
+}
+
+static int nsp32_eh_bus_reset(Scsi_Cmnd *SCpnt)
 {
-       unsigned int base = data->BaseAddress;
-       int wait_time = 0;
-       unsigned char bus;
+       nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
+       unsigned int   base = SCpnt->device->host->io_port;
 
-       if (!((state == ASSERT) || (state == NEGATE))) {
-               nsp32_msg(KERN_ERR, "unknown state designation");
-       }
-       state <<= 5; /* REQ is BIT(5) */
+       nsp32_msg(KERN_INFO, "Bus Reset");      
+       nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%x", SCpnt);
 
-       do {
-               bus = nsp32_read1(base, SCSI_BUS_MONITOR);
-               if ((bus & BUSMON_REQ) == state) {
-                       nsp32_dbg(NSP32_DEBUG_WAIT, 
-                                 "wait_time: %d", wait_time);
-                       return;
-               }
-               udelay(1);
-               wait_time++;
-       } while (wait_time < REQSACK_TIMEOUT_TIME);
+       nsp32_write2(base, IRQ_CONTROL, IRQ_CONTROL_ALL_IRQ_MASK);
+       nsp32_do_bus_reset(data);
+       nsp32_write2(base, IRQ_CONTROL, 0);
 
-       nsp32_msg(KERN_WARNING, "wait REQ timeout, state: %d", state);
+       return SUCCESS; /* SCSI bus reset is succeeded at any time. */
 }
 
-/*
- * It waits until SCSI SACK becomes assertion or negation state.
- */
-static void nsp32_wait_sack(nsp32_hw_data *data, int state)
+static void nsp32_do_bus_reset(nsp32_hw_data *data)
 {
-       unsigned int base = data->BaseAddress;
-       int wait_time = 0;
-       unsigned char bus;
+       unsigned int   base = data->BaseAddress;
+       unsigned short intrdat;
+       int i;
 
-       if (!((state == ASSERT) || (state == NEGATE))) {
-               nsp32_msg(KERN_ERR, "unknown state designation");
+       nsp32_dbg(NSP32_DEBUG_BUSRESET, "in");
+
+       /*
+        * stop all transfer
+        * clear TRANSFERCONTROL_BM_START
+        * clear counter
+        */
+       nsp32_write2(base, TRANSFER_CONTROL, 0);
+       nsp32_write4(base, BM_CNT,           0);
+       nsp32_write4(base, CLR_COUNTER,      CLRCOUNTER_ALLMASK);
+
+       /*
+        * fall back to asynchronous transfer mode
+        * initialize SDTR negotiation flag
+        */
+       for (i = 0; i < NUMBER(data->target); i++) {
+               nsp32_target *target = &data->target[i];
+
+               target->sync_flag = 0;
+               nsp32_set_async(data, target);
        }
-       state <<= 4; /* ACK is BIT(4) */
 
-       do {
-               bus = nsp32_read1(base, SCSI_BUS_MONITOR);
-               if ((bus & BUSMON_ACK) == state) {
-                       nsp32_dbg(NSP32_DEBUG_WAIT,
-                                 "wait_time: %d", wait_time);
-                       return;
-               }
-               udelay(1);
-               wait_time++;
-       } while (wait_time < REQSACK_TIMEOUT_TIME);
+       /*
+        * reset SCSI bus
+        */
+       nsp32_write1(base, SCSI_BUS_CONTROL, BUSCTL_RST);
+       udelay(RESET_HOLD_TIME);
+       nsp32_write1(base, SCSI_BUS_CONTROL, 0);
+       for(i = 0; i < 5; i++) {
+               intrdat = nsp32_read2(base, IRQ_STATUS); /* dummy read */
+               nsp32_dbg(NSP32_DEBUG_BUSRESET, "irq:1: 0x%x", intrdat);
+        }
 
-       nsp32_msg(KERN_WARNING, "wait SACK timeout, state: %d", state);
+       data->CurrentSC = NULL;
 }
 
-/*
- * assert SCSI ACK
- *
- * Note: SCSI ACK assertion needs with ACKENB=1, AUTODIRECTION=1.
- */
-static void nsp32_sack_assert(nsp32_hw_data *data)
+static int nsp32_eh_host_reset(Scsi_Cmnd *SCpnt)
 {
-       unsigned char busctrl;
-       unsigned int base = data->BaseAddress;
+       struct Scsi_Host *host = SCpnt->device->host;
+       unsigned int      base = SCpnt->device->host->io_port;
+       nsp32_hw_data    *data = (nsp32_hw_data *)host->hostdata;
 
-       busctrl  = nsp32_read1(base, SCSI_BUS_CONTROL);
-       busctrl |= (BUSCTL_ACK | AUTODIRECTION | ACKENB);
-       nsp32_write1(base, SCSI_BUS_CONTROL,busctrl);
-}
+       nsp32_msg(KERN_INFO, "Host Reset");     
+       nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%x", SCpnt);
 
-/*
- * negate SCSI ACK
- */
-static void nsp32_sack_negate(nsp32_hw_data *data)
-{
-       unsigned char busctrl;
-       unsigned int base = data->BaseAddress;
+       nsp32hw_init(data);
+       nsp32_write2(base, IRQ_CONTROL, IRQ_CONTROL_ALL_IRQ_MASK);
+       nsp32_do_bus_reset(data);
+       nsp32_write2(base, IRQ_CONTROL, 0);
 
-       busctrl  = nsp32_read1(base, SCSI_BUS_CONTROL);
-       busctrl &= ~BUSCTL_ACK;
-       nsp32_write1(base, SCSI_BUS_CONTROL, busctrl);
+       return SUCCESS; /* Host reset is succeeded at any time. */
 }
 
 
+/**************************************************************************
+ * EEPROM handler
+ */
 
 /*
  * getting EEPROM parameter
@@ -3106,12 +3079,12 @@ static int nsp32_getprom_param(nsp32_hw_data *data)
        ret = nsp32_prom_read(data, 0x7e);
        if (ret != 0x55) {
                nsp32_msg(KERN_INFO, "No EEPROM detected: 0x%x", ret);
-               return (FALSE);
+               return FALSE;
        }
        ret = nsp32_prom_read(data, 0x7f);
        if (ret != 0xaa) {
                nsp32_msg(KERN_INFO, "Invalid number: 0x%x", ret);
-               return (FALSE);
+               return FALSE;
        }
 
        /*
@@ -3119,26 +3092,26 @@ static int nsp32_getprom_param(nsp32_hw_data *data)
         */
        if (vendor == PCI_VENDOR_ID_WORKBIT &&
            device == PCI_DEVICE_ID_WORKBIT_STANDARD) {
-               ret = nsp32_getprom_standard(data);
+               ret = nsp32_getprom_c16(data);
        } else if (vendor == PCI_VENDOR_ID_WORKBIT &&
                   device == PCI_DEVICE_ID_NINJASCSI_32BIB_LOGITEC) {
-               ret = nsp32_getprom_new(data);
+               ret = nsp32_getprom_at24(data);
        } else if (vendor == PCI_VENDOR_ID_WORKBIT &&
                   device == PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO ) {
-               ret = nsp32_getprom_new(data);
+               ret = nsp32_getprom_at24(data);
        } else {
                nsp32_msg(KERN_WARNING, "Unknown EEPROM");
                ret = FALSE;
        }
 
        /* for debug : SPROM data full checking */
-       for (i=0; i<=0x1f; i++) {
+       for (i = 0; i <= 0x1f; i++) {
                val = nsp32_prom_read(data, i);
                nsp32_dbg(NSP32_DEBUG_EEPROM,
                          "rom address 0x%x : 0x%x", i, val);
        }
 
-       return (ret);
+       return ret;
 }
 
 
@@ -3166,15 +3139,15 @@ static int nsp32_getprom_param(nsp32_hw_data *data)
  *   0x1c        :  Constant? (0x01) (clock div?)
  *   0x1d - 0x7c :  Not Used (0xff)
  *   0x7d       :  Not Used? (0xff)
- *   0x7e        :  Constant (0x55), HBA chip revision
- *   0x7f        :  Constant (0xaa), HBA value
+ *   0x7e        :  Constant (0x55), Validity signature
+ *   0x7f        :  Constant (0xaa), Validity signature
  */
-static int nsp32_getprom_new(nsp32_hw_data *data)
+static int nsp32_getprom_at24(nsp32_hw_data *data)
 {
-       int ret, i;
-       int auto_sync;
-       struct nsp32_target *target;
-       int entry;
+       int           ret, i;
+       int           auto_sync;
+       nsp32_target *target;
+       int           entry;
 
        /*
         * Reset time which is designated by EEPROM.
@@ -3206,8 +3179,7 @@ static int nsp32_getprom_new(nsp32_hw_data *data)
                break;
        default:
                nsp32_msg(KERN_WARNING,
-                         "Unsupported Auto Sync mode."
-                         "Fall back to manual mode.");
+                         "Unsupported Auto Sync mode. Fall back to manual mode.");
                auto_sync = TRUE;
        }
 
@@ -3218,12 +3190,12 @@ static int nsp32_getprom_new(nsp32_hw_data *data)
        /*
         * each device Synchronous Transfer Period
         */
-       for (i=0; i<NSP32_HOST_SCSIID; i++) {
+       for (i = 0; i < NSP32_HOST_SCSIID; i++) {
                target = &data->target[i];
                if (auto_sync == TRUE) {
                        target->limit_entry = 0;   /* set as ULTRA20M */
                } else {
-                       ret = nsp32_prom_read(data, i);
+                       ret   = nsp32_prom_read(data, i);
                        entry = nsp32_search_period_entry(data, target, ret);
                        if (entry < 0) {
                                /* search failed... set maximum speed */
@@ -3233,12 +3205,12 @@ static int nsp32_getprom_new(nsp32_hw_data *data)
                }
        }
 
-       return (TRUE);
+       return TRUE;
 }
 
 
 /*
- * ? (I-O Data: SC-NBD) data map:
+ * C16 110 (I-O Data: SC-NBD) data map:
  *
  *   ROMADDR
  *   0x00 - 0x06 :  Device Synchronous Transfer Period (SCSI ID 0 - 6) 
@@ -3254,14 +3226,14 @@ static int nsp32_getprom_new(nsp32_hw_data *data)
  *                     Value 0: Disable, 1: Enable
  *   0x1a - 0x7c :  Not Used? (0)
  *   0x7d       :  Not Used? (0xf8)
- *   0x7e        :  Constant (0x55), HBA chip revision
- *   0x7f        :  Constant (0xaa), HBA value
+ *   0x7e        :  Constant (0x55), Validity signature
+ *   0x7f        :  Constant (0xaa), Validity signature
  */
-static int nsp32_getprom_standard(nsp32_hw_data *data)
+static int nsp32_getprom_c16(nsp32_hw_data *data)
 {
-       int ret, i;
-       struct nsp32_target *target;
-       int entry, val;
+       int           ret, i;
+       nsp32_target *target;
+       int           entry, val;
 
        /*
         * Reset time which is designated by EEPROM.
@@ -3273,7 +3245,7 @@ static int nsp32_getprom_standard(nsp32_hw_data *data)
        /*
         * each device Synchronous Transfer Period
         */
-       for (i=0; i<NSP32_HOST_SCSIID; i++) {
+       for (i = 0; i < NSP32_HOST_SCSIID; i++) {
                target = &data->target[i];
                ret = nsp32_prom_read(data, i);
                switch (ret) {
@@ -3287,10 +3259,11 @@ static int nsp32_getprom_standard(nsp32_hw_data *data)
                        val = 0x32;
                        break;
                case 3:         /* ASYNC */
-                       val = 0x0;
+                       val = 0x00;
                        break;
                default:        /* default 20MB/s */
                        val = 0x0c;
+                       break;
                }
                entry = nsp32_search_period_entry(data, target, val);
                if (entry < 0 || trans_mode == ULTRA20M_MODE) {
@@ -3300,7 +3273,7 @@ static int nsp32_getprom_standard(nsp32_hw_data *data)
                target->limit_entry = entry;
        }
 
-       return (TRUE);
+       return TRUE;
 }
 
 
@@ -3315,59 +3288,59 @@ static int nsp32_prom_read(nsp32_hw_data *data, int romaddr)
        nsp32_prom_start(data);
 
        /* device address */
-       nsp32_prom_write(data, 1);      /* 1 */
-       nsp32_prom_write(data, 0);      /* 0 */
-       nsp32_prom_write(data, 1);      /* 1 */
-       nsp32_prom_write(data, 0);      /* 0 */
-       nsp32_prom_write(data, 0);      /* A2: 0 (GND) */
-       nsp32_prom_write(data, 0);      /* A1: 0 (GND) */
-       nsp32_prom_write(data, 0);      /* A0: 0 (GND) */
+       nsp32_prom_write_bit(data, 1);  /* 1 */
+       nsp32_prom_write_bit(data, 0);  /* 0 */
+       nsp32_prom_write_bit(data, 1);  /* 1 */
+       nsp32_prom_write_bit(data, 0);  /* 0 */
+       nsp32_prom_write_bit(data, 0);  /* A2: 0 (GND) */
+       nsp32_prom_write_bit(data, 0);  /* A1: 0 (GND) */
+       nsp32_prom_write_bit(data, 0);  /* A0: 0 (GND) */
 
        /* R/W: W for dummy write */
-       nsp32_prom_write(data, 0);
+       nsp32_prom_write_bit(data, 0);
 
        /* ack */
-       nsp32_prom_write(data, 0);
+       nsp32_prom_write_bit(data, 0);
 
        /* word address */
-       for (i=7; i>=0; i--) {
-               nsp32_prom_write(data, ((romaddr >> i) & 1));
+       for (i = 7; i >= 0; i--) {
+               nsp32_prom_write_bit(data, ((romaddr >> i) & 1));
        }
 
        /* ack */
-       nsp32_prom_write(data, 0);
+       nsp32_prom_write_bit(data, 0);
 
        /* start condition */
        nsp32_prom_start(data);
 
        /* device address */
-       nsp32_prom_write(data, 1);      /* 1 */
-       nsp32_prom_write(data, 0);      /* 0 */
-       nsp32_prom_write(data, 1);      /* 1 */
-       nsp32_prom_write(data, 0);      /* 0 */
-       nsp32_prom_write(data, 0);      /* A2: 0 (GND) */
-       nsp32_prom_write(data, 0);      /* A1: 0 (GND) */
-       nsp32_prom_write(data, 0);      /* A0: 0 (GND) */
+       nsp32_prom_write_bit(data, 1);  /* 1 */
+       nsp32_prom_write_bit(data, 0);  /* 0 */
+       nsp32_prom_write_bit(data, 1);  /* 1 */
+       nsp32_prom_write_bit(data, 0);  /* 0 */
+       nsp32_prom_write_bit(data, 0);  /* A2: 0 (GND) */
+       nsp32_prom_write_bit(data, 0);  /* A1: 0 (GND) */
+       nsp32_prom_write_bit(data, 0);  /* A0: 0 (GND) */
 
        /* R/W: R */
-       nsp32_prom_write(data, 1);
+       nsp32_prom_write_bit(data, 1);
 
        /* ack */
-       nsp32_prom_write(data, 0);
+       nsp32_prom_write_bit(data, 0);
 
        /* data... */
        val = 0;
-       for (i=7; i>=0; i--) {
-               val += (nsp32_prom_fetch(data) << i);
+       for (i = 7; i >= 0; i--) {
+               val += (nsp32_prom_read_bit(data) << i);
        }
        
        /* no ack */
-       nsp32_prom_write(data, 1);
+       nsp32_prom_write_bit(data, 1);
 
        /* stop condition */
        nsp32_prom_stop(data);
 
-       return (val);
+       return val;
 }
 
 static void nsp32_prom_start (nsp32_hw_data *data)
@@ -3391,69 +3364,236 @@ static void nsp32_prom_stop (nsp32_hw_data *data)
        nsp32_prom_set(data, SCL, 0);
 }
 
-static void nsp32_prom_write (nsp32_hw_data *data, int val)
+static void nsp32_prom_write_bit(nsp32_hw_data *data, int val)
 {
        /* write */
        nsp32_prom_set(data, SDA, val);
-       nsp32_prom_set(data, SCL, 1);
-       nsp32_prom_set(data, SCL, 0);
+       nsp32_prom_set(data, SCL, 1  );
+       nsp32_prom_set(data, SCL, 0  );
 }
 
-static int nsp32_prom_fetch (nsp32_hw_data *data)
+static int nsp32_prom_read_bit(nsp32_hw_data *data)
 {
        int val;
 
        /* read */
        nsp32_prom_set(data, ENA, 0);   /* input mode */
        nsp32_prom_set(data, SCL, 1);
+
        val = nsp32_prom_get(data, SDA);
+
        nsp32_prom_set(data, SCL, 0);
        nsp32_prom_set(data, ENA, 1);   /* output mode */
-       return (val);
+
+       return val;
 }
 
 static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val)
 {
-       int cur;
        int base = data->BaseAddress;
+       int tmp;
 
-       switch(val) {
-       case 0:
-               cur = nsp32_index_read1(base, SERIAL_ROM_CTL);
-               nsp32_index_write1(base, SERIAL_ROM_CTL, cur & ~bit);
-               break;
-       case 1:
-               cur = nsp32_index_read1(base, SERIAL_ROM_CTL);
-               nsp32_index_write1(base, SERIAL_ROM_CTL, cur | bit);
-               break;
-       default:
-               nsp32_msg(KERN_ERR, "val must be 0 or 1");
-               return;
+       tmp = nsp32_index_read1(base, SERIAL_ROM_CTL);
+
+       if (val == 0) {
+               tmp &= ~bit;
+       } else {
+               tmp |=  bit;
        }
 
+       nsp32_index_write1(base, SERIAL_ROM_CTL, tmp);
+
        udelay(10);
 }
 
 static inline int nsp32_prom_get(nsp32_hw_data *data, int bit)
 {
-       int ret;
        int base = data->BaseAddress;
+       int tmp, ret;
 
-       ret = nsp32_index_read1(base, SERIAL_ROM_CTL) & bit;
-       switch (ret) {
-       case 0:
+       if (bit != SDA) {
+               nsp32_msg(KERN_ERR, "return value is not appropriate");
+               return 0;
+       }
+
+
+       tmp = nsp32_index_read1(base, SERIAL_ROM_CTL) & bit;
+
+       if (tmp == 0) {
                ret = 0;
-               break;
-       case SDA:
+       } else {
                ret = 1;
-               break;
-       default:
-               nsp32_msg(KERN_ERR, "return value is not appropriate");
        }
 
        udelay(10);
 
-       return (ret);
+       return ret;
+}
+
+
+/**************************************************************************
+ * Power Management
+ */
+#ifdef CONFIG_PM
+/* Save Device Context */
+static int nsp32_save_state(struct pci_dev *pdev, u32 state)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+
+       nsp32_msg(KERN_INFO, "pci-save_state: stub, pdev=0x%p, state=%ld, slot=%s, host=0x%p", pdev, state, pci_name(pdev), host);
+
+       return 0;
+}
+
+/* Device suspended */
+static int nsp32_suspend(struct pci_dev *pdev, u32 state)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+       nsp32_hw_data    *data = (nsp32_hw_data *)host->hostdata;
+
+       nsp32_msg(KERN_INFO, "pci-suspend: pdev=0x%p, state=%ld, slot=%s, host=0x%p", pdev, state, pci_name(pdev), host);
+
+       pci_save_state     (pdev, data->PciState);
+       pci_disable_device (pdev);
+       pci_set_power_state(pdev, state);
+
+       return 0;
+}
+
+/* Device woken up */
+static int nsp32_resume(struct pci_dev *pdev)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+       nsp32_hw_data    *data = (nsp32_hw_data *)host->hostdata;
+       unsigned short    reg;
+
+       nsp32_msg(KERN_INFO, "pci-resume: pdev=0x%p, slot=%s, host=0x%p", pdev, pci_name(pdev), host);
+
+       pci_set_power_state(pdev, 0);
+       pci_enable_wake    (pdev, 0, 0);
+       pci_restore_state  (pdev, data->PciState);
+
+       reg = nsp32_read2(data->BaseAddress, INDEX_REG);
+
+       nsp32_msg(KERN_INFO, "io=0x%x reg=0x%x", data->BaseAddress, reg);
+
+       if (reg == 0xffff) {
+               nsp32_msg(KERN_INFO, "missing device. abort resume.");
+               return 0;
+       }
+
+       nsp32hw_init      (data);
+       nsp32_do_bus_reset(data);
+
+       nsp32_msg(KERN_INFO, "resume success");
+
+       return 0;
+}
+
+/* Enable wake event */
+static int nsp32_enable_wake(struct pci_dev *pdev, u32 state, int enable)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+
+       nsp32_msg(KERN_INFO, "pci-enable_wake: stub, pdev=0x%p, enable=%d, slot=%s, host=0x%p", pdev, enable, pci_name(pdev), host);
+
+       return 0;
+}
+#endif
+
+/************************************************************************
+ * PCI/Cardbus probe/remove routine
+ */
+static int __devinit nsp32_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       int ret;
+       nsp32_hw_data *data = &nsp32_data_base;
+
+       nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
+
+        ret = pci_enable_device(pdev);
+       if (ret) {
+               nsp32_msg(KERN_ERR, "failed to enable pci device");
+               return ret;
+       }
+
+       data->Pci         = pdev;
+       data->pci_devid   = id;
+       data->IrqNumber   = pdev->irq;
+       data->BaseAddress = pci_resource_start(pdev, 0);
+       data->NumAddress  = pci_resource_len  (pdev, 0);
+       data->MmioAddress = 
+               (unsigned long)ioremap_nocache(pci_resource_start(pdev, 1),
+                                              pci_resource_len  (pdev, 1));
+       data->MmioLength  = pci_resource_len  (pdev, 1);
+
+       pci_set_master(pdev);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+       ret = nsp32_detect(pdev);
+#else
+       ret = scsi_register_host(&nsp32_template);
+#endif
+
+       nsp32_msg(KERN_INFO, "irq: %i mmio: 0x%lx+0x%lx slot: %s model: %s",
+                 pdev->irq,
+                 data->MmioAddress, data->MmioLength,
+                 pci_name(pdev),
+                 nsp32_model[id->driver_data]);
+
+       nsp32_dbg(NSP32_DEBUG_REGISTER, "exit %d", ret);
+
+       return ret;
 }
 
+static void __devexit nsp32_remove(struct pci_dev *pdev)
+{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+#endif
+
+       nsp32_dbg(NSP32_DEBUG_REGISTER, "enter");
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
+        scsi_remove_host(host);
+
+       nsp32_release(host);
+
+       scsi_host_put(host);
+#else
+       scsi_unregister_host(&nsp32_template);  
+#endif
+}
+
+
+
+static struct pci_driver nsp32_driver = {
+       .name           = "nsp32",
+       .id_table       = nsp32_pci_table,
+       .probe          = nsp32_probe,
+       .remove         = __devexit_p(nsp32_remove),
+#ifdef CONFIG_PM
+       .save_state     = nsp32_save_state,
+       .suspend        = nsp32_suspend, 
+       .resume         = nsp32_resume, 
+       .enable_wake    = nsp32_enable_wake,
+#endif
+};
+
+/*********************************************************************
+ * Moule entry point
+ */
+static int __init init_nsp32(void) {
+       nsp32_msg(KERN_INFO, "loading...");
+       return pci_module_init(&nsp32_driver);
+}
+
+static void __exit exit_nsp32(void) {
+       nsp32_msg(KERN_INFO, "unloading...");
+       pci_unregister_driver(&nsp32_driver);
+}
+
+module_init(init_nsp32);
+module_exit(exit_nsp32);
+
 /* end */
index c1b707daafaacfcd9bdae334683d90f146ee9006..aead2f757f0df39ae094fe4e21e121bd44ec0748 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Workbit NinjaSCSI-32Bi/UDE PCI/Cardbus SCSI Host Bus Adapter driver
+ * Workbit NinjaSCSI-32Bi/UDE PCI/CardBus SCSI Host Bus Adapter driver
  * Basic data header
  *
  * This program is free software; you can redistribute it and/or modify
 #ifndef _NSP32_H
 #define _NSP32_H
 
-
 //#define NSP32_DEBUG 9
 
-
 /*
  * VENDOR/DEVICE ID
  */
 #define PCI_VENDOR_ID_IODATA  0x10fc
 #define PCI_VENDOR_ID_WORKBIT 0x1145
 
-#define PCI_DEVICE_ID_NINJASCSI_32BI_CBSC_II  0x0005
-#define PCI_DEVICE_ID_NINJASCSI_32BI_KME      0xf007
-#define PCI_DEVICE_ID_NINJASCSI_32BI_WBT      0x8007
-#define PCI_DEVICE_ID_WORKBIT_STANDARD        0xf010
-#define PCI_DEVICE_ID_WORKBIT_DUALEDGE        0xf011
-#define PCI_DEVICE_ID_NINJASCSI_32BI_LOGITEC  0xf012
-#define PCI_DEVICE_ID_NINJASCSI_32BIB_LOGITEC 0xf013
-#define PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO   0xf015
+#define PCI_DEVICE_ID_NINJASCSI_32BI_CBSC_II   0x0005
+#define PCI_DEVICE_ID_NINJASCSI_32BI_KME       0xf007
+#define PCI_DEVICE_ID_NINJASCSI_32BI_WBT       0x8007
+#define PCI_DEVICE_ID_WORKBIT_STANDARD         0xf010
+#define PCI_DEVICE_ID_WORKBIT_DUALEDGE         0xf011
+#define PCI_DEVICE_ID_NINJASCSI_32BI_LOGITEC   0xf012
+#define PCI_DEVICE_ID_NINJASCSI_32BIB_LOGITEC  0xf013
+#define PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO    0xf015
+#define PCI_DEVICE_ID_NINJASCSI_32UDE_MELCO_II 0x8009
 
 /*
  * MODEL
@@ -42,20 +41,20 @@ enum {
        MODEL_IODATA        = 0,
        MODEL_KME           = 1,
        MODEL_WORKBIT       = 2,
-       MODEL_EXT_ROM       = 3,
+       MODEL_LOGITEC       = 3,
        MODEL_PCI_WORKBIT   = 4,
        MODEL_PCI_LOGITEC   = 5,
        MODEL_PCI_MELCO     = 6,
 };
 
 static char * nsp32_model[] = {
-       "I-O DATA CBSC-II",
-       "KME SCSI card",
-       "Workbit duo SCSI card",
-       "External ROM",
-       "Workbit Standard/IO Data PCI card",
-       "Logitec PCI card",
-       "Melco PCI card",
+       "I-O DATA CBSC-II CardBus card",
+       "KME SCSI CardBus card",
+       "Workbit duo SCSI CardBus card",
+       "Logitec CardBus card with external ROM",
+       "Workbit / I-O DATA PCI card",
+       "Logitec PCI card with external ROM",
+       "Melco CardBus/PCI card with external ROM",
 };
 
 
@@ -64,13 +63,17 @@ static char * nsp32_model[] = {
  */
 #define EXTENDED_SDTR_LEN      0x03
 
+/* Little Endian */
+typedef u32 u32_le;
+typedef u16 u16_le;
 
 /*
  * MACRO
  */
-#define BIT(x)    (1UL << (x))
+#define NUMBER(arr) ((int) (sizeof(arr) / sizeof(arr[0])))
+#define BIT(x)      (1UL << (x))
 #ifndef MIN
-# define MIN(a,b)  ((a) > (b) ? (b) : (a))
+# define MIN(a,b)   ((a) > (b) ? (b) : (a))
 #endif
 
 /*
@@ -111,7 +114,10 @@ static char * nsp32_model[] = {
 # define TIMER_IRQ_MASK             BIT(13)
 # define FIFO_IRQ_MASK              BIT(14)
 # define SCSI_IRQ_MASK              BIT(15)
-# define IRQ_CONTROL_ALL_IRQ_MASK   0xf000
+# define IRQ_CONTROL_ALL_IRQ_MASK   (PCI_IRQ_MASK   | \
+                                     TIMER_IRQ_MASK | \
+                                     FIFO_IRQ_MASK  | \
+                                     SCSI_IRQ_MASK  )
 # define IRQSTATUS_ANY_IRQ          (IRQSTATUS_RESELECT_OCCUER | \
                                     IRQSTATUS_PHASE_CHANGE_IRQ | \
                                     IRQSTATUS_SCSIRESET_IRQ    | \
@@ -121,8 +127,8 @@ static char * nsp32_model[] = {
                                     IRQSTATUS_BMCNTERR_IRQ     | \
                                     IRQSTATUS_AUTOSCSI_IRQ     )
 
-#define TRANSFER_CONTROL 0x02  /* BASE+02, W, W */
-#define TRANSFER_STATUS  0x02  /* BASE+02, W, R */
+#define TRANSFER_CONTROL       0x02    /* BASE+02, W, W */
+#define TRANSFER_STATUS                0x02    /* BASE+02, W, R */
 # define CB_MMIO_MODE        BIT(0)
 # define CB_IO_MODE          BIT(1)
 # define BM_TEST             BIT(2)
@@ -139,26 +145,29 @@ static char * nsp32_model[] = {
 # define ALL_COUNTER_CLR     BIT(14)
 # define FIFOTEST            BIT(15)
 
-#define INDEX_REG 0x04         /* BASE+04, Byte(R/W), Word(R) */
+#define INDEX_REG              0x04    /* BASE+04, Byte(R/W), Word(R) */
 
-#define TIMER_SET 0x06         /* BASE+06, W, R/W */
-# define TIMER_CNT_MASK 0xff
+#define TIMER_SET              0x06    /* BASE+06, W, R/W */
+# define TIMER_CNT_MASK (0xff)
 # define TIMER_STOP     BIT(8)
 
-#define DATA_REG_LOW 0x08      /* BASE+08, LowW, R/W */
-#define DATA_REG_HI  0x0a      /* BASE+0a, Hi-W, R/W */
+#define DATA_REG_LOW           0x08    /* BASE+08, LowW, R/W */
+#define DATA_REG_HI            0x0a    /* BASE+0a, Hi-W, R/W */
 
-#define FIFO_REST_CNT 0x0c     /* BASE+0c, W, R/W */
+#define FIFO_REST_CNT          0x0c    /* BASE+0c, W, R/W */
 # define FIFO_REST_MASK       0x1ff
 # define FIFO_EMPTY_SHLD_FLAG BIT(14)
 # define FIFO_FULL_SHLD_FLAG  BIT(15)
 
-#define SREQ_SMPL_RATE 0x0f    /* BASE+0f, B, R/W */
+#define SREQ_SMPL_RATE         0x0f    /* BASE+0f, B, R/W */
 # define SREQSMPLRATE_RATE0 BIT(0)
 # define SREQSMPLRATE_RATE1 BIT(1)
 # define SAMPLING_ENABLE    BIT(2)
+#  define SMPL_40M (0)                   /* 40MHz:   0-100ns/period */
+#  define SMPL_20M (SREQSMPLRATE_RATE0)  /* 20MHz: 100-200ns/period */
+#  define SMPL_10M (SREQSMPLRATE_RATE1)  /* 10Mhz: 200-   ns/period */
 
-#define SCSI_BUS_CONTROL 0x10  /* BASE+10, B, R/W */
+#define SCSI_BUS_CONTROL       0x10    /* BASE+10, B, R/W */
 # define BUSCTL_SEL         BIT(0)
 # define BUSCTL_RST         BIT(1)
 # define BUSCTL_DATAOUT_ENB BIT(2)
@@ -168,16 +177,21 @@ static char * nsp32_model[] = {
 # define AUTODIRECTION      BIT(6)
 # define ACKENB             BIT(7)
 
-#define CLR_COUNTER 0x12       /* BASE+12, B, W */
+#define CLR_COUNTER            0x12    /* BASE+12, B, W */
 # define ACK_COUNTER_CLR       BIT(0)
 # define SREQ_COUNTER_CLR      BIT(1)
 # define FIFO_HOST_POINTER_CLR BIT(2)
 # define FIFO_REST_COUNT_CLR   BIT(3)
 # define BM_COUNTER_CLR        BIT(4)
 # define SAVED_ACK_CLR         BIT(5)
-# define CLRCOUNTER_ALLMASK    (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5))
-
-#define SCSI_BUS_MONITOR 0x12  /* BASE+12, B, R */
+# define CLRCOUNTER_ALLMASK    (ACK_COUNTER_CLR       | \
+                                SREQ_COUNTER_CLR      | \
+                                FIFO_HOST_POINTER_CLR | \
+                                FIFO_REST_COUNT_CLR   | \
+                                BM_COUNTER_CLR        | \
+                                SAVED_ACK_CLR         )
+
+#define SCSI_BUS_MONITOR       0x12    /* BASE+12, B, R */
 # define BUSMON_MSG BIT(0)
 # define BUSMON_IO  BIT(1)
 # define BUSMON_CD  BIT(2)
@@ -187,20 +201,20 @@ static char * nsp32_model[] = {
 # define BUSMON_SEL BIT(6)
 # define BUSMON_ATN BIT(7)
 
-#define COMMAND_DATA 0x14      /* BASE+14, B, R/W */
+#define COMMAND_DATA           0x14    /* BASE+14, B, R/W */
 
-#define PARITY_CONTROL 0x16    /* BASE+16, B, R/W */
+#define PARITY_CONTROL         0x16    /* BASE+16, B, W */
 # define PARITY_CHECK_ENABLE BIT(0)
 # define PARITY_ERROR_CLEAR  BIT(1)
-#define PARITY_STATUS  0x16
+#define PARITY_STATUS          0x16    /* BASE+16, B, R */
 //# define PARITY_CHECK_ENABLE BIT(0)
 # define PARITY_ERROR_NORMAL BIT(1)
 # define PARITY_ERROR_LSB    BIT(1)
 # define PARITY_ERROR_MSB    BIT(2)
 
-#define RESELECT_ID 0x18       /* BASE+18, B, R */
+#define RESELECT_ID            0x18    /* BASE+18, B, R */
 
-#define COMMAND_CONTROL 0x18   /* BASE+18, W, W */
+#define COMMAND_CONTROL                0x18    /* BASE+18, W, W */
 # define CLEAR_CDB_FIFO_POINTER BIT(0)
 # define AUTO_COMMAND_PHASE     BIT(1)
 # define AUTOSCSI_START         BIT(2)
@@ -211,27 +225,27 @@ static char * nsp32_model[] = {
 # define AUTO_MSGIN_02          BIT(7)
 # define AUTO_MSGIN_03          BIT(8)
 
-#define SET_ARBIT 0x1a         /* BASE+1a, B, W */
+#define SET_ARBIT              0x1a    /* BASE+1a, B, W */
 # define ARBIT_GO    BIT(0)
 # define ARBIT_CLEAR BIT(1)
 
-#define ARBIT_STATUS 0x1a      /* BASE+1a, B, R */
+#define ARBIT_STATUS           0x1a    /* BASE+1a, B, R */
 //# define ARBIT_GO             BIT(0)
 # define ARBIT_WIN            BIT(1)
 # define ARBIT_FAIL           BIT(2)
 # define AUTO_PARAMETER_VALID BIT(3)
 # define SGT_VALID            BIT(4)
 
-#define SYNC_REG 0x1c  /* BASE+1c, B, R/W */
+#define SYNC_REG               0x1c    /* BASE+1c, B, R/W */
 
-#define ACK_WIDTH 0x1d /* BASE+1d, B, R/W */
+#define ACK_WIDTH              0x1d    /* BASE+1d, B, R/W */
 
-#define SCSI_DATA_WITH_ACK 0x20        /* BASE+20, B, R/W */
+#define SCSI_DATA_WITH_ACK     0x20    /* BASE+20, B, R/W */
 #define SCSI_OUT_LATCH_TARGET_ID 0x22  /* BASE+22, B, W */
-#define SCSI_DATA_IN 0x22      /* BASE+22, B, R */
+#define SCSI_DATA_IN           0x22    /* BASE+22, B, R */
 
-#define SCAM_CONTROL 0x24      /* BASE+24, B, W */
-#define SCAM_STATUS  0x24      /* BASE+24, B, R */
+#define SCAM_CONTROL           0x24    /* BASE+24, B, W */
+#define SCAM_STATUS            0x24    /* BASE+24, B, R */
 # define SCAM_MSG    BIT(0)
 # define SCAM_IO     BIT(1)
 # define SCAM_CD     BIT(2)
@@ -239,31 +253,31 @@ static char * nsp32_model[] = {
 # define SCAM_SEL    BIT(4)
 # define SCAM_XFEROK BIT(5)
 
-#define SCAM_DATA 0x26 /* BASE+26, B, R/W */
-# define SD0                                   BIT(0)
-# define SD1                                   BIT(1)
-# define SD2                                   BIT(2)
-# define SD3                                   BIT(3)
-# define SD4                                   BIT(4)
-# define SD5                                   BIT(5)
-# define SD6                                   BIT(6)
-# define SD7                                   BIT(7)
+#define SCAM_DATA              0x26    /* BASE+26, B, R/W */
+# define SD0   BIT(0)
+# define SD1   BIT(1)
+# define SD2   BIT(2)
+# define SD3   BIT(3)
+# define SD4   BIT(4)
+# define SD5   BIT(5)
+# define SD6   BIT(6)
+# define SD7   BIT(7)
 
-#define SACK_CNT 0x28  /* BASE+28, DW, R/W */
-#define SREQ_CNT 0x2c  /* BASE+2c, DW, R/W */
+#define SACK_CNT               0x28    /* BASE+28, DW, R/W */
+#define SREQ_CNT               0x2c    /* BASE+2c, DW, R/W */
 
-#define FIFO_DATA_LOW 0x30     /* BASE+30, B/W/DW, R/W */
-#define FIFO_DATA_HIGH 0x32    /* BASE+32, B/W, R/W */
-#define BM_START_ADR 0x34      /* BASE+34, DW, R/W */
+#define FIFO_DATA_LOW          0x30    /* BASE+30, B/W/DW, R/W */
+#define FIFO_DATA_HIGH         0x32    /* BASE+32, B/W, R/W */
+#define BM_START_ADR           0x34    /* BASE+34, DW, R/W */
 
-#define BM_CNT 0x38    /* BASE+38, DW, R/W */
-# define BM_COUNT_MASK 0x0001ffff
-# define SGTEND        BIT(31)
+#define BM_CNT                 0x38    /* BASE+38, DW, R/W */
+# define BM_COUNT_MASK 0x0001ffffUL
+# define SGTEND        BIT(31)      /* Last SGT marker */
 
-#define SGT_ADR 0x3c   /* BASE+3c, DW, R/W */
-#define WAIT_REG 0x40  /* Bi only */
+#define SGT_ADR                        0x3c    /* BASE+3c, DW, R/W */
+#define WAIT_REG               0x40    /* Bi only */
 
-#define SCSI_EXECUTE_PHASE 0x40        /* BASE+40, W, R */
+#define SCSI_EXECUTE_PHASE     0x40    /* BASE+40, W, R */
 # define COMMAND_PHASE     BIT(0)
 # define DATA_IN_PHASE     BIT(1)
 # define DATA_OUT_PHASE    BIT(2)
@@ -280,14 +294,14 @@ static char * nsp32_model[] = {
 # define MSGIN_04_VALID    BIT(13)
 # define AUTOSCSI_BUSY     BIT(15)
 
-#define SCSI_CSB_IN 0x42       /* BASE+42, B, R */
+#define SCSI_CSB_IN            0x42    /* BASE+42, B, R */
 
-#define SCSI_MSG_OUT 0x44      /* BASE+44, DW, R/W */
+#define SCSI_MSG_OUT           0x44    /* BASE+44, DW, R/W */
 # define MSGOUT_COUNT_MASK (BIT(0)|BIT(1))
-# define MV_VALID            BIT(7)
+# define MV_VALID          BIT(7)
 
-#define SEL_TIME_OUT 0x48      /* BASE+48, W, R/W */
-#define SAVED_SACK_CNT 0x4c    /* BASE+4c, DW, R */
+#define SEL_TIME_OUT           0x48    /* BASE+48, W, R/W */
+#define SAVED_SACK_CNT         0x4c    /* BASE+4c, DW, R */
 
 #define HTOSDATADELAY          0x50    /* BASE+50, B, R/W */
 #define STOHDATADELAY          0x54    /* BASE+54, B, R/W */
@@ -299,21 +313,21 @@ static char * nsp32_model[] = {
 /* indexed register */
 /********************/
 
-#define CLOCK_DIV 0x00 /* BASE+08, IDX+00, B, R/W */
-# define CLOCK_2               BIT(0)  /* MCLK/2 */
-# define CLOCK_4               BIT(1)  /* MCLK/4 */
-# define PCICLK                        BIT(7)  /* PCICLK (33MHz) */
+#define CLOCK_DIV              0x00    /* BASE+08, IDX+00, B, R/W */
+# define CLOCK_2  BIT(0)       /* MCLK/2 */
+# define CLOCK_4  BIT(1)       /* MCLK/4 */
+# define PCICLK          BIT(7)        /* PCICLK (33MHz) */
 
-#define TERM_PWR_CONTROL 0x01  /* BASE+08, IDX+01, B, R/W */
+#define TERM_PWR_CONTROL       0x01    /* BASE+08, IDX+01, B, R/W */
 # define BPWR  BIT(0)
 # define SENSE BIT(1)  /* Read Only */
 
-#define EXT_PORT_DDR 0x02      /* BASE+08, IDX+02, B, R/W */
-#define EXT_PORT     0x03      /* BASE+08, IDX+03, B, R/W */
-# define LED_ON         0
-# define LED_OFF 1
+#define EXT_PORT_DDR           0x02    /* BASE+08, IDX+02, B, R/W */
+#define EXT_PORT               0x03    /* BASE+08, IDX+03, B, R/W */
+# define LED_ON         (0)
+# define LED_OFF BIT(0)
 
-#define IRQ_SELECT 0x04        /* BASE+08, IDX+04, W, R/W */
+#define IRQ_SELECT             0x04    /* BASE+08, IDX+04, W, R/W */
 # define IRQSELECT_RESELECT_IRQ      BIT(0)
 # define IRQSELECT_PHASE_CHANGE_IRQ  BIT(1)
 # define IRQSELECT_SCSIRESET_IRQ     BIT(2)
@@ -326,32 +340,35 @@ static char * nsp32_model[] = {
 # define IRQSELECT_BMCNTERR_IRQ      BIT(9)
 # define IRQSELECT_AUTO_SCSI_SEQ_IRQ BIT(10)
 
-#define OLD_SCSI_PHASE 0x05    /* BASE+08, IDX+05, B, R */
+#define OLD_SCSI_PHASE         0x05    /* BASE+08, IDX+05, B, R */
 # define OLD_MSG  BIT(0)
 # define OLD_IO   BIT(1)
 # define OLD_CD   BIT(2)
 # define OLD_BUSY BIT(3)
 
-#define FIFO_FULL_SHLD_COUNT 0x06      /* BASE+08, IDX+06, B, R/W */
-#define FIFO_EMPTY_SHLD_COUNT 0x07     /* BASE+08, IDX+07, B, R/W */
+#define FIFO_FULL_SHLD_COUNT   0x06    /* BASE+08, IDX+06, B, R/W */
+#define FIFO_EMPTY_SHLD_COUNT  0x07    /* BASE+08, IDX+07, B, R/W */
 
-#define EXP_ROM_CONTROL 0x08   /* BASE+08, IDX+08, B, R/W */
+#define EXP_ROM_CONTROL                0x08    /* BASE+08, IDX+08, B, R/W */ /* external ROM control */
+# define ROM_WRITE_ENB BIT(0)
+# define IO_ACCESS_ENB BIT(1)
+# define ROM_ADR_CLEAR BIT(2)
 
-#define EXP_ROM_ADRL           0x09    /* BASE+08, IDX+09, W, R/W */
+#define EXP_ROM_ADR            0x09    /* BASE+08, IDX+09, W, R/W */
 
 #define EXP_ROM_DATA           0x0a    /* BASE+08, IDX+0a, B, R/W */
 
-#define CHIP_MODE 0x0b /* Bi only */
-# define OEM0 BIT(1)
-# define OEM1 BIT(2)
-# define OPTB BIT(3)
-# define OPTC BIT(4)
-# define OPTD BIT(5)
-# define OPTE BIT(6)
-# define OPTF BIT(7)
-
-#define MISC_WR 0x0c   /* BASE+08, IDX+0c, W, R/W */
-#define MISC_RD 0x0c
+#define CHIP_MODE              0x0b    /* BASE+08, IDX+0b, B, R   */ /* NinjaSCSI-32Bi only */
+# define OEM0 BIT(1)  /* OEM select */ /* 00=I-O DATA, 01=KME, 10=Workbit, 11=Ext ROM */
+# define OEM1 BIT(2)  /* OEM select */
+# define OPTB BIT(3)  /* KME mode select */
+# define OPTC BIT(4)  /* KME mode select */
+# define OPTD BIT(5)  /* KME mode select */
+# define OPTE BIT(6)  /* KME mode select */
+# define OPTF BIT(7)  /* Power management */
+
+#define MISC_WR                        0x0c    /* BASE+08, IDX+0c, W, R/W */
+#define MISC_RD                        0x0c
 # define SCSI_DIRECTION_DETECTOR_SELECT BIT(0)
 # define SCSI2_HOST_DIRECTION_VALID    BIT(1)  /* Read only */
 # define HOST2_SCSI_DIRECTION_VALID    BIT(2)  /* Read only */
@@ -362,7 +379,7 @@ static char * nsp32_model[] = {
 # define MISC_MABORT_MASK              BIT(7)
 # define BMSTOP_CHANGE2_NONDATA_PHASE  BIT(8)
 
-#define BM_CYCLE 0x0d  /* BASE+08, IDX+0d, B, R/W */
+#define BM_CYCLE               0x0d    /* BASE+08, IDX+0d, B, R/W */
 # define BM_CYCLE0              BIT(0)
 # define BM_CYCLE1              BIT(1)
 # define BM_FRAME_ASSERT_TIMING         BIT(2)
@@ -373,20 +390,26 @@ static char * nsp32_model[] = {
 # define MEMRD_CMD1              BIT(7)
 
 
-#define SREQ_EDGH 0x0e /* BASE+08, IDX+0e, B, W */
+#define SREQ_EDGH              0x0e    /* BASE+08, IDX+0e, B, W */
 # define SREQ_EDGH_SELECT BIT(0)
 
-#define UP_CNT         0x0f    /* BASE+08, IDX+0f, B, W */
-#define CFG_CMD_STR      0x10  /* BASE+08, IDX+10, W, R */
-#define CFG_LATE_CACHE   0x11  /* BASE+08, IDX+11, W, R/W */
-#define CFG_BASE_ADR_1   0x12  /* BASE+08, IDX+12, W, R */
-#define CFG_BASE_ADR_2   0x13  /* BASE+08, IDX+13, W, R */
-#define CFG_INLINE       0x14  /* BASE+08, IDX+14, W, R */
+#define UP_CNT                 0x0f    /* BASE+08, IDX+0f, B, W */
+# define REQCNT_UP  BIT(0)
+# define ACKCNT_UP  BIT(1)
+# define BMADR_UP   BIT(4)
+# define BMCNT_UP   BIT(5)
+# define SGT_CNT_UP BIT(7)
 
-#define SERIAL_ROM_CTL 0x15    /* BASE+08, IDX+15, B, R */
-# define SCL                                   BIT(0)
-# define ENA                                   BIT(1)
-# define SDA                                   BIT(2)
+#define CFG_CMD_STR            0x10    /* BASE+08, IDX+10, W, R */
+#define CFG_LATE_CACHE         0x11    /* BASE+08, IDX+11, W, R/W */
+#define CFG_BASE_ADR_1         0x12    /* BASE+08, IDX+12, W, R */
+#define CFG_BASE_ADR_2         0x13    /* BASE+08, IDX+13, W, R */
+#define CFG_INLINE             0x14    /* BASE+08, IDX+14, W, R */
+
+#define SERIAL_ROM_CTL         0x15    /* BASE+08, IDX+15, B, R */
+# define SCL BIT(0)
+# define ENA BIT(1)
+# define SDA BIT(2)
 
 #define FIFO_HST_POINTER       0x16    /* BASE+08, IDX+16, B, R/W */
 #define SREQ_DELAY             0x17    /* BASE+08, IDX+17, B, R/W */
@@ -425,5 +448,229 @@ static char * nsp32_model[] = {
 #define BUSPHASE_STATUS      ( BUSMON_STATUS      & BUSMON_PHASE_MASK )
 #define BUSPHASE_SELECT      ( BUSMON_SEL | BUSMON_IO )
 
-#endif /* _NSP32_H */
+
+/************************************************************************
+ * structure for DMA/Scatter Gather list
+ */
+#define NSP32_SG_SIZE          SG_ALL
+
+typedef struct _nsp32_sgtable {
+       /* values must be little endian */
+       u32_le addr; /* transfer address */
+       u32_le len;  /* transfer length. BIT(31) is for SGT_END mark */
+} __attribute__ ((packed)) nsp32_sgtable;
+
+typedef struct _nsp32_sglun {
+       nsp32_sgtable sgt[NSP32_SG_SIZE+1];     /* SG table */
+} __attribute__ ((packed)) nsp32_sglun;
+#define NSP32_SG_TABLE_SIZE (sizeof(nsp32_sgtable) * NSP32_SG_SIZE * MAX_TARGET * MAX_LUN)
+
+/* Auto parameter mode memory map.   */
+/* All values must be little endian. */
+typedef struct _nsp32_autoparam {
+       u8     cdb[4 * 0x10];    /* SCSI Command                      */
+       u32_le msgout;           /* outgoing messages                 */
+       u8     syncreg;          /* sync register value               */
+       u8     ackwidth;         /* ack width register value          */
+       u8     target_id;        /* target/host device id             */
+       u8     sample_reg;       /* hazard killer sampling rate       */
+       u16_le command_control;  /* command control register          */
+       u16_le transfer_control; /* transfer control register         */
+       u32_le sgt_pointer;      /* SG table physical address for DMA */
+       u32_le dummy[2];
+} __attribute__ ((packed)) nsp32_autoparam;  /* must be packed struct */
+
+/*
+ * host data structure
+ */
+/* message in/out buffer */
+#define MSGOUTBUF_MAX          20
+#define MSGINBUF_MAX           20
+
+/* flag for trans_method */
+#define NSP32_TRANSFER_BUSMASTER       BIT(0)
+#define NSP32_TRANSFER_MMIO            BIT(1)  /* Not supported yet */
+#define NSP32_TRANSFER_PIO             BIT(2)  /* Not supported yet */
+
+
+/*
+ * structure for connected LUN dynamic data
+ *
+ * Note: Currently tagged queuing is disabled, each nsp32_lunt holds
+ *       one SCSI command and one state.
+ */
+#define DISCPRIV_OK            BIT(0)          /* DISCPRIV Enable mode */
+#define MSGIN03                        BIT(1)          /* Auto Msg In 03 Flag  */
+
+typedef struct _nsp32_lunt {
+       Scsi_Cmnd       *SCpnt;     /* Current Handling Scsi_Cmnd */
+       unsigned long    save_datp;  /* Save Data Pointer - saved position from initial address */
+       int              msgin03;       /* auto msg in 03 flag     */
+       unsigned int     sg_num;        /* Total number of SG entries */
+       int              cur_entry;     /* Current SG entry number */
+       nsp32_sglun     *sglun;         /* sg table per lun        */
+       dma_addr_t       sglun_paddr;   /* sglun physical address  */
+} nsp32_lunt;
+
+
+/*
+ * SCSI TARGET/LUN definition
+ */
+#define NSP32_HOST_SCSIID    7  /* SCSI initiator is everytime defined as 7 */
+#define MAX_TARGET          8
+#define MAX_LUN                     8  /* XXX: In SPI3, max number of LUN is 64. */
+
+
+typedef struct _nsp32_sync_table {
+       unsigned char   period_num;     /* period number                  */
+       unsigned char   ackwidth;       /* ack width designated by period */
+       unsigned char   start_period;   /* search range - start period    */
+       unsigned char   end_period;     /* search range - end period      */
+       unsigned char   sample_rate;    /* hazard killer parameter        */
+} nsp32_sync_table;
+
+
+/*
+ * structure for target device static data
+ */
+/* flag for nsp32_target.sync_flag */
+#define SDTR_INITIATOR   BIT(0)    /* sending SDTR from initiator        */
+#define SDTR_TARGET      BIT(1)    /* sending SDTR from target           */
+#define SDTR_DONE        BIT(2)    /* exchanging SDTR has been processed */
+
+/* syncronous period value for nsp32_target.config_max */
+#define FAST5M                 0x32
+#define FAST10M                        0x19
+#define ULTRA20M               0x0c
+
+/* flag for nsp32_target.{sync_offset}, period */
+#define ASYNC_OFFSET           0       /* asynchronous transfer           */
+#define SYNC_OFFSET            0xf     /* synchronous transfer max offset */
+
+/* syncreg:
+  bit:07 06 05 04 03 02 01 00
+      ---PERIOD-- ---OFFSET--   */
+#define TO_SYNCREG(period, offset) (((period) & 0x0f) << 4 | ((offset) & 0x0f))
+
+typedef struct _nsp32_target {
+       unsigned char   syncreg;        /* value for SYNCREG   */
+       unsigned char   ackwidth;       /* value for ACKWIDTH  */
+       unsigned char   period;         /* sync period (0-255) */
+       unsigned char   offset;         /* sync offset (0-15)  */
+       int             sync_flag;      /* SDTR_*, 0           */
+       int             limit_entry;    /* max speed limit entry designated
+                                          by EEPROM configuration */
+       unsigned char   sample_reg;     /* SREQ hazard killer register */
+} nsp32_target;
+
+typedef struct _nsp32_hw_data {
+       int           IrqNumber;
+       int           BaseAddress;
+       int           NumAddress;
+       unsigned long MmioAddress;
+#define NSP32_MMIO_OFFSET 0x0800
+       unsigned long MmioLength;
+
+       Scsi_Cmnd *CurrentSC;
+
+       struct pci_dev             *Pci;
+       const struct pci_device_id *pci_devid;
+       struct Scsi_Host           *Host;
+       spinlock_t                  Lock;
+
+       char info_str[100];
+
+       /* allocated memory region */
+       nsp32_sglun      *sg_list;      /* sglist virtuxal address         */
+       dma_addr_t        sg_paddr;     /* physical address of hw_sg_table */
+       nsp32_autoparam  *autoparam;    /* auto parameter transfer region  */
+       dma_addr_t        auto_paddr;   /* physical address of autoparam   */
+       int               cur_entry;    /* current sgt entry               */
+
+       /* target/LUN */
+       nsp32_lunt       *cur_lunt;     /* Current connected LUN table */
+       nsp32_lunt        lunt[MAX_TARGET][MAX_LUN];  /* All LUN table */
+
+       nsp32_target     *cur_target;   /* Current connected SCSI ID    */
+       nsp32_target      target[MAX_TARGET];        /* SCSI ID */
+       int               cur_id;       /* Current connected target ID  */
+       int               cur_lun;      /* Current connected target LUN */
+
+       /* behavior setting parameters */
+       int               trans_method; /* transfer method flag            */
+       int               resettime;    /* Reset time                      */
+       int               clock;        /* clock dividing flag             */
+       nsp32_sync_table *synct;        /* sync_table determined by clock  */
+       int               syncnum;      /* the max number of synct element */
+
+       /* message buffer */
+       unsigned char msgoutbuf[MSGOUTBUF_MAX]; /* msgout buffer    */
+       char          msgout_len;               /* msgoutbuf length */
+       unsigned char msginbuf [MSGINBUF_MAX];  /* megin buffer     */
+       char          msgin_len;                /* msginbuf length  */
+
+#ifdef CONFIG_PM
+       u32           PciState[16];     /* save PCI state to this area */
+#endif
+} nsp32_hw_data;
+
+/*
+ * TIME definition
+ */
+#define RESET_HOLD_TIME                10000   /* reset time in us (SCSI-2 says the
+                                          minimum is 25us) */
+#define SEL_TIMEOUT_TIME       10000   /* 250ms defined in SCSI specification
+                                          (25.6us/1unit) */
+#define ARBIT_TIMEOUT_TIME     100     /* 100us */
+#define REQSACK_TIMEOUT_TIME   10000   /* max wait time for REQ/SACK assertion
+                                          or negation, 10000us == 10ms */
+
+/**************************************************************************
+ * Compatibility functions
+ */
+
+/* for Kernel 2.4 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+# define scsi_register_host(template)  scsi_register_module(MODULE_SCSI_HA, template)
+# define scsi_unregister_host(template) scsi_unregister_module(MODULE_SCSI_HA, template)
+# define scsi_host_put(host)            scsi_unregister(host)
+# define pci_name(pci_dev)              ((pci_dev)->slot_name)
+
+typedef void irqreturn_t;
+# define IRQ_NONE      /* */
+# define IRQ_HANDLED   /* */
+# define IRQ_RETVAL(x) /* */
+
+/* This is ad-hoc version of scsi_host_get_next() */
+static inline struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *host)
+{
+       if (host == NULL) {
+               return scsi_hostlist;
+       } else {
+               return host->next;
+       }
+}
+
+/* This is ad-hoc version of scsi_host_hn_get() */
+static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno)
+{
+       struct Scsi_Host *host;
+
+       for (host = scsi_host_get_next(NULL); host != NULL;
+            host = scsi_host_get_next(host)) {
+               if (host->host_no == hostno) {
+                       break;
+               }
+       }
+
+       return host;
+}
+#endif
+
+/* for Kernel 2.6 */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+# define __devinitdata /* */
+#endif
+
+#endif /* _NSP32_H */
 /* end */
index 9fa0abfa8f1e81041a4e079ca9f777ad63bfbb28..ef3c59cbcff601b6a1274e07349699c98efc240b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Workbit NinjaSCSI-32Bi/UDE PCI/Cardbus SCSI Host Bus Adapter driver
+ * Workbit NinjaSCSI-32Bi/UDE PCI/CardBus SCSI Host Bus Adapter driver
  * Debug routine
  *
  * This software may be used and distributed according to the terms of
@@ -88,7 +88,7 @@ static void print_commandk (unsigned char *command)
        int i,s;
 //     printk(KERN_DEBUG);
        print_opcodek(command[0]);
-       /*printk(KERN_DEBUG __func__ " ");*/
+       /*printk(KERN_DEBUG "%s ", __FUNCTION__);*/
        if ((command[0] >> 5) == 6 ||
            (command[0] >> 5) == 7 ) {
                s = 12; /* vender specific */
@@ -137,9 +137,9 @@ static void print_commandk (unsigned char *command)
        printk("\n");
 }
 
-static void show_command(Scsi_Cmnd *ptr)
+static void show_command(Scsi_Cmnd *SCpnt)
 {
-       print_commandk(ptr->cmnd);
+       print_commandk(SCpnt->cmnd);
 }
 
 static void show_busphase(unsigned char stat)
@@ -260,3 +260,4 @@ static void nsp32_print_register(int base)
        }
 }
 
+/* end */
index 8b9ecdeb22d3db23431685f41a1b37dbc62a5fb7..0a97c4fa6a059d13de0d7ef6d84d7c96c089d9ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Workbit NinjaSCSI-32Bi/UDE PCI/Cardbus SCSI Host Bus Adapter driver
+ * Workbit NinjaSCSI-32Bi/UDE PCI/CardBus SCSI Host Bus Adapter driver
  * I/O routine
  *
  * This software may be used and distributed according to the terms of
@@ -22,30 +22,30 @@ static inline unsigned char nsp32_read1(unsigned int base,
        return inb(base + index);
 }
 
-static inline void nsp32_write2(unsigned int  base,
-                               unsigned int  index,
+static inline void nsp32_write2(unsigned int   base,
+                               unsigned int   index,
                                unsigned short val)
 {
-       outw(cpu_to_le16(val), (base + index));
+       outw(val, (base + index));
 }
 
 static inline unsigned short nsp32_read2(unsigned int base,
                                         unsigned int index)
 {
-       return le16_to_cpu(inw(base + index));
+       return inw(base + index);
 }
 
 static inline void nsp32_write4(unsigned int  base,
                                unsigned int  index,
                                unsigned long val)
 {
-       outl(cpu_to_le32(val), (base + index));
+       outl(val, (base + index));
 }
 
 static inline unsigned long nsp32_read4(unsigned int base,
                                        unsigned int index)
 {
-       return le32_to_cpu(inl(base + index));
+       return inl(base + index);
 }
 
 /*==============================================*/
@@ -58,7 +58,7 @@ static inline void nsp32_mmio_write1(unsigned long base,
 
        ptr = (unsigned char *)(base + NSP32_MMIO_OFFSET + index);
 
-       *ptr = val;
+       writeb(val, ptr);
 }
 
 static inline unsigned char nsp32_mmio_read1(unsigned long base,
@@ -68,18 +68,18 @@ static inline unsigned char nsp32_mmio_read1(unsigned long base,
 
        ptr = (unsigned char *)(base + NSP32_MMIO_OFFSET + index);
 
-       return *ptr;
+       return readb(ptr);
 }
 
-static inline void nsp32_mmio_write2(unsigned long base,
-                                    unsigned int  index,
+static inline void nsp32_mmio_write2(unsigned long  base,
+                                    unsigned int   index,
                                     unsigned short val)
 {
        volatile unsigned short *ptr;
 
        ptr = (unsigned short *)(base + NSP32_MMIO_OFFSET + index);
 
-       *ptr = cpu_to_le16(val);
+       writew(cpu_to_le16(val), ptr);
 }
 
 static inline unsigned short nsp32_mmio_read2(unsigned long base,
@@ -87,11 +87,9 @@ static inline unsigned short nsp32_mmio_read2(unsigned long base,
 {
        volatile unsigned short *ptr;
 
-       //printk(__FUNCTION__ "\n");
-
        ptr = (unsigned short *)(base + NSP32_MMIO_OFFSET + index);
 
-       return le16_to_cpu(*ptr);
+       return le16_to_cpu(readw(ptr));
 }
 
 static inline void nsp32_mmio_write4(unsigned long base,
@@ -102,7 +100,7 @@ static inline void nsp32_mmio_write4(unsigned long base,
 
        ptr = (unsigned long *)(base + NSP32_MMIO_OFFSET + index);
 
-       *ptr = cpu_to_le32(val);
+       writel(cpu_to_le32(val), ptr);
 }
 
 static inline unsigned long nsp32_mmio_read4(unsigned long base,
@@ -110,16 +108,12 @@ static inline unsigned long nsp32_mmio_read4(unsigned long base,
 {
        volatile unsigned long *ptr;
 
-       //printk(__FUNCTION__ "\n");
-
        ptr = (unsigned long *)(base + NSP32_MMIO_OFFSET + index);
 
-       return le32_to_cpu(*ptr);
+       return le32_to_cpu(readl(ptr));
 }
 
-
-/*=============================================*/
-
+/*==============================================*/
 
 static inline unsigned char nsp32_index_read1(unsigned int base,
                                              unsigned int reg)
@@ -132,7 +126,7 @@ static inline void nsp32_index_write1(unsigned int  base,
                                      unsigned int  reg,
                                      unsigned char val)
 {
-       outb(reg, base + INDEX_REG);
+       outb(reg, base + INDEX_REG   );
        outb(val, base + DATA_REG_LOW);
 }
 
@@ -140,15 +134,15 @@ static inline unsigned short nsp32_index_read2(unsigned int base,
                                               unsigned int reg)
 {
        outb(reg, base + INDEX_REG);
-       return le16_to_cpu(inw(base + DATA_REG_LOW));
+       return inw(base + DATA_REG_LOW);
 }
 
-static inline void nsp32_index_write2(unsigned int  base,
-                                     unsigned int  reg,
+static inline void nsp32_index_write2(unsigned int   base,
+                                     unsigned int   reg,
                                      unsigned short val)
 {
-       outb(reg, base + INDEX_REG);
-       outw(cpu_to_le16(val), base + DATA_REG_LOW);
+       outb(reg, base + INDEX_REG   );
+       outw(val, base + DATA_REG_LOW);
 }
 
 static inline unsigned long nsp32_index_read4(unsigned int base,
@@ -157,8 +151,8 @@ static inline unsigned long nsp32_index_read4(unsigned int base,
        unsigned long h,l;
 
        outb(reg, base + INDEX_REG);
-       l = le16_to_cpu(inw(base + DATA_REG_LOW));
-       h = le16_to_cpu(inw(base + DATA_REG_HI ));
+       l = inw(base + DATA_REG_LOW);
+       h = inw(base + DATA_REG_HI );
 
        return ((h << 16) | l);
 }
@@ -170,15 +164,14 @@ static inline void nsp32_index_write4(unsigned int  base,
        unsigned long h,l;
 
        h = (val & 0xffff0000) >> 16;
-       l = (val & 0x0000ffff) >> 0;
+       l = (val & 0x0000ffff) >>  0;
 
-       outb(reg, base + INDEX_REG);
-       outw(cpu_to_le16(l), base + DATA_REG_LOW);
-       outw(cpu_to_le16(h), base + DATA_REG_HI);
+       outb(reg, base + INDEX_REG   );
+       outw(l,   base + DATA_REG_LOW);
+       outw(h,   base + DATA_REG_HI );
 }
 
-
-/* ===================================*/
+/*==============================================*/
 
 static inline unsigned char nsp32_mmio_index_read1(unsigned int base,
                                                   unsigned int reg)
@@ -188,13 +181,12 @@ static inline unsigned char nsp32_mmio_index_read1(unsigned int base,
        index_ptr = (unsigned short *)(base + NSP32_MMIO_OFFSET + INDEX_REG);
        data_ptr  = (unsigned short *)(base + NSP32_MMIO_OFFSET + DATA_REG_LOW);
 
-       *index_ptr = reg;
-
-       return ((*data_ptr) & 0xff);
+       writeb(reg, index_ptr);
+       return readb(data_ptr);
 }
 
-static inline void nsp32_mmio_index_write1(unsigned int base,
-                                          unsigned int reg,
+static inline void nsp32_mmio_index_write1(unsigned int  base,
+                                          unsigned int  reg,
                                           unsigned char val)
 {
        volatile unsigned short *index_ptr, *data_ptr;
@@ -202,8 +194,8 @@ static inline void nsp32_mmio_index_write1(unsigned int base,
        index_ptr = (unsigned short *)(base + NSP32_MMIO_OFFSET + INDEX_REG);
        data_ptr  = (unsigned short *)(base + NSP32_MMIO_OFFSET + DATA_REG_LOW);
 
-       *index_ptr = reg;
-       *data_ptr  = (unsigned short)val;
+       writeb(reg, index_ptr);
+       writeb(val, data_ptr );
 }
 
 static inline unsigned short nsp32_mmio_index_read2(unsigned int base,
@@ -214,13 +206,12 @@ static inline unsigned short nsp32_mmio_index_read2(unsigned int base,
        index_ptr = (unsigned short *)(base + NSP32_MMIO_OFFSET + INDEX_REG);
        data_ptr  = (unsigned short *)(base + NSP32_MMIO_OFFSET + DATA_REG_LOW);
 
-       *index_ptr = reg;
-
-       return le16_to_cpu(*data_ptr);
+       writeb(reg, index_ptr);
+       return le16_to_cpu(readw(data_ptr));
 }
 
-static inline void nsp32_mmio_index_write2(unsigned int base,
-                                          unsigned int reg,
+static inline void nsp32_mmio_index_write2(unsigned int   base,
+                                          unsigned int   reg,
                                           unsigned short val)
 {
        volatile unsigned short *index_ptr, *data_ptr;
@@ -228,34 +219,33 @@ static inline void nsp32_mmio_index_write2(unsigned int base,
        index_ptr = (unsigned short *)(base + NSP32_MMIO_OFFSET + INDEX_REG);
        data_ptr  = (unsigned short *)(base + NSP32_MMIO_OFFSET + DATA_REG_LOW);
 
-       *index_ptr = reg;
-       *data_ptr  = val;
+       writeb(reg,              index_ptr);
+       writew(cpu_to_le16(val), data_ptr );
 }
 
-/*-------------------------------------------------------------------*/
+/*==============================================*/
 
-static inline void nsp32_multi_read4(unsigned int   BaseAddr,
-                                    unsigned int   Register,
+static inline void nsp32_multi_read4(unsigned int   base,
+                                    unsigned int   reg,
                                     void          *buf,
                                     unsigned long  count)
 {
-       insl(BaseAddr + Register, buf, count);
+       insl(base + reg, buf, count);
 }
 
 static inline void nsp32_fifo_read(unsigned int   base,
                                   void          *buf,
                                   unsigned long  count)
 {
-       //DEBUG(0, __FUNCTION__ "() buf=0x%p, count=0x%lx*4\n", buf, count);
        nsp32_multi_read4(base, FIFO_DATA_LOW, buf, count);
 }
 
-static inline void nsp32_multi_write4(unsigned int   BaseAddr,
-                                     unsigned int   Register,
+static inline void nsp32_multi_write4(unsigned int   base,
+                                     unsigned int   reg,
                                      void          *buf,
                                      unsigned long  count)
 {
-       outsl(BaseAddr + Register, buf, count);
+       outsl(base + reg, buf, count);
 }
 
 static inline void nsp32_fifo_write(unsigned int   base,
@@ -265,5 +255,5 @@ static inline void nsp32_fifo_write(unsigned int   base,
        nsp32_multi_write4(base, FIFO_DATA_LOW, buf, count);
 }
 
-#endif /* _NSP32_IO_H */
+#endif /* _NSP32_IO_H */
 /* end */