patch-2.3.43 linux/drivers/scsi/qla1280.c

Next file: linux/drivers/scsi/qla1280.h
Previous file: linux/drivers/scsi/ql1280_fw.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.42/linux/drivers/scsi/qla1280.c linux/drivers/scsi/qla1280.c
@@ -0,0 +1,6850 @@
+/********************************************************************************
+ *                  QLOGIC LINUX SOFTWARE
+ *
+ * QLogic ISP1x80/1x160 device driver for Linux 2.3.x (redhat 6.X).
+ *
+ * COPYRIGHT (C) 1999-2000 QLOGIC CORPORATION    
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the Qlogic's Linux Software License. See below.
+ *
+ * This program is WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistribution's or source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ ********************************************************************************/
+ 
+/*****************************************************************************************
+			QLOGIC CORPORATION SOFTWARE
+           "GNU" GENERAL PUBLIC LICENSE
+    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION
+                 AND MODIFICATION
+
+This GNU General Public License ("License") applies solely to QLogic Linux 
+Software ("Software") and may be distributed under the terms of this License.  
+ 
+1. You may copy and distribute verbatim copies of the Software's source code as 
+you receive it, in any medium, provided that you conspicuously and appropriately 
+publish on each copy an appropriate copyright notice and disclaimer of warranty;
+keep intact all the notices that refer to this License and to the absence of any
+warranty; and give any other recipients of the Software a copy of this License along
+with the Software. 
+
+You may charge a fee for the physical act of transferring a copy, and you may at your
+option offer warranty protection in exchange for a fee.
+ 
+2. You may modify your copy or copies of the Software or any portion of it, thus forming
+a work based on the Software, and copy and distribute such modifications or work under
+the terms of Section 1 above, provided that you also meet all of these conditions:
+ 
+* a) You must cause the modified files to carry prominent notices stating that you
+changed the files and the date of any change. 
+
+* b) You must cause any work that you distribute or publish that in whole or in part
+contains or is derived from the Software or any part thereof, to be licensed as a
+whole at no charge to all third parties under the terms of this License. 
+
+* c) If the modified Software normally reads commands interactively when run, you
+must cause it, when started running for such interactive use in the most ordinary way,
+to print or display an announcement including an appropriate copyright notice and a 
+notice that there is no warranty (or else, saying that you provide a warranty) and that
+users may redistribute the Software under these conditions, and telling the user how to
+view a copy of this License. (Exception:if the Software itself is interactive but does 
+not normally print such an announcement, your work based on the Software is not required
+to print an announcement.) 
+
+These requirements apply to the modified work as a whole. If identifiable sections of
+that work are not derived from the Software, and can be reasonably considered independent
+and separate works in themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you distribute the same
+sections as part of a whole which is a work based on the Software, the distribution of the
+whole must be on the terms of this License, whose permissions for other licensees extend
+to the entire whole, and thus to each and every part regardless of who wrote it. 
+
+3. You may copy and distribute the Software (or a work based on it, under Section 2) in 
+object code or executable form under the terms of Sections 1 and 2 above provided that
+you also do one of the following: 
+
+* a) Accompany it with the complete corresponding machine-readable source code, which must
+be distributed under the terms of Sections 1 and 2 above on a medium customarily used for
+software interchange; or, 
+
+* b) Accompany it with a written offer, valid for at least three years, to give any third
+party, for a charge no more than your cost of physically performing source distribution,
+a complete machine-readable copy of the corresponding source code, to be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for software interchange;
+or,
+
+* c) Accompany it with the information you received as to the offer to distribute 
+corresponding source code. (This alternative is allowed only for noncommercial distribution
+and only if you received the Software in object code or executable form with such an offer,
+in accord with Subsection b above.) 
+
+The source code for a work means the preferred form of the work for making modifications
+to it. For an executable work, complete source code means all the source code for all 
+modules it contains, plus any associated interface definition files, plus the scripts used
+to control compilation and installation of the executable.     
+
+If distribution of executable or object code is made by offering access to copy from a 
+designated place, then offering equivalent access to copy the source code from the same
+place counts as distribution of the source code, even though third parties are not 
+compelled to copy the source along with the object code. 
+
+4. You may not copy, modify, sublicense, or distribute the Software except as expressly 
+provided under this License. Any attempt otherwise to copy, modify, sublicense or 
+distribute the Software is void, and will automatically terminate your rights under this
+License. However, parties who have received copies, or rights, from you under this License
+will not have their licenses terminated so long as such parties remain in full compliance. 
+
+5. This license grants you world wide, royalty free non-exclusive rights to modify or 
+distribute the Software or its derivative works. These actions are prohibited by law 
+if you do not accept this License. Therefore, by modifying or distributing the Software
+(or any work based on the Software), you indicate your acceptance of this License to do
+so, and all its terms and conditions for copying, distributing or modifying the Software
+or works based on it.
+ 
+6. Each time you redistribute the Software (or any work based on the Software), the 
+recipient automatically receives a license from the original licensor to copy, distribute
+or modify the Software subject to these terms and conditions. You may not impose any 
+further restrictions on the recipients' exercise of the rights granted herein. You are
+not responsible for enforcing compliance by third parties to this License.
+ 
+7. If, as a consequence of a court judgment or allegation of patent infringement or for
+any other reason (not limited to patent issues), conditions are imposed on you 
+(whether by court order, agreement or otherwise) that contradict the conditions of this
+License, they do not excuse you from the conditions of this License. If you cannot 
+distribute so as to satisfy simultaneously your obligations under this License 
+and any other pertinent obligations, then as a consequence you may not distribute the
+Software at all.    
+
+If any portion of this section is held invalid or unenforceable under any particular 
+circumstance, the balance of the section is intended to apply and the section as a whole
+is intended to apply in other circumstances. 
+NO WARRANTY
+
+11. THE SOFTWARE IS PROVIDED WITHOUT A WARRANTY OF ANY KIND. THERE IS NO 
+WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 
+OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, 
+EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. 
+SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+ 
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
+REDISTRIBUTE THE SOFTWARE AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 
+DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 
+DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING 
+BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 
+LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO 
+OPERATE WITH ANY OTHER SOFTWARES), EVEN IF SUCH HOLDER OR OTHER PARTY HAS 
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+END OF TERMS AND CONDITIONS 
+
+*******************************************************************************************/ 
+
+/****************************************************************************
+    Revision History:
+    Rev. 3.00       Jan 17, 1999    DG  Qlogic
+	   - Added 64-bit support.
+    Rev. 2.07       Nov 9, 1999     DG  Qlogic
+	   - Added new routine to set target parameters for ISP12160. 
+    Rev. 2.06       Sept 10, 1999     DG  Qlogic
+       - Added support for ISP12160 Ultra 3 chip.
+    Rev. 2.03       August 3, 1999    Fred Lewis, Intel DuPont
+	- Modified code to remove errors generated when compiling with
+	  Cygnus IA64 Compiler.
+        - Changed conversion of pointers to unsigned longs instead of integers.
+        - Changed type of I/O port variables from uint32_t to unsigned long.
+        - Modified OFFSET macro to work with 64-bit as well as 32-bit.
+        - Changed sprintf and printk format specifiers for pointers to %p.
+        - Changed some int to long type casts where needed in sprintf & printk.
+        - Added l modifiers to sprintf and printk format specifiers for longs.
+        - Removed unused local variables.
+    Rev. 1.20       June 8, 1999      DG,  Qlogic
+         Changes to support RedHat release 6.0 (kernel 2.2.5).  
+       - Added SCSI exclusive access lock (io_request_lock) when accessing 
+         the adapter.
+       - Added changes for the new LINUX interface template. Some new error
+         handling routines have been added to the template, but for now we
+         will use the old ones.
+    -   Initial Beta Release.  
+*****************************************************************************/
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#define QLA1280_VERSION      " 3.00-Beta"
+
+#include <stdarg.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/segment.h>
+#include <asm/byteorder.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/blk.h>
+#include <linux/tqueue.h>
+/* MRS #include <linux/tasks.h> */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+# include <linux/bios32.h>
+#endif
+#include "sd.h"
+#include "scsi.h"
+#include "hosts.h"
+#define UNIQUE_FW_NAME
+#include "qla1280.h"
+#include "ql12160_fw.h"                     /* ISP RISC code */
+#include "ql1280_fw.h"
+
+#include <linux/stat.h>
+#include <linux/malloc.h>        /* for kmalloc() */
+
+
+#ifndef KERNEL_VERSION
+#  define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+
+/*
+ * Compile time Options: 
+ *            0 - Disable and 1 - Enable 
+ */
+#define  QLA1280_64BIT_SUPPORT         1   /* 64-bit Support */
+#define  QL1280_TARGET_MODE_SUPPORT    0   /* Target mode support */
+#define  WATCHDOGTIMER                 0
+#define  MEMORY_MAPPED_IO              0
+#define  DEBUG_QLA1280_INTR            0
+#define  USE_NVRAM_DEFAULTS	       0
+#define  DEBUG_PRINT_NVRAM             0
+#define  LOADING_RISC_ACTIVITY         0
+#define  AUTO_ESCALATE_RESET           0   /* Automatically escalate resets */
+#define  AUTO_ESCALATE_ABORT           0   /* Automatically escalate aborts */
+#define  STOP_ON_ERROR                 0   /* Stop on aborts and resets  */
+#define  STOP_ON_RESET                 0 
+#define  STOP_ON_ABORT                 0 
+#undef   DYNAMIC_MEM_ALLOC
+
+#define  DEBUG_QLA1280                 0    /* Debugging  */
+/* #define CHECKSRBSIZE */
+
+/*
+ * These macros to assist programming
+ */
+
+#define	BZERO(ptr, amt)		memset(ptr, 0, amt)
+#define	BCOPY(src, dst, amt)	memcpy(dst, src, amt)
+#define	KMALLOC(siz)	kmalloc((siz), GFP_ATOMIC)
+#define	KMFREE(ip,siz)	kfree((ip))
+#define	SYS_DELAY(x)		udelay(x);barrier()
+#define QLA1280_DELAY(sec)  mdelay(sec * 1000)
+#define VIRT_TO_BUS(a) virt_to_bus((a))
+#if  QLA1280_64BIT_SUPPORT
+#if  BITS_PER_LONG <= 32
+#define  VIRT_TO_BUS_LOW(a) (uint32_t)virt_to_bus((a))
+#define  VIRT_TO_BUS_HIGH(a) (uint32_t)(0x0)
+#else
+#define  VIRT_TO_BUS_LOW(a) (uint32_t)(0xffffffff & virt_to_bus((a)))
+#define  VIRT_TO_BUS_HIGH(a) (uint32_t)(0xffffffff & (virt_to_bus((a))>>32))
+#endif
+#endif  /* QLA1280_64BIT_SUPPORT */
+
+#define STATIC     
+
+#define NVRAM_DELAY() udelay(500) /* 2 microsecond delay */
+void qla1280_device_queue_depth(scsi_qla_host_t *, Scsi_Device *);
+
+#define  CACHE_FLUSH(a) (RD_REG_WORD(a))
+#define  INVALID_HANDLE    (MAX_OUTSTANDING_COMMANDS+1)
+
+#define  MSW(x)          (uint16_t)((uint32_t)(x) >> 16)
+#define  LSW(x)          (uint16_t)(x)
+#define  MSB(x)          (uint8_t)((uint16_t)(x) >> 8)
+#define  LSB(x)          (uint8_t)(x)
+
+#if  BITS_PER_LONG <= 32
+#define  LS_64BITS(x) (uint32_t)(x)
+#define  MS_64BITS(x) (uint32_t)(0x0)
+#else
+#define  LS_64BITS(x) (uint32_t)(0xffffffff & (x))
+#define  MS_64BITS(x) (uint32_t)(0xffffffff & ((x)>>32) )
+#endif
+
+/*
+ *  QLogic Driver Support Function Prototypes.
+ */
+STATIC void   qla1280_done(scsi_qla_host_t *, srb_t **, srb_t **);
+STATIC void   qla1280_next(scsi_qla_host_t *, scsi_lu_t *, uint8_t);
+STATIC void   qla1280_putq_t(scsi_lu_t *, srb_t *);
+STATIC void   qla1280_done_q_put(srb_t *, srb_t **, srb_t **);
+STATIC void qla1280_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
+#ifdef  QLA1280_UNUSED 
+static void qla1280_dump_regs(struct Scsi_Host *host);
+#endif
+#if  STOP_ON_ERROR 
+static void qla1280_panic(char *, struct Scsi_Host *host);
+#endif
+void qla1280_print_scsi_cmd(Scsi_Cmnd *cmd);
+STATIC void qla1280_abort_queue_single(scsi_qla_host_t *,uint32_t,uint32_t,uint32_t,uint32_t);
+
+STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd       *cp);
+STATIC void qla1280_removeq(scsi_lu_t *q, srb_t *sp);
+STATIC void qla1280_mem_free(scsi_qla_host_t *ha);
+void qla1280_do_dpc(void *p);
+#ifdef  QLA1280_UNUSED 
+static void qla1280_set_flags(char * s);
+#endif
+static char	*qla1280_get_token(char *, char *);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+STATIC inline void mdelay(int);
+#endif
+static inline void qla1280_enable_intrs(scsi_qla_host_t *);
+static inline void qla1280_disable_intrs(scsi_qla_host_t *);
+
+/*
+ *  QLogic ISP1280 Hardware Support Function Prototypes.
+ */
+STATIC uint8_t   qla1280_initialize_adapter(struct scsi_qla_host   *ha);
+STATIC uint8_t   qla1280_enable_tgt(scsi_qla_host_t *, uint8_t);
+STATIC uint8_t   qla1280_isp_firmware(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_pci_config(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_chip_diag(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_setup_chip(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_init_rings(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_nvram_config(scsi_qla_host_t *);
+STATIC uint8_t   qla1280_mailbox_command(scsi_qla_host_t *, uint8_t, uint16_t *);
+STATIC uint8_t   qla1280_bus_reset(scsi_qla_host_t *, uint8_t);
+STATIC uint8_t   qla1280_device_reset(scsi_qla_host_t *, uint8_t, uint32_t);
+STATIC uint8_t   qla1280_abort_device(scsi_qla_host_t *, uint8_t, uint32_t, uint32_t);
+STATIC uint8_t   qla1280_abort_command(scsi_qla_host_t *, srb_t *),
+#if  QLA1280_64BIT_SUPPORT
+                 qla1280_64bit_start_scsi(scsi_qla_host_t *, srb_t *),
+#endif
+                 qla1280_32bit_start_scsi(scsi_qla_host_t *, srb_t *),
+                 qla1280_abort_isp(scsi_qla_host_t *);
+STATIC void      qla1280_nv_write(scsi_qla_host_t *, uint16_t),
+                 qla1280_nv_delay(scsi_qla_host_t *),
+                 qla1280_poll(scsi_qla_host_t *),
+                 qla1280_reset_adapter(scsi_qla_host_t *),
+                 qla1280_marker(scsi_qla_host_t *, uint8_t, uint32_t, uint32_t, uint8_t),
+                 qla1280_isp_cmd(scsi_qla_host_t *),
+                 qla1280_isr(scsi_qla_host_t *, srb_t **, srb_t **),
+                 qla1280_rst_aen(scsi_qla_host_t *),
+                 qla1280_status_entry(scsi_qla_host_t *, sts_entry_t *, srb_t **,
+                                      srb_t **),
+                 qla1280_error_entry(scsi_qla_host_t *, response_t *, srb_t **,
+                                     srb_t **),
+                 qla1280_restart_queues(scsi_qla_host_t *),
+                 qla1280_abort_queues(scsi_qla_host_t *);
+STATIC uint16_t  qla1280_get_nvram_word(scsi_qla_host_t *, uint32_t),
+                 qla1280_nvram_request(scsi_qla_host_t *, uint32_t),
+                 qla1280_debounce_register(volatile uint16_t *);
+STATIC request_t *qla1280_req_pkt(scsi_qla_host_t *);
+int  qla1280_check_for_dead_scsi_bus(scsi_qla_host_t *ha, srb_t *sp);
+STATIC uint8_t qla1280_mem_alloc(scsi_qla_host_t *ha);
+STATIC uint8_t  qla1280_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels);
+
+STATIC uint8_t qla12160_set_target_parameters(scsi_qla_host_t *, uint32_t, uint32_t, uint32_t, nvram160_t *);
+STATIC void qla12160_get_target_parameters(scsi_qla_host_t *, uint32_t, uint32_t, uint32_t);
+
+#if QL1280_TARGET_MODE_SUPPORT
+STATIC void      qla1280_enable_lun(scsi_qla_host_t *, uint8_t, uint32_t),
+                 qla1280_notify_ack(scsi_qla_host_t *, notify_entry_t *),
+                 qla1280_immed_notify(scsi_qla_host_t *, notify_entry_t *),
+                 qla1280_accept_io(scsi_qla_host_t *, ctio_ret_entry_t *),
+#if  QLA1280_64BIT_SUPPORT
+                 qla1280_64bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t,
+                                     paddr32_t *),
+#endif
+                 qla1280_32bit_continue_io(scsi_qla_host_t *, atio_entry_t *, uint32_t,
+                                     paddr32_t *),
+                 qla1280_atio_entry(scsi_qla_host_t *, atio_entry_t *),
+                 qla1280_notify_entry(scsi_qla_host_t *, notify_entry_t *);
+#endif  /* QLA1280_TARGET_MODE_SUPPORT */
+
+#ifdef QL_DEBUG_ROUTINES
+/*
+ *  Driver Debug Function Prototypes.
+ */
+STATIC uint8_t  qla1280_getbyte(uint8_t *);
+STATIC uint16_t qla1280_getword(uint16_t *);
+STATIC uint32_t qla1280_getdword(uint32_t *);
+STATIC void     qla1280_putbyte(uint8_t *, uint8_t),
+                qla1280_putword(uint16_t *, uint16_t),
+                qla1280_putdword(uint32_t *, uint32_t),
+                qla1280_print(caddr_t),
+                qla1280_output_number(uint32_t, uint8_t),
+                qla1280_putc(uint8_t),
+                qla1280_dump_buffer(caddr_t, uint32_t);
+
+char          debug_buff[80];
+#if DEBUG_QLA1280 
+STATIC uint8_t ql_debug_print = 1;
+#else
+STATIC uint8_t ql_debug_print = 0;
+#endif
+#endif
+
+/*
+ * insmod needs to find the variable and make it point to something
+ */
+#ifdef MODULE
+static char *options = NULL;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,18)
+
+/* insmod qla1280 options=verbose" */
+MODULE_PARM(options, "s");  
+#endif
+/*
+ * Just in case someone uses commas to separate items on the insmod
+ * command line, we define a dummy buffer here to avoid having insmod
+ * write wild stuff into our code segment
+ */
+static char dummy_buffer[60] = "Please don't add commas in your insmod command!!\n";
+
+#endif
+
+
+/*
+ * Our directory Entry in /proc/scsi for the user to 
+ * access the driver. 
+ */
+
+#if 0
+
+/* Need to add in proc_fs.h     PROC_SCSI_QL1280 */
+#define PROC_SCSI_QL1280  PROC_SCSI_QLOGICISP
+
+struct proc_dir_entry proc_scsi_qla1280 = {
+    PROC_SCSI_QL1280, 7, "qla1280",                           
+    S_IFDIR | S_IRUGO | S_IXUGO, 2,
+    0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#endif
+
+/* We use the Scsi_Pointer structure that's included with each command
+ * SCSI_Cmnd as a scratchpad for our SRB.
+ *
+ * SCp will always point to the SRB structure (defined in qla1280.h).
+ * It is define as follows:
+ *  - SCp.ptr  -- > pointer back to the cmd
+ *  - SCp.this_residual --> used as forward pointer to next srb
+ *  - SCp.buffer --> used as backward pointer to next srb
+ *  - SCp.buffers_residual --> used as flags field
+ *  - SCp.have_data_in --> not used
+ *  - SCp.sent_command --> not used
+ *  - SCp.phase --> not used
+ */
+
+#define	CMD_SP(Cmnd)		(&(Cmnd)->SCp)
+#define	CMD_XFRLEN(Cmnd)	(Cmnd)->request_bufflen
+#define	CMD_CDBLEN(Cmnd)	(Cmnd)->cmd_len
+#define	CMD_CDBP(Cmnd)		(Cmnd)->cmnd
+#define	CMD_SNSP(Cmnd)		(Cmnd)->sense_buffer
+#define	CMD_SNSLEN(Cmnd)	(sizeof (Cmnd)->sense_buffer)
+#define	CMD_RESULT(Cmnd)	((Cmnd)->result)
+#define	CMD_HANDLE(Cmnd)	((Cmnd)->host_scribble)
+
+/*****************************************/
+/*   ISP Boards supported by this driver */
+/*****************************************/
+#define QLA1280_VENDOR_ID   0x1077
+#define QLA1080_DEVICE_ID   0x1080
+#define QLA1240_DEVICE_ID   0x1240
+#define QLA1280_DEVICE_ID   0x1280
+#define QLA12160_DEVICE_ID  0x1216
+#define QLA10160_DEVICE_ID  0x1016
+#define NUM_OF_ISP_DEVICES        6
+
+typedef struct _qlaboards 
+{
+   unsigned char   bdName[9];       /* Board ID String */
+   unsigned long   device_id;       /* Device PCI ID   */
+   int   numPorts;                  /* Number of SCSI ports */
+   unsigned short   *fwcode;        /* pointer to FW array         */
+   unsigned long    *fwlen;         /* number of words in array    */
+   unsigned short   *fwstart;       /* start address for F/W       */
+   unsigned char   *fwver;          /* Ptr to F/W version array    */
+} qla_boards_t;
+
+struct _qlaboards   QLBoardTbl[NUM_OF_ISP_DEVICES] = 
+{
+   /* Name ,  Board PCI Device ID,         Number of ports */
+  {"QLA1080 ", QLA1080_DEVICE_ID,           1,        
+               &fw1280ei_code01[0],  (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },       
+  {"QLA1240 ", QLA1240_DEVICE_ID,           2,       
+               &fw1280ei_code01[0],  (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },       
+  {"QLA1280 ", QLA1280_DEVICE_ID,           2,      
+               &fw1280ei_code01[0],  (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },       
+  {"QLA12160 ", QLA12160_DEVICE_ID,          2,      
+               &fw12160i_code01[0],  (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] },       
+  {"QLA10160 ", QLA10160_DEVICE_ID,          1,      
+               &fw12160i_code01[0],  (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] },       
+  {"        ",                 0,           0}
+};
+
+static unsigned long qla1280_verbose = 1L;
+static scsi_qla_host_t *qla1280_hostlist = NULL;
+#ifdef QLA1280_PROFILE
+static int qla1280_buffer_size = 0;
+static char *qla1280_buffer = NULL;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3 
+#define ENTER(x)	sprintf(debug_buff,"qla1280 : Entering %s()\n\r", x); \
+                        qla1280_print(debug_buff);
+#define LEAVE(x)	sprintf(debug_buff,"qla1280 : Leaving %s()\n\r", x); \
+                        qla1280_print(debug_buff);
+#define ENTER_INTR(x)	sprintf(debug_buff,"qla1280 : Entering %s()\n\r", x); \
+                        qla1280_print(debug_buff);
+#define LEAVE_INTR(x)	sprintf(debug_buff,"qla1280 : Leaving %s()\n\r", x); \
+                        qla1280_print(debug_buff);
+#define DEBUG3(x)	x
+#else
+#define ENTER(x)
+#define LEAVE(x)
+#define ENTER_INTR(x)
+#define LEAVE_INTR(x)
+#define DEBUG3(x)
+#endif
+
+#if  DEBUG_QLA1280  
+#define COMTRACE(x)
+/* #define COMTRACE(x)     qla1280_putc(x); */
+#define DEBUG(x)	x
+#else
+#define DEBUG(x)
+#define COMTRACE(x)
+#endif
+
+#ifdef QL_DEBUG_LEVEL_2 
+#define DEBUG2(x)	x
+#else
+#define DEBUG2(x)
+#endif
+#define DEBUG5(x)
+
+#if (BITS_PER_LONG==64)
+#   define OFFSET(w)   (((uint64_t) &w) & 0xFF)   /* 256 byte offsets */
+#else
+#   define OFFSET(w)   (((uint32_t) &w) & 0xFF)   /* 256 byte offsets */
+#endif
+
+#define SCSI_BUS_32(scp)   ((scp)->channel)
+#define SCSI_TCN_32(scp)    ((scp)->target)
+#define SCSI_LUN_32(scp)    ((scp)->lun)
+
+/****************************************************************************/
+/*  LINUX -  Loadable Module Functions.                                     */
+/****************************************************************************/
+
+
+/*************************************************************************
+ *   qla1280_set_info
+ *
+ * Description:
+ *   Set parameters for the driver from the /proc filesystem.
+ *
+ * Returns:
+ *************************************************************************/
+int
+qla1280_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
+{
+  return (-ENOSYS);  /* Currently this is a no-op */
+}
+
+/*************************************************************************
+ * qla1280_proc_info
+ *
+ * Description:
+ *   Return information to handle /proc support for the driver.
+ *
+ * buffer - ptrs to a page buffer
+ *
+ * Returns:
+ *************************************************************************/
+#ifdef QLA1280_PROFILE
+#define	PROC_BUF	(&qla1280_buffer[size])
+#define LUN_ID       (targ_lun>>(MAX_T_BITS+MAX_L_BITS)),((targ_lun>>MAX_L_BITS)&0xf), targ_lun&0x7 
+#endif
+int
+qla1280_proc_info ( char *buffer, char **start, off_t offset, int length, 
+                    int hostno, int inout)
+{
+#ifdef QLA1280_PROFILE
+  struct Scsi_Host *host;
+  scsi_qla_host_t *ha;
+  int    size = 0;
+  int  targ_lun;
+  scsi_lu_t  *up;
+  int   no_devices;
+
+  printk("Entering proc_info 0x%p,0x%lx,0x%x,0x%x\n",buffer,offset,length,hostno);
+  host = NULL;
+  /* find the host they want to look at */
+  for(ha=qla1280_hostlist; (ha != NULL) && ha->host->host_no != hostno; ha=ha->next)
+    ;
+
+  if (!ha)
+  {
+    size += sprintf(buffer, "Can't find adapter for host number %d\n", hostno);
+    if (size > length)
+    {
+      return (size);
+    }
+    else
+    {
+      return (length);
+    }
+  }
+
+  host = ha->host;
+  if (inout == TRUE) /* Has data been written to the file? */ 
+  {
+    return (qla1280_set_info(buffer, length, host));
+  }
+
+  /* compute number of active devices */
+  no_devices = 0;
+  for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++)
+  {
+          if( (up = ha->dev[targ_lun]) == NULL )
+              continue;
+          no_devices++;
+  }
+  /* size = 112 * no_devices; */
+  size = 4096;
+  /* round up to the next page */
+  
+  /* 
+   * if our old buffer is the right size use it otherwise 
+   * allocate a new one.
+   */
+  if (qla1280_buffer_size != size)
+  {
+    /* deallocate this buffer and get a new one */
+    if (qla1280_buffer != NULL) 
+    {
+      kfree(qla1280_buffer);
+      qla1280_buffer_size = 0;
+    }
+    qla1280_buffer = kmalloc(size, GFP_KERNEL);
+  }
+  if (qla1280_buffer == NULL)
+  {
+    size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n",
+        __LINE__);
+    return size;
+  }
+  qla1280_buffer_size = size;
+
+  size = 0;
+  size += sprintf(PROC_BUF, "Qlogic 1280/1080 SCSI driver version: ");   /* 43 bytes */
+  size += sprintf(PROC_BUF, "%5s, ", QLA1280_VERSION);                         /* 5        */
+  size += sprintf(PROC_BUF, "Qlogic Firmware version: ");                     /* 25       */
+  size += sprintf(PROC_BUF, "%2d.%2d.%2d",_firmware_version[0],           /* 8        */
+                                          ql12_firmware_version[1],
+                                          ql12_firmware_version[2]);
+  size += sprintf(PROC_BUF, "\n");                                             /* 1       */
+                           
+  size += sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n", QLBoardTbl[ha->devnum].bdName);
+  size += sprintf(PROC_BUF, "Request Queue = 0x%lx, Response Queue = 0x%lx\n",
+                        ha->request_dma,
+                        ha->response_dma);
+  size += sprintf(PROC_BUF, "Request Queue count= 0x%x, Response Queue count= 0x%x\n",
+                        REQUEST_ENTRY_CNT,
+                        RESPONSE_ENTRY_CNT);
+  size += sprintf(PROC_BUF,"Number of pending commands = 0x%lx\n", ha->actthreads);
+  size += sprintf(PROC_BUF,"Number of queued commands = 0x%lx\n", ha->qthreads);
+  size += sprintf(PROC_BUF,"Number of free request entries = %d\n",ha->req_q_cnt);
+  size += sprintf(PROC_BUF, "\n");                                             /* 1       */
+                        
+  size += sprintf(PROC_BUF, "Attached devices:\n");
+  /* scan for all equipment stats */ 
+  for (targ_lun = 0; targ_lun < MAX_EQ; targ_lun++)
+  {
+      if( (up = ha->dev[targ_lun]) == NULL )
+           continue;
+      if( up->io_cnt == 0 )
+      {
+          size += sprintf(PROC_BUF,"(%2d:%2d:%2d) No stats\n",LUN_ID);
+           continue;
+      }
+      /* total reads since boot */
+      /* total writes since boot */
+      /* total requests since boot  */
+      size += sprintf(PROC_BUF, "Total requests %ld,",up->io_cnt);
+      /* current number of pending requests */
+      size += sprintf(PROC_BUF, "(%2d:%2d:%2d) pending requests %d,",LUN_ID,up->q_outcnt);
+      /* avg response time */
+      size += sprintf(PROC_BUF, "Avg response time %ld%%,",(up->resp_time/up->io_cnt)*100);
+      
+      /* avg active time */
+      size += sprintf(PROC_BUF, "Avg active time %ld%%\n",(up->act_time/up->io_cnt)*100);
+  }
+
+  if (size >= qla1280_buffer_size)
+  {
+    printk(KERN_WARNING "qla1280: Overflow buffer in qla1280_proc.c\n");
+  }
+
+  if (offset > size - 1)
+  {
+    kfree(qla1280_buffer);
+    qla1280_buffer = NULL;
+    qla1280_buffer_size = length = 0;
+    *start = NULL;
+  }
+  else
+  {
+    *start = &qla1280_buffer[offset];   /* Start of wanted data */
+    if (size - offset < length)
+    {
+      length = size - offset;
+    }
+  }
+#endif
+
+  return (length);
+}
+
+
+/**************************************************************************
+ * qla1280_detect
+ *    This routine will probe for Qlogic 1280 SCSI host adapters.
+ *    It returns the number of host adapters of a particular
+ *    type that were found.	 It also initialize all data necessary for 
+ *    the driver.  It is passed-in the host number, so that it
+ *    knows where its first entry is in the scsi_hosts[] array.
+ *
+ * Input:
+ *     template - pointer to SCSI template
+ *
+ * Returns:
+ *  num - number of host adapters found.  
+ **************************************************************************/
+int
+qla1280_detect(Scsi_Host_Template *template)
+{
+    int num_hosts = 0;
+    struct Scsi_Host *host;
+    scsi_qla_host_t *ha, *cur_ha;
+    struct _qlaboards  *bdp;
+    int i, j;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,95)
+    unsigned int piobase;
+    unsigned char pci_bus, pci_devfn, pci_irq;
+    config_reg_t   *cfgp = 0;
+#endif
+    device_reg_t   *reg;
+    char   *cp;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+    struct pci_dev *pdev = NULL;
+#else
+    int index;
+#endif
+
+    ENTER("qla1280_detect");
+
+#ifdef CHECKSRBSIZE
+    if (sizeof(srb_t) > sizeof(Scsi_Pointer) )
+    {
+      printk("Redefine SRB - its too big");
+      return 0;
+    }
+#endif
+
+#ifdef MODULE
+	DEBUG(sprintf(debug_buff,"DEBUG: qla1280_detect starts at address = %p\n",qla1280_detect);)
+	DEBUG(qla1280_print(debug_buff);)
+    /*
+    * If we are called as a module, the qla1280 pointer may not be null
+    * and it would point to our bootup string, just like on the lilo
+    * command line.  IF not NULL, then process this config string with
+    * qla1280_setup
+    *
+    * Boot time Options
+    * To add options at boot time add a line to your lilo.conf file like:
+    * append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}"
+    * which will result in the first four devices on the first two
+    * controllers being set to a tagged queue depth of 32.
+    */
+    if(options)
+        qla1280_setup(options, NULL);
+    if(dummy_buffer[0] != 'P')
+        printk(KERN_WARNING "qla1280: Please read the file /usr/src/linux/drivers"
+                "/scsi/README.qla1280\n"
+                "qla1280: to see the proper way to specify options to the qla1280 "
+                "module\n"
+                "qla1280: Specifically, don't use any commas when passing arguments to\n"
+                "qla1280: insmod or else it might trash certain memory areas.\n");
+#endif
+
+    if ((int) !pcibios_present())
+    {
+		printk("scsi: PCI not present\n");
+		return 0;
+    } /* end of IF */
+    bdp = &QLBoardTbl[0];
+    qla1280_hostlist = NULL;
+#if 0
+    template->proc_dir = &proc_scsi_qla1280;
+#else
+    template->proc_name = "qla1280";
+#endif
+    
+	/* Try and find each different type of adapter we support */
+	for( i=0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; i++, bdp++ ) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+		while ((pdev = pci_find_device(QLA1280_VENDOR_ID,
+			bdp->device_id, pdev ) ))  
+#else
+		while (!(pcibios_find_device(QLA1280_VENDOR_ID,
+			bdp->device_id,
+			index++, &pci_bus, &pci_devfn)) )  
+#endif
+                {
+                /* found a adapter */
+		host = scsi_register(template, sizeof(scsi_qla_host_t));
+		ha = (scsi_qla_host_t *) host->hostdata;
+		/* Clear our data area */
+		for( j =0, cp = (char *)ha;  j < sizeof(scsi_qla_host_t); j++)
+			*cp = 0;
+		/* Sanitize the information from PCI BIOS.  */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+		host->irq = pdev->irq;
+/* this depends on release 2.3.18 */
+		host->io_port = pdev->resource[0].start;
+/* MRS	host->io_port = (unsigned int) pdev->base_address[0]; */
+		ha->pci_bus = pdev->bus->number;
+		ha->pci_device_fn = pdev->devfn;
+		ha->pdev = pdev;
+#else
+		pcibios_read_config_byte(pci_bus, pci_devfn, OFFSET(cfgp->interrupt_line), &pci_irq);
+		pcibios_read_config_dword(pci_bus, pci_devfn, OFFSET(cfgp->base_port), &piobase);
+		host->irq = pci_irq;
+		host->io_port = (unsigned int) piobase;
+		ha->pci_bus = pci_bus;
+		ha->pci_device_fn = pci_devfn;
+#endif
+		ha->device_id = bdp->device_id;
+		host->io_port &= PCI_BASE_ADDRESS_IO_MASK;
+    
+                ha->devnum = i;
+                host->io_port &= PCI_BASE_ADDRESS_IO_MASK;
+		if( qla1280_mem_alloc(ha) ) {
+			printk(KERN_INFO "qla1280: Failed to allocate memory for adapter\n");
+		}
+                
+                ha->ports = bdp->numPorts; 
+                ha->iobase = (device_reg_t *) host->io_port;
+                ha->host = host;
+                ha->host_no = host->host_no;
+
+                /* load the F/W, read paramaters, and init the H/W */
+                if (qla1280_initialize_adapter(ha))
+                {
+
+                    printk(KERN_INFO "qla1280: Failed to initialized adapter\n");
+                    qla1280_mem_free(ha);
+                    scsi_unregister(host);
+                    continue;
+                }
+                
+                host->max_channel = bdp->numPorts-1; 
+                ha->instance = num_hosts;
+		/* Register our resources with Linux */
+		if( qla1280_register_with_Linux(ha, bdp->numPorts-1) ) {
+			printk(KERN_INFO "qla1280: Failed to register our resources\n");
+			qla1280_mem_free(ha);
+			scsi_unregister(host);
+			continue;
+		}
+
+
+                reg = ha->iobase;
+                /* Disable ISP interrupts. */
+		qla1280_disable_intrs(ha);
+
+                /* Insure mailbox registers are free. */
+                WRT_REG_WORD(&reg->semaphore, 0);
+                WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+                WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);
+
+                /* Enable chip interrupts. */
+		qla1280_enable_intrs(ha);
+               
+                /* Insert new entry into the list of adapters */
+                ha->next = NULL;
+                if( qla1280_hostlist == NULL )
+                {
+                    cur_ha = qla1280_hostlist = ha;
+                }
+                else
+                {
+                    cur_ha = qla1280_hostlist;
+                    while( cur_ha->next != NULL )
+                        cur_ha = cur_ha->next;
+                    cur_ha->next = ha;
+                }
+                num_hosts++;
+            }  /* end of WHILE */
+        } /* end of FOR */
+
+    LEAVE("qla1280_detect");
+    return num_hosts; 
+}
+
+/**************************************************************************
+*   qla1280_register_with_Linux
+*
+* Description:
+*   Free the passed in Scsi_Host memory structures prior to unloading the
+*   module.
+*
+* Input:
+*     ha - pointer to host adapter structure
+*     maxchannels - MAX number of channels.
+*
+* Returns:
+*  0 - Sucessfully reserved resources.
+*  1 - Failed to reserved a resource.
+**************************************************************************/
+STATIC uint8_t  qla1280_register_with_Linux(scsi_qla_host_t *ha, uint8_t maxchannels)
+{
+
+	struct Scsi_Host *host = ha->host;
+
+	host->can_queue = 0xfffff;  /* unlimited  */
+	host->cmd_per_lun = 1;
+       host->select_queue_depths = qla1280_select_queue_depth;
+	host->n_io_port = 0xFF;
+	host->base = (unsigned long) ha->mmpbase;
+	host->max_channel = maxchannels; 
+       host->max_lun = MAX_LUNS-1; 
+	host->unique_id = ha->instance;
+       host->max_id = MAX_TARGETS; 
+       host->unique_id = ha->instance;
+
+	/* set our host ID  (need to do something about our two IDs) */
+       host->this_id = ha->bus_settings[0].id;
+       /* Register the IRQ with Linux (sharable) */
+       if ( request_irq(host->irq, qla1280_intr_handler, SA_INTERRUPT| SA_SHIRQ, "qla1280", ha))
+       {
+          printk("qla1280 : Failed to reserved interrupt %d already in use\n", host->irq);
+          qla1280_mem_free(ha);
+          scsi_unregister(host);
+	     return 1;
+       }
+
+       /* Register the I/O space with Linux */
+       if (check_region(host->io_port, 0xff))
+       {
+           printk("qla1280 : Failed to reserved i/o region 0x%04lx-0x%04lx already in use\n",
+              host->io_port, host->io_port + 0xff);
+           free_irq(host->irq, NULL);
+           qla1280_mem_free(ha);
+           scsi_unregister(host);
+	     return 1;
+       }
+
+       request_region(host->io_port, 0xff, "qla1280");
+
+	return 0;
+}
+
+
+/**************************************************************************
+ *   qla1280_release
+ *   Free the passed in Scsi_Host memory structures prior to unloading the
+ *   module.
+ **************************************************************************/
+int
+qla1280_release(struct Scsi_Host *host)
+{
+    scsi_qla_host_t *ha = (scsi_qla_host_t *) host->hostdata;
+
+    ENTER("qla1280_release");
+
+    if( !ha->flags.online )
+        return(0);
+
+    /* turn-off interrupts on the card */
+    WRT_REG_WORD(&ha->iobase->ictrl, 0);
+
+    /* Detach interrupts */
+    if(host->irq)
+        free_irq(host->irq, ha);
+
+    /* release io space registers  */
+    if( host->io_port )
+        release_region(host->io_port, 0xff);
+
+#if MEMORY_MAPPED_IO
+    if(ha->mmpbase)
+    {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+        vfree((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK));
+#else
+        iounmap((void *) (((unsigned long) ha->mmpbase) & PAGE_MASK));
+#endif
+    }
+#endif /* MEMORY_MAPPED_IO */
+    qla1280_mem_free(ha);
+
+    ENTER("qla1280_release");
+    return(0);
+}
+
+/**************************************************************************
+ *   qla1280_info
+ *     Return a string describing the driver.
+ **************************************************************************/
+const char *
+qla1280_info(struct Scsi_Host *host)
+{
+    static char qla1280_buffer[125];
+    char *bp;
+    scsi_qla_host_t *ha;
+    qla_boards_t   *bdp; 
+
+    bp = &qla1280_buffer[0];
+    ha = (scsi_qla_host_t *)host->hostdata;
+    bdp = &QLBoardTbl[ha->devnum];
+    memset(bp, 0, sizeof(qla1280_buffer));
+    sprintf(bp,
+            "QLogic %sPCI to SCSI Host Adapter: bus %d device %d irq %d\n"
+            "       Firmware version: %2d.%02d.%02d, Driver version %s",
+            (char *)&bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3, host->irq,
+            bdp->fwver[0],bdp->fwver[1],bdp->fwver[2],
+            QLA1280_VERSION);
+    return(bp);
+}
+
+/**************************************************************************
+ *   qla1200_queuecommand
+ *     Queue a command to the controller.
+ *
+ * Note:
+ * The mid-level driver tries to ensures that queuecommand never gets invoked
+ * concurrently with itself or the interrupt handler (although the
+ * interrupt handler may call this routine as part of request-completion
+ * handling).   Unfortunely, it sometimes calls the scheduler in interrupt
+ * context which is a big NO! NO!.
+ **************************************************************************/
+int
+qla1280_queuecommand(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
+{
+    scsi_qla_host_t *ha;
+    srb_t  *sp;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    struct Scsi_Host *host;
+    uint32_t        b, t, l;
+    scsi_lu_t       *q;
+    u_long          handle;
+
+    ENTER("qla1280_queuecommand");
+    COMTRACE('C') 
+
+    host = cmd->host;
+    ha = (scsi_qla_host_t *) host->hostdata;
+
+    /* send command to adapter */
+    sp = (srb_t *) CMD_SP(cmd);
+    sp->cmd =  cmd;
+    cmd->scsi_done = fn;
+    if (cmd->flags == 0)  /* new command */
+    {
+        sp->flags = 0;
+    }
+
+    DEBUG5(qla1280_print_scsi_cmd(cmd));
+
+    /* Generate LU queue on bus, target, LUN */
+    b = SCSI_BUS_32(cmd);
+    t = SCSI_TCN_32(cmd);
+    l = SCSI_LUN_32(cmd);
+    if((q = LU_Q(ha, b, t, l)) == NULL )
+    {
+        DRIVER_LOCK
+        if( (q = (scsi_lu_t *)KMALLOC(sizeof(struct scsi_lu))) )
+        {
+           LU_Q(ha, b, t, l) = q;
+           BZERO(q,sizeof(struct scsi_lu));
+           DEBUG(sprintf(debug_buff,"Allocate new device queue 0x%x\n",q));
+           DEBUG(qla1280_print(debug_buff));
+           DRIVER_UNLOCK
+        }
+        else
+        {
+            CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16);
+            qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
+            queue_task(&ha->run_qla_bh,&tq_scheduler); 
+            ha->flags.dpc_sched = TRUE;
+            DRIVER_UNLOCK
+            return(0);
+        }
+    }
+    /* Set an invalid handle until we issue the command to ISP */
+    /* then we will set the real handle value.                 */
+    handle = INVALID_HANDLE;  
+    CMD_HANDLE(cmd) = (unsigned char *)handle;
+
+    /* Bookkeeping information */
+    sp->r_start = jiffies;       /* time the request was recieved */
+    sp->u_start = 0;              
+
+    /* add the command to our queue */
+    ha->qthreads++;
+    qla1280_putq_t(q,sp);
+    
+    DEBUG(sprintf(debug_buff,"qla1280_queuecmd: queue pid=%d, hndl=0x%x\n\r",cmd->pid,handle));
+    DEBUG(qla1280_print(debug_buff));
+
+    /* send command to adapter */
+    DRIVER_LOCK
+        if (q->q_outcnt == 0)
+            qla1280_restart_queues(ha);
+    DRIVER_UNLOCK
+    
+    
+    LEAVE("qla1280_queuecommand");
+    return (0);
+}
+
+/**************************************************************************
+ *   qla1200_abort
+ *     Abort the speciifed SCSI command(s).
+ **************************************************************************/
+int
+qla1280_abort(Scsi_Cmnd *cmd)
+{
+    scsi_qla_host_t *ha;
+    srb_t  *sp;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    struct Scsi_Host *host;
+    uint32_t        b, t, l;
+    scsi_lu_t       *q;
+    int return_status = SCSI_ABORT_SUCCESS;
+    int found = 0;
+    int i;
+    u_long     handle;
+    u_short    data;
+
+    ENTER("qla1280_abort");
+    COMTRACE('A')
+    ha = (scsi_qla_host_t *) cmd->host->hostdata;
+    host = cmd->host;
+    DRIVER_LOCK
+
+    /* Get the SCSI request ptr */
+    sp = (srb_t *) CMD_SP(cmd);
+    handle = (u_long) CMD_HANDLE(cmd);
+    if (qla1280_verbose)
+        printk("scsi(%d): ABORT Command=0x%lx, handle=0x%lx\n",(int)ha->host_no,(long)cmd,handle);
+
+    /* Check for pending interrupts. */
+    if( handle == 0L )
+    {
+    COMTRACE('a')
+        /* we never got this command */
+        printk(KERN_INFO "qla1280: Aborting a NULL handle\n");
+        DRIVER_UNLOCK
+                return(SCSI_ABORT_NOT_RUNNING);  /* no action - we don't have command */
+    }
+    data = qla1280_debounce_register(&ha->iobase->istatus);
+    if( !(ha->flags.in_isr) && (data & RISC_INT) )
+    {
+        /* put any pending command in done queue */
+        qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    }
+
+    handle = (u_long) CMD_HANDLE(cmd);
+
+    /* Generate LU queue on bus, target, LUN */
+    b = SCSI_BUS_32(cmd);
+    t = SCSI_TCN_32(cmd);
+    l = SCSI_LUN_32(cmd);
+    if((q = LU_Q(ha, b, t, l)) == NULL )
+    {
+    COMTRACE('a')
+        /* No lun queue -- command must not be active */
+        DRIVER_UNLOCK
+        printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the specified device\n",(int)b,(int)t,(int)l);
+        return(SCSI_ABORT_NOT_RUNNING);  /* no action - we don't have command */
+    }
+
+#if AUTO_ESCALATE_ABORT
+    if ( (sp->flags & SRB_ABORTED) )
+    {
+        DRIVER_UNLOCK
+        DEBUG(qla1280_print("qla1280_abort: Abort escalayted - returning SCSI_ABORT_SNOOZE.\n\r"));
+        return(SCSI_ABORT_SNOOZE);
+    }
+#endif
+
+    if ( (sp->flags & SRB_ABORT_PENDING) )
+    {
+    COMTRACE('a')
+        DRIVER_UNLOCK
+        if( qla1280_verbose  )
+            printk("scsi(): Command has a pending abort message - ABORT_PENDING.\n");
+        DEBUG(qla1280_print("qla1280: Command has a pending abort message - ABORT_PENDING.\n\r"));
+        return(SCSI_ABORT_PENDING);
+    }
+
+#if  STOP_ON_ABORT 
+    printk("Scsi layer issued a ABORT command= 0x%x\n",(int)cmd);
+    DEBUG2(qla1280_print_scsi_cmd(cmd));
+#endif
+
+    ha->flags.in_abort = TRUE;
+    /*
+    * Normally, would would need to search our queue for the specified command
+    * but; since our sp contains the cmd ptr, we can just remove it from our
+    * LUN queue.
+    */
+    if( !(sp->flags&SRB_SENT) )
+    { 
+        found++;
+        if( qla1280_verbose  )
+            printk("scsi(): Command returned from queue aborted.\n");
+        DEBUG(qla1280_print("qla1280: Command returned from queue aborted.\n\r"));
+        /* Remove srb from SCSI LU queue. */
+        qla1280_removeq(q, sp);
+        sp->flags |=  SRB_ABORTED;
+        CMD_RESULT(cmd) = DID_ABORT << 16; 
+        qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
+        return_status = SCSI_ABORT_SUCCESS;
+    }
+    else
+    {  /* find the command in our active list */
+        for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++)
+        {
+            if( sp == ha->outstanding_cmds[i] )
+            {
+                found++;
+                DEBUG(qla1280_print("qla1280: RISC aborting command.\n\r"));
+                qla1280_abort_command(ha,sp);
+                return_status = SCSI_ABORT_PENDING;
+                break;
+            }
+        }
+    }
+
+#if  STOP_ON_ABORT 
+    qla1280_panic("qla1280_abort",ha->host);
+#endif
+    if ( found == 0 )
+        return_status = SCSI_ABORT_NOT_RUNNING;  /* no action - we don't have command */
+
+    DEBUG(sprintf(debug_buff, "qla1280_abort: Aborted status returned = 0x%x.\n\r",return_status));
+    DEBUG(qla1280_print(debug_buff));
+
+    if( ha->done_q_first )
+       qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    if ( found )
+    {
+        qla1280_restart_queues(ha);
+    }
+    ha->flags.in_abort = FALSE;
+    DRIVER_UNLOCK
+
+    LEAVE("qla1280_abort");
+    COMTRACE('a')
+    return(return_status);
+}
+
+/**************************************************************************
+ * qla1200_reset
+ *    The reset function will reset the SCSI bus and abort any executing
+ *    commands. 
+ *
+ * Input:
+ *      cmd = Linux SCSI command packet of the command that cause the
+ *            bus reset.
+ *      flags = SCSI bus reset option flags (see scsi.h)
+ *
+ * Returns:
+ *      DID_RESET in cmd.host_byte of aborted command(s) 
+ *
+ * Note:
+ *      Resetting the bus always succeeds - is has to, otherwise the
+ *      kernel will panic! Try a surgical technique - sending a BUS
+ *      DEVICE RESET message - on the offending target before pulling
+ *      the SCSI bus reset line.
+ **************************************************************************/
+int
+qla1280_reset(Scsi_Cmnd *cmd, unsigned int flags)
+{
+    scsi_qla_host_t *ha;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    uint32_t        b, t, l;
+    srb_t  *sp;
+    typedef enum
+    {
+        ABORT_DEVICE = 1, 
+                DEVICE_RESET = 2, 
+                BUS_RESET    = 3, 
+                ADAPTER_RESET= 4,
+                RESET_DELAYED= 5,
+                FAIL         = 6
+    } action_t;
+    action_t     action = ADAPTER_RESET;
+    u_short    data;
+    scsi_lu_t       *q;
+    int result;
+
+
+    ENTER("qla1280_reset");
+    COMTRACE('R')
+    if (qla1280_verbose)
+        printk("scsi(): Resetting Cmnd=0x%lx, Handle=0x%lx, flags=0x%x\n",(long)cmd,(long)CMD_HANDLE(cmd),flags);
+    if ( cmd == NULL )
+    {
+        printk(KERN_WARNING "(scsi?:?:?:?) Reset called with NULL Scsi_Cmnd "
+                "pointer, failing.\n");
+        return(SCSI_RESET_SNOOZE);
+    }
+    ha = (scsi_qla_host_t *) cmd->host->hostdata;
+    sp = (srb_t *) CMD_SP(cmd);
+
+#if  STOP_ON_RESET 
+    qla1280_panic("qla1280_reset",ha->host);
+#endif 
+
+    DRIVER_LOCK
+    /* Check for pending interrupts. */
+    data = qla1280_debounce_register(&ha->iobase->istatus);
+    if( !(ha->flags.in_isr) && (data & RISC_INT) )
+    {
+        qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    }
+    DRIVER_UNLOCK
+
+    /*
+    * Determine the suggested action that the mid-level driver wants
+    * us to perform.
+    */
+    if( CMD_HANDLE(cmd) == (unsigned char *) 0  )
+    {
+        /* 
+        * if mid-level driver called reset with a orphan SCSI_Cmnd 
+        * (i.e. a command that's not pending ), so perform the 
+        * function specified.
+        */
+        if( (flags & SCSI_RESET_SUGGEST_HOST_RESET) )
+            action = ADAPTER_RESET;
+        else 
+            action = BUS_RESET;
+    }
+    else
+    { /* 
+        * Mid-level driver has called reset with this SCSI_Cmnd and 
+        * its pending.
+        */
+        if( flags & SCSI_RESET_SUGGEST_HOST_RESET )
+            action = ADAPTER_RESET;
+        else if( flags & SCSI_RESET_SUGGEST_BUS_RESET )
+            action = BUS_RESET;
+        else 
+            action = DEVICE_RESET;
+    }
+
+    b = SCSI_BUS_32(cmd);
+    t = SCSI_TCN_32(cmd);
+    l = SCSI_LUN_32(cmd);
+    q = LU_Q(ha, b, t, l);
+
+#if AUTO_ESCALATE_RESET
+    if ( (action & DEVICE_RESET) && (q->q_flag & QLA1280_QRESET) )
+    {
+        printk(KERN_INFO "qla1280(%d): Bus device reset already sent to " "device, escalating.\n", (int)ha->host_no);
+        action = BUS_RESET;
+    }
+    if ( (action & DEVICE_RESET) && (sp->flags & SRB_ABORT_PENDING) )
+    {
+        printk(KERN_INFO "qla1280(%d):Have already attempted to reach " "device with abort device\n", (int)ha->host_no);
+        printk(KERN_INFO "qla1280(%d):message, will escalate to BUS " "RESET.\n",(int) ha->host_no);
+        action = BUS_RESET;
+    }
+#endif
+
+    /*
+    *  By this point, we want to already know what we are going to do,
+    *  so we only need to perform the course of action.
+    */
+    DRIVER_LOCK
+    result = SCSI_RESET_ERROR;
+    switch (action)
+    {
+        case FAIL:
+            break;
+
+        case RESET_DELAYED:
+            result = SCSI_RESET_PENDING;
+            break;
+
+        case ABORT_DEVICE:
+            ha->flags.in_reset = TRUE;
+            if (qla1280_verbose)
+                printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing abort device command.\n", (int)ha->host_no,(int)b,(int)t,(int)l); 
+            qla1280_abort_queue_single(ha,b,t,l,DID_ABORT);
+            if( qla1280_abort_device(ha, b, t, l) == 0)
+                result = SCSI_RESET_PENDING;
+            break;
+
+        case DEVICE_RESET:
+            if (qla1280_verbose)
+                printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing device reset command.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
+            ha->flags.in_reset = TRUE;
+            for (l = 0; l < MAX_LUNS; l++)
+                qla1280_abort_queue_single(ha,b,t,l,DID_ABORT);
+            if( qla1280_device_reset(ha, b, t) == 0 ) 
+                result = SCSI_RESET_PENDING;
+            q->q_flag |= QLA1280_QRESET;
+            break;
+
+        case BUS_RESET:
+                if (qla1280_verbose)
+                    printk(KERN_INFO "qla1280(%d:%d:%d:%d): Issuing BUS DEVICE RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
+            ha->flags.in_reset = TRUE;
+            for (t = 0; t < MAX_TARGETS; t++)
+                for (l = 0; l < MAX_LUNS; l++)
+                    qla1280_abort_queue_single(ha,b,t,l,DID_RESET);
+                qla1280_bus_reset(ha, b);
+                /*
+                * The bus reset routine returns all the outstanding commands back
+                * with "DID_RESET" in the status field after a short delay
+                * by the firmware. If the mid-level time out the SCSI reset before
+                * our delay we may need to ignore it.
+                */
+                /* result = SCSI_RESET_PENDING | SCSI_RESET_BUS_RESET; */
+                result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
+                mdelay(4 * 1000); barrier();
+                if( flags & SCSI_RESET_SYNCHRONOUS )
+                {
+                  CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16);
+                  (*(cmd)->scsi_done)(cmd); 
+                }
+                /* ha->reset_start = jiffies; */
+                break;
+
+            case ADAPTER_RESET:
+            default:
+                if (qla1280_verbose)
+                {
+                    printk(KERN_INFO "scsi(%d:%d:%d:%d): Issued an ADAPTER RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
+                    printk(KERN_INFO "scsi(%d:%d:%d:%d): I/O processing will continue automatically.\n",(int) ha->host_no,(int)b,(int)t,(int)l); 
+                }
+                ha->flags.reset_active = TRUE;
+                /* 
+                * We restarted all of the commands automatically, so the mid-level code can expect 
+                * completions momentitarily.
+                */
+                if( qla1280_abort_isp(ha) == 0 )
+                    result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
+
+                        ha->flags.reset_active = FALSE;
+    }
+
+    if( ha->done_q_first ) 
+        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    qla1280_restart_queues(ha);
+    ha->flags.in_reset = FALSE;
+    
+DRIVER_UNLOCK
+    DEBUG(printk("RESET returning %d\n", result)); 
+
+    COMTRACE('r')
+    LEAVE("qla1280_reset");
+    return( result );
+}
+
+/**************************************************************************
+ * qla1200_biosparam
+ *   Return the disk geometry for the given SCSI device.
+ **************************************************************************/
+int
+qla1280_biosparam(Disk *disk, kdev_t dev, int geom[])
+{
+    int heads, sectors, cylinders;
+
+            heads = 64;
+    sectors = 32;
+    cylinders = disk->capacity / (heads * sectors);
+    if (cylinders > 1024)
+    {
+        heads = 255;
+        sectors = 63;
+        cylinders = disk->capacity / (heads * sectors);
+        /* if (cylinders > 1023)
+        cylinders = 1023; */
+    }
+
+    geom[0] = heads;
+    geom[1] = sectors;
+    geom[2] = cylinders;
+
+    return (0);
+}
+/**************************************************************************
+ * qla1280_intr_handler
+ *   Handles the H/W interrupt
+ **************************************************************************/
+void qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    scsi_qla_host_t *ha;
+    u_short    data;
+    device_reg_t *reg;
+
+    ENTER_INTR("qla1280_intr_handler");
+    COMTRACE('I')
+    ha = (scsi_qla_host_t *) dev_id;
+    if(!ha)
+    {
+        printk(KERN_INFO "scsi(): Interrupt with NULL host ptr\n");
+        COMTRACE('X')
+        return;
+    }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,95)
+    spin_lock_irqsave(&io_request_lock, cpu_flags);
+    if(test_and_set_bit(QLA1280_IN_ISR_BIT, &ha->flags))
+    {
+        COMTRACE('X')
+        return;
+    }
+    ha->isr_count++;
+    reg = ha->iobase;
+     /* disable our interrupt. */
+    WRT_REG_WORD(&reg->ictrl, 0); 
+    data = qla1280_debounce_register(&reg->istatus);
+    /* Check for pending interrupts. */
+    if ( !(data & RISC_INT) )
+    {
+        /* spurious interrupts can happen legally */
+        DEBUG(printk("scsi(%d): Spurious interrupt - ignoring\n",(int)ha->host_no));
+        COMTRACE('X')
+    }
+    else
+      qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    if (ha->done_q_first)
+        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+
+    clear_bit(QLA1280_IN_ISR_BIT, &ha->flags);
+    spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+#else  /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) */
+
+    if( test_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags) )
+    {
+          COMTRACE('X')
+          printk(KERN_INFO "scsi(%d): Already in interrupt - returning \n", (int)ha->host_no);
+          return;
+    }
+    set_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags);
+    ha->isr_count++;
+    reg = ha->iobase;
+     /* disable our interrupt. */
+    WRT_REG_WORD(&reg->ictrl, 0); 
+
+    data = qla1280_debounce_register(&reg->istatus);
+    /* Check for pending interrupts. */
+    if ( !(data & RISC_INT) )
+    {
+        /* spurious interrupts can happen legally */
+        DEBUG(printk("scsi(%d): Spurious interrupt - ignoring\n",(int)ha->host_no));
+        COMTRACE('X')
+    }
+    else
+     qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+
+    /* if no work to do then call the SCSI mid-level right away */
+    if( ha->done_q_first )
+        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+
+    /* Schedule the DPC routine */
+    if (ha->flags.isp_abort_needed || ha->flags.reset_marker ||
+            ha->done_q_first        )
+        {
+            ha->run_qla_bh.data = (void *) ha;
+            ha->run_qla_bh.routine = qla1280_do_dpc; 
+
+             COMTRACE('P') 
+            queue_task_irq(&ha->run_qla_bh,&tq_scheduler); 
+            ha->flags.dpc_sched = TRUE;
+        }
+        clear_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags);
+#endif
+     /* enable our interrupt. */
+        WRT_REG_WORD(&reg->ictrl, ISP_EN_INT + ISP_EN_RISC);
+
+        COMTRACE('i')  
+        LEAVE_INTR("qla1280_intr_handler");
+}
+
+/**************************************************************************
+ *   qla1280_do_dpc
+ *
+ * Description:
+ * This routine is a task that is schedule by the interrupt handler 
+ * to perform the background processing for interrupts.  We put it 
+ * on a task queue that is consumed whenever the scheduler runs; that's
+ * so you can do anything (i.e. put the process to sleep etc).  In fact, the 
+ * mid-level tries to sleep when it reaches the driver threshold 
+ * "host->can_queue". This can cause a panic if we were in our interrupt
+ * code .
+ **************************************************************************/
+void qla1280_do_dpc(void *p)
+{
+    scsi_qla_host_t *ha = (scsi_qla_host_t *) p;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+    COMTRACE('p')  
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+    spin_lock_irqsave(&io_request_lock, cpu_flags);
+#endif
+    if (ha->flags.isp_abort_needed)
+        qla1280_abort_isp(ha);
+
+    if (ha->flags.reset_marker)
+        qla1280_rst_aen(ha);
+
+    if (ha->done_q_first)
+        qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+    ha->flags.dpc_sched = FALSE;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95)
+    spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+#endif
+}
+
+/**************************************************************************
+ *   qla1280_device_queue_depth
+ *
+ * Description:
+ *   Determines the queue depth for a given device.  There are two ways
+ *   a queue depth can be obtained for a tagged queueing device.  One
+ *   way is the default queue depth which is determined by whether
+ *   If it is defined, then it is used
+ *   as the default queue depth.  Otherwise, we use either 4 or 8 as the
+ *   default queue depth (dependent on the number of hardware SCBs).
+ **************************************************************************/
+STATIC void qla1280_device_queue_depth(scsi_qla_host_t *p, Scsi_Device *device)
+{
+    int default_depth = 3;
+    int bus = device->channel;
+    int target = device->id;
+
+    device->queue_depth = default_depth;
+
+    if (device->tagged_supported &&
+        (p->bus_settings[bus].qtag_enables & (BIT_0 << target)) )
+    {
+        device->tagged_queue = 1;
+        device->current_tag = 0;
+        device->queue_depth = p->bus_settings[bus].hiwat; 
+        /* device->queue_depth = 20; */
+        printk(KERN_INFO "scsi(%d:%d:%d:%d): Enabled tagged queuing, queue depth %d.\n",
+                (int)p->host_no, device->channel, device->id,
+                device->lun, device->queue_depth);
+    }
+    qla12160_get_target_parameters(p, bus, target, device->lun);
+
+}
+
+/**************************************************************************
+ *   qla1280_select_queue_depth
+ *
+ *   Sets the queue depth for each SCSI device hanging off the input
+ *   host adapter.  We use a queue depth of 2 for devices that do not
+ *   support tagged queueing.
+ **************************************************************************/
+STATIC void
+qla1280_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs)
+{
+    Scsi_Device *device;
+    scsi_qla_host_t  *p = (scsi_qla_host_t *) host->hostdata;
+
+    ENTER("qla1280_select_queue_depth");
+    for (device = scsi_devs; device != NULL; device = device->next)
+    {
+        if (device->host == host)
+            qla1280_device_queue_depth(p, device);
+    }
+    LEAVE("qla1280_select_queue_depth");
+}
+
+/*--------------------------**
+** Driver Support Routines  **
+**--------------------------*/
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+/*
+ * mdelay
+ *      Delay in milliseconds 
+ *
+ * Input:
+ *      milliseconds  = delay 
+ */
+STATIC inline void mdelay(int milliseconds)
+{
+    int i;
+
+    for(i=0; i<milliseconds; i++)
+        udelay(1000);
+}
+#endif
+
+/*
+ * qla1280_done
+ *      Process completed commands.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ */
+STATIC void
+qla1280_done(scsi_qla_host_t *ha, srb_t **done_q_first, srb_t **done_q_last)
+{
+    srb_t           *sp;
+    scsi_lu_t       *q;
+    uint32_t        b, t, l;
+    Scsi_Cmnd  *cmd;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+    ENTER("qla1280_done");
+    COMTRACE('D') 
+
+    DRIVER_LOCK 
+    while (*done_q_first !=  NULL)
+    {
+        /* remove command from done list */
+                sp = *done_q_first;
+        if (!(*done_q_first = sp->s_next))
+            *done_q_last = NULL;
+        else
+            (*done_q_first)->s_prev = NULL;
+                cmd = sp->cmd;
+        b = SCSI_BUS_32(cmd);
+        t = SCSI_TCN_32(cmd);
+        l = SCSI_LUN_32(cmd);
+        q = LU_Q(ha, b, t, l);
+
+        /* Decrement outstanding commands on device. */
+        if (q->q_outcnt)
+            q->q_outcnt--;
+        if (q->q_outcnt < ha->bus_settings[b].hiwat)
+        {
+            q->q_flag &= ~QLA1280_QBUSY;
+        }
+        
+        q->resp_time += jiffies - sp->r_start;                /* Lun bookkeeping information */
+        q->act_time += jiffies - sp->u_start;
+        q->io_cnt++;
+        if( sp->dir & BIT_5 )
+         q->r_cnt++;
+        else
+         q->w_cnt++;
+
+        switch ( (CMD_RESULT(cmd)>>16))
+        {
+            case DID_RESET:
+                q->q_flag &= ~QLA1280_QRESET;
+                /* Issue marker command. */
+                qla1280_marker(ha, b, t, 0, MK_SYNC_ID); 
+                break;
+            case DID_ABORT:
+                sp->flags &= ~SRB_ABORT_PENDING;
+                sp->flags |= SRB_ABORTED;
+                if (sp->flags & SRB_TIMEOUT)
+                    CMD_RESULT(sp->cmd)= DID_TIME_OUT << 16;
+                break;
+            default:
+                break;
+        }
+
+        /* Call the mid-level driver interrupt handler */
+        CMD_HANDLE(sp->cmd) = (unsigned char *) 0;
+        ha->actthreads--;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+        sti(); 
+        (*(cmd)->scsi_done)(cmd);
+        cli(); 
+#else
+        (*(cmd)->scsi_done)(cmd);
+#endif
+        qla1280_next(ha, q, b);
+    }
+    DRIVER_UNLOCK 
+
+
+    COMTRACE('d') 
+    LEAVE("qla1280_done");
+}
+
+/*
+ * Translates a ISP error to a Linux SCSI error
+ */
+STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd       *cp)
+{
+    int host_status = DID_ERROR;
+#if DEBUG_QLA1280_INTR
+    STATIC char *reason[] =
+    {
+        "DID_OK",
+                "DID_NO_CONNECT",
+                "DID_BUS_BUSY",
+                "DID_TIME_OUT",
+                "DID_BAD_TARGET",
+                "DID_ABORT",
+                "DID_PARITY",
+                "DID_ERROR",
+                "DID_RESET",
+                "DID_BAD_INTR"
+    };
+#endif /* DEBUG_QLA1280_INTR */
+
+    ENTER("qla1280_return_status");
+
+#if DEBUG_QLA1280_INTR
+    /*
+    DEBUG(printk("qla1280_return_status: compl status = 0x%04x\n", sts->comp_status));
+    */
+#endif
+    switch(sts->comp_status)
+    {
+        case CS_COMPLETE:
+            host_status = DID_OK;
+            break;
+        case CS_INCOMPLETE:
+            if (!(sts->state_flags & SF_GOT_BUS))
+                host_status = DID_NO_CONNECT;
+            else if (!(sts->state_flags & SF_GOT_TARGET))
+                host_status = DID_BAD_TARGET;
+            else if (!(sts->state_flags & SF_SENT_CDB))
+                host_status = DID_ERROR;
+            else if (!(sts->state_flags & SF_TRANSFERRED_DATA))
+                host_status = DID_ERROR;
+            else if (!(sts->state_flags & SF_GOT_STATUS))
+                host_status = DID_ERROR;
+            else if (!(sts->state_flags & SF_GOT_SENSE))
+                host_status = DID_ERROR;
+            break;
+        case CS_RESET:
+            host_status = DID_RESET;
+            break;
+        case CS_ABORTED:
+            host_status = DID_ABORT;
+            break;
+        case CS_TIMEOUT:
+            host_status = DID_TIME_OUT;
+            break;
+        case CS_DATA_OVERRUN:
+#ifdef QL_DEBUG_LEVEL_2 
+            printk("Data overrun 0x%x\n",(int)sts->residual_length);
+            qla1280_print(
+                        "\n\rqla1280_isr: response packet data\n\r");
+                        qla1280_dump_buffer((caddr_t)sts,
+                        RESPONSE_ENTRY_SIZE); 
+#endif
+            host_status = DID_ERROR;
+            break;
+        case CS_DATA_UNDERRUN:
+            if ( (CMD_XFRLEN(cp) - sts->residual_length) < cp->underflow)    
+            { 
+              printk("scsi: Underflow detected - retrying command.\n");
+              host_status = DID_ERROR;
+            }
+            else
+                host_status = DID_OK;
+            break;
+        default:
+            host_status = DID_ERROR;
+            break;
+    }
+
+#if DEBUG_QLA1280_INTR
+    sprintf(debug_buff, "qla1280 ISP status: host status (%s) scsi status %x\n\r", reason[host_status], sts->scsi_status);
+    qla1280_print(debug_buff);
+#endif
+
+    LEAVE("qla1280_return_status");
+
+    return (sts->scsi_status & 0xff) | (host_status << 16);
+}
+
+/*
+ * qla1280_done_q_put
+ *      Place SRB command on done queue.
+ *
+ * Input:
+ *      sp           = srb pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ */
+STATIC void
+qla1280_done_q_put(srb_t *sp, srb_t **done_q_first, srb_t **done_q_last)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_put_done_q");
+#endif
+    /* Place block on done queue */
+    DRIVER_LOCK
+            sp->s_next = NULL;
+    sp->s_prev = *done_q_last;
+    if (!*done_q_first)
+        *done_q_first = sp;
+    else
+        (*done_q_last)->s_next = sp;
+    *done_q_last = sp;
+
+    DRIVER_UNLOCK
+#ifdef QL_DEBUG_LEVEL_3
+            LEAVE("qla1280_put_done_q");
+#endif
+}
+
+/*
+ * qla1280_next
+ *      Retrieve and process next job in the queue.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      q  = SCSI LU pointer.
+ *      b  = SCSI bus number.
+ *      SCSI_LU_Q lock must be already obtained and no other locks.
+ *
+ * Output:
+ *      Releases SCSI_LU_Q upon exit.
+ */
+STATIC void
+qla1280_next(scsi_qla_host_t *ha, scsi_lu_t *q, uint8_t b)
+{
+    srb_t   *sp;
+    uint32_t cnt;
+    uint8_t status;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+    ENTER("qla1280_next");
+
+    DRIVER_LOCK
+    while ( ((sp = q->q_first) != NULL) &&     /* we have a queue pending */
+        !(q->q_flag &  QLA1280_QBUSY) &&      /* device not busy */
+        !ha->flags.abort_isp_active &&      /* not resetting the adapter */
+        !(q->q_flag & QLA1280_QSUSP) )      /* device not suspended */
+    {
+        /* Remove srb from SCSI LU queue. */
+        qla1280_removeq(q, sp);
+
+        DEBUG(sprintf(debug_buff,"starting request 0x%p<-(0x%p)\n\r",q,sp));
+        DEBUG(qla1280_print(debug_buff));
+        {
+            /* Set busy flag if reached high water mark. */
+            q->q_outcnt++;
+            if (q->q_outcnt >= ha->bus_settings[b].hiwat)
+                q->q_flag |= QLA1280_QBUSY;
+
+#if  QLA1280_64BIT_SUPPORT
+            if (ha->flags.enable_64bit_addressing)
+                status = qla1280_64bit_start_scsi(ha, sp);
+            else
+#endif
+                status = qla1280_32bit_start_scsi(ha, sp);
+
+            if (status)  /* if couldn't start the request */
+            {
+                if (q->q_outcnt == 1)
+                {
+                    /* Release SCSI LU queue specific lock */
+                    QLA1280_SCSILU_UNLOCK(q);
+
+                    /* Wait for 30 sec for command to be accepted. */
+                    for (cnt = 6000000; cnt; cnt--)
+                    {
+#if  QLA1280_64BIT_SUPPORT
+                        if (ha->flags.enable_64bit_addressing)
+                            status = qla1280_64bit_start_scsi(ha, sp);
+                        else
+#endif
+                            status = qla1280_32bit_start_scsi(ha, sp);
+
+                        if (!status)
+                        {
+                            break;
+                        }
+
+                        /* Go check for pending interrupts. */
+                        qla1280_poll(ha);
+
+                        SYS_DELAY(5);  /* 10 */
+                    }
+                    if (!cnt)
+                    {
+                        /* Set timeout status */
+                        CMD_RESULT(sp->cmd) = DID_TIME_OUT << 16;
+
+#if WATCHDOGTIMER
+                        /* Remove command from watchdog queue. */
+                        if (sp->flags & SRB_WATCHDOG)
+                            qla1280_timeout_remove(ha, sp);
+#endif
+                        COMTRACE('M') 
+                        CMD_HANDLE(sp->cmd) = (unsigned char *) 0;
+
+                        /* Call the mid-level driver interrupt handler */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+                        sti(); 
+                        (*(sp->cmd)->scsi_done)(sp->cmd);
+                        cli(); 
+#else
+                        (*(sp->cmd)->scsi_done)(sp->cmd);
+#endif
+
+                        /* Acquire LU queue specific lock */
+                        QLA1280_SCSILU_LOCK(q);
+
+                        if (q->q_outcnt)
+                            q->q_outcnt--;
+                    }
+                    else
+                        /* Acquire LU queue specific lock */
+                        QLA1280_SCSILU_LOCK(q);
+                }
+                else
+                {   /* Place request back on top of device queue. */
+                    qla1280_putq_t(q, sp);
+
+                    if (q->q_outcnt)
+                        q->q_outcnt--;
+                    if (q->q_outcnt < ha->bus_settings[b].hiwat)
+                        q->q_flag &= ~QLA1280_QBUSY;
+                    break;
+                }
+            }
+        }
+    }
+   DRIVER_UNLOCK
+
+    /* Release SCSI LU queue specific lock */
+    QLA1280_SCSILU_UNLOCK(q);
+
+    LEAVE("qla1280_next");
+}
+
+/*
+ * qla1280_putq_t
+ *      Add the standard SCB job to the top of standard SCB commands.
+ *
+ * Input:
+ *      q  = SCSI LU pointer.
+ *      sp = srb pointer.
+ *      SCSI_LU_Q lock must be already obtained.
+ */
+STATIC void
+qla1280_putq_t(scsi_lu_t *q, srb_t *sp)
+{
+    srb_t *srb_p;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_putq_t");
+#endif
+    DRIVER_LOCK
+    DEBUG(sprintf(debug_buff,"Adding to device 0x%p<-(0x%p)\n\r",q,sp));
+    DEBUG(qla1280_print(debug_buff));
+    sp->s_next = NULL;
+    if (!q->q_first)                  /* If queue empty */
+    {
+        sp->s_prev = NULL;
+        q->q_first = sp;
+        q->q_last = sp;
+    }
+    else
+    {      
+        srb_p = q->q_first;
+        while (srb_p )
+            srb_p = srb_p->s_next;
+
+        if (srb_p)
+        {
+            sp->s_prev = srb_p->s_prev;
+            if (srb_p->s_prev)
+                srb_p->s_prev->s_next = sp;
+            else
+                q->q_first = sp;
+            srb_p->s_prev = sp;
+            sp->s_next = srb_p;
+        }
+        else
+        {
+            sp->s_prev = q->q_last;
+            q->q_last->s_next = sp;
+            q->q_last = sp;
+        }
+    }
+
+    DRIVER_UNLOCK
+#ifdef QL_DEBUG_LEVEL_3
+            LEAVE("qla1280_putq_t");
+#endif
+}
+
+/*
+ * qla1280_removeq
+ *      Function used to remove a command block from the
+ *      LU queue.
+ *
+ * Input:
+ *      q  = SCSI LU pointer.
+ *      sp = srb pointer.
+ *      SCSI_LU_Q lock must be already obtained.
+ */
+STATIC void
+qla1280_removeq(scsi_lu_t *q, srb_t *sp)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+    DEBUG(sprintf(debug_buff,"Removing from device_q (0x%p)->(0x%p)\n\r",q,sp));
+    DEBUG(qla1280_print(debug_buff));
+    DRIVER_LOCK
+            if (sp->s_prev)
+    {
+        if ((sp->s_prev->s_next = sp->s_next) != NULL)
+            sp->s_next->s_prev = sp->s_prev;
+        else
+            q->q_last = sp->s_prev;
+    }
+    else if (!(q->q_first = sp->s_next))
+        q->q_last = NULL;
+    else
+        q->q_first->s_prev = NULL;
+    DRIVER_UNLOCK
+}
+
+/*
+* qla1280_mem_alloc
+*      Allocates adapter memory.
+*
+* Returns:
+*      0  = success.
+*      1  = failure.
+*/
+STATIC uint8_t
+qla1280_mem_alloc(scsi_qla_host_t *ha)
+{
+
+	uint8_t   status = 1;
+
+#ifdef QL_DEBUG_LEVEL_3
+	ENTER("qla1280_mem_alloc");
+#endif
+
+#ifdef DYNAMIC_MEM_ALLOC
+	ha->request_ring = qla1280_alloc_phys(REQUEST_ENTRY_SIZE * REQUEST_ENTRY_CNT,
+	&ha->request_dma);
+	if(ha->request_ring) {
+		ha->response_ring = qla1280_alloc_phys(RESPONSE_ENTRY_SIZE * RESPONSE_ENTRY_CNT,
+		&ha->response_dma);
+		if(ha->response_ring) {
+			status = 0;
+		}
+	}
+#else
+	ha->request_ring = &ha->req[0];
+	ha->request_dma = VIRT_TO_BUS(&ha->req[0]);
+	ha->response_ring = &ha->res[0];
+	ha->response_dma = VIRT_TO_BUS(&ha->res[0]);
+	status = 0;
+#endif
+
+	if(status) {
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+		qla1280_print("qla1280_mem_alloc: **** FAILED ****\n");
+#endif
+	}
+#ifdef QL_DEBUG_LEVEL_3
+	else
+		LEAVE("qla1280_mem_alloc");
+#endif
+	return(status);
+}
+
+/*
+ * qla1280_mem_free
+ *      Frees adapter allocated memory.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_mem_free(scsi_qla_host_t *ha)
+{
+    scsi_lu_t *q;
+    uint32_t  b, t, l;
+
+    ENTER("qlc1280_mem_free");
+    if (ha)
+    {
+        /* Free device queues. */
+        for (b = 0; b < MAX_BUSES; b++)
+        {
+            q = LU_Q(ha, b, ha->bus_settings[b].id, 0);
+            for (t = 0; t < MAX_TARGETS; t++)
+                for (l = 0; l < MAX_LUNS; l++)
+                    if (LU_Q(ha, b, t, l) != NULL && LU_Q(ha, b, t, l) != q)
+                        KMFREE(LU_Q(ha, b, t, l),sizeof(struct scsi_lu));
+                    KMFREE(q, sizeof(struct scsi_lu));
+        }
+        for( b =0; b < MAX_EQ; b++ )
+            ha->dev[b] =  (scsi_lu_t  *)NULL;
+    }
+
+    LEAVE("qlc1280_mem_free");
+}
+
+
+
+
+/****************************************************************************/
+/*                QLogic ISP1280 Hardware Support Functions.                */
+/****************************************************************************/
+
+ /*
+ * qla2100_enable_intrs
+ * qla2100_disable_intrs
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      None      
+ */
+    static inline void qla1280_enable_intrs(scsi_qla_host_t *ha) {
+        device_reg_t *reg;
+
+        reg = ha->iobase;
+        ha->flags.interrupts_on = 1;
+        /* enable risc and host interrupts */
+        WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT+ ISP_EN_RISC));
+    }
+
+    static inline void qla1280_disable_intrs(scsi_qla_host_t *ha) {
+        device_reg_t *reg;
+
+        reg = ha->iobase;
+        ha->flags.interrupts_on = 0;
+        /* disable risc and host interrupts */
+        WRT_REG_WORD(&reg->ictrl, 0);
+    }
+
+/*
+ * qla1280_initialize_adapter
+ *      Initialize board.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_initialize_adapter(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg;
+    uint8_t      status;
+    /* uint8_t      cnt; */
+    uint8_t      b;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_initialize_adapter");
+#endif
+
+    /* Clear adapter flags. */
+    ha->flags.online = FALSE;
+    ha->flags.isp_abort_needed = FALSE;
+    ha->flags.disable_host_adapter = FALSE;
+    ha->flags.reset_active = FALSE;
+    ha->flags.abort_isp_active = FALSE;
+    ha->flags.watchdog_enabled = FALSE;
+
+    DEBUG(printk("Configure PCI space for adapter...\n"));
+    if (!(status = qla1280_pci_config(ha)))
+    {
+        reg = ha->iobase;
+
+        /* Disable ISP interrupts. */
+        WRT_REG_WORD(&reg->ictrl, 0);
+
+        /* Insure mailbox registers are free. */
+        WRT_REG_WORD(&reg->semaphore, 0);
+        WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+        WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);
+
+        /* If firmware needs to be loaded */
+        if (qla1280_verbose)
+         printk("scsi(%d): Determining if RISC is loaded...\n",(int)ha->host_no);
+        if (qla1280_isp_firmware(ha))
+        {
+            if (qla1280_verbose)
+              printk("scsi(%d): Verifying chip...\n",(int)ha->host_no);
+            if (!(status = qla1280_chip_diag(ha)))
+            {
+                if (qla1280_verbose)
+                  printk("scsi(%d): Setup chip...\n",(int)ha->host_no);
+                status = qla1280_setup_chip(ha); 
+            }
+        }
+
+        if (!status)
+        {
+            /* Setup adapter based on NVRAM parameters. */
+            if (qla1280_verbose)
+              printk("scsi(%d): Configure NVRAM parameters...\n",(int)ha->host_no);
+            qla1280_nvram_config(ha);
+
+            if (!ha->flags.disable_host_adapter &&
+                !qla1280_init_rings(ha))
+            {
+                /* Issue SCSI reset. */
+                for (b = 0; b < ha->ports; b++)
+                    if (!ha->bus_settings[b].disable_scsi_reset)
+                    {
+                      /* dg 03/13 if we can't reset twice then bus is dead */
+                        if( qla1280_bus_reset(ha, b) )
+                           if( qla1280_bus_reset(ha, b) )
+                           {
+                               ha->bus_settings[b].scsi_bus_dead = TRUE;
+                            }
+                    }
+
+                    do
+                    {
+                        /* Issue marker command. */
+                        ha->flags.reset_marker = FALSE;
+                        for (b = 0; b < ha->ports; b++)
+                        {
+                            ha->bus_settings[b].reset_marker = FALSE;
+                            qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
+                        }
+                    }while (ha->flags.reset_marker);
+
+                    ha->flags.online = TRUE;
+
+                    /* Enable host adapter target mode. */
+                    for (b = 0; b < ha->ports; b++)
+                    {
+                        if (!(status = qla1280_enable_tgt(ha, b)))
+                        {
+                            /* for (cnt = 0; cnt < MAX_LUNS; cnt++)
+                            {
+                                qla1280_enable_lun(ha, b, cnt);
+                                 qla1280_poll(ha);
+                            }*/
+                        }
+                        else
+                            break;
+                    }
+            }
+            else
+                status = 1;
+        }
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_initialize_adapter: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_initialize_adapter");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_enable_tgt
+ *      Enable target mode.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI bus number.
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_enable_tgt(scsi_qla_host_t *ha, uint8_t b)
+{
+    uint8_t     status = 0;
+    /*  uint16_t    mb[MAILBOX_REGISTER_COUNT]; */
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_enable_tgt: entered\n\r");
+#endif
+
+    /* Enable target mode. */
+    /*
+    mb[0] = MBC_ENABLE_TARGET_MODE;
+    mb[1] = BIT_15;
+    mb[2] = (uint16_t)(b << 15);
+    status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+    */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_enable_tgt: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_enable_tgt: exiting normally\n\r");
+#endif
+    return(status);
+}
+
+/*
+ * ISP Firmware Test
+ *      Checks if present version of RISC firmware is older than
+ *      driver firmware.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = firmware does not need to be loaded.
+ */
+STATIC uint8_t
+qla1280_isp_firmware(scsi_qla_host_t *ha)
+{
+    nvram_t     *nv    = (nvram_t *)ha->response_ring; 
+    uint16_t    *wptr;
+    uint8_t     chksum;
+    uint8_t     cnt;
+    uint8_t     status = 0;    /* dg 2/27 always loads RISC */
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+    ENTER("qla1280_isp_firmware");
+
+    /* Verify valid NVRAM checksum. */
+    wptr = (uint16_t *)ha->response_ring;
+    DEBUG(printk("qla1280_isp_firmware: Reading NVRAM\n"));
+    chksum = 0;
+    for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++)
+    {
+        *wptr = qla1280_get_nvram_word(ha, cnt);
+        chksum += (uint8_t)*wptr;
+        chksum += (uint8_t)(*wptr >> 8);
+        wptr++;
+    }
+    DEBUG(printk("qla1280_isp_firmware: Completed Reading NVRAM\n"));
+
+#if defined(QL_DEBUG_LEVEL_3)
+    sprintf(debug_buff,"qla1280_isp_firmware: NVRAM Magic ID= %c %c %c\n\r",(char *) nv->id[0],nv->id[1],nv->id[2]);
+    qla1280_print(debug_buff);
+#endif
+
+    /* Bad NVRAM data, load RISC code. */
+    if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
+        nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1)
+    {
+        printk(KERN_INFO "qla1280_isp_firmware: Bad checksum or magic number or version in NVRAM.\n");
+        ha->flags.disable_risc_code_load = FALSE;
+    }
+    else
+        ha->flags.disable_risc_code_load = nv->cntr_flags_1.disable_loading_risc_code;
+
+    if (ha->flags.disable_risc_code_load)
+    {
+#if defined(QL_DEBUG_LEVEL_3)
+        qla1280_print("qla1280_isp_firmware: Telling RISC to verify checksum of loaded BIOS code.\n\r");
+#endif
+        /* Verify checksum of loaded RISC code. */
+        mb[0] = MBC_VERIFY_CHECKSUM;
+        /* mb[1] = ql12_risc_code_addr01; */
+        mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
+
+        if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0])))
+        {
+            /* Start firmware execution. */
+#if defined(QL_DEBUG_LEVEL_3)
+            qla1280_print("qla1280_isp_firmware: Startng F/W execution.\n\r");
+#endif
+            mb[0] = MBC_EXECUTE_FIRMWARE;
+            /* mb[1] = ql12_risc_code_addr01; */
+            mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
+            qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+        }
+        else
+            printk(KERN_INFO "qla1280: RISC checksum failed.\n");
+    }
+    else
+    {
+        DEBUG(printk("qla1280: NVRAM configured to load RISC load.\n"));
+        status = 1;
+     }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print(
+                "qla1280_isp_firmware: **** Load RISC code ****\n\r");
+#endif
+    LEAVE("qla1280_isp_firmware");
+    return(status);
+}
+
+/*
+ * PCI configuration
+ *      Setup device PCI configuration registers.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_pci_config(scsi_qla_host_t *ha)
+{
+    uint8_t      status = 1;
+    uint32_t     command;
+#if MEMORY_MAPPED_IO
+    uint32_t  page_offset, base;
+    uint32_t   mmapbase;
+#endif
+    config_reg_t *creg = 0;
+    uint16_t     buf_wd;
+
+    ENTER("qla1280_pci_config");
+
+    /* Get command register. */
+    if (pci_read_config_word(ha->pdev,OFFSET(creg->command), &buf_wd) == PCIBIOS_SUCCESSFUL)
+    {
+        command = buf_wd;
+        /*
+        * Set Bus Master Enable, Memory Address Space Enable and
+        * reset any error bits.
+        */
+        buf_wd &= ~0x7;
+#if MEMORY_MAPPED_IO
+        DEBUG(printk("qla1280: MEMORY MAPPED IO is enabled.\n"));
+        buf_wd |= BIT_2 + BIT_1 + BIT_0;
+#else
+        buf_wd |= BIT_2 + BIT_0;
+#endif
+        if( pci_write_config_word(ha->pdev,OFFSET(creg->command), buf_wd) )
+        {
+            printk(KERN_WARNING "qla1280: Could not write config word.\n");
+        }
+        /* Get expansion ROM address. */
+        if (pci_read_config_word(ha->pdev,OFFSET(creg->expansion_rom), &buf_wd) == PCIBIOS_SUCCESSFUL)
+        {
+            /* Reset expansion ROM address decode enable. */
+            buf_wd &= ~BIT_0;
+            if (pci_write_config_word(ha->pdev,OFFSET(creg->expansion_rom), buf_wd) == PCIBIOS_SUCCESSFUL)
+            {
+#if MEMORY_MAPPED_IO
+                /* Get memory mapped I/O address. */
+                pci_read_config_dword(ha->pdev,OFFSET(cfgp->mem_base_addr), &mmapbase);
+                mmapbase &= PCI_BASE_ADDRESS_MEM_MASK;
+
+                /* Find proper memory chunk for memory map I/O reg. */
+                base = mmapbase & PAGE_MASK;
+                page_offset = mmapbase - base;
+                /* Get virtual address for I/O registers. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+                ha->mmpbase = ioremap_nocache(base, page_offset + 256);
+#else
+                ha->mmpbase = vremap(base,page_offset + 256);
+#endif
+                if( ha->mmpbase )
+                {
+                    ha->mmpbase += page_offset;
+                    /* ha->iobase = ha->mmpbase; */
+                    status = 0;
+                }
+#else /* MEMORY_MAPPED_IO */
+                status = 0;
+#endif /* MEMORY_MAPPED_IO */
+            }
+        }
+    }
+
+    LEAVE("qla1280_pci_config");
+    return(status);
+}
+
+/*
+ * Chip diagnostics
+ *      Test chip for proper operation.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_chip_diag(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg   = ha->iobase;
+    uint8_t      status = 0;
+    uint16_t     data;
+    uint32_t     cnt;
+    uint16_t     mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    sprintf(debug_buff, "qla1280_chip_diag: testing device at 0x%p \n\r",&reg->id_l);
+    qla1280_print(debug_buff);
+#endif
+
+    /* Soft reset chip and wait for it to finish. */
+    WRT_REG_WORD(&reg->ictrl, ISP_RESET); 
+    data = qla1280_debounce_register(&reg->ictrl);
+    for (cnt = 6000000; cnt && data & ISP_RESET; cnt--)
+    {
+        SYS_DELAY(5);
+        data = RD_REG_WORD(&reg->ictrl);
+    }
+    if (cnt)
+    {
+        /* Reset register not cleared by chip reset. */
+#if defined(QL_DEBUG_LEVEL_3)
+        qla1280_print("qla1280_chip_diag: reset register cleared by chip reset\n\r");
+#endif
+        WRT_REG_WORD(&reg->cfg_1, 0);
+
+        /* Reset RISC and disable BIOS which
+        allows RISC to execute out of RAM. */
+        WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
+        WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
+        WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
+        data = qla1280_debounce_register(&reg->mailbox0);
+        for (cnt = 6000000; cnt && data == MBS_BUSY; cnt--)
+        {
+            SYS_DELAY(5);
+            data = RD_REG_WORD(&reg->mailbox0);
+        }
+
+        if (cnt)
+        {
+            /* Check product ID of chip */
+#if defined(QL_DEBUG_LEVEL_3)
+            qla1280_print("qla1280_chip_diag: Checking product ID of chip\n\r");
+#endif
+            if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
+                (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
+                RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
+                RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
+                RD_REG_WORD(&reg->mailbox4) != PROD_ID_4)
+            {
+                printk(KERN_INFO "qla1280: Wrong product ID = 0x%x,0x%x,0x%x,0x%x\n",
+                        RD_REG_WORD(&reg->mailbox1),
+                        RD_REG_WORD(&reg->mailbox2),
+                        RD_REG_WORD(&reg->mailbox3),
+                        RD_REG_WORD(&reg->mailbox4) );
+                status = 1;
+            }
+            else
+            {
+                DEBUG(printk("qla1280_chip_diag: Checking mailboxes of chip\n"));
+                /* Wrap Incoming Mailboxes Test. */
+                mb[0] = MBC_MAILBOX_REGISTER_TEST;
+                mb[1] = 0xAAAA;
+                mb[2] = 0x5555;
+                mb[3] = 0xAA55;
+                mb[4] = 0x55AA;
+                mb[5] = 0xA5A5;
+                mb[6] = 0x5A5A;
+                mb[7] = 0x2525;
+                if (!(status = qla1280_mailbox_command(ha,
+                    (BIT_7|BIT_6|BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0),
+                    &mb[0])))
+                {
+                    if (mb[1] != 0xAAAA || mb[2] != 0x5555 ||
+                        mb[3] != 0xAA55 || mb[4] != 0x55AA)
+                        status = 1;
+                    if (mb[5] != 0xA5A5 || mb[6] != 0x5A5A ||
+                        mb[7] != 0x2525)
+                        status = 1;
+                    if( status == 1 )
+                        printk(KERN_INFO "qla1280: Failed mailbox check\n");
+                }
+            }
+        }
+        else
+            status = 1;
+    }
+    else
+        status = 1;
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_chip_diag: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_chip_diag: exiting normally\n\r");
+#endif
+    return(status);
+}
+
+/*
+ * Setup chip
+ *      Load and start RISC firmware.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_setup_chip(scsi_qla_host_t *ha)
+{
+    uint8_t      status = 0;
+    uint16_t     risc_address;
+    uint16_t     *risc_code_address;
+    long         risc_code_size;
+    uint16_t     mb[MAILBOX_REGISTER_COUNT];
+#ifdef QLA1280_UNUSED
+    int i;
+#endif
+    uint16_t     cnt;
+    int          num;
+    uint8_t    *tbuf, *sp;
+    u_long     p_tbuf;
+    int i;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_setup_chip");
+#endif
+
+	if( (tbuf = (uint8_t *)KMALLOC(8000) ) == NULL )
+        {
+            printk("setup_chip: couldn't alloacte memory\n");
+            return(1);
+        }
+        p_tbuf =  VIRT_TO_BUS(tbuf);
+    /* Load RISC code. */
+    /* 
+    risc_address      = ql12_risc_code_addr01;
+    risc_code_address = &ql12_risc_code01[0];
+    risc_code_size    = ql12_risc_code_length01;
+    */
+    risc_address = *QLBoardTbl[ha->devnum].fwstart;  
+    risc_code_address = QLBoardTbl[ha->devnum].fwcode;  
+    risc_code_size    = (long)(*QLBoardTbl[ha->devnum].fwlen & 0xffff);  
+
+    DEBUG(printk("qla1280: DMAing RISC code (%d) words.\n",(int)risc_code_size));
+    DEBUG(sprintf(debug_buff,"qla1280_setup_chip:  Loading RISC code size =(%ld).\n\r",risc_code_size);)
+    DEBUG(qla1280_print(debug_buff));
+    num =0;
+    while (risc_code_size > 0 && !status)
+    {
+        cnt = 2000 >> 1;
+
+        if ( cnt > risc_code_size ) 
+            cnt = risc_code_size;
+
+        DEBUG(sprintf(debug_buff,"qla1280_setup_chip:  loading risc @ =(0x%p),%d,%d(0x%x).\n\r",risc_code_address,cnt,num,risc_address);)
+        DEBUG(qla1280_print(debug_buff));
+        printk("qla1280_setup_chip:  loading risc @ =code=(0x%p),cnt=%d,seg=%d,addr=0x%x\n\r",risc_code_address,cnt,num,risc_address);
+        BCOPY((caddr_t) risc_code_address,(caddr_t) ha->request_ring, (cnt <<1));
+        mb[0] = MBC_LOAD_RAM; 
+        /* mb[0] = MBC_LOAD_RAM_A64; */
+        mb[1] = risc_address;
+        mb[4] = cnt;
+        mb[3] = (uint16_t)  ha->request_dma & 0xffff;
+        mb[2] = (uint16_t) (ha->request_dma >> 16) & 0xffff;
+        mb[7] = (uint16_t) (MS_64BITS(ha->request_dma) & 0xffff);
+        mb[6] = (uint16_t) (MS_64BITS(ha->request_dma) >> 16) & 0xffff;
+        printk("qla1280_setup_chip: op=%d  0x%lx = 0x%4x,0x%4x,0x%4x,0x%4x\n",mb[0],ha->request_dma,mb[6],mb[7],mb[2],mb[3]);
+        if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
+            &mb[0]))  )
+        {
+            printk("Failed to load partial segment of f/w\n");
+            break;
+        }
+        /* dump it back */
+
+#if 0
+        mb[0] = MBC_DUMP_RAM_A64;
+        mb[1] = risc_address;
+        mb[4] = cnt;
+        mb[3] = (uint16_t)  p_tbuf & 0xffff;
+        mb[2] = (uint16_t) (p_tbuf >> 16) & 0xffff;
+        mb[7] = (uint16_t) (p_tbuf >> 32) & 0xffff;
+        mb[6] = (uint16_t) (p_tbuf >> 48) & 0xffff;
+
+        if( (status = qla1280_mailbox_command(ha, BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
+            &mb[0]))  )
+        {
+            printk("Failed to dump partial segment of f/w\n");
+            break;
+        }
+        sp =  (uint8_t *)ha->request_ring;
+        for (i = 0; i < (cnt<< 1) ; i++)
+        {
+            if( tbuf[i] != sp[i] )
+            {
+               printk("qla1280 : firmware compare error @ byte (0x%x)\n",i);
+                break;
+            }
+        }
+
+#endif
+        risc_address += cnt;
+        risc_code_size = risc_code_size - cnt;
+        risc_code_address = risc_code_address + cnt;
+        num++;
+    }
+#ifdef QLA1280_UNUSED
+    DEBUG(ql_debug_print = 0;)
+    {
+        for (i = 0; i < ql12_risc_code_length01; i++)
+        {
+            mb[0] = 0x4;
+            mb[1] = ql12_risc_code_addr01 + i;
+            mb[2] = ql12_risc_code01[i];
+
+            status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0,
+                    &mb[0]);
+            if (status)
+            {
+                printk("qla1280 : firmware load failure\n");
+                break;
+            }
+
+            mb[0] = 0x5;
+            mb[1] = ql12_risc_code_addr01 + i;
+            mb[2] = 0;
+
+            status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0,
+                    &mb[0]);
+            if (status)
+            {
+                printk("qla1280 : firmware dump failure\n");
+                break;
+            }
+            if( mb[2] != ql12_risc_code01[i] )
+                printk("qla1280 : firmware compare error @ (0x%x)\n",ql12_risc_code_addr01+i);
+        }
+    }
+    DEBUG(ql_debug_print = 1;)
+#endif
+
+    /* Verify checksum of loaded RISC code. */
+    if (!status)
+    {
+        DEBUG(printk("qla1280_setup_chip: Verifying checksum of loaded RISC code.\n");)
+        mb[0] = MBC_VERIFY_CHECKSUM;
+        /* mb[1] = ql12_risc_code_addr01; */
+        mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
+        
+        if (!(status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0])))
+        {
+            /* Start firmware execution. */
+            DEBUG(qla1280_print("qla1280_setup_chip: start firmware running.\n\r");)
+            mb[0] = MBC_EXECUTE_FIRMWARE;
+            /* mb[1] = ql12_risc_code_addr01; */
+            mb[1] = *QLBoardTbl[ha->devnum].fwstart;  
+            qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+        }
+        else
+            printk("qla1280_setup_chip: Failed checksum.\n");
+    }
+
+	KMFREE(tbuf,8000);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_setup_chip: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_setup_chip");
+#endif
+    return(status);
+}
+
+/*
+ * Initialize rings
+ *
+ * Input:
+ *      ha                = adapter block pointer.
+ *      ha->request_ring  = request ring virtual address
+ *      ha->response_ring = response ring virtual address
+ *      ha->request_dma   = request ring physical address
+ *      ha->response_dma  = response ring physical address
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_init_rings(scsi_qla_host_t *ha)
+{
+    uint8_t     status = 0;
+    uint16_t    cnt;
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_init_rings");
+#endif
+    /* Clear outstanding commands array. */
+    for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+        ha->outstanding_cmds[cnt] = 0;
+
+    /* Initialize request queue. */
+    ha->request_ring_ptr = ha->request_ring;
+    ha->req_ring_index   = 0;
+    ha->req_q_cnt        = REQUEST_ENTRY_CNT;
+    /* mb[0] = MBC_INIT_REQUEST_QUEUE; */
+    mb[0] = MBC_INIT_REQUEST_QUEUE_A64;
+    mb[1] = REQUEST_ENTRY_CNT;
+    mb[3] = (uint16_t)LS_64BITS(ha->request_dma);
+    mb[2] = (uint16_t)( LS_64BITS(ha->request_dma) >> 16);
+    mb[4] = 0;
+    mb[7] = (uint16_t)MS_64BITS(ha->request_dma);
+    mb[6] = (uint16_t)( MS_64BITS(ha->request_dma) >> 16);
+    if (!(status = qla1280_mailbox_command(ha,
+        BIT_7|BIT_6|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0,
+        &mb[0])))
+    {
+        /* Initialize response queue. */
+        ha->response_ring_ptr = ha->response_ring;
+        ha->rsp_ring_index    = 0;
+        /* mb[0] = MBC_INIT_RESPONSE_QUEUE; */
+        mb[0] = MBC_INIT_RESPONSE_QUEUE_A64;
+        mb[1] = RESPONSE_ENTRY_CNT;
+        mb[3] = (uint16_t)LS_64BITS(ha->response_dma);
+        mb[2] = (uint16_t)(LS_64BITS(ha->response_dma) >> 16);
+        mb[5] = 0;
+        mb[7] = (uint16_t)MS_64BITS(ha->response_dma);
+        mb[6] = (uint16_t)(MS_64BITS(ha->response_dma) >> 16);
+        status = qla1280_mailbox_command(ha,
+                BIT_7|BIT_6|BIT_5|BIT_3|BIT_2|BIT_1|BIT_0,
+                &mb[0]);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_init_rings: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_init_rings");
+#endif
+    return(status);
+}
+
+/*
+ * NVRAM configuration.
+ *
+ * Input:
+ *      ha                = adapter block pointer.
+ *      ha->request_ring  = request ring virtual address
+ *
+ * Output:
+ *      host adapters parameters in host adapter block
+ *
+ * Returns:
+ *      0 = success.
+ */
+STATIC uint8_t
+qla1280_nvram_config(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg   = ha->iobase;
+    nvram_t      *nv    = (nvram_t *)ha->response_ring; 
+    uint8_t      status = 0;
+    uint32_t     b, t, l;
+    uint16_t     *wptr;
+    uint16_t     mb[MAILBOX_REGISTER_COUNT];
+    uint8_t      cnt;
+    uint8_t      chksum;
+    uint32_t     nvsize;
+
+#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4)
+    uint8_t      saved_print_status = ql_debug_print;
+#endif
+    ENTER("qla1280_nvram_config");
+#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4)
+    ql_debug_print = FALSE;
+#endif
+
+    /* Verify valid NVRAM checksum. */
+#if  USE_NVRAM_DEFAULTS
+    chksum = 1;
+#else
+    wptr = (uint16_t *)ha->response_ring;
+    chksum = 0;
+    if( ha->device_id == QLA12160_DEVICE_ID ||  
+        ha->device_id == QLA10160_DEVICE_ID )  
+    nvsize = sizeof(nvram160_t)/2;
+    else
+    nvsize = sizeof(nvram_t)/2;
+    for( cnt = 0; cnt < nvsize; cnt++ ) 
+    {
+        *wptr = qla1280_get_nvram_word(ha, cnt); 
+        chksum += (uint8_t)*wptr;
+        chksum += (uint8_t)(*wptr >> 8);
+        wptr++;
+    }
+#endif
+
+
+    /* Bad NVRAM data, set defaults parameters. */
+    if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
+        nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1)
+    {
+#if  USE_NVRAM_DEFAULTS
+        DEBUG(printk("Using defaults for NVRAM\n"));
+#else
+        DEBUG(printk("Using defaults for NVRAM: \n"));
+        DEBUG(printk("checksum=0x%x, Id=%c, version=0x%x\n",chksum,nv->id[0],nv->version));
+#if defined(QL_DEBUG_LEVEL_3)
+        /* ql_debug_print = 1;
+        qla1280_dump_buffer((caddr_t)ha->response_ring, REQUEST_ENTRY_SIZE);
+        ql_debug_print = 0; */
+#endif
+                wptr = (uint16_t *)ha->response_ring;
+        for (cnt = 0; cnt < sizeof(nvram_t)/2; cnt++)
+            *wptr++ = 0;
+#endif
+
+
+        /* nv->cntr_flags_1.disable_loading_risc_code = 1; */
+        nv->firmware_feature.w = BIT_0;
+        nv->termination.f.scsi_bus_0_control = 3;
+        nv->termination.f.scsi_bus_1_control = 3;
+        nv->termination.f.auto_term_support = 1;
+
+        for (b = 0; b < MAX_BUSES; b++)
+        {
+            nv->bus[b].config_1.initiator_id = 7;
+            nv->bus[b].bus_reset_delay = 5;
+            nv->bus[b].config_2.async_data_setup_time = 9;
+            nv->bus[b].config_2.req_ack_active_negation = 1;
+            nv->bus[b].config_2.data_line_active_negation = 1;
+            nv->bus[b].selection_timeout = 250;
+            nv->bus[b].max_queue_depth = 256;
+
+            for (t = 0; t < MAX_TARGETS; t++)
+            {
+                nv->bus[b].target[t].parameter.f.auto_request_sense = 1;
+                nv->bus[b].target[t].parameter.f.disconnect_allowed = 1;
+                nv->bus[b].target[t].parameter.f.tag_queuing = 1;
+                nv->bus[b].target[t].flags.device_enable = 1;
+            }
+        }
+
+#if  USE_NVRAM_DEFAULTS
+        status = 0;
+#else
+        status = 1;
+#endif
+    }
+    else
+    {
+        /* Always force AUTO sense for LINUX SCSI */
+        for (b = 0; b < MAX_BUSES; b++)
+            for (t = 0; t < MAX_TARGETS; t++)
+            {
+                nv->bus[b].target[t].parameter.f.auto_request_sense = 1;
+            }
+    }
+#if  DEBUG_PRINT_NVRAM
+    ql_debug_print = 1;
+    sprintf(debug_buff,"qla1280 : initiator scsi id bus[0]=%d\n\r",
+            nv->bus[0].config_1.initiator_id);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : initiator scsi id bus[1]=%d\n\r",
+            nv->bus[1].config_1.initiator_id);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : bus reset delay[0]=%d\n\r",
+            nv->bus[0].bus_reset_delay);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : bus reset delay[1]=%d\n\r",
+            nv->bus[1].bus_reset_delay);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : retry count[0]=%d\n\r",
+            nv->bus[0].retry_count);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : retry delay[0]=%d\n\r",
+            nv->bus[0].retry_delay);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : retry count[1]=%d\n\r",
+            nv->bus[1].retry_count);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : retry delay[1]=%d\n\r",
+            nv->bus[1].retry_delay);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : async data setup time[0]=%d\n\r",
+            nv->bus[0].config_2.async_data_setup_time);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : async data setup time[1]=%d\n\r",
+            nv->bus[1].config_2.async_data_setup_time);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : req/ack active negation[0]=%d\n\r",
+            nv->bus[0].config_2.req_ack_active_negation);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : req/ack active negation[1]=%d\n\r",
+            nv->bus[1].config_2.req_ack_active_negation);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : data line active negation[0]=%d\n\r",
+            nv->bus[0].config_2.data_line_active_negation);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : data line active negation[1]=%d\n\r",
+            nv->bus[1].config_2.data_line_active_negation);
+    qla1280_print(debug_buff);
+
+
+    sprintf(debug_buff,"qla1280 : disable loading risc code=%d\n\r",
+            nv->cntr_flags_1.disable_loading_risc_code);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : enable 64bit addressing=%d\n\r",
+            nv->cntr_flags_1.enable_64bit_addressing);
+    qla1280_print(debug_buff);
+
+    sprintf(debug_buff,"qla1280 : selection timeout limit[0]=%d\n\r",
+            nv->bus[0].selection_timeout);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : selection timeout limit[1]=%d\n\r",
+            nv->bus[1].selection_timeout);
+
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : max queue depth[0]=%d\n\r",
+            nv->bus[0].max_queue_depth);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"qla1280 : max queue depth[1]=%d\n\r",
+            nv->bus[1].max_queue_depth);
+    qla1280_print(debug_buff);
+#endif
+
+    DEBUG(ql_debug_print = 0;)
+
+    /* Disable RISC load of firmware. */
+    ha->flags.disable_risc_code_load =
+            nv->cntr_flags_1.disable_loading_risc_code;
+    /* Enable 64bit addressing. */
+    ha->flags.enable_64bit_addressing =
+            nv->cntr_flags_1.enable_64bit_addressing;
+
+    /* Set ISP hardware DMA burst */
+    mb[0] = nv->isp_config.c;
+    WRT_REG_WORD(&reg->cfg_1, mb[0]);
+
+    /* Set SCSI termination. */
+    WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
+    mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
+    WRT_REG_WORD(&reg->gpio_data, mb[0]);
+
+    /* ISP parameter word. */
+    mb[0] = MBC_SET_SYSTEM_PARAMETER;
+    mb[1] = nv->isp_parameter;
+    status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+
+    /* Firmware feature word. */
+    mb[0] = MBC_SET_FIRMWARE_FEATURES;
+    mb[1] = nv->firmware_feature.w & (BIT_1|BIT_0);
+    status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+
+    /* Retry count and delay. */
+    mb[0] = MBC_SET_RETRY_COUNT;
+    mb[1] = nv->bus[0].retry_count;
+    mb[2] = nv->bus[0].retry_delay;
+    mb[6] = nv->bus[1].retry_count;
+    mb[7] = nv->bus[1].retry_delay;
+    status |= qla1280_mailbox_command(ha, BIT_7|BIT_6|BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    /* ASYNC data setup time. */
+    mb[0] = MBC_SET_ASYNC_DATA_SETUP;
+    mb[1] = nv->bus[0].config_2.async_data_setup_time;
+    mb[2] = nv->bus[1].config_2.async_data_setup_time;
+    status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    /* Active negation states. */
+    mb[0] = MBC_SET_ACTIVE_NEGATION;
+    mb[1] = 0;
+    if (nv->bus[0].config_2.req_ack_active_negation)
+        mb[1] |= BIT_5;
+    if (nv->bus[0].config_2.data_line_active_negation)
+        mb[1] |= BIT_4;
+    mb[2] = 0;
+    if (nv->bus[1].config_2.req_ack_active_negation)
+        mb[2] |= BIT_5;
+    if (nv->bus[1].config_2.data_line_active_negation)
+        mb[2] |= BIT_4;
+    status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    /* Selection timeout. */
+    mb[0] = MBC_SET_SELECTION_TIMEOUT;
+    mb[1] = nv->bus[0].selection_timeout;
+    mb[2] = nv->bus[1].selection_timeout;
+    status |= qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    for (b = 0; b < ha->ports; b++)
+    {
+        /* SCSI Reset Disable. */
+        ha->bus_settings[b].disable_scsi_reset = nv->bus[b].config_1.scsi_reset_disable;
+
+        /* Initiator ID. */
+        ha->bus_settings[b].id = nv->bus[b].config_1.initiator_id;
+        mb[0] = MBC_SET_INITIATOR_ID;
+        mb[1] = b ? ha->bus_settings[b].id | BIT_7 : ha->bus_settings[b].id;
+        status |= qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+
+        /* Reset Delay. */
+        ha->bus_settings[b].bus_reset_delay = nv->bus[b].bus_reset_delay;
+
+        /* Command queue depth per device. */
+        ha->bus_settings[b].hiwat = nv->bus[b].max_queue_depth - 1;
+
+        /* Set target parameters. */
+        for (t = 0; t < MAX_TARGETS; t++)
+        {
+            if( ha->device_id == QLA12160_DEVICE_ID ||  
+                ha->device_id == QLA10160_DEVICE_ID )  
+            {
+                status = qla12160_set_target_parameters(ha,b,t,0,(nvram160_t *)nv);
+            }
+			else
+            {
+                /* Set Target Parameters. */
+                mb[0] = MBC_SET_TARGET_PARAMETERS;
+                mb[1] = (uint16_t)(b ? t | BIT_7 :t);
+                mb[1] <<= 8;
+                mb[2] = nv->bus[b].target[t].parameter.c << 8;
+                mb[2] |= TP_AUTO_REQUEST_SENSE;
+                mb[2] &= ~TP_STOP_QUEUE;
+                mb[3] = nv->bus[b].target[t].flags.sync_offset << 8;
+                mb[3] |= nv->bus[b].target[t].sync_period;
+                status |= qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0,
+                    &mb[0]);
+            }
+
+            /* Save Tag queuing enable flag. */
+            mb[0] = BIT_0 << t;
+            if (nv->bus[b].target[t].parameter.f.tag_queuing)
+                ha->bus_settings[b].qtag_enables |= mb[0];
+
+            /* Save Device enable flag. */
+            if (nv->bus[b].target[t].flags.device_enable)
+                ha->bus_settings[b].device_enables |= mb[0];
+
+            /* Save LUN disable flag. */
+            if (nv->bus[b].target[t].flags.lun_disable)
+                ha->bus_settings[b].lun_disables |= mb[0];
+
+            /* Set Device Queue Parameters. */
+            for (l = 0; l < MAX_LUNS; l++)
+            {
+                mb[0] = MBC_SET_DEVICE_QUEUE;
+                mb[1] = (uint16_t)(b ? t | BIT_7 :t);
+                mb[1] = mb[1] << 8 | l;
+                mb[2] = nv->bus[b].max_queue_depth;
+                mb[3] = nv->bus[b].target[t].execution_throttle;
+                status |= qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0,
+                        &mb[0]);
+            }
+        }
+    }
+    DEBUG(ql_debug_print = 0;)
+
+#if defined(QL_DEBUG_ROUTINES) && !defined(QL_DEBUG_LEVEL_4)
+    ql_debug_print = saved_print_status;
+#endif
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    DEBUG(if (status))
+        DEBUG(qla1280_print("qla1280_nvram_config: **** FAILED ****\n\r");)
+#endif
+    LEAVE("qla1280_nvram_config");
+    return(status);
+}
+
+/*
+ * Get NVRAM data word
+ *      Calculates word position in NVRAM and calls request routine to
+ *      get the word from NVRAM.
+ *
+ * Input:
+ *      ha      = adapter block pointer.
+ *      address = NVRAM word address.
+ *
+ * Returns:
+ *      data word.
+ */
+STATIC uint16_t
+qla1280_get_nvram_word(scsi_qla_host_t *ha, uint32_t address)
+{
+    uint32_t nv_cmd;
+    uint16_t data;
+
+#ifdef QL_DEBUG_ROUTINES
+    uint8_t  saved_print_status = ql_debug_print;
+#endif
+#ifdef QL_DEBUG_LEVEL_4
+    ENTER("qla1280_get_nvram_word");
+#endif
+
+    nv_cmd = address << 16;
+    nv_cmd |= NV_READ_OP;
+
+#ifdef QL_DEBUG_ROUTINES
+    ql_debug_print = FALSE;
+#endif
+    data = qla1280_nvram_request(ha, nv_cmd);
+#ifdef QL_DEBUG_ROUTINES
+    ql_debug_print = saved_print_status;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_4
+    qla1280_print("qla1280_get_nvram_word: exiting normally NVRAM data = ");
+    qla1280_output_number((uint32_t)data, 16);
+    qla1280_print("\n\r");
+#endif
+    return(data);
+}
+
+/*
+ * NVRAM request
+ *      Sends read command to NVRAM and gets data from NVRAM.
+ *
+ * Input:
+ *      ha     = adapter block pointer.
+ *      nv_cmd = Bit 26     = start bit
+ *               Bit 25, 24 = opcode
+ *               Bit 23-16  = address
+ *               Bit 15-0   = write data
+ *
+ * Returns:
+ *      data word.
+ */
+STATIC uint16_t
+qla1280_nvram_request(scsi_qla_host_t *ha, uint32_t nv_cmd)
+{
+    uint8_t      cnt;
+    device_reg_t *reg = ha->iobase;
+    uint16_t     data = 0;
+    uint16_t     reg_data;
+
+    /* Send command to NVRAM. */
+
+    nv_cmd <<= 5;
+    for (cnt = 0; cnt < 11; cnt++)
+    {
+        if (nv_cmd & BIT_31)
+            qla1280_nv_write(ha, NV_DATA_OUT);
+        else
+            qla1280_nv_write(ha, 0);
+        nv_cmd <<= 1;
+    }
+
+    /* Read data from NVRAM. */
+
+    for (cnt = 0; cnt < 16; cnt++)
+    {
+        WRT_REG_WORD(&reg->nvram, NV_SELECT+NV_CLOCK);
+        /* qla1280_nv_delay(ha); */
+        NVRAM_DELAY();
+        data <<= 1;
+        reg_data = RD_REG_WORD(&reg->nvram);
+        if (reg_data & NV_DATA_IN)
+            data |= BIT_0;
+        WRT_REG_WORD(&reg->nvram, NV_SELECT);
+        /* qla1280_nv_delay(ha); */
+        NVRAM_DELAY();
+    }
+
+    /* Deselect chip. */
+
+    WRT_REG_WORD(&reg->nvram, NV_DESELECT);
+    /* qla1280_nv_delay(ha); */
+    NVRAM_DELAY();
+
+    return(data);
+}
+
+STATIC void
+qla1280_nv_write(scsi_qla_host_t *ha, uint16_t data)
+{
+    device_reg_t *reg = ha->iobase;
+
+    WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
+    NVRAM_DELAY();
+    /* qla1280_nv_delay(ha); */
+    WRT_REG_WORD(&reg->nvram, data | NV_SELECT | NV_CLOCK);
+    /* qla1280_nv_delay(ha); */
+    NVRAM_DELAY();
+    WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
+    /* qla1280_nv_delay(ha); */
+    NVRAM_DELAY();
+}
+
+STATIC void
+qla1280_nv_delay(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg = ha->iobase;
+    int          cnt  = NV_DELAY_COUNT;
+    uint16_t     data = 0;
+
+    while (cnt--)
+        data |= RD_REG_WORD(&reg->nvram);
+}
+
+/*
+ * Mailbox Command
+ *      Issue mailbox command and waits for completion.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      mr = mailbox registers to load.
+ *      mb = data pointer for mailbox registers.
+ *
+ * Output:
+ *      mb[MAILBOX_REGISTER_COUNT] = returned mailbox data.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_mailbox_command(scsi_qla_host_t *ha, uint8_t mr, uint16_t *mb)
+{
+    device_reg_t *reg   = ha->iobase;
+    uint8_t      status = 0;
+    uint32_t     cnt;
+    uint16_t     *optr, *iptr;
+    uint16_t     data;
+    srb_t        *done_q_first = 0;
+    srb_t        *done_q_last = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_mailbox_command");
+#endif
+
+    /* Acquire interrupt specific lock */
+    QLA1280_INTR_LOCK(ha);
+    DRIVER_LOCK
+            ha->flags.mbox_busy = TRUE;
+
+    /* Load mailbox registers. */
+    optr = (uint16_t *)&reg->mailbox0;
+    iptr = mb;
+    for (cnt = 0; cnt < MAILBOX_REGISTER_COUNT; cnt++)
+    {
+        if (mr & BIT_0)
+        {
+            WRT_REG_WORD(optr, (*iptr));
+        }
+
+        mr >>= 1;
+        optr++;
+        iptr++;
+    }
+    /* Issue set host interrupt command. */
+    ha->flags.mbox_int = FALSE;
+    WRT_REG_WORD(&reg->host_cmd, HC_SET_HOST_INT);
+    data = qla1280_debounce_register(&reg->istatus);
+
+    /* Wait for 30 seconds for command to finish. */
+    for (cnt = 30000000; cnt > 0 && !ha->flags.mbox_int; cnt--)
+    {
+        /* Check for pending interrupts. */
+        if (data & RISC_INT)
+        {
+            qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+        }
+        SYS_DELAY(1);
+        data = RD_REG_WORD(&reg->istatus);
+    }
+
+    /* Check for mailbox command timeout. */
+    if ( !cnt )
+    {
+#ifdef QL_DEBUG_LEVEL_2
+        qla1280_print(
+                "qla1280_mailbox_command: **** Command Timeout, mailbox0 = ");
+        qla1280_output_number((uint32_t)mb[0], 16);
+        qla1280_print(" ****\n\r");
+#endif
+        ha->flags.isp_abort_needed = TRUE; 
+        status = 1;
+    }
+    else if (ha->mailbox_out[0] != MBS_CMD_CMP)
+        status = 1;
+
+    /* Load return mailbox registers. */
+    optr = mb;
+    iptr = (uint16_t *)&ha->mailbox_out[0];
+    mr = MAILBOX_REGISTER_COUNT;
+    while (mr--)
+        *optr++ = *iptr++;
+
+    /* Go check for any response interrupts pending. */
+    ha->flags.mbox_busy = FALSE;
+    qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+
+    /* Release interrupt specific lock */
+    QLA1280_INTR_UNLOCK(ha);
+    DRIVER_UNLOCK
+
+            if (ha->flags.isp_abort_needed)
+        qla1280_abort_isp(ha);
+
+    if (ha->flags.reset_marker)
+        qla1280_rst_aen(ha);
+
+    if (done_q_first)
+        qla1280_done(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+    {
+        qla1280_print("qla1280_mailbox_command: **** FAILED, mailbox0 = ");
+        qla1280_output_number((uint32_t)mb[0], 16);
+        qla1280_print(" ****\n\r");
+    }
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_mailbox_command");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_poll
+ *      Polls ISP for interrupts.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_poll(scsi_qla_host_t *ha)
+{
+    device_reg_t    *reg   = ha->iobase;
+    uint16_t        data;
+    srb_t           *done_q_first = 0;
+    srb_t           *done_q_last = 0;
+
+#ifdef QL_DEBUG_LEVEL_3
+    /* ENTER("qla1280_poll"); */
+#endif
+
+    /* Acquire interrupt specific lock */
+    QLA1280_INTR_LOCK(ha);
+
+    /* Check for pending interrupts. */
+    data = RD_REG_WORD(&reg->istatus);
+    if (data & RISC_INT)
+        qla1280_isr(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+
+    /* Release interrupt specific lock */
+    QLA1280_INTR_UNLOCK(ha);
+
+    if (!ha->flags.mbox_busy)
+    {
+        if (ha->flags.isp_abort_needed)
+            qla1280_abort_isp(ha);
+        if (ha->flags.reset_marker)
+            qla1280_rst_aen(ha);
+    }
+
+    if (done_q_first)
+        qla1280_done(ha, (srb_t **)&done_q_first, (srb_t **)&done_q_last);
+
+#ifdef QL_DEBUG_LEVEL_3
+    /* LEAVE("qla1280_poll"); */
+#endif
+}
+
+/*
+ * qla1280_bus_reset
+ *      Issue SCSI bus reset.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI bus number.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_bus_reset(scsi_qla_host_t *ha, uint8_t b)
+{
+    uint8_t     status;
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_bus_reset: entered\n\r");
+#endif
+   if( qla1280_verbose )
+   {
+    printk("scsi(%d): Resetting SCSI BUS (%d)\n",(int)ha->host_no,b);
+   }
+
+    mb[0] = MBC_BUS_RESET;
+    mb[1] = ha->bus_settings[b].bus_reset_delay;
+    mb[2] = (uint16_t)b;
+    status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    if (status)
+    {
+        if (ha->bus_settings[b].failed_reset_count > 2)                  /* dg - 03/13/99 */
+            ha->bus_settings[b].scsi_bus_dead = TRUE;
+        ha->bus_settings[b].failed_reset_count++;
+    }
+	else
+    {
+       QLA1280_DELAY(4);
+       ha->bus_settings[b].scsi_bus_dead = FALSE;                         /* dg - 03/13/99 */
+       ha->bus_settings[b].failed_reset_count = 0;
+       /* Issue marker command. */
+       qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
+    }
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_bus_reset: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_bus_reset: exiting normally\n\r");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_device_reset
+ *      Issue bus device reset message to the target.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI BUS number.
+ *      t  = SCSI ID.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_device_reset(scsi_qla_host_t *ha, uint8_t b, uint32_t t)
+{
+    uint8_t     status;
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_device_reset");
+#endif
+
+    mb[0] = MBC_ABORT_TARGET;
+    mb[1] = (b ? (t | BIT_7) : t) << 8;
+    mb[2] = 1;
+    status = qla1280_mailbox_command(ha, BIT_2|BIT_1|BIT_0, &mb[0]);
+
+    /* Issue marker command. */
+    qla1280_marker(ha, b, t, 0, MK_SYNC_ID);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_device_reset: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_device_reset");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_abort_device
+ *      Issue an abort message to the device
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI BUS.
+ *      t  = SCSI ID.
+ *      l  = SCSI LUN.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_abort_device(scsi_qla_host_t *ha, uint8_t b, uint32_t t, uint32_t l)
+{
+    uint8_t     status;
+    uint16_t    mb[MAILBOX_REGISTER_COUNT];
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_abort_device");
+#endif
+
+    mb[0] = MBC_ABORT_DEVICE;
+    mb[1] = (b ? t | BIT_7 : t) << 8 | l;
+    status = qla1280_mailbox_command(ha, BIT_1|BIT_0, &mb[0]);
+
+    /* Issue marker command. */
+    qla1280_marker(ha, b, t, l, MK_SYNC_ID_LUN);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_abort_device: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_abort_device");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_abort_command
+ *      Abort command aborts a specified IOCB.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      sp = SB structure pointer.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_abort_command(scsi_qla_host_t *ha, srb_t *sp)
+{
+    uint8_t         status;
+    uint16_t        mb[MAILBOX_REGISTER_COUNT];
+    uint32_t        b, t, l;
+    uint32_t        handle;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_abort_command");
+#endif
+
+    /* Locate handle number. */
+    for (handle = 0; handle < MAX_OUTSTANDING_COMMANDS; handle++)
+        if (ha->outstanding_cmds[handle] == sp)
+            break;
+
+                b  = SCSI_BUS_32(sp->cmd);
+        t  = SCSI_TCN_32(sp->cmd);
+        l  = SCSI_LUN_32(sp->cmd);
+
+        mb[0] = MBC_ABORT_COMMAND;
+        mb[1] = (b ? t | BIT_7 : t) << 8 | l;
+        mb[2] = handle >> 16;
+        mb[3] = (uint16_t)handle;
+        status = qla1280_mailbox_command(ha, BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+        if (status)
+            qla1280_print("qla1280_abort_command: **** FAILED ****\n\r");
+#endif
+        sp->flags |= SRB_ABORT_PENDING;
+
+        LEAVE("qla1280_abort_command");
+        return(status);
+}
+
+/*
+ * qla1280_reset_adapter
+ *      Reset adapter.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_reset_adapter(scsi_qla_host_t *ha)
+{
+    device_reg_t *reg = ha->iobase;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_reset_adapter");
+#endif
+
+    /* Disable ISP chip */
+    ha->flags.online = FALSE;
+    WRT_REG_WORD(&reg->ictrl, ISP_RESET);
+    WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
+    WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
+    WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_reset_adapter");
+#endif
+}
+
+/*
+ *  Issue marker command.
+ *      Function issues marker IOCB.
+ *
+ * Input:
+ *      ha   = adapter block pointer.
+ *      b    = SCSI BUS number
+ *      t    = SCSI ID
+ *      l    = SCSI LUN
+ *      type = marker modifier
+ */
+STATIC void
+qla1280_marker(scsi_qla_host_t *ha, uint8_t b, uint32_t t, uint32_t l, uint8_t type)
+{
+    mrk_entry_t     *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_marker");
+#endif
+
+    /* Get request packet. */
+    if ( (pkt = (mrk_entry_t *)qla1280_req_pkt(ha)) )
+    {
+        pkt->entry_type = MARKER_TYPE;
+        pkt->lun = (uint8_t)l;
+        pkt->target = (uint8_t)(b ? (t | BIT_7) : t);
+        pkt->modifier = type;
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_marker");
+#endif
+}
+
+#if  QLA1280_64BIT_SUPPORT
+/*
+ * qla1280_64bit_start_scsi
+ *      The start SCSI is responsible for building request packets on
+ *      request ring and modifying ISP input pointer.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      sp = SB structure pointer.
+ *
+ * Returns:
+ *      0 = success, was able to issue command.
+ */
+STATIC uint8_t
+qla1280_64bit_start_scsi(scsi_qla_host_t *ha, srb_t *sp)
+{
+    device_reg_t    *reg   = ha->iobase;
+    uint8_t         status = 0;
+    Scsi_Cmnd       *cmd = sp->cmd;
+    uint32_t        cnt;
+    cmd_a64_entry_t     *pkt;
+    uint16_t        req_cnt;
+    uint16_t        seg_cnt;
+    struct scatterlist    *sg = (struct scatterlist *) NULL;
+    uint32_t        *dword_ptr;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_64bit_start_scsi:");
+#endif
+
+    if( qla1280_check_for_dead_scsi_bus(ha, sp) )
+    {
+        return(0);
+    }
+
+    /* Calculate number of entries and segments required. */
+    seg_cnt = 0;
+    req_cnt = 1;
+    if (cmd->use_sg)
+    {
+        seg_cnt =  cmd->use_sg;
+        sg = (struct scatterlist *) cmd->request_buffer;
+            
+        if (seg_cnt > 2)
+        {
+           req_cnt += (uint16_t)(seg_cnt - 2) / 5;
+           if ((uint16_t)(seg_cnt - 2) % 5)
+               req_cnt++;
+        }
+    }
+    else if (cmd->request_bufflen)  /* If data transfer. */
+    {
+        DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen));
+        seg_cnt = 1;
+    }
+
+    /* Acquire ring specific lock */
+    QLA1280_RING_LOCK(ha);
+
+    if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt)
+    {
+        /* Calculate number of free request entries. */
+        cnt = RD_REG_WORD(&reg->mailbox4);
+        if (ha->req_ring_index < cnt)
+            ha->req_q_cnt = cnt - ha->req_ring_index;
+        else
+            ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
+    }
+
+    /* If room for request in request ring. */
+    if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt)
+    {
+        /* Check for room in outstanding command list. */
+        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
+            ha->outstanding_cmds[cnt] != 0; cnt++)
+            ;
+
+        if (cnt < MAX_OUTSTANDING_COMMANDS)
+        {
+            ha->outstanding_cmds[cnt] = sp;
+            ha->req_q_cnt -= req_cnt;
+            CMD_HANDLE(sp->cmd) = (unsigned char *) (u_long) cnt;
+
+            /*
+            * Build command packet.
+            */
+            pkt = (cmd_a64_entry_t *)ha->request_ring_ptr;
+
+            pkt->entry_type = COMMAND_A64_TYPE;
+            pkt->entry_count = (uint8_t)req_cnt;
+            pkt->sys_define = (uint8_t)ha->req_ring_index;
+            pkt->handle = (uint32_t)cnt;
+
+            /* Zero out remaining portion of packet. */
+            dword_ptr = (uint32_t *)pkt + 2;
+            for (cnt = 2; cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                *dword_ptr++ = 0;
+
+            /* Set ISP command timeout. */
+            pkt->timeout = (uint16_t)30;
+
+            /* Set device target ID and LUN */
+            pkt->lun = SCSI_LUN_32(cmd);
+            pkt->target = SCSI_BUS_32(cmd) ?
+                    (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
+
+            /* Enable simple tag queuing if device supports it. */
+            if (cmd->device->tagged_queue )
+                pkt->control_flags |= BIT_3;
+
+            /* Load SCSI command packet. */
+            pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd);
+            BCOPY(&(CMD_CDBP(cmd)), pkt->scsi_cdb, pkt->cdb_len);
+            DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]));
+
+            /*
+            * Load data segments.
+            */
+            if (seg_cnt)                /* If data transfer. */
+            {
+                /* Set transfer direction. */
+                if ( (cmd->data_cmnd[0] == WRITE_6) )
+                    pkt->control_flags |= BIT_6;
+                else
+                    pkt->control_flags |= (BIT_5|BIT_6);
+                    
+                sp->dir = pkt->control_flags & (BIT_5|BIT_6);
+
+                /* Set total data segment count. */
+                pkt->dseg_count = seg_cnt;
+
+                /* Setup packet address segment pointer. */
+                dword_ptr = (uint32_t *)&pkt->dseg_0_address;
+
+                if (cmd->use_sg)              /* If scatter gather */
+                {
+                    /* Load command entry data segments. */
+                    for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--)
+                    {
+                        DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length));
+                        DEBUG(qla1280_print(debug_buff));
+                        *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address));
+                        *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address));
+                        *dword_ptr++ = sg->length;
+                        sg++;
+                    }
+#ifdef QL_DEBUG_LEVEL_5
+                    qla1280_print(
+                            "qla1280_64bit_start_scsi: Scatter/gather command packet data - ");
+                    qla1280_print("b ");
+                    qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+                    qla1280_print(" t ");
+                    qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                    qla1280_print(" d ");
+                    qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                    qla1280_print("\n\r");
+                    qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+                    /*
+                    * Build continuation packets.
+                    */
+                    while (seg_cnt > 0)
+                    {
+                        /* Adjust ring index. */
+                        ha->req_ring_index++;
+                        if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+                        {
+                            ha->req_ring_index = 0;
+                            ha->request_ring_ptr = ha->request_ring;
+                        }
+                        else
+                            ha->request_ring_ptr++;
+
+                        pkt = (cmd_a64_entry_t *)ha->request_ring_ptr;
+
+                        /* Zero out packet. */
+                        dword_ptr = (uint32_t *)pkt;
+                        for (cnt = 0;cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                            *dword_ptr++ = 0;
+
+                        /* Load packet defaults. */
+                        ((cont_a64_entry_t *)pkt)->entry_type =
+                                CONTINUE_A64_TYPE;
+                        ((cont_a64_entry_t *)pkt)->entry_count = 1;
+                        ((cont_a64_entry_t *)pkt)->sys_define = (uint8_t)
+                                ha->req_ring_index;
+
+                        /* Setup packet address segment pointer. */
+                        dword_ptr = (uint32_t *)
+                                &((cont_a64_entry_t *)pkt)->dseg_0_address;
+
+                        /* Load continuation entry data segments. */
+                        for (cnt = 0; cnt < 5 && seg_cnt; cnt++, seg_cnt--)
+                        {
+                            *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(sg->address));
+                            *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(sg->address));
+                            *dword_ptr++ = sg->length;
+                            sg++;
+                        }
+#ifdef QL_DEBUG_LEVEL_5
+                        qla1280_print(
+                                "qla1280_64bit_start_scsi: continuation packet data - c");
+                        qla1280_print(" b ");
+                        qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+
+                        qla1280_print(" t ");
+                        qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                        qla1280_print(" d ");
+                        qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                        qla1280_print("\n\r");
+                        qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+                    }
+                }
+                else                    /* No scatter gather data transfer */
+                {
+                    *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_LOW(cmd->request_buffer));
+                    *dword_ptr++ = cpu_to_le32(VIRT_TO_BUS_HIGH(cmd->request_buffer));
+                    *dword_ptr = (uint32_t) cmd->request_bufflen;
+#ifdef QL_DEBUG_LEVEL_5
+                    qla1280_print(
+                            "qla1280_64bit_start_scsi: No scatter/gather command packet data - c");
+                    qla1280_print(" b ");
+                    qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+                    qla1280_print(" t ");
+                    qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                    qla1280_print(" d ");
+                    qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                    qla1280_print("\n\r");
+                    qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+                }
+            }
+#ifdef QL_DEBUG_LEVEL_5
+            else                            /* No data transfer */
+            {
+                *dword_ptr++ = (uint32_t) 0;
+                *dword_ptr++ = (uint32_t) 0;
+                *dword_ptr = (uint32_t)  0;
+                qla1280_print(
+                        "qla1280_64bit_start_scsi: No data, command packet data - c");
+                qla1280_print(" b ");
+                qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+                qla1280_print(" t ");
+                qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                qla1280_print(" d ");
+                qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                qla1280_print("\n\r");
+                qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+            }
+#endif
+            /* Adjust ring index. */
+            ha->req_ring_index++;
+            if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+            {
+                ha->req_ring_index = 0;
+                ha->request_ring_ptr = ha->request_ring;
+            }
+            else
+                ha->request_ring_ptr++;
+
+            /* Set chip new ring index. */
+            WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
+        }
+        else
+        {
+            status = 1;
+#ifdef QL_DEBUG_LEVEL_2
+            qla1280_print(
+                    "qla1280_64bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r");
+            qla1280_print(" req_q_cnt=");
+            qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
+#endif
+        }
+    }
+    else
+    {
+        status = 1;
+#ifdef QL_DEBUG_LEVEL_2
+        qla1280_print("qla1280_64bit_start_scsi: in-ptr=");
+        qla1280_output_number((uint32_t)ha->req_ring_index, 16);
+        qla1280_print(" req_q_cnt=");
+        qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
+        qla1280_print(" req_cnt=");
+        qla1280_output_number((uint32_t)req_cnt, 16);
+        qla1280_print("\n\r");
+#endif
+    }
+
+    /* Release ring specific lock */
+    QLA1280_RING_UNLOCK(ha);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (status)
+        qla1280_print("qla1280_64bit_start_scsi: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_64bit_start_scsi: exiting normally\n\r");
+#endif
+    return(status);
+}
+#endif  /* QLA1280_64BIT_SUPPORT */
+
+/*
+ * qla1280_32bit_start_scsi
+ *      The start SCSI is responsible for building request packets on
+ *      request ring and modifying ISP input pointer.
+ *
+ *      The Qlogic firmware interface allows every queue slot to have a SCSI
+ *      command and up to 4 scatter/gather (SG) entries.  If we need more
+ *      than 4 SG entries, then continuation entries are used that can 
+ *      hold another 7 entries each.  The start routine determines if there
+ *      is eought empty slots then build the combination of requests to 
+ *      fulfill the OS request.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      sp = SCSI Request Block structure pointer.
+ *
+ * Returns:
+ *      0 = success, was able to issue command.
+ */
+STATIC uint8_t
+qla1280_32bit_start_scsi(scsi_qla_host_t *ha, srb_t *sp)
+{
+    device_reg_t    *reg   = ha->iobase;
+    uint8_t         status = 0;
+    Scsi_Cmnd       *cmd = sp->cmd;
+    uint32_t        cnt;
+    cmd_entry_t     *pkt;
+    uint16_t        req_cnt;
+    uint16_t        seg_cnt;
+    struct scatterlist    *sg = (struct scatterlist *) NULL;
+    uint8_t        *data_ptr;
+    uint32_t        *dword_ptr;
+
+    ENTER("qla1280_32bit_start_scsi");
+
+
+    if( qla1280_check_for_dead_scsi_bus(ha, sp) )
+    {
+        return(0);
+    }
+
+    /* Calculate number of entries and segments required. */
+    req_cnt = 1;
+    if (cmd->use_sg)
+    {
+        /*
+        * We must build an SG list in adapter format, as the kernel's SG list
+        * cannot be used directly because of data field size (__alpha__)
+        * differences and the kernel SG list uses virtual addresses where
+        * we need physical addresses.
+        */
+        seg_cnt =  cmd->use_sg;
+        sg = (struct scatterlist *) cmd->request_buffer;
+        /* 
+        * if greater than four sg entries then we need to allocate
+        * continuation entries
+        */
+        if (seg_cnt > 4)
+        {
+            req_cnt += (uint16_t)(seg_cnt - 4) / 7;
+            if ((uint16_t)(seg_cnt - 4) % 7)
+                req_cnt++;
+        }
+        DEBUG(sprintf(debug_buff,"S/G for data transfer -num segs(%d), req blk cnt(%d)\n\r",seg_cnt,req_cnt));
+        DEBUG(qla1280_print(debug_buff));
+    }
+    else if (cmd->request_bufflen)  /* If data transfer. */
+    {
+        DEBUG(printk("Single data transfer (0x%x)\n",cmd->request_bufflen));
+        seg_cnt = 1;
+    }
+    else
+    {
+        DEBUG(printk("No data transfer \n"));
+        seg_cnt = 0;
+    }
+
+    /* Acquire ring specific lock */
+    QLA1280_RING_LOCK(ha);
+
+    if ((uint16_t)(req_cnt + 2) >= ha->req_q_cnt)
+    {
+        /* Calculate number of free request entries. */
+        cnt = RD_REG_WORD(&reg->mailbox4);
+        if (ha->req_ring_index < cnt)
+            ha->req_q_cnt = cnt - ha->req_ring_index;
+        else
+            ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
+    }
+
+    DEBUG(sprintf(debug_buff,"Number of free entries = (%d)\n\r",ha->req_q_cnt));
+    DEBUG(qla1280_print(debug_buff));
+    /* If room for request in request ring. */
+    if ((uint16_t)(req_cnt + 2) < ha->req_q_cnt)
+    {
+        /* Check for empty slot in outstanding command list. */
+        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
+            (ha->outstanding_cmds[cnt] != 0); cnt++)
+            ;
+
+        if (cnt < MAX_OUTSTANDING_COMMANDS)
+        {
+            CMD_HANDLE(sp->cmd) = (unsigned char *)(unsigned long)cnt;
+            ha->outstanding_cmds[cnt] = sp;
+            ha->req_q_cnt -= req_cnt;
+
+            /*
+            * Build command packet.
+            */
+            pkt = (cmd_entry_t *)ha->request_ring_ptr;
+
+            pkt->entry_type = COMMAND_TYPE;
+            pkt->entry_count = (uint8_t)req_cnt;
+            pkt->sys_define = (uint8_t)ha->req_ring_index;
+            pkt->handle = (uint32_t)cnt;
+
+            /* Zero out remaining portion of packet. */
+            dword_ptr = (uint32_t *)pkt + 2;
+            for (cnt = 2; cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                *dword_ptr++ = 0;
+
+            /* Set ISP command timeout. */
+            pkt->timeout = (uint16_t)30;
+
+            /* Set device target ID and LUN */
+            pkt->lun = SCSI_LUN_32(cmd);
+            pkt->target = SCSI_BUS_32(cmd) ?
+                    (SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
+
+            /* Enable simple tag queuing if device supports it. */
+            if (cmd->device->tagged_queue )
+                pkt->control_flags |= BIT_3;
+
+            /* Load SCSI command packet. */
+            pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd);
+            data_ptr = (uint8_t *) &(CMD_CDBP(cmd));
+            for (cnt = 0; cnt < pkt->cdb_len; cnt++)
+                pkt->scsi_cdb[cnt] = *data_ptr++;
+            DEBUG(printk("Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]));
+            /*
+            * Load data segments.
+            */
+            if (seg_cnt)
+            {
+                DEBUG(printk("loading data segments..\n"));
+                /* Set transfer direction (READ and WRITE) */
+                /* Linux doesn't tell us                   */
+
+                /*
+                * 3/10 dg - Normally, we should need this check with our F/W
+                * but because of a small issue with it we do.
+                *
+                * For block devices, cmd->request.cmd has the operation 
+                * For character devices, this isn't always set properly, so
+                * we need to check data_cmnd[0].  This catches the conditions
+                * for st.c, but not sg. Generic commands are pass down to us.
+                */
+                if ( (cmd->data_cmnd[0] == WRITE_6) )
+                    pkt->control_flags |= BIT_6;
+                else
+                    pkt->control_flags |= (BIT_5|BIT_6);
+                    
+                sp->dir = pkt->control_flags & (BIT_5|BIT_6);
+
+                /* Set total data segment count. */
+                pkt->dseg_count = seg_cnt;
+
+                /* Setup packet address segment pointer. */
+                dword_ptr = (uint32_t *)&pkt->dseg_0_address;
+
+                if (cmd->use_sg)     /* If scatter gather */
+                {
+                    DEBUG(qla1280_print("Building S/G data segments..\n\r"));
+                    DEBUG(qla1280_dump_buffer((caddr_t)sg, 4*16 ));
+                    /* Load command entry data segments. */
+                    for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--)
+                    {
+                        *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(sg->address));
+                        *dword_ptr++ = sg->length;
+                        DEBUG(sprintf(debug_buff,"SG Segment ap=0x%p, len=0x%x\n\r",sg->address,sg->length));
+                        DEBUG(qla1280_print(debug_buff));
+                        sg++;
+                    }
+                    /*
+                    * Build continuation packets.
+                    */
+                    while (seg_cnt > 0)
+                    {
+                        /* Adjust ring index. */
+                        ha->req_ring_index++;
+                        if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+                        {
+                            ha->req_ring_index = 0;
+                            ha->request_ring_ptr = ha->request_ring;
+                        }
+                        else
+                            ha->request_ring_ptr++;
+
+                        pkt = (cmd_entry_t *)ha->request_ring_ptr;
+
+                        /* Zero out packet. */
+                        dword_ptr = (uint32_t *)pkt;
+                        for (cnt = 0;cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                            *dword_ptr++ = 0;
+
+                        /* Load packet defaults. */
+                        ((cont_entry_t *)pkt)->entry_type =
+                                CONTINUE_TYPE;
+                        ((cont_entry_t *)pkt)->entry_count = 1;
+
+                        ((cont_entry_t *)pkt)->sys_define = (uint8_t)
+                                ha->req_ring_index;
+
+                        /* Setup packet address segment pointer. */
+                        dword_ptr = (uint32_t *)
+                                &((cont_entry_t *)pkt)->dseg_0_address;
+
+                        /* Load continuation entry data segments. */
+                        for (cnt = 0; cnt < 7 && seg_cnt; cnt++, seg_cnt--)
+                        {
+                            *dword_ptr++ = (u_int) cpu_to_le32(VIRT_TO_BUS(sg->address));
+                            *dword_ptr++ = sg->length;
+                            sg++;
+                        }
+#ifdef QL_DEBUG_LEVEL_5
+                        qla1280_print(
+                                "qla1280_32bit_start_scsi: continuation packet data - scsi(");
+                        qla1280_output_number((uint32_t)SCSI_BUS_32(cmd), 10);
+                        qla1280_print(":");
+                        qla1280_output_number((uint32_t)SCSI_TCN_32(cmd), 10);
+                        qla1280_print(":");
+                        qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10);
+                        qla1280_print(")\n\r");
+                        qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+                    }
+                }
+                else                    /* No scatter gather data transfer */
+                {
+                    *dword_ptr++ = (uint32_t) cpu_to_le32(VIRT_TO_BUS(cmd->request_buffer));
+                    *dword_ptr = (uint32_t) cmd->request_bufflen;
+                    DEBUG(printk("Single Segment ap=0x%p, len=0x%x\n",cmd->request_buffer,cmd->request_bufflen));
+                }
+            }
+            else                            /* No data transfer */
+            {
+                *dword_ptr++ = (uint32_t) 0;
+                *dword_ptr = (uint32_t)  0;
+#ifdef QL_DEBUG_LEVEL_5
+                qla1280_print(
+                        "qla1280_32bit_start_scsi: No data, command packet data - ");
+                qla1280_print("\n\r");
+                qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE);
+#endif
+            }
+#ifdef QL_DEBUG_LEVEL_5
+            qla1280_print("qla1280_32bit_start_scsi: First IOCB block:\n\r");
+            qla1280_dump_buffer((caddr_t)ha->request_ring_ptr, REQUEST_ENTRY_SIZE);
+#endif
+            /* Adjust ring index. */
+            ha->req_ring_index++;
+            if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+            {
+                ha->req_ring_index = 0;
+                ha->request_ring_ptr = ha->request_ring;
+            }
+            else
+                ha->request_ring_ptr++;
+
+            /* Set chip new ring index. */
+            DEBUG(qla1280_print("qla1280_32bit_start_scsi: Wakeup RISC for pending command\n\r"));
+            ha->qthreads--;
+            sp->u_start = jiffies;
+            sp->flags |= SRB_SENT;
+            ha->actthreads++;
+            /* qla1280_output_number((uint32_t)ha->actthreads++, 16); */
+            WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
+        }
+        else
+        {
+            status = 1;
+#ifdef QL_DEBUG_LEVEL_2
+            qla1280_print(
+                    "qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING ARRAY\n\r");
+            qla1280_print(" req_q_cnt=");
+            qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
+            qla1280_print("\n\r");
+#endif
+        }
+    }
+    else
+    {
+        status = 1;
+#ifdef QL_DEBUG_LEVEL_2
+        /*  qla1280_print("qla1280_32bit_start_scsi: in-ptr=");
+        qla1280_output_number((uint32_t)ha->req_ring_index, 16);
+        qla1280_print(" req_q_cnt=");
+        qla1280_output_number((uint32_t)ha->req_q_cnt, 16);
+        qla1280_print(" req_cnt=");
+        qla1280_output_number((uint32_t)req_cnt, 16);
+        qla1280_print("\n\r"); */
+#endif
+    }
+
+    /* Release ring specific lock */
+    QLA1280_RING_UNLOCK(ha);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    /* if (status)
+    qla1280_print("qla1280_32bit_start_scsi: **** FAILED ****\n\r"); */
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+            LEAVE("qla1280_32bit_start_scsi");
+#endif
+    return(status);
+}
+
+/*
+ * qla1280_req_pkt
+ *      Function is responsible for locking ring and
+ *      getting a zeroed out request packet.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ *
+ * Returns:
+ *      0 = failed to get slot.
+ */
+STATIC request_t *
+qla1280_req_pkt(scsi_qla_host_t *ha)
+{
+    device_reg_t    *reg = ha->iobase;
+    request_t       *pkt = 0;
+    uint16_t        cnt;
+    uint32_t        *dword_ptr;
+    uint32_t        timer;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_req_pkt");
+#endif
+
+    /* Wait for 30 seconds for slot. */
+    for (timer = 15000000; timer; timer--)
+    {
+        /* Acquire ring specific lock */
+        QLA1280_RING_LOCK(ha);
+
+        if (ha->req_q_cnt > 0)
+        {
+            /* Calculate number of free request entries. */
+            cnt = RD_REG_WORD(&reg->mailbox4);
+            if (ha->req_ring_index < cnt)
+                ha->req_q_cnt = cnt - ha->req_ring_index;
+            else
+                ha->req_q_cnt = REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
+        }
+
+        /* Found empty request ring slot? */
+        if (ha->req_q_cnt > 0)
+        {
+            ha->req_q_cnt--;
+            pkt = ha->request_ring_ptr;
+
+            /* Zero out packet. */
+            dword_ptr = (uint32_t *)pkt;
+            for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++)
+                *dword_ptr++ = 0;
+
+            /* Set system defined field. */
+            pkt->sys_define = (uint8_t)ha->req_ring_index;
+
+            /* Set entry count. */
+            pkt->entry_count = 1;
+
+            break;
+        }
+
+        /* Release ring specific lock */
+        QLA1280_RING_UNLOCK(ha);
+
+        SYS_DELAY(2);   /* 10 */ 
+
+        /* Check for pending interrupts. */
+        qla1280_poll(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_req_pkt: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_req_pkt: exiting normally\n\r");
+#endif
+    return(pkt);
+}
+
+/*
+ * qla1280_isp_cmd
+ *      Function is responsible for modifying ISP input pointer.
+ *      Releases ring lock.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ */
+STATIC void
+qla1280_isp_cmd(scsi_qla_host_t *ha)
+{
+    device_reg_t    *reg = ha->iobase;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_isp_cmd");
+#endif
+
+#ifdef QL_DEBUG_LEVEL_5
+    qla1280_print("qla1280_isp_cmd: IOCB data:\n\r");
+    qla1280_dump_buffer((caddr_t)ha->request_ring_ptr, REQUEST_ENTRY_SIZE); 
+#endif
+
+    /* Adjust ring index. */
+    ha->req_ring_index++;
+    if (ha->req_ring_index == REQUEST_ENTRY_CNT)
+    {
+        ha->req_ring_index = 0;
+        ha->request_ring_ptr = ha->request_ring;
+    }
+    else
+        ha->request_ring_ptr++;
+
+    /* Set chip new ring index. */
+    WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
+
+    /* Release ring specific lock */
+    QLA1280_RING_UNLOCK(ha);
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_isp_cmd");
+#endif
+}
+
+/*
+ * qla1280_enable_lun
+ *      Issue enable LUN entry IOCB.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      b  = SCSI BUS number.
+ *      l  = LUN number.
+ */
+STATIC void
+qla1280_enable_lun(scsi_qla_host_t *ha, uint8_t b, uint32_t l)
+{
+    elun_entry_t    *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_enable_lun: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    /*
+    if (pkt = (elun_entry_t *)qla1280_req_pkt(ha))
+    {
+    pkt->entry_type = ENABLE_LUN_TYPE;
+    pkt->lun = (uint16_t)(b ? l | BIT_15 : l);
+    pkt->command_count = 32;
+    pkt->immed_notify_count = 1;
+    pkt->group_6_length = MAX_CMDSZ;
+    pkt->group_7_length = MAX_CMDSZ;
+    pkt->timeout = 0x30;
+
+    qla1280_isp_cmd(ha);
+    }
+    */
+    pkt = (elun_entry_t *)1;
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_enable_lun: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_enable_lun: exiting normally\n\r");
+#endif
+}
+
+#if QL1280_TARGET_MODE_SUPPORT
+/****************************************************************************/
+/*                      Target Mode Support Functions.                      */
+/****************************************************************************/
+
+/*
+ * qla1280_notify_ack
+ *      Issue notify acknowledge IOCB.
+ *      If sequence ID is zero, acknowledgement of
+ *      SCSI bus reset or bus device reset is assumed.
+ *
+ * Input:
+ *      ha      = adapter block pointer.
+ *      inotify = immediate notify entry pointer.
+ */
+STATIC void
+qla1280_notify_ack(scsi_qla_host_t *ha, notify_entry_t *inotify)
+{
+    nack_entry_t    *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_notify_ack: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (nack_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = NOTIFY_ACK_TYPE;
+        pkt->lun = inotify->lun;
+        pkt->initiator_id = inotify->initiator_id;
+        pkt->target_id = inotify->target_id;
+        if (inotify->seq_id == 0)
+            pkt->event = BIT_7;
+        else
+            pkt->seq_id = inotify->seq_id;
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_notify_ack: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_notify_ack: exiting normally\n\r");
+#endif
+}
+
+/*
+ * qla1280_immed_notify
+ *      Issue immediate notify IOCB for LUN 0.
+ *
+ * Input:
+ *      ha      = adapter block pointer.
+ *      inotify = immediate notify entry pointer.
+ */
+STATIC void
+qla1280_immed_notify(scsi_qla_host_t *ha, notify_entry_t *inotify)
+{
+    notify_entry_t    *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_immed_notify: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (notify_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = IMMED_NOTIFY_TYPE;
+        pkt->lun = inotify->lun;
+        pkt->initiator_id = inotify->initiator_id;
+        pkt->target_id = inotify->target_id;
+        pkt->status = 1;
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_immed_notify: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_immed_notify: exiting normally\n\r");
+#endif
+}
+
+/*
+ * qla1280_accept_io
+ *      Issue accept target I/O IOCB for LUN 0.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ *      ctio = ctio returned entry pointer.
+ */
+STATIC void
+qla1280_accept_io(scsi_qla_host_t *ha, ctio_ret_entry_t *ctio)
+{
+    atio_entry_t    *pkt;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_accept_io: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (atio_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = ACCEPT_TGT_IO_TYPE;
+        pkt->lun = ctio->lun;
+        pkt->initiator_id = ctio->initiator_id;
+        pkt->target_id = ctio->target_id;
+        pkt->tag_value = ctio->tag_value;
+        pkt->status = 1;
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_accept_io: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_accept_io: exiting normally\n\r");
+#endif
+}
+
+/*
+ * qla1280_64bit_continue_io
+ *      Issue continue target I/O IOCB.
+ *
+ * Input:
+ *      ha   = adapter block pointer.
+ *      atio = atio pointer.
+ *      len  = total bytecount.
+ *      addr = physical address pointer.
+ */
+STATIC void
+qla1280_64bit_continue_io(scsi_qla_host_t *ha, atio_entry_t *atio, uint32_t len,
+                    paddr32_t *addr)
+{
+    ctio_a64_entry_t *pkt;
+    uint32_t         *dword_ptr;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_64bit_continue_io: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (ctio_a64_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = CTIO_A64_TYPE;
+        pkt->lun = atio->lun;
+        pkt->initiator_id = atio->initiator_id;
+        pkt->target_id = atio->target_id;
+        pkt->option_flags = atio->option_flags;
+        pkt->tag_value = atio->tag_value;
+        pkt->scsi_status = atio->scsi_status;
+
+        if (len)
+        {
+            pkt->dseg_count = 1;
+            pkt->transfer_length = len;
+            pkt->dseg_0_length = len;
+            dword_ptr = (uint32_t *)addr;
+            pkt->dseg_0_address[0] = *dword_ptr++;
+            pkt->dseg_0_address[1] = *dword_ptr;
+        }
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_64bit_continue_io: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_64bit_continue_io: exiting normally\n\r");
+#endif
+}
+
+/*
+ * qla1280_32bit_continue_io
+ *      Issue continue target I/O IOCB.
+ *
+ * Input:
+ *      ha   = adapter block pointer.
+ *      atio = atio pointer.
+ *      len  = total bytecount.
+ *      addr = physical address pointer.
+ */
+STATIC void
+qla1280_32bit_continue_io(scsi_qla_host_t *ha, atio_entry_t *atio, uint32_t len,
+                    paddr32_t *addr)
+{
+    ctio_entry_t *pkt;
+    uint32_t     *dword_ptr;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_32bit_continue_io: entered\n\r");
+#endif
+
+    /* Get request packet. */
+    if (pkt = (ctio_entry_t *)qla1280_req_pkt(ha))
+    {
+        pkt->entry_type = CONTINUE_TGT_IO_TYPE;
+        pkt->lun = atio->lun;
+        pkt->initiator_id = atio->initiator_id;
+        pkt->target_id = atio->target_id;
+        pkt->option_flags = atio->option_flags;
+        pkt->tag_value = atio->tag_value;
+        pkt->scsi_status = atio->scsi_status;
+
+        if (len)
+        {
+            pkt->dseg_count = 1;
+            pkt->transfer_length = len;
+            pkt->dseg_0_length = len;
+            dword_ptr = (uint32_t *)addr;
+            pkt->dseg_0_address = *dword_ptr;
+        }
+
+        /* Issue command to ISP */
+        qla1280_isp_cmd(ha);
+    }
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+    if (!pkt)
+        qla1280_print("qla1280_32bit_continue_io: **** FAILED ****\n\r");
+#endif
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        qla1280_print("qla1280_32bit_continue_io: exiting normally\n\r");
+#endif
+}
+#endif /* QL1280_TARGET_MODE_SUPPORT */
+
+/****************************************************************************/
+/*                        Interrupt Service Routine.                        */
+/****************************************************************************/
+
+/****************************************************************************
+ *  qla1280_isr
+ *      Calls I/O done on command completion.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ *      INTR_LOCK must be already obtained.
+ ****************************************************************************/
+STATIC void
+qla1280_isr(scsi_qla_host_t *ha, srb_t **done_q_first, srb_t **done_q_last)
+{
+    device_reg_t    *reg = ha->iobase;
+    response_t      *pkt;
+    srb_t           *sp;
+    uint16_t        mailbox[MAILBOX_REGISTER_COUNT];
+    uint16_t        *wptr;
+    uint32_t        index;
+
+    ENTER("qla1280_isr");
+
+
+    /* Save mailbox register 5 */
+    mailbox[5] = RD_REG_WORD(&reg->mailbox5);
+
+    /* Check for mailbox interrupt. */
+
+    mailbox[0] = RD_REG_WORD(&reg->semaphore);
+    if (mailbox[0] & BIT_0)
+    {
+        /* Get mailbox data. */
+
+        wptr = &mailbox[0];
+        *wptr++ = RD_REG_WORD(&reg->mailbox0);
+        *wptr++ = RD_REG_WORD(&reg->mailbox1);
+        *wptr = RD_REG_WORD(&reg->mailbox2);
+        if (mailbox[0] != MBA_SCSI_COMPLETION)
+        {
+            wptr++;
+            *wptr++ = RD_REG_WORD(&reg->mailbox3);
+            *wptr++ = RD_REG_WORD(&reg->mailbox4);
+            wptr++;
+            *wptr++ = RD_REG_WORD(&reg->mailbox6);
+            *wptr   = RD_REG_WORD(&reg->mailbox7);
+        }
+
+        /* Release mailbox registers. */
+
+        WRT_REG_WORD(&reg->semaphore, 0);
+        WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+
+#ifdef QL_DEBUG_LEVEL_5
+        qla1280_print("qla1280_isr: mailbox interrupt mailbox[0] = ");
+        qla1280_output_number((uint32_t)mailbox[0], 16);
+        qla1280_print("\n\r");
+#endif
+
+        /* Handle asynchronous event */
+
+        switch (mailbox[0])
+        {
+            case MBA_SCSI_COMPLETION:   /* Response completion */
+#ifdef QL_DEBUG_LEVEL_5
+                qla1280_print("qla1280_isr: mailbox response completion\n\r");
+#endif
+                if (ha->flags.online)
+                {
+                    /* Get outstanding command index. */
+                    index = (uint32_t)(mailbox[2] << 16 | mailbox[1]);
+
+                    /* Validate handle. */
+                    if (index < MAX_OUTSTANDING_COMMANDS)
+                        sp = ha->outstanding_cmds[index];
+                    else
+                        sp = 0;
+
+                    if (sp)
+                    {
+                        /* Free outstanding command slot. */
+                        ha->outstanding_cmds[index] = 0;
+
+                        /* Save ISP completion status */
+                        CMD_RESULT(sp->cmd) = 0;
+
+                        /* Place block on done queue */
+                        sp->s_next = NULL;
+                        sp->s_prev = *done_q_last;
+                        if (!*done_q_first)
+                            *done_q_first = sp;
+                        else
+                            (*done_q_last)->s_next = sp;
+                        *done_q_last = sp;
+                    }
+                    else
+                    {
+#ifdef QL_DEBUG_LEVEL_2
+                            qla1280_print("qla1280_isr: ISP invalid handle\n\r");
+#endif
+                            printk(KERN_WARNING "qla1280: ISP invalid handle");
+                            ha->flags.isp_abort_needed = TRUE;
+                    }
+                }
+                break;
+            case MBA_BUS_RESET:         /* SCSI Bus Reset */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: asynchronous BUS_RESET\n\r");
+#endif
+                ha->flags.reset_marker = TRUE;
+                index = mailbox[6] & BIT_0;
+                ha->bus_settings[index].reset_marker = TRUE;
+                break;
+            case MBA_SYSTEM_ERR:        /* System Error */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: ISP System Error - mbx1=");
+                qla1280_output_number((uint32_t)mailbox[1], 16);
+                qla1280_print(", mbx2=");
+                qla1280_output_number((uint32_t)mailbox[2], 16);
+                qla1280_print(", mbx3=");
+                qla1280_output_number((uint32_t)mailbox[3], 16);
+                qla1280_print("\n\r");
+#endif
+                printk(KERN_WARNING
+                        "qla1280: ISP System Error - mbx1=%xh, mbx2=%xh, mbx3=%xh\n",
+                        mailbox[1], mailbox[2], mailbox[3]);
+                ha->flags.isp_abort_needed = TRUE;
+                break;
+            case MBA_REQ_TRANSFER_ERR:  /* Request Transfer Error */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: ISP Request Transfer Error\n\r");
+#endif
+                printk(KERN_WARNING "qla1280: ISP Request Transfer Error\n");
+                ha->flags.isp_abort_needed = TRUE;
+                break;
+            case MBA_RSP_TRANSFER_ERR:  /* Response Transfer Error */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: ISP Response Transfer Error\n\r");
+#endif
+                printk(KERN_WARNING "qla1280: ISP Response Transfer Error\n");
+                ha->flags.isp_abort_needed = TRUE;
+                break;
+            case MBA_WAKEUP_THRES:      /* Request Queue Wake-up */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: asynchronous WAKEUP_THRES\n\r");
+#endif
+                break;
+            case MBA_TIMEOUT_RESET:     /* Execution Timeout Reset */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print("qla1280_isr: asynchronous TIMEOUT_RESET\n\r");
+#endif
+                break;
+            case MBA_DEVICE_RESET:         /* Bus Device Reset */
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print(
+                        "qla1280_isr: asynchronous BUS_DEVICE_RESET\n\r");
+#endif
+                ha->flags.reset_marker = TRUE;
+                index = mailbox[6] & BIT_0;
+                ha->bus_settings[index].reset_marker = TRUE;
+                break;
+            case MBA_BUS_MODE_CHANGE:
+#ifdef QL_DEBUG_LEVEL_2
+                qla1280_print(
+                        "qla1280_isr: asynchronous BUS_MODE_CHANGE\n\r");
+#endif
+                break;
+            default:
+                if (mailbox[0] < MBA_ASYNC_EVENT)
+                {
+                        wptr = &mailbox[0];
+                        ha->mailbox_out[0] = *wptr++;
+                        ha->mailbox_out[1] = *wptr++;
+                        ha->mailbox_out[2] = *wptr++;
+                        ha->mailbox_out[3] = *wptr++;
+                        ha->mailbox_out[4] = *wptr++;
+                        ha->mailbox_out[5] = *wptr++;
+                        ha->mailbox_out[6] = *wptr++;
+                        ha->mailbox_out[7] = *wptr;
+                        ha->flags.mbox_int = TRUE;
+                }
+                break;
+        }
+    }
+    else
+        WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
+
+    /*
+    * Response ring
+    */
+    if (ha->flags.online && !ha->flags.mbox_busy)
+    {
+        if (mailbox[5] < RESPONSE_ENTRY_CNT)
+        {
+            while (ha->rsp_ring_index != mailbox[5])
+            {
+                pkt = ha->response_ring_ptr;
+
+#ifdef QL_DEBUG_LEVEL_5
+                qla1280_print("qla1280_isr: ha->rsp_ring_index = ");
+                qla1280_output_number((uint32_t)ha->rsp_ring_index, 16);
+                qla1280_print(" mailbox[5] = ");
+                qla1280_output_number((uint32_t)mailbox[5], 16);
+                qla1280_print("\n\rqla1280_isr: response packet data\n\r");
+                qla1280_dump_buffer((caddr_t)pkt, RESPONSE_ENTRY_SIZE);
+#endif
+
+#if defined(QL_DEBUG_LEVEL_2) && !defined(QL_DEBUG_LEVEL_5)
+                if (pkt->entry_type == STATUS_TYPE)
+                {
+                    if ((uint8_t)(pkt->scsi_status) || pkt->comp_status ||
+                        pkt->entry_status)
+                    {
+                        DEBUG(qla1280_print("qla1280_isr: ha->rsp_ring_index = ");)
+                        DEBUG(qla1280_output_number((uint32_t)ha->rsp_ring_index,
+                                16);)
+                        DEBUG(qla1280_print(" mailbox[5] = ");)
+                        DEBUG(qla1280_output_number((uint32_t)mailbox[5], 16);)
+                        DEBUG(qla1280_print( "\n\r comp_status = ");)
+                        DEBUG(qla1280_output_number((uint32_t)pkt->comp_status,16);)
+                        DEBUG(qla1280_print( ", ");)
+                        DEBUG(qla1280_print( " scsi_status = ");)
+                        DEBUG(qla1280_output_number((uint32_t)pkt->scsi_status,16);)
+                        DEBUG(qla1280_print( "\n\r");)
+                        /* qla1280_print(
+                        "\n\rqla1280_isr: response packet data\n\r");
+                        qla1280_dump_buffer((caddr_t)pkt,
+                        RESPONSE_ENTRY_SIZE); */
+                    }
+                }
+                else
+                {
+                    qla1280_print("qla1280_isr: ha->rsp_ring_index = ");
+                    qla1280_output_number((uint32_t)ha->rsp_ring_index, 16);
+                    qla1280_print(" mailbox[5] = ");
+                    qla1280_output_number((uint32_t)mailbox[5], 16);
+                    qla1280_print(
+                            "\n\rqla1280_isr: response packet data\n\r");
+                    qla1280_dump_buffer((caddr_t)pkt, RESPONSE_ENTRY_SIZE);
+                }
+#endif
+                if (pkt->entry_type == STATUS_TYPE || pkt->entry_status)
+                {
+                    if (pkt->entry_type == STATUS_TYPE)
+                        qla1280_status_entry(ha, (sts_entry_t *)pkt,
+                                done_q_first, done_q_last);
+                    else
+                        qla1280_error_entry(ha, pkt,
+                                done_q_first, done_q_last);
+
+                    /* Adjust ring index. */
+                    ha->rsp_ring_index++;
+                    if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT)
+                    {
+                        ha->rsp_ring_index = 0;
+                        ha->response_ring_ptr = ha->response_ring;
+                    }
+                    else
+                        ha->response_ring_ptr++;
+                    WRT_REG_WORD(&reg->mailbox5, ha->rsp_ring_index);
+                }
+#if QLA1280_TARGET_MODE_SUPPORT
+                else
+                {
+                    pkt = &response_entry;
+
+                    /* Copy packet. */
+                    dptr1 = (uint32_t *)ha->response_ring_ptr;
+                    dptr2 = (uint32_t *)pkt;
+                    for (index = 0; index < RESPONSE_ENTRY_SIZE/4; index++)
+                        *dptr2++ = *dptr1++;
+
+                    /* Adjust ring index. */
+                    ha->rsp_ring_index++;
+                    if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT)
+                    {
+                        ha->rsp_ring_index = 0;
+                        ha->response_ring_ptr = ha->response_ring;
+                    }
+                    else
+                        ha->response_ring_ptr++;
+                    WRT_REG_WORD(&reg->mailbox5, ha->rsp_ring_index);
+
+                    /* Release interrupt specific lock */
+                    QLA1280_INTR_UNLOCK(ha);
+
+                    switch (pkt->entry_type)
+                    {
+                        case ACCEPT_TGT_IO_TYPE:
+                            qla1280_atio_entry(ha, (atio_entry_t *)pkt);
+                            break;
+                        case IMMED_NOTIFY_TYPE:
+                            qla1280_notify_entry(ha, (notify_entry_t *)pkt);
+                            break;
+                        case CTIO_RET_TYPE:
+                            qla1280_accept_io(ha, (ctio_ret_entry_t *)pkt);
+                            break;
+                        default:
+                            break;
+                    }
+
+                    /* Acquire interrupt specific lock */
+                    QLA1280_INTR_LOCK(ha);
+                }
+#endif
+            }
+        }
+        else
+        {
+            ha->flags.isp_abort_needed = TRUE;
+#ifdef QL_DEBUG_LEVEL_2
+            qla1280_print("qla1280_isr: Response pointer Error\n");
+#endif
+        }
+    }
+
+    LEAVE("qla1280_isr");
+}
+
+/*
+ *  qla1280_rst_aen
+ *      Processes asynchronous reset.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ */
+STATIC void
+qla1280_rst_aen(scsi_qla_host_t *ha)
+{
+#if QL1280_TARGET_MODE_SUPPORT
+    notify_entry_t  nentry;
+#endif
+    uint8_t         b;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_rst_aen");
+#endif
+
+    if (ha->flags.online && !ha->flags.reset_active &&
+        !ha->flags.abort_isp_active)
+    {
+        ha->flags.reset_active = TRUE;
+        while (ha->flags.reset_marker)
+        {
+            /* Issue marker command. */
+            ha->flags.reset_marker = FALSE;
+            for (b = 0; b < ha->ports && !ha->flags.reset_marker; b++)
+            {
+                if (ha->bus_settings[b].reset_marker)
+                {
+                    ha->bus_settings[b].reset_marker = FALSE;
+                    qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
+
+                    if (!ha->flags.reset_marker)
+                    {
+#if QL1280_TARGET_MODE_SUPPORT
+                        /* Issue notify acknowledgement command. */
+                        bzero((caddr_t)&nentry, sizeof(notify_entry_t));
+
+                        nentry.initiator_id = nentry.target_id = b ?
+                                ha->bus_settings[b].id | BIT_7 :
+                        ha->bus_settings[b].id;
+                        qla1280_notify_entry(ha, &nentry);
+#endif
+
+                        /* Asynchronous event notification */
+                    }
+                }
+            }
+        }
+    }
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_rst_aen");
+#endif
+}
+
+#if QL1280_TARGET_MODE_SUPPORT
+/*
+ *  qla1280_atio_entry
+ *      Processes received ISP accept target I/O entry.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ *      pkt = entry pointer.
+ */
+STATIC void
+qla1280_atio_entry(scsi_qla_host_t *ha, atio_entry_t *pkt)
+{
+    uint64_t    *a64;
+    uint64_t    *end_a64;
+    paddr32_t   phy_addr[2];
+    paddr32_t   end_addr[2];
+    uint32_t    len;
+    uint32_t    offset;
+    uint8_t     t;
+    uint8_t     *sense_ptr;
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_atio_entry: entered\n\r");
+#endif
+
+    t = pkt->initiator_id;
+    sense_ptr = ha->tsense + t * TARGET_SENSE_SIZE;
+    a64 = (uint64_t *)&phy_addr[0];
+    end_a64 = (uint64_t *)&end_addr[0];
+
+    switch (pkt->status & ~BIT_7)
+    {
+        case 7:                         /* Path invalid */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+            qla1280_print("qla1280_atio_entry: Path invalid\n\r");
+#endif
+            break;
+        case 0x14:                  /* Target Bus Phase Sequence Failure */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+            qla1280_print(
+                    "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r");
+#endif
+            if (pkt->status & BIT_7)
+            {
+                BCOPY((caddr_t)&pkt->sense_data, sense_ptr,TARGET_SENSE_SIZE);
+            }
+            else
+            {
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    *sense_ptr = 0x70;
+                    *(sense_ptr+2) = SD_HARDERR;
+                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                    *(sense_ptr+12) = SC_SELFAIL;
+            }
+            pkt->scsi_status = S_CKCON;
+            pkt->option_flags |= (uint32_t)OF_SSTS | (uint32_t)OF_NO_DATA;
+            if (ha->flags.enable_64bit_addressing)
+                qla1280_64bit_continue_io(ha, pkt, 0, 0);
+            else
+                qla1280_32bit_continue_io(ha, pkt, 0, 0);
+            break;
+        case 0x16:                  /* Requested Capability Not Available */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+            qla1280_print(
+                    "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r");
+#endif
+            break;
+        case 0x17:                  /* Bus Device Reset Message Received */
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+            qla1280_print(
+                    "qla1280_atio_entry: Target Bus Phase Sequence Failure\n\r");
+#endif
+            break;
+        case 0x3D:                  /* CDB Received */
+
+            /* Check for invalid LUN */
+            if (pkt->lun && pkt->cdb[0] != SS_INQUIR &&
+                pkt->cdb[0] != SS_REQSEN)
+                pkt->cdb[0] = SS_TEST;
+
+            switch (pkt->cdb[0])
+            {
+                case SS_TEST:
+#ifdef QL_DEBUG_LEVEL_3
+                    qla1280_print("qla1280_atio_entry: SS_TEST\n\r");
+#endif
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    len = 0;
+                    if (pkt->lun == 0)
+                        pkt->scsi_status = S_GOOD;
+                    else
+                    {
+                        *sense_ptr = 0x70;
+                        *(sense_ptr+2) = SD_ILLREQ;
+                        *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                        *(sense_ptr+12) = SC_INVLUN;
+                        pkt->scsi_status = S_CKCON;
+                    }
+
+                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                            (uint32_t)OF_NO_DATA;
+                    break;
+                case SS_REQSEN:
+#ifdef QL_DEBUG_LEVEL_3
+                    qla1280_print("qla1280_atio_entry: SS_REQSEN\n\r");
+#endif
+                    phy_addr[0] = ha->tsense_dma;
+                    phy_addr[1] = 0;
+                    *a64 += t * TARGET_SENSE_SIZE;
+                    if (pkt->cdb[4] > TARGET_SENSE_SIZE)
+                        len = TARGET_SENSE_SIZE;
+                    else
+                        len = pkt->cdb[4];
+                    pkt->scsi_status = S_GOOD;
+                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                            (uint32_t)OF_DATA_IN;
+                    break;
+                case SS_INQUIR:
+#ifdef QL_DEBUG_LEVEL_3
+                    qla1280_print("qla1280_atio_entry: SS_INQUIR\n\r");
+#endif
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    phy_addr[0] = ha->tbuf_dma;
+                    phy_addr[1] = 0;
+                    *a64 += TARGET_INQ_OFFSET;
+
+                    if (pkt->lun == 0)
+                    {
+                            ha->tbuf->inq.id_type = ID_PROCESOR;
+                            ha->tbuf->inq.id_pqual = ID_QOK;
+                    }
+                    else
+                    {
+                            ha->tbuf->inq.id_type = ID_NODEV;
+                            ha->tbuf->inq.id_pqual = ID_QNOLU;
+                    }
+
+                    if (pkt->cdb[4] > sizeof(struct ident))
+                        len = sizeof(struct ident);
+                    else
+                        len = pkt->cdb[4];
+                    pkt->scsi_status = S_GOOD;
+                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                            (uint32_t)OF_DATA_IN;
+                    break;
+                case SM_WRDB:
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    offset = pkt->cdb[5];
+                    offset |= pkt->cdb[4] << 8;
+                    offset |= pkt->cdb[3] << 16;
+                    len = pkt->cdb[8];
+                    len |= pkt->cdb[7] << 8;
+                    len |= pkt->cdb[6] << 16;
+                    end_addr[0] = phy_addr[0] = ha->tbuf_dma;
+                    end_addr[1] = phy_addr[1] = 0;
+                    *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
+                    switch (pkt->cdb[1] & 7)
+                    {
+                        case RW_BUF_HDATA:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_HDATA\n\r");
+#endif
+                            if (len > TARGET_DATA_SIZE + 4)
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                qla1280_print("qla1280_atio_entry: SM_WRDB, length > buffer size\n\r");
+#endif
+                                *sense_ptr = 0x70;
+                                *(sense_ptr+2) = SD_ILLREQ;
+                                *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                                *(sense_ptr+12) = SC_ILLCDB;
+                                pkt->scsi_status = S_CKCON;
+                                pkt->option_flags |= (uint32_t)OF_SSTS |
+                                        (uint32_t)OF_NO_DATA;
+                                len = 0;
+                            }
+                            else if (len)
+                            {
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_DATA_OUT;
+#ifdef QL_DEBUG_LEVEL_3
+                                    qla1280_print("qla1280_atio_entry: Issuing SDI_TARMOD_WRCOMP\n\r");
+#endif
+                                    sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
+                                            pkt->target_id, pkt->lun, 0, offset);
+                            }
+                            else
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_WRDB, zero length\n\r");
+#endif
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+
+                            break;
+                        case RW_BUF_DATA:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_DATA\n\r");
+#endif
+                            *a64 += offset + TARGET_DATA_OFFSET;
+                            if (pkt->cdb[2] != 0 || *a64 >= *end_a64 ||
+                                *a64 + len > *end_a64)
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_WRDB, RW_BUF_DATA BAD\n\r");
+                                    qla1280_print("buf_id=");
+                                    qla1280_output_number((uint32_t)pkt->cdb[2], 16);
+                                    qla1280_print(", offset=");
+                                    qla1280_output_number((uint32_t)offset, 16);
+                                    qla1280_print(", length=");
+                                    qla1280_output_number((uint32_t)len, 16);
+                                    qla1280_print("\n\r");
+#endif
+                                    *sense_ptr = 0x70;
+                                    *(sense_ptr+2) = SD_ILLREQ;
+                                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                                    *(sense_ptr+12) = SC_ILLCDB;
+                                    len = 0;
+                                    pkt->scsi_status = S_CKCON;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            else if (len)
+                            {
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_DATA_OUT;
+#ifdef QL_DEBUG_LEVEL_3
+                                    qla1280_print("qla1280_atio_entry: Issuing SDI_TARMOD_WRCOMP\n\r");
+#endif
+                                    sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
+                                            pkt->target_id, pkt->lun, 0, offset);
+                            }
+                            else
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_WRDB, zero length\n\r");
+#endif
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            break;
+                        default:
+#ifdef QL_DEBUG_LEVEL_2
+                            qla1280_print("qla1280_atio_entry: SM_WRDB unknown mode\n\r");
+#endif
+                            *sense_ptr = 0x70;
+                            *(sense_ptr+2) = SD_ILLREQ;
+                            *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                            *(sense_ptr+12) = SC_ILLCDB;
+                            len = 0;
+                            pkt->scsi_status = S_CKCON;
+                            pkt->option_flags |= (uint32_t)OF_SSTS |
+                                    (uint32_t)OF_NO_DATA;
+                            break;
+                    }
+                    break;
+                case SM_RDDB:
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    offset = pkt->cdb[5];
+                    offset |= pkt->cdb[4] << 8;
+                    offset |= pkt->cdb[3] << 16;
+                    len = pkt->cdb[8];
+                    len |= pkt->cdb[7] << 8;
+                    len |= pkt->cdb[6] << 16;
+                    end_addr[0] = phy_addr[0] = ha->tbuf_dma;
+                    end_addr[1] = phy_addr[1] = 0;
+                    *end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
+                    switch (pkt->cdb[1] & 7)
+                    {
+                        case RW_BUF_HDATA:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_HDATA\n\r");
+#endif
+                            if (len)
+                            {
+                                ha->tbuf->hdr[0] = 0;
+                                ha->tbuf->hdr[1] =
+                                        (uint8_t)(TARGET_DATA_SIZE >> 16);
+                                ha->tbuf->hdr[2] =
+                                        (uint8_t)(TARGET_DATA_SIZE >> 8);
+                                ha->tbuf->hdr[3] = (uint8_t)TARGET_DATA_SIZE;
+                                if (len > TARGET_DATA_SIZE + 4)
+                                    len = TARGET_DATA_SIZE + 4;
+                                pkt->scsi_status = S_GOOD;
+                                pkt->option_flags |= (uint32_t)OF_SSTS |
+                                        (uint32_t)OF_DATA_IN;
+                            }
+                            else
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r");
+#endif
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            break;
+                        case RW_BUF_DATA:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DATA\n\r");
+#endif
+                            *a64 += offset + TARGET_DATA_OFFSET;
+                            if (pkt->cdb[2] != 0 || *a64 >= *end_a64)
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DATA BAD\n\r");
+                                    qla1280_print("buf_id=");
+                                    qla1280_output_number((uint32_t)pkt->cdb[2], 16);
+                                    qla1280_print(", offset=");
+                                    qla1280_output_number((uint32_t)offset, 16);
+                                    qla1280_print("\n\r");
+#endif
+                                    *sense_ptr = 0x70;
+                                    *(sense_ptr+2) = SD_ILLREQ;
+                                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                                    *(sense_ptr+12) = SC_ILLCDB;
+                                    len = 0;
+                                    pkt->scsi_status = S_CKCON;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            else
+                            {
+                                    if (*a64 + len > *end_a64)
+                                        len = *end_a64 - *a64;
+                                    if (len)
+                                    {
+                                        pkt->scsi_status = S_GOOD;
+                                        pkt->option_flags |= (uint32_t)OF_SSTS |
+                                                (uint32_t)OF_DATA_IN;
+                                    }
+                                    else
+                                    {
+#ifdef QL_DEBUG_LEVEL_2
+                                            qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r");
+#endif
+                                            pkt->scsi_status = S_GOOD;
+                                            pkt->option_flags |= (uint32_t)OF_SSTS |
+                                                    (uint32_t)OF_NO_DATA;
+                                    }
+                            }
+                            break;
+                        case RW_BUF_DESC:
+#ifdef QL_DEBUG_LEVEL_3
+                            qla1280_print("qla1280_atio_entry: SM_RDDB, RW_BUF_DESC\n\r");
+#endif
+                            if (len)
+                            {
+                                    if (len > 4)
+                                        len = 4;
+
+                                    ha->tbuf->hdr[0] = 0;
+                                    if (pkt->cdb[2] != 0)
+                                    {
+                                        ha->tbuf->hdr[1] = 0;
+                                        ha->tbuf->hdr[2] = 0;
+                                        ha->tbuf->hdr[3] = 0;
+                                    }
+                                    else
+                                    {
+                                            ha->tbuf->hdr[1] =
+                                                    (uint8_t)(TARGET_DATA_SIZE >> 16);
+                                            ha->tbuf->hdr[2] =
+                                                    (uint8_t)(TARGET_DATA_SIZE >> 8);
+                                            ha->tbuf->hdr[3] =
+                                                    (uint8_t)TARGET_DATA_SIZE;
+                                    }
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_DATA_IN;
+                            }
+                            else
+                            {
+#ifdef QL_DEBUG_LEVEL_2
+                                    qla1280_print("qla1280_atio_entry: SM_RDDB, zero length\n\r");
+#endif
+                                    pkt->scsi_status = S_GOOD;
+                                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                                            (uint32_t)OF_NO_DATA;
+                            }
+                            break;
+                        default:
+#ifdef QL_DEBUG_LEVEL_2
+                            qla1280_print("qla1280_atio_entry: SM_RDDB unknown mode\n\r");
+#endif
+                            *sense_ptr = 0x70;
+                            *(sense_ptr+2) = SD_ILLREQ;
+                            *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                            *(sense_ptr+12) = SC_ILLCDB;
+                            len = 0;
+                            pkt->scsi_status = S_CKCON;
+                            pkt->option_flags |= (uint32_t)OF_SSTS |
+                                    (uint32_t)OF_NO_DATA;
+                            break;
+                    }
+                    break;
+                default:
+#ifdef QL_DEBUG_LEVEL_2
+                    qla1280_print("qla1280_atio_entry: Unknown SCSI command\n\r");
+                    qla1280_dump_buffer((caddr_t)&pkt->cdb[0], pkt->cdb_len);
+#endif
+                    bzero(sense_ptr, TARGET_SENSE_SIZE);
+                    *sense_ptr = 0x70;
+                    *(sense_ptr+2) = SD_ILLREQ;
+                    *(sense_ptr+7) = TARGET_SENSE_SIZE-8;
+                    *(sense_ptr+12) = SC_INVOPCODE;
+                    len = 0;
+                    pkt->scsi_status = S_CKCON;
+                    pkt->option_flags |= (uint32_t)OF_SSTS |
+                            (uint32_t)OF_NO_DATA;
+                    break;
+            }
+            if (ha->flags.enable_64bit_addressing)
+                qla1280_64bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr);
+            else
+                qla1280_32bit_continue_io(ha, pkt, len, (paddr32_t *)&phy_addr);
+            break;
+        default:
+            break;
+    }
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_atio_entry: exiting normally\n\r");
+#endif
+}
+
+/*
+ *  qla1280_notify_entry
+ *      Processes received ISP immediate notify entry.
+ *
+ * Input:
+ *      ha  = adapter block pointer.
+ *      pkt = entry pointer.
+ */
+STATIC void
+qla1280_notify_entry(scsi_qla_host_t *ha, notify_entry_t *pkt)
+{
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_notify_entry: entered\n\r");
+#endif
+
+    /* Acknowledge immediate notify */
+    qla1280_notify_ack(ha, pkt);
+
+    /* Issue notify entry to increment resource count */
+    qla1280_immed_notify(ha, pkt);
+
+#ifdef QL_DEBUG_LEVEL_3
+    qla1280_print("qla1280_notify_entry: exiting normally\n\r");
+#endif
+}
+
+#endif  /* QLA1280_TARGET_MODE_SUPPORT */
+/*
+ *  qla1280_status_entry
+ *      Processes received ISP status entry.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *      pkt          = entry pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ */
+STATIC void
+qla1280_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt, srb_t **done_q_first,
+                     srb_t **done_q_last)
+{
+    uint32_t        b, t, l;
+    uint8_t         sense_sz = 0;
+    srb_t           *sp;
+    scsi_lu_t       *q;
+    Scsi_Cmnd       *cp;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_status_entry");
+#endif
+
+    /* Validate handle. */
+    if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
+        sp = ha->outstanding_cmds[pkt->handle];
+    else
+        sp = 0;
+
+    if (sp)
+    {
+        /* Free outstanding command slot. */
+        ha->outstanding_cmds[pkt->handle] = 0;
+
+        cp = sp->cmd;
+        /* Generate LU queue on cntrl, target, LUN */
+        b = SCSI_BUS_32(cp);
+        t = SCSI_TCN_32(cp);
+        l = SCSI_LUN_32(cp);
+        q = LU_Q(ha, b, t, l);
+        if( pkt->comp_status || pkt->scsi_status )
+        {
+            DEBUG(qla1280_print( "scsi: comp_status = ");)
+            DEBUG(qla1280_output_number((uint32_t)pkt->comp_status,16);)
+            DEBUG(qla1280_print( ", ");)
+            DEBUG(qla1280_print( " scsi_status = ");)
+            DEBUG(qla1280_output_number((uint32_t)pkt->scsi_status,16);)
+            DEBUG(qla1280_print( "\n\r");)
+            DEBUG(qla1280_print(", handle = ");)
+            DEBUG(qla1280_output_number((uint32_t)pkt->handle, 16);)
+            DEBUG(qla1280_print("\n\r");)
+        }
+
+        /* Target busy */
+        if ( pkt->scsi_status & SS_BUSY_CONDITION &&
+            pkt->scsi_status != SS_RESERVE_CONFLICT   )
+        {
+            CMD_RESULT(cp) = (int) (DID_BUS_BUSY << 16) |
+                    (pkt->scsi_status & 0xff);
+        }
+        else
+        {
+
+            /* Save ISP completion status */
+            CMD_RESULT(cp) = qla1280_return_status( pkt, cp );
+
+            if (pkt->scsi_status & SS_CHECK_CONDITION)
+            {
+                BZERO(cp->sense_buffer, CMD_SNSLEN(cp));
+                if (pkt->comp_status != CS_ARS_FAILED)
+                {
+                    if ( pkt->req_sense_length < CMD_SNSLEN(cp)  )
+                        sense_sz = pkt->req_sense_length;
+                    else
+                        sense_sz = CMD_SNSLEN(cp) - 1;
+
+                    BCOPY((caddr_t)&pkt->req_sense_data, cp->sense_buffer, sense_sz);
+
+                }
+#ifdef QL_DEBUG_LEVEL_2
+                DEBUG(qla1280_print(
+                        "qla1280_status_entry: Check condition Sense data, b");)
+                DEBUG(qla1280_output_number((uint32_t)b, 10);)
+                DEBUG(qla1280_print("t");)
+                DEBUG(qla1280_output_number((uint32_t)t, 10);)
+                DEBUG(qla1280_print("d");)
+                DEBUG(qla1280_output_number((uint32_t)l, 10);)
+                DEBUG(qla1280_print("\n\r");)
+                DEBUG(if (sense_sz))
+                    DEBUG(qla1280_dump_buffer(cp->sense_buffer, sense_sz);)
+#endif
+            }
+        }
+        /* Place command on done queue. */
+        qla1280_done_q_put(sp, done_q_first, done_q_last);
+    }
+    else
+    {
+#ifdef QL_DEBUG_LEVEL_2
+        qla1280_print("qla1280_status_entry: ISP Invalid handle\n\r");
+#endif
+        printk(KERN_WARNING "qla1280: Status Entry invalid handle\n");
+        ha->flags.isp_abort_needed = TRUE;
+    }
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_status_entry");
+#endif
+}
+
+/*
+ *  qla1280_error_entry
+ *      Processes error entry.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *      pkt          = entry pointer.
+ *      done_q_first = done queue first pointer.
+ *      done_q_last  = done queue last pointer.
+ */
+STATIC void
+qla1280_error_entry(scsi_qla_host_t *ha, response_t *pkt, srb_t **done_q_first,
+                    srb_t **done_q_last)
+{
+    srb_t   *sp;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_error_entry");
+#endif
+
+#ifdef QL_DEBUG_LEVEL_2
+    if (pkt->entry_status & BIT_3)
+        qla1280_print("qla1280_error_entry: BAD PAYLOAD flag error\n\r");
+    else if (pkt->entry_status & BIT_2)
+        qla1280_print("qla1280_error_entry: BAD HEADER flag error\n\r");
+    else if (pkt->entry_status & BIT_1)
+        qla1280_print("qla1280_error_entry: FULL flag error\n\r");
+    else
+        qla1280_print("qla1280_error_entry: UNKNOWN flag error\n\r");
+#endif
+
+    /* Validate handle. */
+    if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
+        sp = ha->outstanding_cmds[pkt->handle];
+    else
+        sp = 0;
+
+    if (sp)
+    {
+        /* Free outstanding command slot. */
+        ha->outstanding_cmds[pkt->handle] = 0;
+
+        /* Bad payload or header */
+        if (pkt->entry_status & (BIT_3 + BIT_2))
+        {
+            /* Bad payload or header, set error status. */
+            /* CMD_RESULT(sp->cmd) = CS_BAD_PAYLOAD; */
+            CMD_RESULT(sp->cmd) = (int) DID_ERROR << 16;
+        }
+        else if (pkt->entry_status & BIT_1 ) /* FULL flag */
+        {
+            CMD_RESULT(sp->cmd) = (int) DID_BUS_BUSY << 16;
+        }
+        else
+        {
+            /* Set error status. */
+            CMD_RESULT(sp->cmd) =(int)  DID_ERROR << 16;
+        }
+        /* Place command on done queue. */
+        qla1280_done_q_put(sp, done_q_first, done_q_last);
+    }
+#if  QLA1280_64BIT_SUPPORT
+    else if (pkt->entry_type == COMMAND_A64_TYPE)
+    {
+#ifdef QL_DEBUG_LEVEL_2
+        qla1280_print("qla1280_error_entry: ISP Invalid handle\n\r");
+#endif
+        printk(KERN_WARNING "!qla1280: Error Entry invalid handle");
+        ha->flags.isp_abort_needed = TRUE;
+    }
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3
+    LEAVE("qla1280_error_entry");
+#endif
+}
+
+/*
+ *  qla1280_abort_isp
+ *      Resets ISP and aborts all outstanding commands.
+ *
+ * Input:
+ *      ha           = adapter block pointer.
+ *
+ * Returns:
+ *      0 = success
+ */
+STATIC uint8_t
+qla1280_abort_isp(scsi_qla_host_t *ha)
+{
+    device_reg_t    *reg = ha->iobase;
+    uint8_t         status = 0;
+    uint16_t        cnt;
+    srb_t           *sp;
+    scsi_lu_t       *q;
+    uint32_t        b, t, l;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+    unsigned long cpu_flags = 0;
+#endif
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_abort_isp");
+#endif
+
+    DRIVER_LOCK
+            ha->flags.isp_abort_needed = FALSE;
+    if (!ha->flags.abort_isp_active && ha->flags.online)
+    {
+        ha->flags.abort_isp_active = TRUE;
+
+        /* Disable ISP interrupts. */
+        WRT_REG_WORD(&reg->ictrl, 0);
+
+        /* Dequeue all commands in outstanding command list. */
+        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+        {
+            sp = ha->outstanding_cmds[cnt];
+            if (sp)
+            {
+                ha->outstanding_cmds[cnt] = 0;
+
+                /* Generate LU queue on controller, target, LUN */
+                b = SCSI_BUS_32(sp->cmd);
+                t = SCSI_TCN_32(sp->cmd);
+                l = SCSI_LUN_32(sp->cmd);
+
+                q = (scsi_lu_t       *)LU_Q(ha, b, t, l);
+
+                /* Reset outstanding command count. */
+                q->q_outcnt = 0;
+                q->q_flag &= ~QLA1280_QBUSY;
+                q->q_flag =  0;
+
+                /* Adjust watchdog timer for command. */
+                /* if (sp->flags & SRB_WATCHDOG)
+                sp->timeout += 2; */
+
+                /* Place request back on top of device queue. */
+                /* sp->flags &= ~(SRB_SENT | SRB_TIMEOUT); */ 
+                sp->flags = 0;
+                qla1280_putq_t(q, sp);
+            }
+        }
+
+        /* If firmware needs to be loaded */
+        if (qla1280_isp_firmware(ha))
+        {
+            if (!(status = qla1280_chip_diag(ha)))
+                status = qla1280_setup_chip(ha); 
+        }
+
+        if (!status)
+        {
+            /* Setup adapter based on NVRAM parameters. */
+            qla1280_nvram_config(ha); 
+
+            if (!(status = qla1280_init_rings(ha)))
+            {
+                /* Issue SCSI reset. */
+                for (b = 0; b < ha->ports; b++)
+                {
+                    qla1280_bus_reset(ha, b);
+                }
+                do
+                {
+                    /* Issue marker command. */
+                    ha->flags.reset_marker = FALSE;
+                    for (b = 0; b < ha->ports; b++)
+                    {
+                        ha->bus_settings[b].reset_marker = FALSE;
+                        qla1280_marker(ha, b, 0, 0, MK_SYNC_ALL);
+                    }
+                }while (ha->flags.reset_marker);
+
+                /* Enable host adapter target mode. */
+                for (b = 0; b < ha->ports; b++)
+                {
+                    if (!(status = qla1280_enable_tgt(ha, b)))
+                    {
+                        for (cnt = 0; cnt < MAX_LUNS; cnt++)
+                        {
+                            /* qla1280_enable_lun(ha, b, cnt); */
+                            qla1280_poll(ha);
+                        }
+                    }
+                    else
+                        break;
+                }
+
+                if (!status)
+                { 
+                    /* Enable ISP interrupts. */
+                    WRT_REG_WORD(&reg->ictrl, ISP_EN_INT + ISP_EN_RISC);
+                    ha->flags.abort_isp_active = FALSE;
+                    /* Restart queues that may have been stopped. */
+                    qla1280_restart_queues(ha);
+                }
+            }
+        }
+    }
+
+    if (status)
+    {
+        printk(KERN_WARNING
+                "qla1280: ISP error recovery failed, board disabled");
+        qla1280_reset_adapter(ha);
+        qla1280_abort_queues(ha);
+
+#if defined(QL_DEBUG_LEVEL_2) || defined(QL_DEBUG_LEVEL_3)
+        qla1280_print("qla1280_abort_isp: **** FAILED ****\n\r");
+#endif
+    }
+#ifdef QL_DEBUG_LEVEL_3
+    else
+        LEAVE("qla1280_abort_isp");
+#endif
+    DRIVER_UNLOCK
+
+            return(status);
+}
+
+/*
+ *  qla1280_restart_queues
+ *      Restart all device queues.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_restart_queues(scsi_qla_host_t *ha)
+{
+    scsi_lu_t *q;
+    uint32_t  b, t, l;
+
+#ifdef QL_DEBUG_LEVEL_3
+    ENTER("qla1280_restart_queues");
+#endif
+
+    for (b = 0; b < ha->ports; b++)
+        for (t = 0; t < MAX_TARGETS; t++)
+            for (l = 0; l < MAX_LUNS; l++)
+            {
+                q = (scsi_lu_t *) LU_Q(ha, b, t, l);
+                if (q != NULL)
+                {
+                    /* Acquire LU queue specific lock */
+                    QLA1280_SCSILU_LOCK(q);
+
+                    if (q->q_first)
+                        qla1280_next(ha, q, b);
+                    else
+                        /* Release LU queue specific lock */
+                        QLA1280_SCSILU_UNLOCK(q);
+                }
+            }
+#ifdef QL_DEBUG_LEVEL_3
+            qla1280_print("qla1280_restart_queues: exiting normally\n");
+#endif
+}
+
+/*
+ *  qla1280_abort_queue_single
+ *      Abort all commands on a device queues.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void qla1280_abort_queue_single(scsi_qla_host_t *ha,uint32_t b,uint32_t t,uint32_t l,uint32_t stat)
+{
+    scsi_lu_t *q;
+    srb_t     *sp, *sp_next; 
+
+    ENTER("qla1280_abort_queue_single");
+    q = (scsi_lu_t * )LU_Q(ha, b, t, l);
+    if (q != NULL)
+    {
+        /* Acquire LU queue specific lock */
+        QLA1280_SCSILU_LOCK(q);
+
+        sp = q->q_first;
+        q->q_first = q->q_last = NULL;
+
+        QLA1280_SCSILU_UNLOCK(q);
+
+        while (sp)
+        {
+            sp_next = sp->s_next;
+            CMD_RESULT(sp->cmd) = stat;
+            qla1280_done_q_put(sp, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last);
+            sp = sp_next;
+        }
+    }
+    LEAVE("qla1280_abort_queue_single");
+}
+
+/*
+ *  qla1280_abort_queues
+ *      Abort all commands on device queues.
+ *
+ * Input:
+ *      ha = adapter block pointer.
+ */
+STATIC void
+qla1280_abort_queues(scsi_qla_host_t *ha)
+{
+    uint32_t  b, t, l;
+
+    ENTER("qla1280_abort_queues");
+
+    for (b = 0; b < ha->ports; b++)
+        for (t = 0; t < MAX_TARGETS; t++)
+            for (l = 0; l < MAX_LUNS; l++)
+                qla1280_abort_queue_single(ha,b,t,l,DID_RESET);
+
+            LEAVE("qla1280_abort_queues");
+}
+
+/*
+ * qla1280_debounce_register
+ *      Debounce register.
+ *
+ * Input:
+ *      port = register address.
+ *
+ * Returns:
+ *      register value.
+ */
+STATIC uint16_t
+qla1280_debounce_register(volatile uint16_t *addr)
+{
+    volatile uint16_t ret;
+    volatile uint16_t ret2;
+
+    do
+    {
+        ret = RD_REG_WORD(addr);
+        ret2 = RD_REG_WORD(addr);
+    }while (ret != ret2);
+
+    return(ret);
+}
+
+
+/*
+ * Declarations for load module
+ */
+#ifdef MODULE
+Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
+
+#include "scsi_module.c"
+#endif
+
+/************************************************************************
+ * qla1280_check_for_dead_scsi_bus                                      *
+ *                                                                      *
+ *    This routine checks for a dead SCSI bus                           *
+ ************************************************************************/
+#define SET_SXP_BANK            0x0100
+#define SCSI_PHASE_INVALID      0x87FF
+int  qla1280_check_for_dead_scsi_bus(scsi_qla_host_t *ha, srb_t *sp)
+{
+    uint16_t  config_reg, scsi_control;
+    device_reg_t    *reg = ha->iobase;
+    uint32_t  b;
+    Scsi_Cmnd       *cp;
+
+    /*
+     * If SCSI Bus is Dead because of bad termination,
+     * we will return a status of Selection timeout.
+     */
+ 
+     cp = sp->cmd;
+     b = SCSI_BUS_32(cp);
+    if (ha->bus_settings[b].scsi_bus_dead)
+    {
+        WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
+        config_reg = RD_REG_WORD(&reg->cfg_1);
+        WRT_REG_WORD(&reg->cfg_1,SET_SXP_BANK);
+        scsi_control = RD_REG_WORD(&reg->scsiControlPins);
+        WRT_REG_WORD(&reg->cfg_1,config_reg);
+        WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
+
+        if (scsi_control == SCSI_PHASE_INVALID)
+        {
+            CMD_RESULT(cp) = DID_NO_CONNECT << 16;
+            CMD_HANDLE(cp) = (unsigned char *) 0;
+            /* ha->actthreads--; */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
+            sti(); 
+            (*(cp)->scsi_done)(cp);
+            cli(); 
+#else
+            (*(cp)->scsi_done)(cp);
+#endif
+            return(TRUE);   /* bus is dead */
+        }
+        else
+        {
+            ha->bus_settings[b].scsi_bus_dead = FALSE;
+            ha->bus_settings[b].failed_reset_count= 0; 
+        }
+    }
+    return(FALSE);   /* bus is not dead */
+}
+
+STATIC uint8_t
+qla12160_set_target_parameters(scsi_qla_host_t *ha, uint32_t b, uint32_t t, uint32_t l, nvram160_t *nv)
+{
+    uint16_t        mb[MAILBOX_REGISTER_COUNT];
+
+    /* Set Target Parameters. */
+    mb[0] = MBC_SET_TARGET_PARAMETERS;
+    mb[1] = (uint16_t)(b ? t | BIT_7 :t);
+    mb[1] <<= 8;
+    mb[2] = nv->bus[b].target[t].parameter.c << 8;
+    mb[2] |= TP_AUTO_REQUEST_SENSE;
+    mb[2] &= ~TP_STOP_QUEUE;
+    mb[2] |=  (nv->bus[b].target[t].flags.enable_ppr << 5);
+    mb[3] = nv->bus[b].target[t].flags.sync_offset << 8;
+    mb[3] |= nv->bus[b].target[t].sync_period;
+
+    mb[6] = nv->bus[b].target[t].flags.ppr_options << 8;
+    mb[6] |= nv->bus[b].target[t].flags.ppr_bus_width;
+    return( qla1280_mailbox_command(ha, BIT_6|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]) ) ;
+}
+
+STATIC void
+qla12160_get_target_parameters(scsi_qla_host_t *ha, uint32_t b, uint32_t t, uint32_t l)
+{
+    uint16_t        mb[MAILBOX_REGISTER_COUNT];
+
+    mb[0] = MBC_GET_TARGET_PARAMETERS;
+    mb[1] = (uint16_t)(b ? t | BIT_7 :t);
+    mb[1] <<= 8;
+    qla1280_mailbox_command(ha, BIT_6|BIT_3|BIT_2|BIT_1|BIT_0, &mb[0]);
+    if( mb[3] != 0 )
+    printk(KERN_INFO "scsi(%d:%d:%d:%d): Synchronous tranfer at period %d, offset %d. \n",
+        (int)ha->host_no, b, t, l, (mb[3] &0xff), (mb[3] >> 8));
+
+    if ( (mb[2] & BIT_5) &&  ((mb[6] >> 8) & 0xff) >= 2 )
+            printk(KERN_INFO "scsi(%d:%d:%d:%d): Dual Transition enabled.\n",
+                          (int)ha->host_no, b, t, l);
+}
+
+
+#ifdef QL_DEBUG_ROUTINES
+/****************************************************************************/
+/*                         Driver Debug Functions.                          */
+/****************************************************************************/
+
+/*
+ *  Get byte from I/O port
+ */
+STATIC uint8_t
+qla1280_getbyte(uint8_t *port)
+{
+    uint8_t ret;
+
+#if MEMORY_MAPPED_IO
+    ret = *port;
+#else
+    ret = inb((int)port);
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_getbyte: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)ret, 16);
+        qla1280_print("\n\r");
+    }
+
+    return(ret);
+}
+
+/*
+ *  Get word from I/O port
+ */
+STATIC uint16_t
+qla1280_getword(uint16_t *port)
+{
+    uint16_t ret;
+
+#if MEMORY_MAPPED_IO
+    ret = *port;
+#else
+    ret = inw((int)port);
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_getword: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)ret, 16);
+        qla1280_print("\n\r");
+    }
+
+    return(ret);
+}
+
+/*
+ *  Get double word from I/O port
+ */
+STATIC uint32_t
+qla1280_getdword(uint32_t *port)
+{
+    uint32_t ret;
+
+#if MEMORY_MAPPED_IO
+    ret = *port;
+#else
+    ret = inl((int)port);
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_getdword: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)ret, 16);
+        qla1280_print("\n\r");
+    }
+
+    return(ret);
+}
+
+/*
+ *  Send byte to I/O port
+ */
+STATIC void
+qla1280_putbyte(uint8_t *port, uint8_t data)
+{
+#if MEMORY_MAPPED_IO
+    *port = data;
+#else
+    outb(data, (int)port);
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_putbyte: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)data, 16);
+        qla1280_print("\n\r");
+    }
+}
+
+/*
+ *  Send word to I/O port
+ */
+STATIC void
+qla1280_putword(uint16_t *port, uint16_t data)
+{
+#if MEMORY_MAPPED_IO
+    *port = data;
+#else
+#ifdef _LINUX_IOPORTS
+    outw(data, (int)port);
+#else
+    outw((int)port, data);
+#endif
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_putword: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)data, 16);
+        qla1280_print("\n\r");
+    }
+}
+
+/*
+ *  Send double word to I/O port
+ */
+STATIC void
+qla1280_putdword(uint32_t *port, uint32_t data)
+{
+#if MEMORY_MAPPED_IO
+    *port = data;
+#else
+#ifdef _LINUX_IOPORTS
+    outl(data,(int)port);
+#else
+    outl((int)port, data);
+#endif
+#endif
+
+    if (ql_debug_print)
+    {
+        qla1280_print("qla1280_putdword: address = ");
+        qla1280_output_number((uint32_t)port, 16);
+        qla1280_print(" data = 0x");
+        qla1280_output_number((uint32_t)data, 16);
+        qla1280_print("\n\r");
+    }
+}
+
+/*
+ * Dummy function to prevent warnings for
+ * declared and unused debug functions
+ */
+void
+qla1280_debug(void)
+{
+    qla1280_getbyte(0);
+    qla1280_getword(0);
+    qla1280_getdword(0);
+    qla1280_putbyte(0, 0);
+    qla1280_putword(0, 0);
+    qla1280_putdword(0, 0);
+}
+
+/*
+ *  Out character to COM2 port.
+ *      PORT must be at standard address for COM2 = 0x2F8,
+ *      or COM1 = 0x3F8
+ */
+#define OUTB(addr,data)   outb((data),(addr))
+
+STATIC void
+qla1280_putc(uint8_t c)
+{
+#ifdef QL_DEBUG_CONSOLE
+    printk("%c", c);
+#else
+    int     com_addr              = 0x2f8;
+    int     hardware_flow_control = 1;
+    int     software_flow_control = 0;
+    uint8_t data;
+
+    /* Wait for transmitter holding and shift registers for empty. */
+    do
+    {
+        data = inb(com_addr+5);
+    }while (!(data & BIT_6));
+
+    /*
+    * Set BAUD rate for COM2 to 19200 (0x6)
+    */
+
+    /* Select rate divisor. */
+    OUTB(com_addr+3, 0x83); 
+
+    /* BAUD rate divisor LSB. */
+    OUTB(com_addr, 0xc);                    /* 0xC = 9600 baud */
+
+    /* BAUD rate divisor MSB. */
+    OUTB(com_addr+1, 0);
+
+    /* Set No parity, 8 bits, 1 stop bit and
+    select interrupt enable register. */
+    OUTB(com_addr+3, 3);
+
+    /* Disable interrupts. */
+    OUTB(com_addr+1, 0);
+
+    /* Set data terminal ready and request to send */
+    OUTB(com_addr+4,3);
+
+    if (hardware_flow_control)
+    {
+        /* Wait for clear-to-send and data-set-ready */
+        do
+        {
+            data = inb(com_addr+6) & (BIT_5 + BIT_4);
+        }while (data != (BIT_5 + BIT_4));
+    }
+    else if (software_flow_control)
+    {
+        /* Test for data ready. */
+        data = inb(com_addr+5);
+        if (data & BIT_0)
+        {
+            /* If XOFF */
+            data = inb(com_addr);
+            if (data == '\023')
+            {
+                /* Wait for XON */
+                do
+                {
+                    /* Wait for char */
+                    do
+                    {
+                        data = inb(com_addr+5);
+                    }while (!(data & BIT_0));
+                    data = inb(com_addr);
+                }while (data != '\021');
+            }
+        }
+    }
+
+    /* Output character. */
+    OUTB(com_addr, c);
+#endif
+}
+
+/*
+ *  Out NULL terminated string to COM port.
+ */
+STATIC void
+qla1280_print(caddr_t s)
+{
+    if (ql_debug_print)
+    {
+#ifdef QL_DEBUG_CONSOLE
+        printk("%s",s);
+#else
+        /* Output string. */
+        while (*s)
+            qla1280_putc(*s++);
+#endif
+    }
+}
+
+/*
+ *  Output long number to COM port.
+ */
+STATIC void
+qla1280_output_number(uint32_t n, uint8_t base)
+{
+    int8_t str[12];
+    int8_t *s     = &str[11];
+    int8_t output = 0;
+    int8_t hex    = FALSE;
+
+    if (ql_debug_print)
+    {
+        if (base == 10 || base == 16)
+        {
+            if (base == 16 && n > 9)
+                hex = TRUE;
+
+            *s = 0;
+            do
+            {
+                s--;
+                *s = n % base;
+                if (*s > 9)
+                    *s += 55;
+                else
+                    *s += '0';
+                n /= base;
+            }while (n);
+
+            for (; *s; s++)
+            {
+                if (*s != '0')
+                    output = 1;
+                if (output)
+                    qla1280_putc(*s);
+            }
+            if (!output)
+                qla1280_putc(*--s);
+
+            if (hex)
+                qla1280_putc('h');
+        }
+    }
+}
+
+STATIC void
+qla1280_dump_buffer(caddr_t b, uint32_t size)
+{
+    uint32_t cnt;
+    uint8_t c;
+
+    if (ql_debug_print)
+    {
+        qla1280_print(
+                " 0   1   2   3   4   5   6   7   8   9   Ah  Bh  Ch  Dh  Eh  Fh\n\r");
+        qla1280_print(
+                "---------------------------------------------------------------\n\r");
+
+        for (cnt = 0; cnt < size; )
+        {
+            c = *b++;
+            if (c < 16)
+                qla1280_putc(' ');
+            qla1280_output_number((uint32_t)c, 16);
+            cnt++;
+            if (!(cnt % 16))
+                qla1280_print("\n\r");
+            else if (c < 10)
+                qla1280_print("  ");
+            else
+                qla1280_putc(' ');
+        }
+        if (cnt % 16)
+            qla1280_print("\n\r");
+    }
+}
+/**************************************************************************
+ *   ql1280_print_scsi_cmd
+ *
+ **************************************************************************/
+void qla1280_print_scsi_cmd(Scsi_Cmnd *cmd)
+{
+    scsi_qla_host_t *ha;
+    struct Scsi_Host  *host = cmd->host;
+    srb_t           *sp;
+   /* struct scatterlist *sg; */
+
+    int i;
+    ha = (scsi_qla_host_t *) host->hostdata;
+
+    ql_debug_print = 1;
+    sp = (srb_t *) CMD_SP(cmd);
+    sprintf(debug_buff,"SCSI Command @= 0x%p, Handle=0x%p\n\r", cmd, CMD_HANDLE(cmd));
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"  chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n\r",
+            cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);
+    qla1280_print(debug_buff);
+    qla1280_print(" CDB = ");
+    for (i = 0; i < cmd->cmd_len; i++)
+    {
+        sprintf(debug_buff,"0x%02x ", cmd->cmnd[i]);
+        qla1280_print(debug_buff);
+    }
+    sprintf(debug_buff,"  seg_cnt =%d\n\r",cmd->use_sg);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"  request buffer=0x%p, request buffer len=0x%x\n\r",cmd->request_buffer,cmd->request_bufflen);
+    qla1280_print(debug_buff);
+    /* if( cmd->use_sg )
+    {
+       sg = (struct scatterlist *) cmd->request_buffer;
+       qla1280_print("  SG buffer: \n\r");
+       qla1280_dump_buffer((caddr_t)sg, (cmd->use_sg*sizeof(struct scatterlist)) );
+    } */
+    sprintf(debug_buff,"  tag=%d, flags=0x%x, transfersize=0x%x \n\r", 
+            cmd->tag, cmd->flags,cmd->transfersize );
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"  Pid=%d, SP=0x%p\n\r", (int)cmd->pid, CMD_SP(cmd));
+    qla1280_print(debug_buff);
+    sprintf(debug_buff,"  r_start=0x%lx, u_start=0x%lx\n\r",sp->r_start,sp->u_start);
+    qla1280_print(debug_buff);
+    sprintf(debug_buff," underflow size = 0x%x, direction=0x%x, req.cmd=0x%x \n\r", cmd->underflow, sp->dir,cmd->request.cmd);    
+    qla1280_print(debug_buff);
+}
+/**************************************************************************
+ *   ql1280_dump_device
+ *
+ **************************************************************************/
+void
+ql1280_dump_device(scsi_qla_host_t *ha)
+{
+
+    Scsi_Cmnd       *cp;
+    srb_t           *sp;
+    int i;
+    qla1280_print("Outstanding Commands on controller:\n\r");   
+    for ( i=0; i < MAX_OUTSTANDING_COMMANDS; i++ )
+    {
+        if( (sp = ha->outstanding_cmds[i]) == NULL )
+            continue;
+        if( (cp = sp->cmd) == NULL )
+            continue;
+        qla1280_print_scsi_cmd(cp);
+    }
+
+}
+#endif
+
+#ifdef  QLA1280_UNUSED 
+/**************************************************************************
+ *   ql1280_dump_regs
+ *
+ **************************************************************************/
+static void qla1280_dump_regs(struct Scsi_Host *host)
+{
+    printk("Mailbox registers:\n");
+    printk("qla1280 : mbox 0 0x%04x \n", inw(host->io_port + 0x70));
+    printk("qla1280 : mbox 1 0x%04x \n", inw(host->io_port + 0x72));
+    printk("qla1280 : mbox 2 0x%04x \n", inw(host->io_port + 0x74));
+    printk("qla1280 : mbox 3 0x%04x \n", inw(host->io_port + 0x76));
+    printk("qla1280 : mbox 4 0x%04x \n", inw(host->io_port + 0x78));
+    printk("qla1280 : mbox 5 0x%04x \n", inw(host->io_port + 0x7a));
+}
+#endif
+
+
+
+#if  STOP_ON_ERROR 
+/**************************************************************************
+ *   ql1280_panic
+ *
+ **************************************************************************/
+static void qla1280_panic(char *cp, struct Scsi_Host *host)
+{
+    scsi_qla_host_t *ha;
+    long  *fp;
+
+    ha = (scsi_qla_host_t *) host->hostdata;
+    printk("qla1280 - PANIC:  %s\n",cp);
+    printk("Current time=0x%lx\n", jiffies);
+    printk("Number of pending commands =0x%lx\n", ha->actthreads);
+    printk("Number of SCSI queued commands =0x%lx\n", ha->qthreads);
+    printk("Number of free entries = (%d)\n",ha->req_q_cnt);
+    printk("Request Queue @ 0x%lx, Response Queue @ 0x%lx\n",
+                        ha->request_dma,
+                        ha->response_dma);
+    printk("Request In Ptr %d\n", ha->req_ring_index );
+    fp = (long *) &ha->flags;
+    printk("HA flags =0x%lx\n", *fp);
+    DEBUG2(ql_debug_print = 1;)
+    /* DEBUG2(ql1280_dump_device((scsi_qla_host_t *) host->hostdata)); */
+#ifdef  QLA1280_UNUSED 
+    qla1280_dump_regs(host);
+#endif
+    sti();  
+    panic("Ooops");  
+    /* cli(); 
+    for(;;)
+    { 
+        barrier();
+    sti();  
+    }
+    */
+}
+#endif
+
+#ifdef  QLA1280_UNUSED 
+static void qla1280_set_flags(char * s)
+{
+}
+#endif
+
+/**************************************************************************
+ *   qla1280_setup
+ *
+ *   Handle Linux boot parameters. This routine allows for assigning a value
+ *   to a parameter with a ':' between the parameter and the value.
+ *   ie. qla1280=max_reqs:0x0A,verbose
+ **************************************************************************/
+void
+qla1280_setup(char *s, int *dummy)
+{
+    char *end, *str, *cp;
+
+#ifdef  QLA1280_UNUSED 
+    static struct
+    {
+        const char *name;
+        int      siz;
+        void  (*func)();
+        int   arg;
+    } options[] =
+    {
+        { "dump_regs", 9,  &qla1280_dump_regs, 0 
+        },
+        { "verbose", 7, &qla1280_set_flags, 0x1 
+        },
+        { "",    0, NULL, 0 
+        }
+    };
+#endif
+
+    printk("scsi: Processing Option str = %s\n", s);
+    end = strchr(s, '\0');
+    /* locate command */
+    str = s;
+    for( cp = s; *cp && cp != end; cp++ ) 
+    {
+       cp = qla1280_get_token(cp, str);
+       printk("scsi: token str = %s\n", str);
+       /* if found execute routine */
+
+    }
+    
+}
+
+static char	*qla1280_get_token(char *cmdline, char *str )
+{
+    register	char 	*cp = cmdline;
+
+        /* skip preceeding spaces */
+        while(strchr(cp,' '))
+            ++cp;
+        /* symbol starts here */
+        str = cp;
+        /* skip char if not a space or : */
+        while (*cp && !( strchr(cp,' ') || strchr(cp,':'))  )
+            cp++;
+        *cp = '\0';
+        return( cp );
+}
+
+/*
+ * Overrides for Emacs so that we almost follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 2
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -2
+ * c-argdecl-indent: 2
+ * c-label-offset: -2
+ * c-continued-statement-offset: 2
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)