patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / message / fusion / mptscsih.c
1 /*
2  *  linux/drivers/message/fusion/mptscsih.c
3  *      High performance SCSI / Fibre Channel SCSI Host device driver.
4  *      For use with PCI chip/adapter(s):
5  *          LSIFC9xx/LSI409xx Fibre Channel
6  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
7  *
8  *  Credits:
9  *      This driver would not exist if not for Alan Cox's development
10  *      of the linux i2o driver.
11  *
12  *      A special thanks to Pamela Delaney (LSI Logic) for tons of work
13  *      and countless enhancements while adding support for the 1030
14  *      chip family.  Pam has been instrumental in the development of
15  *      of the 2.xx.xx series fusion drivers, and her contributions are
16  *      far too numerous to hope to list in one place.
17  *
18  *      A huge debt of gratitude is owed to David S. Miller (DaveM)
19  *      for fixing much of the stupid and broken stuff in the early
20  *      driver while porting to sparc64 platform.  THANK YOU!
21  *
22  *      (see mptbase.c)
23  *
24  *  Copyright (c) 1999-2004 LSI Logic Corporation
25  *  Original author: Steven J. Ralston
26  *  (mailto:sjralston1@netscape.net)
27  *  (mailto:mpt_linux_developer@lsil.com)
28  *
29  *  $Id: mptscsih.c,v 1.104 2002/12/03 21:26:34 pdelaney Exp $
30  */
31 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
32 /*
33     This program is free software; you can redistribute it and/or modify
34     it under the terms of the GNU General Public License as published by
35     the Free Software Foundation; version 2 of the License.
36
37     This program is distributed in the hope that it will be useful,
38     but WITHOUT ANY WARRANTY; without even the implied warranty of
39     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40     GNU General Public License for more details.
41
42     NO WARRANTY
43     THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
44     CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
45     LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
46     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
47     solely responsible for determining the appropriateness of using and
48     distributing the Program and assumes all risks associated with its
49     exercise of rights under this Agreement, including but not limited to
50     the risks and costs of program errors, damage to or loss of data,
51     programs or equipment, and unavailability or interruption of operations.
52
53     DISCLAIMER OF LIABILITY
54     NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
55     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56     DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
57     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
58     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
59     USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
60     HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
61
62     You should have received a copy of the GNU General Public License
63     along with this program; if not, write to the Free Software
64     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
65 */
66 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
67
68 #include <linux/module.h>
69 #include <linux/kernel.h>
70 #include <linux/init.h>
71 #include <linux/errno.h>
72 #include <linux/kdev_t.h>
73 #include <linux/blkdev.h>
74 #include <linux/delay.h>        /* for mdelay */
75 #include <linux/interrupt.h>    /* needed for in_interrupt() proto */
76 #include <linux/reboot.h>       /* notifier code */
77 #include "../../scsi/scsi.h"
78 #include <scsi/scsi_host.h>
79
80
81 #include "mptbase.h"
82 #include "mptscsih.h"
83 #include "isense.h"
84
85 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
86 #define my_NAME         "Fusion MPT SCSI Host driver"
87 #define my_VERSION      MPT_LINUX_VERSION_COMMON
88 #define MYNAM           "mptscsih"
89
90 MODULE_AUTHOR(MODULEAUTHOR);
91 MODULE_DESCRIPTION(my_NAME);
92 MODULE_LICENSE("GPL");
93
94 /* Set string for command line args from insmod */
95 #ifdef MODULE
96 char *mptscsih = 0;
97 #endif
98
99 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
100
101 typedef struct _BIG_SENSE_BUF {
102         u8              data[MPT_SENSE_BUFFER_ALLOC];
103 } BIG_SENSE_BUF;
104
105 #define MPT_SCANDV_GOOD                 (0x00000000) /* must be 0 */
106 #define MPT_SCANDV_DID_RESET            (0x00000001)
107 #define MPT_SCANDV_SENSE                (0x00000002)
108 #define MPT_SCANDV_SOME_ERROR           (0x00000004)
109 #define MPT_SCANDV_SELECTION_TIMEOUT    (0x00000008)
110 #define MPT_SCANDV_ISSUE_SENSE          (0x00000010)
111
112 #define MPT_SCANDV_MAX_RETRIES          (10)
113
114 #define MPT_ICFLAG_BUF_CAP      0x01    /* ReadBuffer Read Capacity format */
115 #define MPT_ICFLAG_ECHO         0x02    /* ReadBuffer Echo buffer format */
116 #define MPT_ICFLAG_PHYS_DISK    0x04    /* Any SCSI IO but do Phys Disk Format */
117 #define MPT_ICFLAG_TAGGED_CMD   0x08    /* Do tagged IO */
118 #define MPT_ICFLAG_DID_RESET    0x20    /* Bus Reset occurred with this command */
119 #define MPT_ICFLAG_RESERVED     0x40    /* Reserved has been issued */
120
121 typedef struct _internal_cmd {
122         char            *data;          /* data pointer */
123         dma_addr_t      data_dma;       /* data dma address */
124         int             size;           /* transfer size */
125         u8              cmd;            /* SCSI Op Code */
126         u8              bus;            /* bus number */
127         u8              id;             /* SCSI ID (virtual) */
128         u8              lun;
129         u8              flags;          /* Bit Field - See above */
130         u8              physDiskNum;    /* Phys disk number, -1 else */
131         u8              rsvd2;
132         u8              rsvd;
133 } INTERNAL_CMD;
134
135 typedef struct _negoparms {
136         u8 width;
137         u8 offset;
138         u8 factor;
139         u8 flags;
140 } NEGOPARMS;
141
142 typedef struct _dv_parameters {
143         NEGOPARMS        max;
144         NEGOPARMS        now;
145         u8               cmd;
146         u8               id;
147         u16              pad1;
148 } DVPARAMETERS;
149
150
151 /*
152  *  Other private/forward protos...
153  */
154 static int      mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
155 static void     mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
156 static int      mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
157
158 static int      mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
159                                  SCSIIORequest_t *pReq, int req_idx);
160 static void     mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
161 static int      mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
162 static void     copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
163 static int      mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
164 static u32      SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
165 static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
166 static void     post_pendingQ_commands(MPT_SCSI_HOST *hd);
167
168 static int      mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
169 static int      mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
170
171 static int      mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
172 static int      mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
173
174 static void     mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
175 void            mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
176 static void     mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
177 static void     mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
178 static void     mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
179 static int      mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
180 static int      mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
181 static int      mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
182 static void     mptscsih_timer_expired(unsigned long data);
183 static void     mptscsih_taskmgmt_timeout(unsigned long data);
184 static void     mptscsih_schedule_reset(void *hd);
185 static int      mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
186 static int      mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
187
188 static struct mpt_work_struct   mptscsih_rstTask;
189
190 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
191 static int      mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
192 static void     mptscsih_domainValidation(void *hd);
193 static int      mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
194 static void     mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
195 static int      mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
196 static void     mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
197 static void     mptscsih_fillbuf(char *buffer, int size, int index, int width);
198 #endif
199 #ifdef MODULE
200 static int      mptscsih_setup(char *str);
201 #endif
202 /* module entry point */
203 static int  __init   mptscsih_init  (void);
204 static void __exit   mptscsih_exit  (void);
205
206 static int  mptscsih_probe (struct pci_dev *, const struct pci_device_id *);
207 static void mptscsih_remove(struct pci_dev *);
208 static void mptscsih_shutdown(struct device *);
209 #ifdef CONFIG_PM
210 static int mptscsih_suspend(struct pci_dev *pdev, u32 state);
211 static int mptscsih_resume(struct pci_dev *pdev);
212 #endif
213
214
215 /*
216  *      Private data...
217  */
218
219 static int      mpt_scsi_hosts = 0;
220
221 static int      ScsiDoneCtx = -1;
222 static int      ScsiTaskCtx = -1;
223 static int      ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
224
225 #define SNS_LEN(scp)    sizeof((scp)->sense_buffer)
226
227 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
228 /*
229  * Domain Validation task structure
230  */
231 static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
232 static int dvtaskQ_active = 0;
233 static int dvtaskQ_release = 0;
234 static struct mpt_work_struct   mptscsih_dvTask;
235 #endif
236
237 /*
238  * Wait Queue setup
239  */
240 static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
241 static int scandv_wait_done = 1;
242
243 /* Driver default setup
244  */
245 static struct mptscsih_driver_setup
246         driver_setup = MPTSCSIH_DRIVER_SETUP;
247
248 #ifdef MPTSCSIH_DBG_TIMEOUT
249 static Scsi_Cmnd *foo_to[8];
250 #endif
251
252 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
253
254 /* see mptscsih.h */
255
256 static struct scsi_host_template driver_template = {
257         .proc_name                      = "mptscsih",
258         .proc_info                      = x_scsi_proc_info,
259         .name                           = "MPT SCSI Host",
260         .info                           = x_scsi_info,
261         .queuecommand                   = x_scsi_queuecommand,
262         .slave_alloc                    = x_scsi_slave_alloc,
263         .slave_configure                = x_scsi_slave_configure,
264         .slave_destroy                  = x_scsi_slave_destroy,
265         .eh_abort_handler               = x_scsi_abort,
266         .eh_device_reset_handler        = x_scsi_dev_reset,
267         .eh_bus_reset_handler           = x_scsi_bus_reset,
268         .eh_host_reset_handler          = x_scsi_host_reset,
269         .bios_param                     = x_scsi_bios_param,
270         .can_queue                      = MPT_SCSI_CAN_QUEUE,
271         .this_id                        = -1,
272         .sg_tablesize                   = MPT_SCSI_SG_DEPTH,
273         .max_sectors                    = MPT_SCSI_MAX_SECTORS,
274         .cmd_per_lun                    = MPT_SCSI_CMD_PER_LUN,
275         .use_clustering                 = ENABLE_CLUSTERING,
276 };
277
278 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
279 /*
280  *  Private inline routines...
281  */
282 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
283 /* 19991030 -sralston
284  *  Return absolute SCSI data direction:
285  *     1 = _DATA_OUT
286  *     0 = _DIR_NONE
287  *    -1 = _DATA_IN
288  *
289  * Changed: 3-20-2002 pdelaney to use the default data
290  * direction and the defines set up in the
291  * 2.4 kernel series
292  *     1 = _DATA_OUT    changed to SCSI_DATA_WRITE (1)
293  *     0 = _DIR_NONE    changed to SCSI_DATA_NONE (3)
294  *    -1 = _DATA_IN     changed to SCSI_DATA_READ (2)
295  * If the direction is unknown, fall through to original code.
296  *
297  * Mid-layer bug fix(): sg interface generates the wrong data
298  * direction in some cases. Set the direction the hard way for
299  * the most common commands.
300  */
301 static inline int
302 mptscsih_io_direction(Scsi_Cmnd *cmd)
303 {
304         switch (cmd->cmnd[0]) {
305         case WRITE_6:
306         case WRITE_10:
307         case WRITE_16:
308                 return SCSI_DATA_WRITE;
309                 break;
310         case READ_6:
311         case READ_10:
312         case READ_16:
313                 return SCSI_DATA_READ;
314                 break;
315         }
316
317         if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN)
318                 return cmd->sc_data_direction;
319
320         switch (cmd->cmnd[0]) {
321         /*  _DATA_OUT commands  */
322         case WRITE_6:           case WRITE_10:          case WRITE_12:
323         case WRITE_16:
324         case WRITE_LONG:        case WRITE_SAME:        case WRITE_BUFFER:
325         case WRITE_VERIFY:      case WRITE_VERIFY_12:
326         case COMPARE:           case COPY:              case COPY_VERIFY:
327         case SEARCH_EQUAL:      case SEARCH_HIGH:       case SEARCH_LOW:
328         case SEARCH_EQUAL_12:   case SEARCH_HIGH_12:    case SEARCH_LOW_12:
329         case MODE_SELECT:       case MODE_SELECT_10:    case LOG_SELECT:
330         case SEND_DIAGNOSTIC:   case CHANGE_DEFINITION: case UPDATE_BLOCK:
331         case SET_WINDOW:        case MEDIUM_SCAN:       case SEND_VOLUME_TAG:
332         case REASSIGN_BLOCKS:
333         case PERSISTENT_RESERVE_OUT:
334         case 0xea:
335         case 0xa3:
336                 return SCSI_DATA_WRITE;
337
338         /*  No data transfer commands  */
339         case SEEK_6:            case SEEK_10:
340         case RESERVE:           case RELEASE:
341         case TEST_UNIT_READY:
342         case START_STOP:
343         case ALLOW_MEDIUM_REMOVAL:
344                 return SCSI_DATA_NONE;
345
346         /*  Conditional data transfer commands  */
347         case FORMAT_UNIT:
348                 if (cmd->cmnd[1] & 0x10)        /* FmtData (data out phase)? */
349                         return SCSI_DATA_WRITE;
350                 else
351                         return SCSI_DATA_NONE;
352
353         case VERIFY:
354                 if (cmd->cmnd[1] & 0x02)        /* VERIFY:BYTCHK (data out phase)? */
355                         return SCSI_DATA_WRITE;
356                 else
357                         return SCSI_DATA_NONE;
358
359         case RESERVE_10:
360                 if (cmd->cmnd[1] & 0x03)        /* RESERVE:{LongID|Extent} (data out phase)? */
361                         return SCSI_DATA_WRITE;
362                 else
363                         return SCSI_DATA_NONE;
364
365         /*  Must be data _IN!  */
366         default:
367                 return SCSI_DATA_READ;
368         }
369 } /* mptscsih_io_direction() */
370
371 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
372 /**
373  *      mptscsih_add_sge - Place a simple SGE at address pAddr.
374  *      @pAddr: virtual address for SGE
375  *      @flagslength: SGE flags and data transfer length
376  *      @dma_addr: Physical address
377  *
378  *      This routine places a MPT request frame back on the MPT adapter's
379  *      FreeQ.
380  */
381 static inline void
382 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
383 {
384         if (sizeof(dma_addr_t) == sizeof(u64)) {
385                 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
386                 u32 tmp = dma_addr & 0xFFFFFFFF;
387
388                 pSge->FlagsLength = cpu_to_le32(flagslength);
389                 pSge->Address.Low = cpu_to_le32(tmp);
390                 tmp = (u32) ((u64)dma_addr >> 32);
391                 pSge->Address.High = cpu_to_le32(tmp);
392
393         } else {
394                 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
395                 pSge->FlagsLength = cpu_to_le32(flagslength);
396                 pSge->Address = cpu_to_le32(dma_addr);
397         }
398 } /* mptscsih_add_sge() */
399
400 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
401 /**
402  *      mptscsih_add_chain - Place a chain SGE at address pAddr.
403  *      @pAddr: virtual address for SGE
404  *      @next: nextChainOffset value (u32's)
405  *      @length: length of next SGL segment
406  *      @dma_addr: Physical address
407  *
408  *      This routine places a MPT request frame back on the MPT adapter's
409  *      FreeQ.
410  */
411 static inline void
412 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
413 {
414         if (sizeof(dma_addr_t) == sizeof(u64)) {
415                 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
416                 u32 tmp = dma_addr & 0xFFFFFFFF;
417
418                 pChain->Length = cpu_to_le16(length);
419                 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
420
421                 pChain->NextChainOffset = next;
422
423                 pChain->Address.Low = cpu_to_le32(tmp);
424                 tmp = (u32) ((u64)dma_addr >> 32);
425                 pChain->Address.High = cpu_to_le32(tmp);
426         } else {
427                 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
428                 pChain->Length = cpu_to_le16(length);
429                 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
430                 pChain->NextChainOffset = next;
431                 pChain->Address = cpu_to_le32(dma_addr);
432         }
433 } /* mptscsih_add_chain() */
434
435 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
436 /*
437  *      mptscsih_getFreeChainBuffes - Function to get a free chain
438  *      from the MPT_SCSI_HOST FreeChainQ.
439  *      @hd: Pointer to the MPT_SCSI_HOST instance
440  *      @req_idx: Index of the SCSI IO request frame. (output)
441  *
442  *      return SUCCESS or FAILED
443  */
444 static inline int
445 mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
446 {
447         MPT_FRAME_HDR *chainBuf;
448         unsigned long flags;
449         int rc;
450         int chain_idx;
451
452         spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
453         if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
454
455                 int offset;
456
457                 chainBuf = hd->FreeChainQ.head;
458                 Q_DEL_ITEM(&chainBuf->u.frame.linkage);
459                 offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
460                 chain_idx = offset / hd->ioc->req_sz;
461                 rc = SUCCESS;
462         }
463         else {
464                 rc = FAILED;
465                 chain_idx = MPT_HOST_NO_CHAIN;
466         }
467         spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
468
469
470         *retIndex = chain_idx;
471
472         dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
473                         hd->ioc->name, *retIndex, chainBuf));
474
475         return rc;
476 } /* mptscsih_getFreeChainBuffer() */
477
478 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
479 /*
480  *      mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
481  *      SCSIIORequest_t Message Frame.
482  *      @hd: Pointer to MPT_SCSI_HOST structure
483  *      @SCpnt: Pointer to Scsi_Cmnd structure
484  *      @pReq: Pointer to SCSIIORequest_t structure
485  *
486  *      Returns ...
487  */
488 static int
489 mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
490                 SCSIIORequest_t *pReq, int req_idx)
491 {
492         char    *psge;
493         char    *chainSge;
494         struct scatterlist *sg;
495         int      frm_sz;
496         int      sges_left, sg_done;
497         int      chain_idx = MPT_HOST_NO_CHAIN;
498         int      sgeOffset;
499         int      numSgeSlots, numSgeThisFrame;
500         u32      sgflags, sgdir, thisxfer = 0;
501         int      chain_dma_off = 0;
502         int      newIndex;
503         int      ii;
504         dma_addr_t v2;
505
506         sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
507         if (sgdir == MPI_SCSIIO_CONTROL_WRITE)  {
508                 sgdir = MPT_TRANSFER_HOST_TO_IOC;
509         } else {
510                 sgdir = MPT_TRANSFER_IOC_TO_HOST;
511         }
512
513         psge = (char *) &pReq->SGL;
514         frm_sz = hd->ioc->req_sz;
515
516         /* Map the data portion, if any.
517          * sges_left  = 0 if no data transfer.
518          */
519         if ( (sges_left = SCpnt->use_sg) ) {
520                 sges_left = pci_map_sg(hd->ioc->pcidev,
521                                (struct scatterlist *) SCpnt->request_buffer,
522                                SCpnt->use_sg,
523                                scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
524                 if (sges_left == 0)
525                         return FAILED;
526         } else if (SCpnt->request_bufflen) {
527                 dma_addr_t       buf_dma_addr;
528                 scPrivate       *my_priv;
529
530                 buf_dma_addr = pci_map_single(hd->ioc->pcidev,
531                                       SCpnt->request_buffer,
532                                       SCpnt->request_bufflen,
533                                       scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
534
535                 /* We hide it here for later unmap. */
536                 my_priv = (scPrivate *) &SCpnt->SCp;
537                 my_priv->p1 = (void *)(ulong) buf_dma_addr;
538
539                 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
540                                 hd->ioc->name, SCpnt, SCpnt->request_bufflen));
541
542                 mptscsih_add_sge((char *) &pReq->SGL,
543                         0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
544                         buf_dma_addr);
545
546                 return SUCCESS;
547         }
548
549         /* Handle the SG case.
550          */
551         sg = (struct scatterlist *) SCpnt->request_buffer;
552         sg_done  = 0;
553         sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
554         chainSge = NULL;
555
556         /* Prior to entering this loop - the following must be set
557          * current MF:  sgeOffset (bytes)
558          *              chainSge (Null if original MF is not a chain buffer)
559          *              sg_done (num SGE done for this MF)
560          */
561
562 nextSGEset:
563         numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
564         numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
565
566         sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
567
568         /* Get first (num - 1) SG elements
569          * Skip any SG entries with a length of 0
570          * NOTE: at finish, sg and psge pointed to NEXT data/location positions
571          */
572         for (ii=0; ii < (numSgeThisFrame-1); ii++) {
573                 thisxfer = sg_dma_len(sg);
574                 if (thisxfer == 0) {
575                         sg ++; /* Get next SG element from the OS */
576                         sg_done++;
577                         continue;
578                 }
579
580                 v2 = sg_dma_address(sg);
581                 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
582
583                 sg++;           /* Get next SG element from the OS */
584                 psge += (sizeof(u32) + sizeof(dma_addr_t));
585                 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
586                 sg_done++;
587         }
588
589         if (numSgeThisFrame == sges_left) {
590                 /* Add last element, end of buffer and end of list flags.
591                  */
592                 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
593                                 MPT_SGE_FLAGS_END_OF_BUFFER |
594                                 MPT_SGE_FLAGS_END_OF_LIST;
595
596                 /* Add last SGE and set termination flags.
597                  * Note: Last SGE may have a length of 0 - which should be ok.
598                  */
599                 thisxfer = sg_dma_len(sg);
600
601                 v2 = sg_dma_address(sg);
602                 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
603                 /*
604                 sg++;
605                 psge += (sizeof(u32) + sizeof(dma_addr_t));
606                 */
607                 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
608                 sg_done++;
609
610                 if (chainSge) {
611                         /* The current buffer is a chain buffer,
612                          * but there is not another one.
613                          * Update the chain element
614                          * Offset and Length fields.
615                          */
616                         mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
617                 } else {
618                         /* The current buffer is the original MF
619                          * and there is no Chain buffer.
620                          */
621                         pReq->ChainOffset = 0;
622                 }
623         } else {
624                 /* At least one chain buffer is needed.
625                  * Complete the first MF
626                  *  - last SGE element, set the LastElement bit
627                  *  - set ChainOffset (words) for orig MF
628                  *             (OR finish previous MF chain buffer)
629                  *  - update MFStructPtr ChainIndex
630                  *  - Populate chain element
631                  * Also
632                  * Loop until done.
633                  */
634
635                 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
636                                 hd->ioc->name, sg_done));
637
638                 /* Set LAST_ELEMENT flag for last non-chain element
639                  * in the buffer. Since psge points at the NEXT
640                  * SGE element, go back one SGE element, update the flags
641                  * and reset the pointer. (Note: sgflags & thisxfer are already
642                  * set properly).
643                  */
644                 if (sg_done) {
645                         u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
646                         sgflags = le32_to_cpu(*ptmp);
647                         sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
648                         *ptmp = cpu_to_le32(sgflags);
649                 }
650
651                 if (chainSge) {
652                         /* The current buffer is a chain buffer.
653                          * chainSge points to the previous Chain Element.
654                          * Update its chain element Offset and Length (must
655                          * include chain element size) fields.
656                          * Old chain element is now complete.
657                          */
658                         u8 nextChain = (u8) (sgeOffset >> 2);
659                         sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
660                         mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
661                 } else {
662                         /* The original MF buffer requires a chain buffer -
663                          * set the offset.
664                          * Last element in this MF is a chain element.
665                          */
666                         pReq->ChainOffset = (u8) (sgeOffset >> 2);
667                 }
668
669                 sges_left -= sg_done;
670
671
672                 /* NOTE: psge points to the beginning of the chain element
673                  * in current buffer. Get a chain buffer.
674                  */
675                 if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
676                         return FAILED;
677
678                 /* Update the tracking arrays.
679                  * If chainSge == NULL, update ReqToChain, else ChainToChain
680                  */
681                 if (chainSge) {
682                         hd->ChainToChain[chain_idx] = newIndex;
683                 } else {
684                         hd->ReqToChain[req_idx] = newIndex;
685                 }
686                 chain_idx = newIndex;
687                 chain_dma_off = hd->ioc->req_sz * chain_idx;
688
689                 /* Populate the chainSGE for the current buffer.
690                  * - Set chain buffer pointer to psge and fill
691                  *   out the Address and Flags fields.
692                  */
693                 chainSge = (char *) psge;
694                 dsgprintk((KERN_INFO "  Current buff @ %p (index 0x%x)",
695                                 psge, req_idx));
696
697                 /* Start the SGE for the next buffer
698                  */
699                 psge = (char *) (hd->ChainBuffer + chain_dma_off);
700                 sgeOffset = 0;
701                 sg_done = 0;
702
703                 dsgprintk((KERN_INFO "  Chain buff @ %p (index 0x%x)\n",
704                                 psge, chain_idx));
705
706                 /* Start the SGE for the next buffer
707                  */
708
709                 goto nextSGEset;
710         }
711
712         return SUCCESS;
713 } /* mptscsih_AddSGE() */
714
715 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
716 /*
717  *      mptscsih_io_done - Main SCSI IO callback routine registered to
718  *      Fusion MPT (base) driver
719  *      @ioc: Pointer to MPT_ADAPTER structure
720  *      @mf: Pointer to original MPT request frame
721  *      @r: Pointer to MPT reply frame (NULL if TurboReply)
722  *
723  *      This routine is called from mpt.c::mpt_interrupt() at the completion
724  *      of any SCSI IO request.
725  *      This routine is registered with the Fusion MPT (base) driver at driver
726  *      load/init time via the mpt_register() API call.
727  *
728  *      Returns 1 indicating alloc'd request frame ptr should be freed.
729  */
730 static int
731 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
732 {
733         Scsi_Cmnd       *sc;
734         MPT_SCSI_HOST   *hd;
735         SCSIIORequest_t *pScsiReq;
736         SCSIIOReply_t   *pScsiReply;
737         u16              req_idx;
738
739         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
740
741         req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
742         sc = hd->ScsiLookup[req_idx];
743         if (sc == NULL) {
744                 MPIHeader_t *hdr = (MPIHeader_t *)mf;
745
746                 /* Remark: writeSDP1 will use the ScsiDoneCtx
747                  * If a SCSI I/O cmd, device disabled by OS and
748                  * completion done. Cannot touch sc struct. Just free mem.
749                  */
750                 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
751                         printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
752                         ioc->name);
753
754                 mptscsih_freeChainBuffers(hd, req_idx);
755                 return 1;
756         }
757
758         dmfprintk((MYIOC_s_INFO_FMT
759                 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
760                 ioc->name, mf, mr, sc, req_idx));
761
762         sc->result = DID_OK << 16;              /* Set default reply as OK */
763         pScsiReq = (SCSIIORequest_t *) mf;
764         pScsiReply = (SCSIIOReply_t *) mr;
765
766 #ifdef MPTSCSIH_DBG_TIMEOUT
767         if (ioc->timeout_cnt > 0) {
768                 int ii, left = 0;
769
770                 for (ii=0; ii < 8; ii++) {
771                         if (sc == foo_to[ii]) {
772                                 printk(MYIOC_s_INFO_FMT "complete (%p, %ld)\n",
773                                         ioc->name, sc, jiffies);
774                                 foo_to[ii] = NULL;
775                         }
776                         if (foo_to[ii] != NULL)
777                                 left++;
778                 }
779
780                 if (left == 0) {
781                         ioc->timeout_maxcnt = 0;
782                         ioc->timeout_cnt = 0;
783                 }
784         }
785 #endif
786
787         if (pScsiReply == NULL) {
788                 /* special context reply handling */
789                 ;
790         } else {
791                 u32      xfer_cnt;
792                 u16      status;
793                 u8       scsi_state, scsi_status;
794
795                 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
796                 scsi_state = pScsiReply->SCSIState;
797
798                 dprintk((KERN_NOTICE "  Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
799                                 ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
800                                 mf, mr, sc));
801                 dprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh"
802                                 ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
803                                 status, scsi_state, pScsiReply->SCSIStatus,
804                                 le32_to_cpu(pScsiReply->IOCLogInfo)));
805
806                 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
807                         copy_sense_data(sc, hd, mf, pScsiReply);
808                 
809                 /*
810                  *  Look for + dump FCP ResponseInfo[]!
811                  */
812                 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
813                         printk(KERN_NOTICE "  FCP_ResponseInfo=%08xh\n",
814                         le32_to_cpu(pScsiReply->ResponseInfo));
815                 }
816
817                 switch(status) {
818                 case MPI_IOCSTATUS_BUSY:                        /* 0x0002 */
819                         /* CHECKME!
820                          * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
821                          * But not: DID_BUS_BUSY lest one risk
822                          * killing interrupt handler:-(
823                          */
824                         sc->result = STS_BUSY;
825                         break;
826
827                 case MPI_IOCSTATUS_SCSI_INVALID_BUS:            /* 0x0041 */
828                 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:       /* 0x0042 */
829                         sc->result = DID_BAD_TARGET << 16;
830                         break;
831
832                 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
833                         /* Spoof to SCSI Selection Timeout! */
834                         sc->result = DID_NO_CONNECT << 16;
835
836                         if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
837                                 hd->sel_timeout[pScsiReq->TargetID]++;
838                         break;
839
840                 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
841                 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
842                 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
843                         /* Linux handles an unsolicited DID_RESET better
844                          * than an unsolicited DID_ABORT.
845                          */
846                         sc->result = DID_RESET << 16;
847
848                         /* GEM Workaround. */
849                         if (hd->is_spi)
850                                 mptscsih_no_negotiate(hd, sc->device->id);
851                         break;
852
853                 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:      /* 0x0049 */
854                 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
855                         /*
856                          *  Do upfront check for valid SenseData and give it
857                          *  precedence!
858                          */
859                         scsi_status = pScsiReply->SCSIStatus;
860                         sc->result = (DID_OK << 16) | scsi_status;
861                         xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
862                         if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
863                                 /* Have already saved the status and sense data
864                                  */
865                                 ;
866                         } else {
867                                 if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) {
868                                         sc->result = DID_SOFT_ERROR << 16;
869                                 }
870                                 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
871                                         /* What to do?
872                                         */
873                                         sc->result = DID_SOFT_ERROR << 16;
874                                 }
875                                 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
876                                         /*  Not real sure here either...  */
877                                         sc->result = DID_RESET << 16;
878                                 }
879                         }
880
881                         /* Give report and update residual count.
882                          */
883                         dprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
884                                         sc->underflow));
885                         dprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
886
887                         sc->resid = sc->request_bufflen - xfer_cnt;
888                         dprintk((KERN_NOTICE "  SET sc->resid=%02xh\n", sc->resid));
889                         
890                         /* Report Queue Full
891                          */
892                         if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
893                                 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
894                         
895                         break;
896
897                 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
898                 case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
899                         sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
900                         if (scsi_state == 0) {
901                                 ;
902                         } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
903                                 /*
904                                  * If running against circa 200003dd 909 MPT f/w,
905                                  * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
906                                  * (QUEUE_FULL) returned from device! --> get 0x0000?128
907                                  * and with SenseBytes set to 0.
908                                  */
909                                 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
910                                         mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
911
912                         }
913                         else if (scsi_state &
914                                  (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
915                            ) {
916                                 /*
917                                  * What to do?
918                                  */
919                                 sc->result = DID_SOFT_ERROR << 16;
920                         }
921                         else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
922                                 /*  Not real sure here either...  */
923                                 sc->result = DID_RESET << 16;
924                         }
925                         else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
926                                 /* Device Inq. data indicates that it supports
927                                  * QTags, but rejects QTag messages.
928                                  * This command completed OK.
929                                  *
930                                  * Not real sure here either so do nothing...  */
931                         }
932
933                         if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
934                                 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
935
936                         /* Add handling of:
937                          * Reservation Conflict, Busy,
938                          * Command Terminated, CHECK
939                          */
940                         break;
941
942                 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:         /* 0x0047 */
943                                 sc->result = DID_SOFT_ERROR << 16;
944                         break;
945
946                 case MPI_IOCSTATUS_INVALID_FUNCTION:            /* 0x0001 */
947                 case MPI_IOCSTATUS_INVALID_SGL:                 /* 0x0003 */
948                 case MPI_IOCSTATUS_INTERNAL_ERROR:              /* 0x0004 */
949                 case MPI_IOCSTATUS_RESERVED:                    /* 0x0005 */
950                 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:      /* 0x0006 */
951                 case MPI_IOCSTATUS_INVALID_FIELD:               /* 0x0007 */
952                 case MPI_IOCSTATUS_INVALID_STATE:               /* 0x0008 */
953                 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:           /* 0x0044 */
954                 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
955                 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:       /* 0x004A */
956                 default:
957                         /*
958                          * What to do?
959                          */
960                         sc->result = DID_SOFT_ERROR << 16;
961                         break;
962
963                 }       /* switch(status) */
964
965                 dprintk((KERN_NOTICE "  sc->result set to %08xh\n", sc->result));
966         } /* end of address reply case */
967
968         /* Unmap the DMA buffers, if any. */
969         if (sc->use_sg) {
970                 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
971                             sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
972         } else if (sc->request_bufflen) {
973                 scPrivate       *my_priv;
974
975                 my_priv = (scPrivate *) &sc->SCp;
976                 pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
977                            sc->request_bufflen,
978                            scsi_to_pci_dma_dir(sc->sc_data_direction));
979         }
980
981         hd->ScsiLookup[req_idx] = NULL;
982
983         sc->scsi_done(sc);              /* Issue the command callback */
984
985         /* Free Chain buffers */
986         mptscsih_freeChainBuffers(hd, req_idx);
987         return 1;
988 }
989
990 /*
991  * Flush all commands on the doneQ.
992  * Lock Q when deleting/adding members
993  * Lock io_request_lock for OS callback.
994  */
995 static void
996 flush_doneQ(MPT_SCSI_HOST *hd)
997 {
998         MPT_DONE_Q      *buffer;
999         Scsi_Cmnd       *SCpnt;
1000         unsigned long    flags;
1001
1002         /* Flush the doneQ.
1003          */
1004         dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n"));
1005         while (1) {
1006                 spin_lock_irqsave(&hd->freedoneQlock, flags);
1007                 if (Q_IS_EMPTY(&hd->doneQ)) {
1008                         spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1009                         break;
1010                 }
1011
1012                 buffer = hd->doneQ.head;
1013                 /* Delete from Q
1014                  */
1015                 Q_DEL_ITEM(buffer);
1016
1017                 /* Set the Scsi_Cmnd pointer
1018                  */
1019                 SCpnt = (Scsi_Cmnd *) buffer->argp;
1020                 buffer->argp = NULL;
1021
1022                 /* Add to the freeQ
1023                  */
1024                 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1025                 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1026
1027                 /* Do the OS callback.
1028                  */
1029                 SCpnt->scsi_done(SCpnt);
1030         }
1031
1032         return;
1033 }
1034
1035 /*
1036  * Search the doneQ for a specific command. If found, delete from Q.
1037  * Calling function will finish processing.
1038  */
1039 static void
1040 search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt)
1041 {
1042         unsigned long    flags;
1043         MPT_DONE_Q      *buffer;
1044
1045         spin_lock_irqsave(&hd->freedoneQlock, flags);
1046         if (!Q_IS_EMPTY(&hd->doneQ)) {
1047                 buffer = hd->doneQ.head;
1048                 do {
1049                         Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp;
1050                         if (SCpnt == sc) {
1051                                 Q_DEL_ITEM(buffer);
1052                                 SCpnt->result = sc->result;
1053
1054                                 /* Set the Scsi_Cmnd pointer
1055                                  */
1056                                 buffer->argp = NULL;
1057
1058                                 /* Add to the freeQ
1059                                  */
1060                                 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1061                                 break;
1062                         }
1063                 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ);
1064         }
1065         spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1066         return;
1067 }
1068
1069 /*
1070  *      mptscsih_flush_running_cmds - For each command found, search
1071  *              Scsi_Host instance taskQ and reply to OS.
1072  *              Called only if recovering from a FW reload.
1073  *      @hd: Pointer to a SCSI HOST structure
1074  *
1075  *      Returns: None.
1076  *
1077  *      Must be called while new I/Os are being queued.
1078  */
1079 static void
1080 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
1081 {
1082         Scsi_Cmnd       *SCpnt;
1083         MPT_FRAME_HDR   *mf;
1084         MPT_DONE_Q      *buffer;
1085         int              ii;
1086         int              max = hd->ioc->req_depth;
1087         unsigned long    flags;
1088
1089         dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
1090         for (ii= 0; ii < max; ii++) {
1091                 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
1092
1093                         /* Command found.
1094                          */
1095
1096                         /* Search pendingQ, if found,
1097                          * delete from Q.
1098                          */
1099                         mptscsih_search_pendingQ(hd, ii);
1100
1101                         /* Null ScsiLookup index
1102                          */
1103                         hd->ScsiLookup[ii] = NULL;
1104
1105                         mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);
1106                         dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
1107                                         mf, SCpnt));
1108
1109                         /* Set status, free OS resources (SG DMA buffers)
1110                          * Do OS callback
1111                          * Free driver resources (chain, msg buffers)
1112                          */
1113                         if (scsi_device_online(SCpnt->device)) {
1114                                 if (SCpnt->use_sg) {
1115                                         pci_unmap_sg(hd->ioc->pcidev,
1116                                                 (struct scatterlist *) SCpnt->request_buffer,
1117                                                 SCpnt->use_sg,
1118                                                 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1119                                 } else if (SCpnt->request_bufflen) {
1120                                         scPrivate       *my_priv;
1121
1122                                         my_priv = (scPrivate *) &SCpnt->SCp;
1123                                         pci_unmap_single(hd->ioc->pcidev,
1124                                                 (dma_addr_t)(ulong)my_priv->p1,
1125                                                 SCpnt->request_bufflen,
1126                                                 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1127                                 }
1128                         }
1129                         SCpnt->result = DID_RESET << 16;
1130                         SCpnt->host_scribble = NULL;
1131
1132                         /* Free Chain buffers */
1133                         mptscsih_freeChainBuffers(hd, ii);
1134
1135                         /* Free Message frames */
1136                         mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
1137
1138 #if 1
1139                         /* Post to doneQ, do not reply until POST phase
1140                          * of reset handler....prevents new commands from
1141                          * being queued.
1142                          */
1143                         spin_lock_irqsave(&hd->freedoneQlock, flags);
1144                         if (!Q_IS_EMPTY(&hd->freeQ)) {
1145                                 buffer = hd->freeQ.head;
1146                                 Q_DEL_ITEM(buffer);
1147
1148                                 /* Set the Scsi_Cmnd pointer
1149                                  */
1150                                 buffer->argp = (void *)SCpnt;
1151
1152                                 /* Add to the doneQ
1153                                  */
1154                                 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
1155                                 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1156                         } else {
1157                                 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1158                                 SCpnt->scsi_done(SCpnt);
1159                         }
1160 #else
1161                         SCpnt->scsi_done(SCpnt);        /* Issue the command callback */
1162 #endif
1163
1164                 }
1165         }
1166
1167         return;
1168 }
1169
1170 /*
1171  *      mptscsih_search_running_cmds - Delete any commands associated
1172  *              with the specified target and lun. Function called only
1173  *              when a lun is disable by mid-layer.
1174  *              Do NOT access the referenced Scsi_Cmnd structure or
1175  *              members. Will cause either a paging or NULL ptr error.
1176  *      @hd: Pointer to a SCSI HOST structure
1177  *      @target: target id
1178  *      @lun: lun
1179  *
1180  *      Returns: None.
1181  *
1182  *      Called from slave_destroy.
1183  */
1184 static void
1185 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
1186 {
1187         SCSIIORequest_t *mf = NULL;
1188         int              ii;
1189         int              max = hd->ioc->req_depth;
1190
1191         dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
1192                         target, lun, max));
1193
1194         for (ii=0; ii < max; ii++) {
1195                 if (hd->ScsiLookup[ii] != NULL) {
1196
1197                         mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
1198
1199                         dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
1200                                         hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
1201
1202                         if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
1203                                 continue;
1204
1205                         /* Cleanup
1206                          */
1207                         hd->ScsiLookup[ii] = NULL;
1208                         mptscsih_freeChainBuffers(hd, ii);
1209                         mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, (MPT_FRAME_HDR *)mf);
1210                 }
1211         }
1212
1213         return;
1214 }
1215
1216 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1217 /*
1218  *      mptscsih_initChainBuffers - Allocate memory for and initialize
1219  *      chain buffers, chain buffer control arrays and spinlock.
1220  *      @hd: Pointer to MPT_SCSI_HOST structure
1221  *      @init: If set, initialize the spin lock.
1222  */
1223 static int
1224 mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
1225 {
1226         MPT_FRAME_HDR   *chain;
1227         u8              *mem;
1228         unsigned long   flags;
1229         int             sz, ii, num_chain;
1230         int             scale, num_sge;
1231
1232         /* chain buffer allocation done from PrimeIocFifos */   
1233         if (hd->ioc->fifo_pool == NULL) 
1234                 return -1;
1235         
1236         hd->ChainBuffer = hd->ioc->chain_alloc;
1237         hd->ChainBufferDMA = hd->ioc->chain_alloc_dma;
1238         
1239         dprintk((KERN_INFO "  ChainBuffer    @ %p(%p), sz=%d\n",
1240                  hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, hd->ioc->chain_alloc_sz));
1241                 
1242         /* ReqToChain size must equal the req_depth
1243          * index = req_idx
1244          */
1245         if (hd->ReqToChain == NULL) {
1246                 sz = hd->ioc->req_depth * sizeof(int);
1247                 mem = kmalloc(sz, GFP_ATOMIC);
1248                 if (mem == NULL)
1249                         return -1;
1250
1251                 hd->ReqToChain = (int *) mem;
1252         }
1253         for (ii = 0; ii < hd->ioc->req_depth; ii++)
1254                 hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
1255
1256         /* ChainToChain size must equal the total number
1257          * of chain buffers to be allocated.
1258          * index = chain_idx
1259          *
1260          * Calculate the number of chain buffers needed(plus 1) per I/O
1261          * then multiply the the maximum number of simultaneous cmds
1262          *
1263          * num_sge = num sge in request frame + last chain buffer
1264          * scale = num sge per chain buffer if no chain element
1265          */
1266         scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1267         if (sizeof(dma_addr_t) == sizeof(u64))
1268                 num_sge =  scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
1269         else
1270                 num_sge =  1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
1271
1272         num_chain = 1;
1273         while (hd->max_sge - num_sge > 0) {
1274                 num_chain++;
1275                 num_sge += (scale - 1);
1276         }
1277         num_chain++;
1278
1279         if ((int) hd->ioc->chip_type > (int) FC929)
1280                 num_chain *= MPT_SCSI_CAN_QUEUE;
1281         else
1282                 num_chain *= MPT_FC_CAN_QUEUE;
1283
1284         hd->num_chain = num_chain;
1285
1286         sz = num_chain * sizeof(int);
1287         if (hd->ChainToChain == NULL) {
1288                 mem = kmalloc(sz, GFP_ATOMIC);
1289                 if (mem == NULL)
1290                         return -1;
1291
1292                 hd->ChainToChain = (int *) mem;
1293         } else {
1294                 mem = (u8 *) hd->ChainToChain;
1295         }
1296         memset(mem, 0xFF, sz);
1297
1298
1299         /* Initialize the free chain Q.
1300          */
1301         if (init) {
1302                 spin_lock_init(&hd->FreeChainQlock);
1303         }
1304
1305         spin_lock_irqsave (&hd->FreeChainQlock, flags);
1306         Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);
1307
1308         /* Post the chain buffers to the FreeChainQ.
1309          */
1310         mem = (u8 *)hd->ChainBuffer;
1311         for (ii=0; ii < num_chain; ii++) {
1312                 chain = (MPT_FRAME_HDR *) mem;
1313                 Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);
1314                 mem += hd->ioc->req_sz;
1315         }
1316         spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
1317
1318         return 0;
1319 }
1320
1321 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1322 /*
1323  *  Hack! It might be nice to report if a device is returning QUEUE_FULL
1324  *  but maybe not each and every time...
1325  */
1326 static long last_queue_full = 0;
1327
1328 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1329 /*
1330  *      mptscsih_report_queue_full - Report QUEUE_FULL status returned
1331  *      from a SCSI target device.
1332  *      @sc: Pointer to Scsi_Cmnd structure
1333  *      @pScsiReply: Pointer to SCSIIOReply_t
1334  *      @pScsiReq: Pointer to original SCSI request
1335  *
1336  *      This routine periodically reports QUEUE_FULL status returned from a
1337  *      SCSI target device.  It reports this to the console via kernel
1338  *      printk() API call, not more than once every 10 seconds.
1339  */
1340 static void
1341 mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1342 {
1343         long time = jiffies;
1344
1345         if (time - last_queue_full > 10 * HZ) {
1346                 char *ioc_str = "ioc?";
1347
1348                 if (sc->device && sc->device->host != NULL && sc->device->host->hostdata != NULL)
1349                         ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name;
1350                 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1351                                 ioc_str, 0, sc->device->id, sc->device->lun));
1352                 last_queue_full = time;
1353         }
1354 }
1355
1356 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1357 static char *info_kbuf = NULL;
1358
1359 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1360 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1361 /*
1362  *      mptscsih_probe - Installs scsi devices per bus.
1363  *      @pdev: Pointer to pci_dev structure
1364  *
1365  *      Returns 0 for success, non-zero for failure.
1366  *
1367  */
1368
1369 static int
1370 mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1371 {
1372         struct Scsi_Host        *sh;
1373         MPT_SCSI_HOST           *hd;
1374         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
1375         MPT_DONE_Q              *freedoneQ;
1376         unsigned long            flags;
1377         int                      sz, ii;
1378         int                      numSGE = 0;
1379         int                      scale;
1380         int                      ioc_cap;
1381         u8                      *mem;
1382         int                     error=0;
1383
1384
1385         /* 20010202 -sralston
1386          *  Added sanity check on readiness of the MPT adapter.
1387          */
1388         if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1389                 printk(MYIOC_s_WARN_FMT
1390                   "Skipping because it's not operational!\n",
1391                   ioc->name);
1392                 return -ENODEV;
1393         }
1394
1395         if (!ioc->active) {
1396                 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1397                   ioc->name);
1398                 return -ENODEV;
1399         }
1400
1401         /*  Sanity check - ensure at least 1 port is INITIATOR capable
1402          */
1403         ioc_cap = 0;
1404         for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1405                 if (ioc->pfacts[ii].ProtocolFlags &
1406                     MPI_PORTFACTS_PROTOCOL_INITIATOR)
1407                         ioc_cap ++;
1408         }
1409
1410         if (!ioc_cap) {
1411                 printk(MYIOC_s_WARN_FMT
1412                         "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1413                         ioc->name, ioc);
1414                 return -ENODEV;
1415         }
1416
1417         sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));
1418         
1419         if (!sh) {
1420                 printk(MYIOC_s_WARN_FMT
1421                         "Unable to register controller with SCSI subsystem\n",
1422                         ioc->name);
1423                 return -1;
1424         }
1425         
1426         spin_lock_irqsave(&ioc->FreeQlock, flags);
1427
1428         /* Attach the SCSI Host to the IOC structure
1429          */
1430         ioc->sh = sh;
1431
1432         sh->io_port = 0;
1433         sh->n_io_port = 0;
1434         sh->irq = 0;
1435
1436         /* set 16 byte cdb's */
1437         sh->max_cmd_len = 16;
1438
1439         /* Yikes!  This is important!
1440          * Otherwise, by default, linux
1441          * only scans target IDs 0-7!
1442          * pfactsN->MaxDevices unreliable
1443          * (not supported in early
1444          *      versions of the FW).
1445          * max_id = 1 + actual max id,
1446          * max_lun = 1 + actual last lun,
1447          *      see hosts.h :o(
1448          */
1449         if ((int)ioc->chip_type > (int)FC929) {
1450                 sh->max_id = MPT_MAX_SCSI_DEVICES;
1451         } else {
1452         /* For FC, increase the queue depth
1453          * from MPT_SCSI_CAN_QUEUE (31)
1454          * to MPT_FC_CAN_QUEUE (63).
1455          */
1456                 sh->can_queue = MPT_FC_CAN_QUEUE;
1457                 sh->max_id =
1458                   MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1459         }
1460                 
1461         sh->max_lun = MPT_LAST_LUN + 1;
1462         sh->max_sectors = MPT_SCSI_MAX_SECTORS;
1463         sh->max_channel = 0;
1464         sh->this_id = ioc->pfacts[0].PortSCSIID;
1465                 
1466         /* Required entry.
1467          */
1468         sh->unique_id = ioc->id;
1469
1470         /* Verify that we won't exceed the maximum
1471          * number of chain buffers
1472          * We can optimize:  ZZ = req_sz/sizeof(SGE)
1473          * For 32bit SGE's:
1474          *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1475          *               + (req_sz - 64)/sizeof(SGE)
1476          * A slightly different algorithm is required for
1477          * 64bit SGEs.
1478          */
1479         scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1480         if (sizeof(dma_addr_t) == sizeof(u64)) {
1481                 numSGE = (scale - 1) *
1482                   (ioc->facts.MaxChainDepth-1) + scale +
1483                   (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1484                   sizeof(u32));
1485         } else {
1486                 numSGE = 1 + (scale - 1) *
1487                   (ioc->facts.MaxChainDepth-1) + scale +
1488                   (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1489                   sizeof(u32));
1490         }
1491                 
1492         if (numSGE < sh->sg_tablesize) {
1493                 /* Reset this value */
1494                 dprintk((MYIOC_s_INFO_FMT
1495                   "Resetting sg_tablesize to %d from %d\n",
1496                   ioc->name, numSGE, sh->sg_tablesize));
1497                 sh->sg_tablesize = numSGE;
1498         }
1499
1500         /* Set the pci device pointer in Scsi_Host structure.
1501          */
1502         scsi_set_device(sh, &ioc->pcidev->dev);
1503
1504         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1505
1506         hd = (MPT_SCSI_HOST *) sh->hostdata;
1507         hd->ioc = ioc;
1508         hd->max_sge = sh->sg_tablesize;
1509
1510         if ((int)ioc->chip_type > (int)FC929)
1511         hd->is_spi = 1;
1512
1513         if (DmpService && (ioc->chip_type == FC919 ||
1514           ioc->chip_type == FC929)) {
1515                 hd->is_multipath = 1;
1516         }
1517
1518         /* SCSI needs Scsi_Cmnd lookup table!
1519          * (with size equal to req_depth*PtrSz!)
1520          */
1521         sz = hd->ioc->req_depth * sizeof(void *);
1522         mem = kmalloc(sz, GFP_ATOMIC);
1523         if (mem == NULL) {
1524                 error = -ENOMEM;
1525                 goto mptscsih_probe_failed;
1526         }
1527
1528         memset(mem, 0, sz);
1529         hd->ScsiLookup = (struct scsi_cmnd **) mem;
1530
1531         dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
1532                  ioc->name, hd->ScsiLookup, sz));
1533                 
1534         if (mptscsih_initChainBuffers(hd, 1) < 0) {
1535                 error = -EINVAL;
1536                 goto mptscsih_probe_failed;
1537         }
1538
1539         /* Allocate memory for free and doneQ's
1540          */
1541         sz = sh->can_queue * sizeof(MPT_DONE_Q);
1542         mem = kmalloc(sz, GFP_ATOMIC);
1543         if (mem == NULL) {
1544                 error = -ENOMEM;
1545                 goto mptscsih_probe_failed;
1546         }
1547
1548         memset(mem, 0xFF, sz);
1549         hd->memQ = mem;
1550
1551         /* Initialize the free, done and pending Qs.
1552          */
1553         Q_INIT(&hd->freeQ, MPT_DONE_Q);
1554         Q_INIT(&hd->doneQ, MPT_DONE_Q);
1555         Q_INIT(&hd->pendingQ, MPT_DONE_Q);
1556         spin_lock_init(&hd->freedoneQlock);
1557
1558         mem = hd->memQ;
1559         for (ii=0; ii < sh->can_queue; ii++) {
1560                 freedoneQ = (MPT_DONE_Q *) mem;
1561                 Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
1562                 mem += sizeof(MPT_DONE_Q);
1563         }
1564
1565         /* Initialize this Scsi_Host
1566          * internal task Q.
1567          */
1568         Q_INIT(&hd->taskQ, MPT_FRAME_HDR);
1569         hd->taskQcnt = 0;
1570                 
1571         /* Allocate memory for the device structures.
1572          * A non-Null pointer at an offset
1573          * indicates a device exists.
1574          * max_id = 1 + maximum id (hosts.h)
1575          */
1576         sz = sh->max_id * sizeof(void *);
1577         mem = kmalloc(sz, GFP_ATOMIC);
1578         if (mem == NULL) {
1579                 error = -ENOMEM;
1580                 goto mptscsih_probe_failed;
1581         }
1582
1583         memset(mem, 0, sz);
1584         hd->Targets = (VirtDevice **) mem;
1585
1586         dprintk((KERN_INFO
1587           "  Targets @ %p, sz=%d\n", hd->Targets, sz));
1588
1589         /* Clear the TM flags
1590          */
1591         hd->tmPending = 0;
1592         hd->tmState = TM_STATE_NONE;
1593         hd->resetPending = 0;
1594         hd->abortSCpnt = NULL;
1595         hd->tmPtr = NULL;
1596         hd->numTMrequests = 0;
1597                 
1598         /* Clear the pointer used to store
1599          * single-threaded commands, i.e., those
1600          * issued during a bus scan, dv and
1601          * configuration pages.
1602          */
1603         hd->cmdPtr = NULL;
1604
1605         /* Initialize this SCSI Hosts' timers
1606          * To use, set the timer expires field
1607          * and add_timer
1608          */
1609         init_timer(&hd->timer);
1610         hd->timer.data = (unsigned long) hd;
1611         hd->timer.function = mptscsih_timer_expired;
1612
1613         init_timer(&hd->TMtimer);
1614         hd->TMtimer.data = (unsigned long) hd;
1615         hd->TMtimer.function = mptscsih_taskmgmt_timeout;
1616         hd->qtag_tick = jiffies;
1617
1618         /* Moved Earlier Pam D */
1619         /* ioc->sh = sh;        */
1620
1621 #ifdef MPTSCSIH_DBG_TIMEOUT
1622         hd->ioc->timeout_hard = 0;
1623         hd->ioc->timeout_delta = 30 * HZ;
1624         hd->ioc->timeout_maxcnt = 0;
1625         hd->ioc->timeout_cnt = 0;
1626         for (ii=0; ii < 8; ii++)
1627                 foo_to[ii] = NULL;
1628 #endif
1629         if (hd->is_spi) {
1630                 /* Update with the driver setup
1631                  * values.
1632                  */
1633                 if (hd->ioc->spi_data.maxBusWidth >
1634                   driver_setup.max_width) {
1635                         hd->ioc->spi_data.maxBusWidth =
1636                           driver_setup.max_width;
1637                 }
1638
1639                 if (hd->ioc->spi_data.minSyncFactor <
1640                   driver_setup.min_sync_fac) {
1641                         hd->ioc->spi_data.minSyncFactor =
1642                           driver_setup.min_sync_fac;
1643                 }
1644
1645                 if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) {
1646                         hd->ioc->spi_data.maxSyncOffset = 0;
1647                 }
1648
1649                 hd->ioc->spi_data.Saf_Te = driver_setup.saf_te;
1650
1651                 hd->negoNvram = 0;
1652 #ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1653                 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1654 #endif
1655                 if (driver_setup.dv == 0) {
1656                         hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1657                 }
1658
1659                 hd->ioc->spi_data.forceDv = 0;
1660                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1661                         hd->ioc->spi_data.dvStatus[ii] =
1662                           MPT_SCSICFG_NEGOTIATE;
1663                 }
1664
1665                 if (hd->negoNvram == 0) {
1666                         for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
1667                                 hd->ioc->spi_data.dvStatus[ii] |=
1668                                   MPT_SCSICFG_DV_NOT_DONE;
1669                 }
1670
1671                 ddvprintk((MYIOC_s_INFO_FMT
1672                         "dv %x width %x factor %x saf_te %x\n",
1673                         hd->ioc->name, driver_setup.dv,
1674                         driver_setup.max_width,
1675                         driver_setup.min_sync_fac,
1676                         driver_setup.saf_te));
1677         }
1678
1679         mpt_scsi_hosts++;
1680
1681         error = scsi_add_host (sh, &ioc->pcidev->dev);
1682         if(error) {
1683                 dprintk((KERN_ERR MYNAM
1684                   "scsi_add_host failed\n"));
1685                 goto mptscsih_probe_failed;
1686         }
1687
1688         scsi_scan_host(sh);
1689         return 0;
1690
1691 mptscsih_probe_failed:
1692
1693         mptscsih_remove(pdev);
1694         return error;
1695
1696 }
1697
1698 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1699 /*
1700  *      mptscsih_remove - Removed scsi devices
1701  *      @pdev: Pointer to pci_dev structure
1702  *
1703  *
1704  */
1705 static void
1706 mptscsih_remove(struct pci_dev *pdev)
1707 {
1708         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
1709         struct Scsi_Host        *host = ioc->sh;
1710         MPT_SCSI_HOST           *hd;
1711         int                     count;
1712         unsigned long           flags;
1713
1714         if(!host)
1715                 return;
1716
1717         scsi_remove_host(host);
1718
1719 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1720         /* Check DV thread active */
1721         count = 10 * HZ;
1722         spin_lock_irqsave(&dvtaskQ_lock, flags);
1723         if (dvtaskQ_active) {
1724                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1725                 while(dvtaskQ_active && --count) {
1726                         set_current_state(TASK_INTERRUPTIBLE);
1727                         schedule_timeout(1);
1728                 }
1729         } else {
1730                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1731         }
1732         if (!count)
1733                 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
1734 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
1735         else
1736                 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
1737 #endif
1738 #endif
1739
1740         hd = (MPT_SCSI_HOST *)host->hostdata;
1741         if (hd != NULL) {
1742                 int sz1, sz2, sz3, sztarget=0;
1743                 int szr2chain = 0;
1744                 int szc2chain = 0;
1745                 int szQ = 0;
1746
1747                 mptscsih_shutdown(&pdev->dev);
1748
1749                 sz1 = sz2 = sz3 = 0;
1750
1751                 if (hd->ScsiLookup != NULL) {
1752                         sz1 = hd->ioc->req_depth * sizeof(void *);
1753                         kfree(hd->ScsiLookup);
1754                         hd->ScsiLookup = NULL;
1755                 }
1756
1757                 if (hd->ReqToChain != NULL) {
1758                         szr2chain = hd->ioc->req_depth * sizeof(int);
1759                         kfree(hd->ReqToChain);
1760                         hd->ReqToChain = NULL;
1761                 }
1762
1763                 if (hd->ChainToChain != NULL) {
1764                         szc2chain = hd->num_chain * sizeof(int);
1765                         kfree(hd->ChainToChain);
1766                         hd->ChainToChain = NULL;
1767                 }
1768
1769                 if (hd->memQ != NULL) {
1770                         szQ = host->can_queue * sizeof(MPT_DONE_Q);
1771                         kfree(hd->memQ);
1772                         hd->memQ = NULL;
1773                 }
1774
1775                 if (hd->Targets != NULL) {
1776                         int max, ii;
1777
1778                         /*
1779                          * Free any target structures that were allocated.
1780                          */
1781                         if (hd->is_spi) {
1782                                 max = MPT_MAX_SCSI_DEVICES;
1783                         } else {
1784                                 max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1785                         }
1786                         for (ii=0; ii < max; ii++) {
1787                                 if (hd->Targets[ii]) {
1788                                         kfree(hd->Targets[ii]);
1789                                         hd->Targets[ii] = NULL;
1790                                         sztarget += sizeof(VirtDevice);
1791                                 }
1792                         }
1793
1794                         /*
1795                          * Free pointer array.
1796                          */
1797                         sz3 = max * sizeof(void *);
1798                         kfree(hd->Targets);
1799                         hd->Targets = NULL;
1800                 }
1801
1802                 dprintk((MYIOC_s_INFO_FMT
1803                   "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",
1804                   hd->ioc->name, sz1, szchain, sz3, sztarget));
1805                 dprintk(("Free'd done and free Q (%d) memory\n", szQ));
1806
1807                 /* NULL the Scsi_Host pointer
1808                  */
1809                 hd->ioc->sh = NULL;
1810         }
1811
1812         scsi_host_put(host);
1813         mpt_scsi_hosts--;
1814
1815 }
1816
1817 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1818 /*
1819  *      mptscsih_shutdown - reboot notifier
1820  *
1821  */
1822 static void
1823 mptscsih_shutdown(struct device * dev)
1824 {
1825         MPT_ADAPTER             *ioc = pci_get_drvdata(to_pci_dev(dev));
1826         struct Scsi_Host        *host = ioc->sh;
1827         MPT_SCSI_HOST           *hd;
1828
1829         if(!host)
1830                 return;
1831
1832         hd = (MPT_SCSI_HOST *)host->hostdata;
1833
1834         /* Flush the cache of this adapter
1835          */
1836         if(hd != NULL)
1837                 mptscsih_synchronize_cache(hd, 0);
1838
1839 }
1840
1841 #ifdef CONFIG_PM
1842 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1843 /*
1844  *      mptscsih_suspend - Fusion MPT scsie driver suspend routine.
1845  *
1846  *
1847  */
1848 static int
1849 mptscsih_suspend(struct pci_dev *pdev, u32 state)
1850 {
1851         mptscsih_shutdown(&pdev->dev);
1852         return 0;
1853 }
1854
1855 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1856 /*
1857  *      mptscsih_resume - Fusion MPT scsi driver resume routine.
1858  *
1859  *
1860  */
1861 static int
1862 mptscsih_resume(struct pci_dev *pdev)
1863 {
1864         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
1865         struct Scsi_Host        *host = ioc->sh;
1866         MPT_SCSI_HOST           *hd;
1867
1868         if(!host)
1869                 return 0;
1870
1871         hd = (MPT_SCSI_HOST *)host->hostdata;
1872         if(!hd)
1873                 return 0;
1874
1875 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1876         {
1877         unsigned long lflags;
1878         spin_lock_irqsave(&dvtaskQ_lock, lflags);
1879         if (!dvtaskQ_active) {
1880                 dvtaskQ_active = 1;
1881                 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1882                 MPT_INIT_WORK(&mptscsih_dvTask,
1883                   mptscsih_domainValidation, (void *) hd);
1884                 SCHEDULE_TASK(&mptscsih_dvTask);
1885         } else {
1886                 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1887         }
1888         }
1889 #endif
1890         return 0;
1891 }
1892
1893 #endif
1894
1895 static struct mpt_pci_driver mptscsih_driver = {
1896         .probe          = mptscsih_probe,
1897         .remove         = mptscsih_remove,
1898         .shutdown       = mptscsih_shutdown,
1899 #ifdef CONFIG_PM
1900         .suspend        = mptscsih_suspend,
1901         .resume         = mptscsih_resume,
1902 #endif
1903 };
1904
1905
1906 /*  SCSI host fops start here...  */
1907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1908 /**
1909  *      mptscsih_init - Register MPT adapter(s) as SCSI host(s) with
1910  *      linux scsi mid-layer.
1911  *
1912  *      Returns 0 for success, non-zero for failure.
1913  */
1914 static int __init
1915 mptscsih_init(void)
1916 {
1917
1918         show_mptmod_ver(my_NAME, my_VERSION);
1919
1920         ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
1921         ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
1922         ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
1923
1924         if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
1925                 dprintk((KERN_INFO MYNAM
1926                   ": Registered for IOC event notifications\n"));
1927         }
1928
1929         if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
1930                 dprintk((KERN_INFO MYNAM
1931                   ": Registered for IOC reset notifications\n"));
1932         }
1933
1934 #ifdef MODULE
1935         /* Evaluate the command line arguments, if any */
1936         if (mptscsih)
1937                 mptscsih_setup(mptscsih);
1938 #endif
1939
1940         if(mpt_device_driver_register(&mptscsih_driver,
1941           MPTSCSIH_DRIVER) != 0 ) {
1942                 dprintk((KERN_INFO MYNAM
1943                 ": failed to register dd callbacks\n"));
1944         }
1945
1946         return 0;
1947
1948 }
1949
1950 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1951 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1952 /**
1953  *      mptscsih_exit - Unregisters MPT adapter(s)
1954  *
1955  */
1956 static void __exit
1957 mptscsih_exit(void)
1958 {
1959         MPT_ADAPTER     *ioc;
1960
1961         /* removing devices */
1962         for(ioc = mpt_adapter_find_first(); ioc != NULL;
1963           ioc = mpt_adapter_find_next(ioc)) {
1964                 if ((ioc->last_state != MPI_IOC_STATE_OPERATIONAL) ||
1965                   (ioc->sh == NULL))
1966                         continue;
1967                 mptscsih_remove(ioc->pcidev);
1968         }
1969
1970         mpt_reset_deregister(ScsiDoneCtx);
1971         dprintk((KERN_INFO MYNAM
1972           ": Deregistered for IOC reset notifications\n"));
1973
1974         mpt_event_deregister(ScsiDoneCtx);
1975         dprintk((KERN_INFO MYNAM
1976           ": Deregistered for IOC event notifications\n"));
1977
1978         mpt_device_driver_deregister(MPTSCSIH_DRIVER);
1979         mpt_deregister(ScsiScanDvCtx);
1980         mpt_deregister(ScsiTaskCtx);
1981         mpt_deregister(ScsiDoneCtx);
1982
1983         if (info_kbuf != NULL)
1984                 kfree(info_kbuf);
1985
1986 }
1987
1988 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1989 /**
1990  *      mptscsih_info - Return information about MPT adapter
1991  *      @SChost: Pointer to Scsi_Host structure
1992  *
1993  *      (linux Scsi_Host_Template.info routine)
1994  *
1995  *      Returns pointer to buffer where information was written.
1996  */
1997 const char *
1998 mptscsih_info(struct Scsi_Host *SChost)
1999 {
2000         MPT_SCSI_HOST *h;
2001         int size = 0;
2002
2003         if (info_kbuf == NULL)
2004                 if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
2005                         return info_kbuf;
2006
2007         h = (MPT_SCSI_HOST *)SChost->hostdata;
2008         info_kbuf[0] = '\0';
2009         if (h) {
2010                 mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
2011                 info_kbuf[size-1] = '\0';
2012         }
2013
2014         return info_kbuf;
2015 }
2016
2017 struct info_str {
2018         char *buffer;
2019         int   length;
2020         int   offset;
2021         int   pos;
2022 };
2023
2024 static void copy_mem_info(struct info_str *info, char *data, int len)
2025 {
2026         if (info->pos + len > info->length)
2027                 len = info->length - info->pos;
2028
2029         if (info->pos + len < info->offset) {
2030                 info->pos += len;
2031                 return;
2032         }
2033
2034         if (info->pos < info->offset) {
2035                 data += (info->offset - info->pos);
2036                 len  -= (info->offset - info->pos);
2037         }
2038
2039         if (len > 0) {
2040                 memcpy(info->buffer + info->pos, data, len);
2041                 info->pos += len;
2042         }
2043 }
2044
2045 static int copy_info(struct info_str *info, char *fmt, ...)
2046 {
2047         va_list args;
2048         char buf[81];
2049         int len;
2050
2051         va_start(args, fmt);
2052         len = vsprintf(buf, fmt, args);
2053         va_end(args);
2054
2055         copy_mem_info(info, buf, len);
2056         return len;
2057 }
2058
2059 static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
2060 {
2061         struct info_str info;
2062
2063         info.buffer     = pbuf;
2064         info.length     = len;
2065         info.offset     = offset;
2066         info.pos        = 0;
2067
2068         copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
2069         copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
2070         copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
2071         copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
2072
2073         return ((info.pos > info.offset) ? info.pos - info.offset : 0);
2074 }
2075
2076 #ifndef MPTSCSIH_DBG_TIMEOUT
2077 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len)
2078 {
2079         /* Not yet implemented */
2080         return len;
2081 }
2082 #else
2083 #define is_digit(c)     ((c) >= '0' && (c) <= '9')
2084 #define digit_to_bin(c) ((c) - '0')
2085 #define is_space(c)     ((c) == ' ' || (c) == '\t')
2086
2087 #define UC_DBG_TIMEOUT          0x01
2088 #define UC_DBG_HARDRESET        0x02
2089
2090 static int skip_spaces(char *ptr, int len)
2091 {
2092         int cnt, c;
2093
2094         for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --);
2095
2096         return (len - cnt);
2097 }
2098
2099 static int get_int_arg(char *ptr, int len, ulong *pv)
2100 {
2101         int cnt, c;
2102         ulong   v;
2103         for (v =  0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) {
2104                 v = (v * 10) + digit_to_bin(c);
2105         }
2106
2107         if (pv)
2108                 *pv = v;
2109
2110         return (len - cnt);
2111 }
2112
2113
2114 static int is_keyword(char *ptr, int len, char *verb)
2115 {
2116         int verb_len = strlen(verb);
2117
2118         if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))
2119                 return verb_len;
2120         else
2121                 return 0;
2122 }
2123
2124 #define SKIP_SPACES(min_spaces)                                         \
2125         if ((arg_len = skip_spaces(ptr,len)) < (min_spaces))            \
2126                 return -EINVAL;                                         \
2127         ptr += arg_len;                                                 \
2128         len -= arg_len;
2129
2130 #define GET_INT_ARG(v)                                                  \
2131         if (!(arg_len = get_int_arg(ptr,len, &(v))))                    \
2132                 return -EINVAL;                                         \
2133         ptr += arg_len;                                                 \
2134         len -= arg_len;
2135
2136 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length)
2137 {
2138         char *ptr = buffer;
2139         char btmp[24];  /* REMOVE */
2140         int arg_len;
2141         int len = length;
2142         int cmd;
2143         ulong number = 1;
2144         ulong delta = 10;
2145
2146         if ((len > 0) && (ptr[len -1] == '\n'))
2147                 --len;
2148
2149         if (len < 22) {
2150                 strncpy(btmp, buffer, len);
2151                 btmp[len+1]='\0';
2152         } else {
2153                 strncpy(btmp, buffer, 22);
2154                 btmp[23]='\0';
2155         }
2156         printk("user_command:  ioc %d, buffer %s, length %d\n",
2157                         ioc->id, btmp, length);
2158
2159         if ((arg_len = is_keyword(ptr, len, "timeout")) != 0)
2160                 cmd = UC_DBG_TIMEOUT;
2161         else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0)
2162                 cmd = UC_DBG_HARDRESET;
2163         else
2164                 return -EINVAL;
2165
2166         ptr += arg_len;
2167         len -= arg_len;
2168
2169         switch(cmd) {
2170                 case UC_DBG_TIMEOUT:
2171                         SKIP_SPACES(1);
2172                         GET_INT_ARG(number);
2173                         SKIP_SPACES(1);
2174                         GET_INT_ARG(delta);
2175                         break;
2176         }
2177
2178         printk("user_command: cnt=%ld delta=%ld\n", number, delta);
2179
2180         if (len)
2181                 return -EINVAL;
2182         else {
2183                 if (cmd == UC_DBG_HARDRESET) {
2184                         ioc->timeout_hard = 1;
2185                 } else if (cmd == UC_DBG_TIMEOUT) {
2186                         /* process this command ...
2187                          */
2188                         ioc->timeout_maxcnt = 0;
2189                         ioc->timeout_delta = delta < 2 ? 2 : delta;
2190                         ioc->timeout_cnt = 0;
2191                         ioc->timeout_maxcnt = number < 8 ? number: 8;
2192                 }
2193         }
2194         /* Not yet implemented */
2195         return length;
2196 }
2197 #endif
2198
2199 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2200 /**
2201  *      mptscsih_proc_info - Return information about MPT adapter
2202  *
2203  *      (linux Scsi_Host_Template.info routine)
2204  *
2205  *      buffer: if write, user data; if read, buffer for user
2206  *      length: if write, return length;
2207  *      offset: if write, 0; if read, the current offset into the buffer from
2208  *              the previous read.
2209  *      hostno: scsi host number
2210  *      func:   if write = 1; if read = 0
2211  */
2212 int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
2213                         int length, int func)
2214 {
2215         MPT_ADAPTER     *ioc;
2216         MPT_SCSI_HOST   *hd = NULL;
2217         int size = 0;
2218
2219         dprintk(("Called mptscsih_proc_info: hostno=%d, func=%d\n", host->host_no, func));
2220         dprintk(("buffer %p, start=%p (%p) offset=%ld length = %d\n",
2221                         buffer, start, *start, offset, length));
2222
2223         for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
2224                 if ((ioc->sh) && (ioc->sh == host)) {
2225                         hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2226                         break;
2227                 }
2228         }
2229         if ((ioc == NULL) || (ioc->sh == NULL) || (hd == NULL))
2230                 return 0;
2231
2232         if (func) {
2233                 size = mptscsih_user_command(ioc, buffer, length);
2234         } else {
2235                 if (start)
2236                         *start = buffer;
2237
2238                 size = mptscsih_host_info(ioc, buffer, offset, length);
2239         }
2240
2241         return size;
2242 }
2243
2244
2245 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2246 #define ADD_INDEX_LOG(req_ent)  do { } while(0)
2247
2248 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2249 /**
2250  *      mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
2251  *      @SCpnt: Pointer to Scsi_Cmnd structure
2252  *      @done: Pointer SCSI mid-layer IO completion function
2253  *
2254  *      (linux Scsi_Host_Template.queuecommand routine)
2255  *      This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest
2256  *      from a linux Scsi_Cmnd request and send it to the IOC.
2257  *
2258  *      Returns 0. (rtn value discarded by linux scsi mid-layer)
2259  */
2260 int
2261 mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2262 {
2263         MPT_SCSI_HOST           *hd;
2264         MPT_FRAME_HDR           *mf;
2265         SCSIIORequest_t         *pScsiReq;
2266         VirtDevice              *pTarget;
2267         MPT_DONE_Q              *buffer;
2268         unsigned long            flags;
2269         int      target;
2270         int      lun;
2271         int      datadir;
2272         u32      datalen;
2273         u32      scsictl;
2274         u32      scsidir;
2275         u32      cmd_len;
2276         int      my_idx;
2277         int      ii;
2278         int      rc;
2279         int      did_errcode;
2280         int      issueCmd;
2281
2282         did_errcode = 0;
2283         hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
2284         target = SCpnt->device->id;
2285         lun = SCpnt->device->lun;
2286         SCpnt->scsi_done = done;
2287
2288         pTarget = hd->Targets[target];
2289
2290         dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
2291                         (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
2292
2293         if (hd->resetPending) {
2294                 /* Prevent new commands from being issued
2295                  * while reloading the FW. Reset timer to 60 seconds,
2296                  * as the FW can take some time to come ready.
2297                  * For New EH, cmds on doneQ posted to FW.
2298                  */
2299                 did_errcode = 1;
2300                 mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));
2301                 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
2302                         (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2303                 goto did_error;
2304         }
2305
2306         /*
2307          *  Put together a MPT SCSI request...
2308          */
2309         if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
2310                 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
2311                                 hd->ioc->name));
2312                 did_errcode = 2;
2313                 goto did_error;
2314         }
2315
2316         pScsiReq = (SCSIIORequest_t *) mf;
2317
2318         my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2319
2320         ADD_INDEX_LOG(my_idx);
2321
2322         /*
2323          *  The scsi layer should be handling this stuff
2324          *  (In 2.3.x it does -DaveM)
2325          */
2326
2327         /*  BUG FIX!  19991030 -sralston
2328          *    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
2329          *    Seems we may receive a buffer (datalen>0) even when there
2330          *    will be no data transfer!  GRRRRR...
2331          */
2332         datadir = mptscsih_io_direction(SCpnt);
2333         if (datadir == SCSI_DATA_READ) {
2334                 datalen = SCpnt->request_bufflen;
2335                 scsidir = MPI_SCSIIO_CONTROL_READ;      /* DATA IN  (host<--ioc<--dev) */
2336         } else if (datadir == SCSI_DATA_WRITE) {
2337                 datalen = SCpnt->request_bufflen;
2338                 scsidir = MPI_SCSIIO_CONTROL_WRITE;     /* DATA OUT (host-->ioc-->dev) */
2339         } else {
2340                 datalen = 0;
2341                 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
2342         }
2343
2344         /* Default to untagged. Once a target structure has been allocated,
2345          * use the Inquiry data to determine if device supports tagged.
2346          */
2347         if (   pTarget
2348             && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
2349             && (SCpnt->device->tagged_supported)) {
2350                 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
2351         } else {
2352                 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
2353         }
2354
2355         /* Use the above information to set up the message frame
2356          */
2357         pScsiReq->TargetID = (u8) target;
2358         pScsiReq->Bus = (u8) SCpnt->device->channel;
2359         pScsiReq->ChainOffset = 0;
2360         pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
2361         pScsiReq->CDBLength = SCpnt->cmd_len;
2362         pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2363         pScsiReq->Reserved = 0;
2364         pScsiReq->MsgFlags = mpt_msg_flags();
2365         pScsiReq->LUN[0] = 0;
2366         pScsiReq->LUN[1] = lun;
2367         pScsiReq->LUN[2] = 0;
2368         pScsiReq->LUN[3] = 0;
2369         pScsiReq->LUN[4] = 0;
2370         pScsiReq->LUN[5] = 0;
2371         pScsiReq->LUN[6] = 0;
2372         pScsiReq->LUN[7] = 0;
2373         pScsiReq->Control = cpu_to_le32(scsictl);
2374
2375         /*
2376          *  Write SCSI CDB into the message
2377          */
2378         cmd_len = SCpnt->cmd_len;
2379         for (ii=0; ii < cmd_len; ii++)
2380                 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
2381
2382         for (ii=cmd_len; ii < 16; ii++)
2383                 pScsiReq->CDB[ii] = 0;
2384
2385         /* DataLength */
2386         pScsiReq->DataLength = cpu_to_le32(datalen);
2387
2388         /* SenseBuffer low address */
2389         pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
2390                                            + (my_idx * MPT_SENSE_BUFFER_ALLOC));
2391
2392         /* Now add the SG list
2393          * Always have a SGE even if null length.
2394          */
2395         rc = SUCCESS;
2396         if (datalen == 0) {
2397                 /* Add a NULL SGE */
2398                 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
2399                         (dma_addr_t) -1);
2400         } else {
2401                 /* Add a 32 or 64 bit SGE */
2402                 rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
2403         }
2404
2405
2406         if (rc == SUCCESS) {
2407                 hd->ScsiLookup[my_idx] = SCpnt;
2408                 SCpnt->host_scribble = NULL;
2409
2410                 /* SCSI specific processing */
2411                 issueCmd = 1;
2412                 if (hd->is_spi) {
2413                         int dvStatus = hd->ioc->spi_data.dvStatus[target];
2414
2415                         if (dvStatus || hd->ioc->spi_data.forceDv) {
2416
2417                                 /* Write SDP1 on this I/O to this target */
2418                                 if (dvStatus & MPT_SCSICFG_NEGOTIATE) {
2419                                         mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);
2420                                         dvStatus &= ~MPT_SCSICFG_NEGOTIATE;
2421                                         hd->ioc->spi_data.dvStatus[target] =  dvStatus;
2422                                 } else if (dvStatus & MPT_SCSICFG_BLK_NEGO) {
2423                                         mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO);
2424                                         dvStatus &= ~MPT_SCSICFG_BLK_NEGO;
2425                                         hd->ioc->spi_data.dvStatus[target] =  dvStatus;
2426                                 }
2427
2428 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2429                                 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
2430                                         (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
2431                                         unsigned long lflags;
2432                                         /* Schedule DV if necessary */
2433                                         spin_lock_irqsave(&dvtaskQ_lock, lflags);
2434                                         if (!dvtaskQ_active) {
2435                                                 dvtaskQ_active = 1;
2436                                                 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2437                                                 MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
2438
2439                                                 SCHEDULE_TASK(&mptscsih_dvTask);
2440                                         } else {
2441                                                 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2442                                         }
2443                                         hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
2444                                 }
2445
2446                                 /* Trying to do DV to this target, extend timeout.
2447                                  * Wait to issue intil flag is clear
2448                                  */
2449                                 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
2450                                         mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
2451                                         issueCmd = 0;
2452                                 }
2453
2454                                 /* Set the DV flags.
2455                                  */
2456                                 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
2457                                         mptscsih_set_dvflags(hd, pScsiReq);
2458 #endif
2459                         }
2460                 }
2461
2462 #ifdef MPTSCSIH_DBG_TIMEOUT
2463                 if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) {
2464                         foo_to[hd->ioc->timeout_cnt] = SCpnt;
2465                         hd->ioc->timeout_cnt++;
2466                         //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta);
2467                         issueCmd = 0;
2468                         printk(MYIOC_s_WARN_FMT
2469                                 "to pendingQ: (sc=%p, mf=%p, time=%ld)\n",
2470                                 hd->ioc->name, SCpnt, mf, jiffies);
2471                 }
2472 #endif
2473
2474                 if (issueCmd) {
2475                         mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2476                         dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
2477                                         hd->ioc->name, SCpnt, mf, my_idx));
2478                 } else {
2479                         ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",
2480                                         hd->ioc->name, SCpnt, my_idx));
2481                         /* Place this command on the pendingQ if possible */
2482                         spin_lock_irqsave(&hd->freedoneQlock, flags);
2483                         if (!Q_IS_EMPTY(&hd->freeQ)) {
2484                                 buffer = hd->freeQ.head;
2485                                 Q_DEL_ITEM(buffer);
2486
2487                                 /* Save the mf pointer
2488                                  */
2489                                 buffer->argp = (void *)mf;
2490
2491                                 /* Add to the pendingQ
2492                                  */
2493                                 Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);
2494                                 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2495                         } else {
2496                                 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2497                                 SCpnt->result = (DID_BUS_BUSY << 16);
2498                                 SCpnt->scsi_done(SCpnt);
2499                         }
2500                 }
2501         } else {
2502                 mptscsih_freeChainBuffers(hd, my_idx);
2503                 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2504                 did_errcode = 3;
2505                 goto did_error;
2506         }
2507
2508         return 0;
2509
2510 did_error:
2511         dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n",
2512                         hd->ioc->name, did_errcode, SCpnt));
2513         /* Just wish OS to issue a retry */
2514         SCpnt->result = (DID_BUS_BUSY << 16);
2515         spin_lock_irqsave(&hd->freedoneQlock, flags);
2516         if (!Q_IS_EMPTY(&hd->freeQ)) {
2517                 dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n",
2518                         (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2519                 buffer = hd->freeQ.head;
2520                 Q_DEL_ITEM(buffer);
2521
2522                 /* Set the Scsi_Cmnd pointer
2523                  */
2524                 buffer->argp = (void *)SCpnt;
2525
2526                 /* Add to the doneQ
2527                  */
2528                 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
2529                 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2530         } else {
2531                 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2532                 SCpnt->scsi_done(SCpnt);
2533         }
2534
2535         return 0;
2536 }
2537
2538 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2539 /*
2540  *      mptscsih_freeChainBuffers - Function to free chain buffers associated
2541  *      with a SCSI IO request
2542  *      @hd: Pointer to the MPT_SCSI_HOST instance
2543  *      @req_idx: Index of the SCSI IO request frame.
2544  *
2545  *      Called if SG chain buffer allocation fails and mptscsih callbacks.
2546  *      No return.
2547  */
2548 static void
2549 mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
2550 {
2551         MPT_FRAME_HDR *chain;
2552         unsigned long flags;
2553         int chain_idx;
2554         int next;
2555
2556         /* Get the first chain index and reset
2557          * tracker state.
2558          */
2559         chain_idx = hd->ReqToChain[req_idx];
2560         hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
2561
2562         while (chain_idx != MPT_HOST_NO_CHAIN) {
2563
2564                 /* Save the next chain buffer index */
2565                 next = hd->ChainToChain[chain_idx];
2566
2567                 /* Free this chain buffer and reset
2568                  * tracker
2569                  */
2570                 hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
2571
2572                 chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
2573                                         + (chain_idx * hd->ioc->req_sz));
2574                 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2575                 Q_ADD_TAIL(&hd->FreeChainQ.head,
2576                                         &chain->u.frame.linkage, MPT_FRAME_HDR);
2577                 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2578
2579                 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
2580                                 hd->ioc->name, chain_idx));
2581
2582                 /* handle next */
2583                 chain_idx = next;
2584         }
2585         return;
2586 }
2587
2588 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2589 /*
2590  *      Reset Handling
2591  */
2592
2593 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2594 /*
2595  *      mptscsih_TMHandler - Generic handler for SCSI Task Management.
2596  *      Fall through to mpt_HardResetHandler if: not operational, too many
2597  *      failed TM requests or handshake failure.
2598  *
2599  *      @ioc: Pointer to MPT_ADAPTER structure
2600  *      @type: Task Management type
2601  *      @target: Logical Target ID for reset (if appropriate)
2602  *      @lun: Logical Unit for reset (if appropriate)
2603  *      @ctx2abort: Context for the task to be aborted (if appropriate)
2604  *      @sleepFlag: If set, use udelay instead of schedule in handshake code.
2605  *
2606  *      Remark: Currently invoked from a non-interrupt thread (_bh).
2607  *
2608  *      Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
2609  *      will be active.
2610  *
2611  *      Returns 0 for SUCCESS or -1 if FAILED.
2612  */
2613 static int
2614 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
2615 {
2616         MPT_ADAPTER     *ioc;
2617         int              rc = -1;
2618         int              doTask = 1;
2619         u32              ioc_raw_state;
2620         unsigned long    flags;
2621
2622         /* If FW is being reloaded currently, return success to
2623          * the calling function.
2624          */
2625         if (hd == NULL)
2626                 return 0;
2627
2628         ioc = hd->ioc;
2629         if (ioc == NULL) {
2630                 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
2631                 return FAILED;
2632         }
2633         dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
2634
2635         // SJR - CHECKME - Can we avoid this here?
2636         // (mpt_HardResetHandler has this check...)
2637         spin_lock_irqsave(&ioc->diagLock, flags);
2638         if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
2639                 spin_unlock_irqrestore(&ioc->diagLock, flags);
2640                 return FAILED;
2641         }
2642         spin_unlock_irqrestore(&ioc->diagLock, flags);
2643
2644         /* Do not do a Task Management if there are
2645          * too many failed TMs on this adapter.
2646          */
2647         if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM)
2648                 doTask = 0;
2649
2650         /*  Wait a fixed amount of time for the TM pending flag to be cleared.
2651          *  If we time out and not bus reset, then we return a FAILED status to the caller.
2652          *  The call to mptscsih_tm_pending_wait() will set the pending flag if we are
2653          *  successful. Otherwise, reload the FW.
2654          */
2655         if (mptscsih_tm_pending_wait(hd) == FAILED) {
2656                 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
2657                         dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
2658                            "Timed out waiting for last TM (%d) to complete! \n",
2659                            hd->ioc->name, hd->tmPending));
2660                         return FAILED;
2661                 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
2662                         dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
2663                            "Timed out waiting for last TM (%d) to complete! \n",
2664                            hd->ioc->name, hd->tmPending));
2665                         return FAILED;
2666                 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2667                         dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
2668                            "Timed out waiting for last TM (%d) to complete! \n",
2669                            hd->ioc->name, hd->tmPending));
2670                         if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
2671                                 return FAILED;
2672
2673                         doTask = 0;
2674                 }
2675         } else {
2676                 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2677                 hd->tmPending |=  (1 << type);
2678                 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2679         }
2680
2681         /* Is operational?
2682          */
2683         ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
2684
2685 #ifdef MPT_DEBUG_RESET
2686         if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
2687                 printk(MYIOC_s_WARN_FMT
2688                         "TM Handler: IOC Not operational(0x%x)!\n",
2689                         hd->ioc->name, ioc_raw_state);
2690         }
2691 #endif
2692
2693         if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
2694                                 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
2695
2696                 /* Isse the Task Mgmt request.
2697                  */
2698                 if (hd->hard_resets < -1)
2699                         hd->hard_resets++;
2700                 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag);
2701                 if (rc) {
2702                         printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
2703                 } else {
2704                         dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
2705                 }
2706         }
2707
2708 #ifdef MPTSCSIH_DBG_TIMEOUT
2709         if (hd->ioc->timeout_hard)
2710                 rc = 1;
2711 #endif
2712
2713         /* Only fall through to the HRH if this is a bus reset
2714          */
2715         if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
2716                 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
2717                 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
2718                          hd->ioc->name));
2719                 rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
2720         }
2721
2722         dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
2723
2724         return rc;
2725 }
2726
2727
2728 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2729 /*
2730  *      mptscsih_IssueTaskMgmt - Generic send Task Management function.
2731  *      @hd: Pointer to MPT_SCSI_HOST structure
2732  *      @type: Task Management type
2733  *      @target: Logical Target ID for reset (if appropriate)
2734  *      @lun: Logical Unit for reset (if appropriate)
2735  *      @ctx2abort: Context for the task to be aborted (if appropriate)
2736  *      @sleepFlag: If set, use udelay instead of schedule in handshake code.
2737  *
2738  *      Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
2739  *      or a non-interrupt thread.  In the former, must not call schedule().
2740  *
2741  *      Not all fields are meaningfull for all task types.
2742  *
2743  *      Returns 0 for SUCCESS, -999 for "no msg frames",
2744  *      else other non-zero value returned.
2745  */
2746 static int
2747 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
2748 {
2749         MPT_FRAME_HDR   *mf;
2750         SCSITaskMgmt_t  *pScsiTm;
2751         int              ii;
2752         int              retval;
2753
2754         /* Return Fail to calling function if no message frames available.
2755          */
2756         if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
2757                 dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
2758                                 hd->ioc->name));
2759                 //return FAILED;
2760                 return -999;
2761         }
2762         dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
2763                         hd->ioc->name, mf));
2764
2765         /* Format the Request
2766          */
2767         pScsiTm = (SCSITaskMgmt_t *) mf;
2768         pScsiTm->TargetID = target;
2769         pScsiTm->Bus = channel;
2770         pScsiTm->ChainOffset = 0;
2771         pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
2772
2773         pScsiTm->Reserved = 0;
2774         pScsiTm->TaskType = type;
2775         pScsiTm->Reserved1 = 0;
2776         pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
2777                             ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
2778
2779         for (ii= 0; ii < 8; ii++) {
2780                 pScsiTm->LUN[ii] = 0;
2781         }
2782         pScsiTm->LUN[1] = lun;
2783
2784         for (ii=0; ii < 7; ii++)
2785                 pScsiTm->Reserved2[ii] = 0;
2786
2787         pScsiTm->TaskMsgContext = ctx2abort;
2788         dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n",
2789                         hd->ioc->name, ctx2abort, type));
2790
2791         /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
2792                 mpt_put_msg_frame(hd->ioc->id, mf);
2793         * Save the MF pointer in case the request times out.
2794         */
2795         hd->tmPtr = mf;
2796         hd->numTMrequests++;
2797         hd->TMtimer.expires = jiffies + timeout;
2798         add_timer(&hd->TMtimer);
2799
2800         if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
2801                                 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
2802         != 0) {
2803                 dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
2804                         " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
2805                 hd->numTMrequests--;
2806                 hd->tmPtr = NULL;
2807                 del_timer(&hd->TMtimer);
2808                 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
2809         }
2810
2811         return retval;
2812 }
2813
2814 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2815 /**
2816  *      mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
2817  *      @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
2818  *
2819  *      (linux Scsi_Host_Template.eh_abort_handler routine)
2820  *
2821  *      Returns SUCCESS or FAILED.
2822  */
2823 int
2824 mptscsih_abort(Scsi_Cmnd * SCpnt)
2825 {
2826         MPT_SCSI_HOST   *hd;
2827         MPT_FRAME_HDR   *mf;
2828         u32              ctx2abort;
2829         int              scpnt_idx;
2830         spinlock_t      *host_lock = SCpnt->device->host->host_lock;
2831
2832         /* If we can't locate our host adapter structure, return FAILED status.
2833          */
2834         if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
2835                 SCpnt->result = DID_RESET << 16;
2836                 SCpnt->scsi_done(SCpnt);
2837                 dtmprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
2838                            "Can't locate host! (sc=%p)\n",
2839                            SCpnt));
2840                 return FAILED;
2841         }
2842
2843         if (hd->resetPending)
2844                 return FAILED;
2845
2846         printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
2847                hd->ioc->name, SCpnt);
2848
2849         if (hd->timeouts < -1)
2850                 hd->timeouts++;
2851
2852         /* Find this command
2853          */
2854         if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
2855                 /* Cmd not found in ScsiLookup. If found in
2856                  * doneQ, delete from Q. Do OS callback.
2857                  */
2858                 search_doneQ_for_cmd(hd, SCpnt);
2859
2860                 SCpnt->result = DID_RESET << 16;
2861                 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
2862                            "Command not in the active list! (sc=%p)\n",
2863                            hd->ioc->name, SCpnt));
2864                 return SUCCESS;
2865         }
2866
2867         /* If this command is pended, then timeout/hang occurred
2868          * during DV. Post command and flush pending Q
2869          * and then following up with the reset request.
2870          */
2871         if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
2872                 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2873                 post_pendingQ_commands(hd);
2874                 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
2875                            "Posting pended cmd! (sc=%p)\n",
2876                            hd->ioc->name, SCpnt));
2877         }
2878
2879         /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
2880          * (the IO to be ABORT'd)
2881          *
2882          * NOTE: Since we do not byteswap MsgContext, we do not
2883          *       swap it here either.  It is an opaque cookie to
2884          *       the controller, so it does not matter. -DaveM
2885          */
2886         mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
2887         ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
2888
2889         hd->abortSCpnt = SCpnt;
2890
2891         spin_unlock_irq(host_lock);
2892         if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
2893                 SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
2894                 ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP)
2895                 < 0) {
2896
2897                 /* The TM request failed and the subsequent FW-reload failed!
2898                  * Fatal error case.
2899                  */
2900                 printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
2901                        hd->ioc->name, SCpnt);
2902
2903                 /* We must clear our pending flag before clearing our state.
2904                  */
2905                 hd->tmPending = 0;
2906                 hd->tmState = TM_STATE_NONE;
2907
2908                 spin_lock_irq(host_lock);
2909                 return FAILED;
2910         }
2911         spin_lock_irq(host_lock);
2912         return FAILED;
2913
2914 }
2915
2916 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2917 /**
2918  *      mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant
2919  *      @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
2920  *
2921  *      (linux Scsi_Host_Template.eh_dev_reset_handler routine)
2922  *
2923  *      Returns SUCCESS or FAILED.
2924  */
2925 int
2926 mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
2927 {
2928         MPT_SCSI_HOST   *hd;
2929         spinlock_t      *host_lock = SCpnt->device->host->host_lock;
2930
2931         /* If we can't locate our host adapter structure, return FAILED status.
2932          */
2933         if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2934                 dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
2935                            "Can't locate host! (sc=%p)\n",
2936                            SCpnt));
2937                 return FAILED;
2938         }
2939
2940         if (hd->resetPending)
2941                 return FAILED;
2942
2943         printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
2944                hd->ioc->name, SCpnt);
2945
2946         /* Unsupported for SCSI. Supported for FCP
2947          */
2948         if (hd->is_spi)
2949                 return FAILED;
2950
2951         spin_unlock_irq(host_lock);
2952         if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
2953                 SCpnt->device->channel, SCpnt->device->id,
2954                 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
2955                 < 0){
2956                 /* The TM request failed and the subsequent FW-reload failed!
2957                  * Fatal error case.
2958                  */
2959                 printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
2960                                 hd->ioc->name, SCpnt);
2961                 hd->tmPending = 0;
2962                 hd->tmState = TM_STATE_NONE;
2963                 spin_lock_irq(host_lock);
2964                 return FAILED;
2965         }
2966         spin_lock_irq(host_lock);
2967         return SUCCESS;
2968
2969 }
2970
2971 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2972 /**
2973  *      mptscsih_bus_reset - Perform a SCSI BUS_RESET!  new_eh variant
2974  *      @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
2975  *
2976  *      (linux Scsi_Host_Template.eh_bus_reset_handler routine)
2977  *
2978  *      Returns SUCCESS or FAILED.
2979  */
2980 int
2981 mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
2982 {
2983         MPT_SCSI_HOST   *hd;
2984         spinlock_t      *host_lock = SCpnt->device->host->host_lock;
2985
2986         /* If we can't locate our host adapter structure, return FAILED status.
2987          */
2988         if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2989                 dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
2990                            "Can't locate host! (sc=%p)\n",
2991                            SCpnt ) );
2992                 return FAILED;
2993         }
2994
2995         printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
2996                hd->ioc->name, SCpnt);
2997
2998         if (hd->timeouts < -1)
2999                 hd->timeouts++;
3000
3001         /* We are now ready to execute the task management request. */
3002         spin_unlock_irq(host_lock);
3003 //      printk("testing start : mptscsih_schedule_reset\n");
3004 //      mptscsih_schedule_reset(hd);
3005 //      printk("testing end: mptscsih_schedule_reset\n");
3006         if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
3007                 SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
3008             < 0){
3009
3010                 /* The TM request failed and the subsequent FW-reload failed!
3011                  * Fatal error case.
3012                  */
3013                 printk(MYIOC_s_WARN_FMT
3014                        "Error processing TaskMgmt request (sc=%p)\n",
3015                        hd->ioc->name, SCpnt);
3016                 hd->tmPending = 0;
3017                 hd->tmState = TM_STATE_NONE;
3018                 spin_lock_irq(host_lock);
3019                 return FAILED;
3020         }
3021         spin_lock_irq(host_lock);
3022         return SUCCESS;
3023 }
3024
3025 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3026 /**
3027  *      mptscsih_host_reset - Perform a SCSI host adapter RESET!
3028  *      new_eh variant
3029  *      @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
3030  *
3031  *      (linux Scsi_Host_Template.eh_host_reset_handler routine)
3032  *
3033  *      Returns SUCCESS or FAILED.
3034  */
3035 int
3036 mptscsih_host_reset(Scsi_Cmnd *SCpnt)
3037 {
3038         MPT_SCSI_HOST *  hd;
3039         int              status = SUCCESS;
3040         spinlock_t      *host_lock = SCpnt->device->host->host_lock;
3041
3042         /*  If we can't locate the host to reset, then we failed. */
3043         if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
3044                 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3045                              "Can't locate host! (sc=%p)\n",
3046                              SCpnt ) );
3047                 return FAILED;
3048         }
3049
3050         printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
3051                hd->ioc->name, SCpnt);
3052
3053         /*  If our attempts to reset the host failed, then return a failed
3054          *  status.  The host will be taken off line by the SCSI mid-layer.
3055          */
3056         spin_unlock_irq(host_lock);
3057         if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
3058                 status = FAILED;
3059         } else {
3060                 /*  Make sure TM pending is cleared and TM state is set to
3061                  *  NONE.
3062                  */
3063                 hd->tmPending = 0;
3064                 hd->tmState = TM_STATE_NONE;
3065         }
3066         spin_lock_irq(host_lock);
3067
3068
3069         dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3070                      "Status = %s\n",
3071                      (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
3072
3073         return status;
3074 }
3075
3076 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3077 /**
3078  *      mptscsih_tm_pending_wait - wait for pending task management request to
3079  *              complete.
3080  *      @hd: Pointer to MPT host structure.
3081  *
3082  *      Returns {SUCCESS,FAILED}.
3083  */
3084 static int
3085 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
3086 {
3087         unsigned long  flags;
3088         int            loop_count = 10 * 4;  /* Wait 10 seconds */
3089         int            status = FAILED;
3090
3091         do {
3092                 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
3093                 if (hd->tmState == TM_STATE_NONE) {
3094                         hd->tmState = TM_STATE_IN_PROGRESS;
3095                         hd->tmPending = 1;
3096                         spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3097                         status = SUCCESS;
3098                         break;
3099                 }
3100                 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3101                 set_current_state(TASK_INTERRUPTIBLE);
3102                 schedule_timeout(HZ/4);
3103         } while (--loop_count);
3104
3105         return status;
3106 }
3107
3108 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3109 /**
3110  *      mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
3111  *      @ioc: Pointer to MPT_ADAPTER structure
3112  *      @mf: Pointer to SCSI task mgmt request frame
3113  *      @mr: Pointer to SCSI task mgmt reply frame
3114  *
3115  *      This routine is called from mptbase.c::mpt_interrupt() at the completion
3116  *      of any SCSI task management request.
3117  *      This routine is registered with the MPT (base) driver at driver
3118  *      load/init time via the mpt_register() API call.
3119  *
3120  *      Returns 1 indicating alloc'd request frame ptr should be freed.
3121  */
3122 static int
3123 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3124 {
3125         SCSITaskMgmtReply_t     *pScsiTmReply;
3126         SCSITaskMgmt_t          *pScsiTmReq;
3127         MPT_SCSI_HOST           *hd;
3128         unsigned long            flags;
3129         u8                       tmType = 0;
3130
3131         dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
3132                         ioc->name, mf, mr));
3133         if (ioc->sh) {
3134                 /* Depending on the thread, a timer is activated for
3135                  * the TM request.  Delete this timer on completion of TM.
3136                  * Decrement count of outstanding TM requests.
3137                  */
3138                 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
3139                 if (hd->tmPtr) {
3140                         del_timer(&hd->TMtimer);
3141                 }
3142                 dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
3143                         ioc->name, hd->taskQcnt));
3144         } else {
3145                 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
3146                         ioc->name));
3147                 return 1;
3148         }
3149
3150         if (mr == NULL) {
3151                 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
3152                         ioc->name, mf));
3153                 return 1;
3154         } else {
3155                 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
3156                 pScsiTmReq = (SCSITaskMgmt_t*)mf;
3157
3158                 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
3159                 tmType = pScsiTmReq->TaskType;
3160
3161                 dtmprintk((KERN_INFO "  TaskType = %d, TerminationCount=%d\n",
3162                                 tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
3163
3164                 /* Error?  (anything non-zero?) */
3165                 if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
3166                         u16      iocstatus;
3167
3168                         iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3169                         dtmprintk((KERN_INFO "  SCSI TaskMgmt (%d) - Oops!\n", tmType));
3170                         dtmprintk((KERN_INFO "  IOCStatus = %04xh\n", iocstatus));
3171                         dtmprintk((KERN_INFO "  IOCLogInfo = %08xh\n",
3172                                  le32_to_cpu(pScsiTmReply->IOCLogInfo)));
3173
3174                         /* clear flags and continue.
3175                          */
3176                         if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
3177                                 hd->abortSCpnt = NULL;
3178
3179                         /* If an internal command is present
3180                          * or the TM failed - reload the FW.
3181                          * FC FW may respond FAILED to an ABORT
3182                          */
3183                         if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
3184                                 if ((hd->cmdPtr) ||
3185                                     (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
3186                                         if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
3187                                                 printk((KERN_WARNING
3188                                                         " Firmware Reload FAILED!!\n"));
3189                                         }
3190                                 }
3191                         }
3192                 } else {
3193                         dtmprintk((KERN_INFO "  SCSI TaskMgmt SUCCESS!\n"));
3194
3195                         hd->numTMrequests--;
3196                         hd->abortSCpnt = NULL;
3197                         flush_doneQ(hd);
3198
3199                 }
3200         }
3201
3202         hd->tmPtr = NULL;
3203         spin_lock_irqsave(&ioc->FreeQlock, flags);
3204         hd->tmPending = 0;
3205         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3206         hd->tmState = TM_STATE_NONE;
3207
3208         return 1;
3209 }
3210
3211 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3212 /*
3213  *      This is anyones guess quite frankly.
3214  */
3215 int
3216 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
3217                 sector_t capacity, int geom[])
3218 {
3219         int             heads;
3220         int             sectors;
3221         sector_t        cylinders;
3222 #ifdef CONFIG_LBD
3223         ulong           dummy;
3224 #endif
3225
3226         heads = 64;
3227         sectors = 32;
3228 #ifdef CONFIG_LBD
3229         dummy = heads * sectors;
3230         cylinders = capacity;
3231         sector_div(cylinders,dummy);
3232 #else
3233         cylinders = (ulong)capacity / (heads * sectors);
3234 #endif
3235
3236         /*
3237          * Handle extended translation size for logical drives
3238          * > 1Gb
3239          */
3240         if ((ulong)capacity >= 0x200000) {
3241                 heads = 255;
3242                 sectors = 63;
3243 #ifdef CONFIG_LBD
3244                 dummy = heads * sectors;
3245                 cylinders = capacity;
3246                 sector_div(cylinders,dummy);
3247 #else
3248                 cylinders = (ulong)capacity / (heads * sectors);
3249 #endif
3250         }
3251
3252         /* return result */
3253         geom[0] = heads;
3254         geom[1] = sectors;
3255         geom[2] = cylinders;
3256
3257         dprintk((KERN_NOTICE
3258                 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
3259                 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
3260
3261         return 0;
3262 }
3263
3264 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3265 /*
3266  *      OS entry point to allow host driver to alloc memory
3267  *      for each scsi device. Called once per device the bus scan.
3268  *      Return non-zero if allocation fails.
3269  *      Init memory once per id (not LUN).
3270  */
3271 int
3272 mptscsih_slave_alloc(Scsi_Device *device)
3273 {
3274         struct Scsi_Host        *host = device->host;
3275         MPT_SCSI_HOST           *hd;
3276         VirtDevice              *vdev;
3277
3278         hd = (MPT_SCSI_HOST *)host->hostdata;
3279
3280         if (hd == NULL)
3281                 return -ENODEV;
3282
3283         if ((vdev = hd->Targets[device->id]) == NULL) {
3284                 if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
3285                         printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%d) FAILED!\n",
3286                         hd->ioc->name, (int)sizeof(VirtDevice));
3287                         return -ENOMEM;
3288                 } else {
3289                         memset(vdev, 0, sizeof(VirtDevice));
3290                         rwlock_init(&vdev->VdevLock);
3291                         Q_INIT(&vdev->WaitQ, void);
3292                         Q_INIT(&vdev->SentQ, void);
3293                         Q_INIT(&vdev->DoneQ, void);
3294                         vdev->tflags = 0;
3295                         vdev->ioc_id = hd->ioc->id;
3296                         vdev->target_id = device->id;
3297                         vdev->bus_id = hd->port;
3298
3299                         hd->Targets[device->id] = vdev;
3300                 }
3301         }
3302         vdev->num_luns++;
3303
3304         return 0;
3305 }
3306
3307 /*
3308  *      OS entry point to allow for host driver to free allocated memory
3309  *      Called if no device present or device being unloaded
3310  */
3311 void
3312 mptscsih_slave_destroy(Scsi_Device *device)
3313 {
3314         struct Scsi_Host        *host = device->host;
3315         MPT_SCSI_HOST           *hd;
3316         VirtDevice              *vdev;
3317         int                     raid_volume=0;
3318
3319         hd = (MPT_SCSI_HOST *)host->hostdata;
3320
3321         if (hd == NULL)
3322                 return;
3323
3324         mptscsih_search_running_cmds(hd, device->id, device->lun);
3325
3326         /* Free memory and reset all flags for this target
3327          */
3328         if ((vdev = hd->Targets[device->id]) != NULL) {
3329                 vdev->num_luns--;
3330
3331                 if (vdev->luns[0] & (1 << device->lun))
3332                         vdev->luns[0] &= ~(1 << device->lun);
3333
3334                 /* Free device structure only if number of luns is 0.
3335                  */
3336                 if (vdev->num_luns == 0) {
3337                         kfree(hd->Targets[device->id]);
3338                         hd->Targets[device->id] = NULL;
3339
3340                         if (!hd->is_spi) 
3341                                 return;
3342
3343                         if((hd->ioc->spi_data.isRaid) && (hd->ioc->spi_data.pIocPg3)) {
3344                         int i;
3345                                 for(i=0;i<hd->ioc->spi_data.pIocPg3->NumPhysDisks &&
3346                                         raid_volume==0;i++)
3347                                                 
3348                                         if(device->id == 
3349                                           hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) {
3350                                                 raid_volume=1;
3351                                                 hd->ioc->spi_data.forceDv |=
3352                                                   MPT_SCSICFG_RELOAD_IOC_PG3;
3353                                         }
3354                         }
3355
3356                         if(!raid_volume){
3357                                 hd->ioc->spi_data.dvStatus[device->id] =
3358                                 MPT_SCSICFG_NEGOTIATE;
3359
3360                                 if (hd->negoNvram == 0)
3361                                         hd->ioc->spi_data.dvStatus[device->id]
3362                                         |= MPT_SCSICFG_DV_NOT_DONE;
3363                         }
3364                 }
3365         }
3366         
3367         return;
3368 }
3369
3370 /*
3371  *      OS entry point to adjust the queue_depths on a per-device basis.
3372  *      Called once per device the bus scan. Use it to force the queue_depth
3373  *      member to 1 if a device does not support Q tags.
3374  *      Return non-zero if fails.
3375  */
3376 int
3377 mptscsih_slave_configure(Scsi_Device *device)
3378 {
3379         struct Scsi_Host        *sh = device->host;
3380         VirtDevice              *pTarget;
3381         MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sh->hostdata;
3382
3383         if ((hd == NULL) || (hd->Targets == NULL)) {
3384                 return 0;
3385         }
3386
3387         dsprintk((MYIOC_s_INFO_FMT
3388                 "device @ %p, id=%d, LUN=%d, channel=%d\n",
3389                 hd->ioc->name, device, device->id, device->lun, device->channel));
3390         dsprintk((MYIOC_s_INFO_FMT
3391                 "sdtr %d wdtr %d ppr %d inq length=%d\n",
3392                 hd->ioc->name, device->sdtr, device->wdtr,
3393                 device->ppr, device->inquiry_len));
3394
3395         if (device->id > sh->max_id) {
3396                 /* error case, should never happen */
3397                 scsi_adjust_queue_depth(device, 0, 1);
3398                 goto slave_configure_exit;
3399         }
3400
3401         pTarget = hd->Targets[device->id];
3402
3403         if (pTarget == NULL) {
3404                 /* error case - don't know about this device */
3405                 scsi_adjust_queue_depth(device, 0, 1);
3406                 goto slave_configure_exit;
3407         }
3408
3409         mptscsih_initTarget(hd, device->channel, device->id, device->lun,
3410                 device->inquiry, device->inquiry_len );
3411         scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3412                 MPT_SCSI_CMD_PER_DEV_HIGH);
3413         if ( hd->is_spi ) {
3414                 if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
3415                         if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
3416                                 scsi_adjust_queue_depth(device, 0, 1);
3417                         else if (((pTarget->inq_data[0] & 0x1f) == 0x00)
3418                           && (pTarget->minSyncFactor <= MPT_ULTRA160 ))
3419                                 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3420                                         MPT_SCSI_CMD_PER_DEV_HIGH);
3421                         else
3422                                 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3423                                         MPT_SCSI_CMD_PER_DEV_LOW);
3424                 } else {
3425                         /* error case - No Inq. Data */
3426                         scsi_adjust_queue_depth(device, 0, 1);
3427                 }
3428         }
3429
3430         dsprintk((MYIOC_s_INFO_FMT
3431                 "Queue depth=%d, tflags=%x\n",
3432                 hd->ioc->name, device->queue_depth, pTarget->tflags));
3433
3434         dsprintk((MYIOC_s_INFO_FMT
3435                 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
3436                 hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
3437
3438 slave_configure_exit:
3439
3440         dsprintk((MYIOC_s_INFO_FMT
3441                 "tagged %d, simple %d, ordered %d\n",
3442                 hd->ioc->name,device->tagged_supported, device->simple_tags,
3443                 device->ordered_tags));
3444
3445         return 0;
3446 }
3447
3448
3449 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3450 /*
3451  *  Private routines...
3452  */
3453
3454 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3455 /* Utility function to copy sense data from the scsi_cmnd buffer
3456  * to the FC and SCSI target structures.
3457  *
3458  */
3459 static void
3460 copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
3461 {
3462         VirtDevice      *target;
3463         SCSIIORequest_t *pReq;
3464         u32              sense_count = le32_to_cpu(pScsiReply->SenseCount);
3465         int              index;
3466         char             devFoo[96];
3467         IO_Info_t        thisIo;
3468
3469         /* Get target structure
3470          */
3471         pReq = (SCSIIORequest_t *) mf;
3472         index = (int) pReq->TargetID;
3473         target = hd->Targets[index];
3474         if (hd->is_multipath && sc->device->hostdata)
3475                 target = (VirtDevice *) sc->device->hostdata;
3476
3477         if (sense_count) {
3478                 u8 *sense_data;
3479                 int req_index;
3480
3481                 /* Copy the sense received into the scsi command block. */
3482                 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3483                 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
3484                 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
3485
3486                 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
3487                  */
3488                 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
3489                         if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
3490                                 int idx;
3491                                 MPT_ADAPTER *ioc = hd->ioc;
3492
3493                                 idx = ioc->eventContext % ioc->eventLogSize;
3494                                 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
3495                                 ioc->events[idx].eventContext = ioc->eventContext;
3496
3497                                 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
3498                                         (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
3499                                         (pReq->Bus << 8) || pReq->TargetID;
3500
3501                                 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
3502
3503                                 ioc->eventContext++;
3504                         }
3505                 }
3506
3507                 /* Print an error report for the user.
3508                  */
3509                 thisIo.cdbPtr = sc->cmnd;
3510                 thisIo.sensePtr = sc->sense_buffer;
3511                 thisIo.SCSIStatus = pScsiReply->SCSIStatus;
3512                 thisIo.DoDisplay = 1;
3513                 if (hd->is_multipath)
3514                         sprintf(devFoo, "%d:%d:%d",
3515                                         hd->ioc->id,
3516                                         pReq->TargetID,
3517                                         pReq->LUN[1]);
3518                 else
3519                         sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->device->id, sc->device->lun);
3520                 thisIo.DevIDStr = devFoo;
3521 /* fubar */
3522                 thisIo.dataPtr = NULL;
3523                 thisIo.inqPtr = NULL;
3524                 if (sc->device) {
3525                         thisIo.inqPtr = sc->device->vendor-8;   /* FIXME!!! */
3526                 }
3527                 (void) mpt_ScsiHost_ErrorReport(&thisIo);
3528
3529         } else {
3530                 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
3531                                 hd->ioc->name));
3532         }
3533
3534         return;
3535 }
3536
3537 static u32
3538 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
3539 {
3540         MPT_SCSI_HOST *hd;
3541         int i;
3542
3543         hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
3544
3545         for (i = 0; i < hd->ioc->req_depth; i++) {
3546                 if (hd->ScsiLookup[i] == sc) {
3547                         return i;
3548                 }
3549         }
3550
3551         return -1;
3552 }
3553
3554
3555 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3556 /* Search the pendingQ for a command with specific index.
3557  * If found, delete and return mf pointer
3558  * If not found, return NULL
3559  */
3560 static MPT_FRAME_HDR *
3561 mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx)
3562 {
3563         unsigned long    flags;
3564         MPT_DONE_Q      *buffer;
3565         MPT_FRAME_HDR   *mf = NULL;
3566         MPT_FRAME_HDR   *cmdMfPtr;
3567
3568         ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
3569         cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
3570         spin_lock_irqsave(&hd->freedoneQlock, flags);
3571         if (!Q_IS_EMPTY(&hd->pendingQ)) {
3572                 buffer = hd->pendingQ.head;
3573                 do {
3574                         mf = (MPT_FRAME_HDR *) buffer->argp;
3575                         if (mf == cmdMfPtr) {
3576                                 Q_DEL_ITEM(buffer);
3577
3578                                 /* clear the arg pointer
3579                                  */
3580                                 buffer->argp = NULL;
3581
3582                                 /* Add to the freeQ
3583                                  */
3584                                 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
3585                                 break;
3586                         }
3587                         mf = NULL;
3588                 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ);
3589         }
3590         spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3591         ddvtprintk((" ...return %p\n", mf));
3592         return mf;
3593 }
3594
3595 /* Post all commands on the pendingQ to the FW.
3596  * Lock Q when deleting/adding members
3597  * Lock io_request_lock for OS callback.
3598  */
3599 static void
3600 post_pendingQ_commands(MPT_SCSI_HOST *hd)
3601 {
3602         MPT_FRAME_HDR   *mf;
3603         MPT_DONE_Q      *buffer;
3604         unsigned long    flags;
3605
3606         /* Flush the pendingQ.
3607          */
3608         ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name));
3609         while (1) {
3610                 spin_lock_irqsave(&hd->freedoneQlock, flags);
3611                 if (Q_IS_EMPTY(&hd->pendingQ)) {
3612                         spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3613                         break;
3614                 }
3615
3616                 buffer = hd->pendingQ.head;
3617                 /* Delete from Q
3618                  */
3619                 Q_DEL_ITEM(buffer);
3620
3621                 mf = (MPT_FRAME_HDR *) buffer->argp;
3622                 buffer->argp = NULL;
3623
3624                 /* Add to the freeQ
3625                  */
3626                 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
3627                 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3628
3629                 if (!mf) {
3630                         /* This should never happen */
3631                         printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf);
3632                         continue;
3633                 }
3634
3635                 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
3636
3637 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
3638                 {
3639                         u16              req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3640                         Scsi_Cmnd       *sc = hd->ScsiLookup[req_idx];
3641                         printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
3642                                         hd->ioc->name, sc, req_idx, mf);
3643                 }
3644 #endif
3645         }
3646
3647         return;
3648 }
3649
3650 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3651 static int
3652 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
3653 {
3654         MPT_SCSI_HOST   *hd;
3655         unsigned long    flags;
3656
3657         dtmprintk((KERN_WARNING MYNAM
3658                         ": IOC %s_reset routed to SCSI host driver!\n",
3659                         reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
3660                         reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
3661
3662         /* If a FW reload request arrives after base installed but
3663          * before all scsi hosts have been attached, then an alt_ioc
3664          * may have a NULL sh pointer.
3665          */
3666         if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
3667                 return 0;
3668         else
3669                 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3670
3671         if (reset_phase == MPT_IOC_SETUP_RESET) {
3672                 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
3673
3674                 /* Clean Up:
3675                  * 1. Set Hard Reset Pending Flag
3676                  * All new commands go to doneQ
3677                  */
3678                 hd->resetPending = 1;
3679
3680         } else if (reset_phase == MPT_IOC_PRE_RESET) {
3681                 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
3682
3683                 /* 2. Flush running commands
3684                  *      Clean drop test code - if compiled
3685                  *      Clean ScsiLookup (and associated memory)
3686                  *      AND clean mytaskQ
3687                  */
3688
3689                 /* 2a. Drop Test Command.
3690                  */
3691
3692                 /* 2b. Reply to OS all known outstanding I/O commands.
3693                  */
3694                 mptscsih_flush_running_cmds(hd);
3695
3696                 /* 2c. If there was an internal command that
3697                  * has not completed, configuration or io request,
3698                  * free these resources.
3699                  */
3700                 if (hd->cmdPtr) {
3701                         del_timer(&hd->timer);
3702                         mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr);
3703                 }
3704
3705                 /* 2d. If a task management has not completed,
3706                  * free resources associated with this request.
3707                  */
3708                 if (hd->tmPtr) {
3709                         del_timer(&hd->TMtimer);
3710                         mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr);
3711                 }
3712
3713 #ifdef MPTSCSIH_DBG_TIMEOUT
3714                 ioc->timeout_hard = 0;
3715 #endif
3716
3717                 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
3718
3719         } else {
3720                 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
3721
3722                 /* Once a FW reload begins, all new OS commands are
3723                  * redirected to the doneQ w/ a reset status.
3724                  * Init all control structures.
3725                  */
3726
3727                 /* ScsiLookup initialization
3728                  */
3729                 {
3730                         int ii;
3731                         for (ii=0; ii < hd->ioc->req_depth; ii++)
3732                                 hd->ScsiLookup[ii] = NULL;
3733                 }
3734
3735                 /* 2. Chain Buffer initialization
3736                  */
3737                 mptscsih_initChainBuffers(hd, 0);
3738
3739                 /* 3. tmPtr clear
3740                  */
3741                 if (hd->tmPtr) {
3742                         hd->tmPtr = NULL;
3743                 }
3744
3745                 /* 4. Renegotiate to all devices, if SCSI
3746                  */
3747                 if (hd->is_spi)
3748                         mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
3749
3750                 /* 5. Enable new commands to be posted
3751                  */
3752                 spin_lock_irqsave(&ioc->FreeQlock, flags);
3753                 hd->tmPending = 0;
3754                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3755                 hd->resetPending = 0;
3756                 hd->numTMrequests = 0;
3757                 hd->tmState = TM_STATE_NONE;
3758
3759                 /* 6. If there was an internal command,
3760                  * wake this process up.
3761                  */
3762                 if (hd->cmdPtr) {
3763                         /*
3764                          * Wake up the original calling thread
3765                          */
3766                         hd->pLocal = &hd->localReply;
3767                         hd->pLocal->completion = MPT_SCANDV_DID_RESET;
3768                         scandv_wait_done = 1;
3769                         wake_up(&scandv_waitq);
3770                         hd->cmdPtr = NULL;
3771                 }
3772
3773                 /* 7. Flush doneQ
3774                  */
3775                 flush_doneQ(hd);
3776
3777                 /* 8. Set flag to force DV and re-read IOC Page 3
3778                  */
3779                 if (hd->is_spi) {
3780                         ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
3781                         ddvtprintk(("Set reload IOC Pg3 Flag\n"));
3782                 }
3783
3784                 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
3785
3786         }
3787
3788         return 1;               /* currently means nothing really */
3789 }
3790
3791 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3792 static int
3793 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
3794 {
3795         MPT_SCSI_HOST *hd;
3796         u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
3797
3798         dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
3799                         ioc->name, event));
3800
3801         switch (event) {
3802         case MPI_EVENT_UNIT_ATTENTION:                  /* 03 */
3803                 /* FIXME! */
3804                 break;
3805         case MPI_EVENT_IOC_BUS_RESET:                   /* 04 */
3806         case MPI_EVENT_EXT_BUS_RESET:                   /* 05 */
3807                 hd = NULL;
3808                 if (ioc->sh) {
3809                         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3810                         if (hd && (hd->is_spi) && (hd->soft_resets < -1))
3811                                 hd->soft_resets++;
3812                 }
3813                 break;
3814         case MPI_EVENT_LOGOUT:                          /* 09 */
3815                 /* FIXME! */
3816                 break;
3817
3818                 /*
3819                  *  CHECKME! Don't think we need to do
3820                  *  anything for these, but...
3821                  */
3822         case MPI_EVENT_RESCAN:                          /* 06 */
3823         case MPI_EVENT_LINK_STATUS_CHANGE:              /* 07 */
3824         case MPI_EVENT_LOOP_STATE_CHANGE:               /* 08 */
3825                 /*
3826                  *  CHECKME!  Falling thru...
3827                  */
3828                 break;
3829
3830         case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
3831 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3832                 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
3833                  * if DV disabled. Need to check for target mode.
3834                  */
3835                 hd = NULL;
3836                 if (ioc->sh)
3837                         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3838
3839                 if (hd && (hd->is_spi) && (hd->negoNvram == 0)) {
3840                         ScsiCfgData     *pSpi;
3841                         Ioc3PhysDisk_t  *pPDisk;
3842                         int              numPDisk;
3843                         u8               reason;
3844                         u8               physDiskNum;
3845
3846                         reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
3847                         if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
3848                                 /* New or replaced disk.
3849                                  * Set DV flag and schedule DV.
3850                                  */
3851                                 pSpi = &ioc->spi_data;
3852                                 physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
3853                                 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
3854                                 if (pSpi->pIocPg3) {
3855                                         pPDisk =  pSpi->pIocPg3->PhysDisk;
3856                                         numPDisk =pSpi->pIocPg3->NumPhysDisks;
3857
3858                                         while (numPDisk) {
3859                                                 if (physDiskNum == pPDisk->PhysDiskNum) {
3860                                                         pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
3861                                                         pSpi->forceDv = MPT_SCSICFG_NEED_DV;
3862                                                         ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
3863                                                         break;
3864                                                 }
3865                                                 pPDisk++;
3866                                                 numPDisk--;
3867                                         }
3868
3869                                         if (numPDisk == 0) {
3870                                                 /* The physical disk that needs DV was not found
3871                                                  * in the stored IOC Page 3. The driver must reload
3872                                                  * this page. DV routine will set the NEED_DV flag for
3873                                                  * all phys disks that have DV_NOT_DONE set.
3874                                                  */
3875                                                 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
3876                                                 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
3877                                         }
3878                                 }
3879                         }
3880                 }
3881 #endif
3882
3883 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
3884                 printk("Raid Event RF: ");
3885                 {
3886                         u32 *m = (u32 *)pEvReply;
3887                         int ii;
3888                         int n = (int)pEvReply->MsgLength;
3889                         for (ii=6; ii < n; ii++)
3890                                 printk(" %08x", le32_to_cpu(m[ii]));
3891                         printk("\n");
3892                 }
3893 #endif
3894                 break;
3895
3896         case MPI_EVENT_NONE:                            /* 00 */
3897         case MPI_EVENT_LOG_DATA:                        /* 01 */
3898         case MPI_EVENT_STATE_CHANGE:                    /* 02 */
3899         case MPI_EVENT_EVENT_CHANGE:                    /* 0A */
3900         default:
3901                 dprintk((KERN_INFO "  Ignoring event (=%02Xh)\n", event));
3902                 break;
3903         }
3904
3905         return 1;               /* currently means nothing really */
3906 }
3907
3908 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3909 /*
3910  *  Private data...
3911  */
3912 static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
3913
3914 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3915 /* old symsense.c stuff... */
3916 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3917 /*
3918  * Private data...
3919  * To protect ourselves against those that would pass us bogus pointers
3920  */
3921 static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
3922     = { 0x1F, 0x00, 0x00, 0x00,
3923         0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3924         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3925         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3926         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3927 static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
3928     = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
3929         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3930         0x00, 0x00 };
3931 static u8 dummyCDB[16]
3932     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3933         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3934 static u8 dummyScsiData[16]
3935     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3936         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3937
3938 static char *ScsiStatusString[] = {
3939         "GOOD",                                 /* 00h */
3940         NULL,                                   /* 01h */
3941         "CHECK CONDITION",                      /* 02h */
3942         NULL,                                   /* 03h */
3943         "CONDITION MET",                        /* 04h */
3944         NULL,                                   /* 05h */
3945         NULL,                                   /* 06h */
3946         NULL,                                   /* 07h */
3947         "BUSY",                                 /* 08h */
3948         NULL,                                   /* 09h */
3949         NULL,                                   /* 0Ah */
3950         NULL,                                   /* 0Bh */
3951         NULL,                                   /* 0Ch */
3952         NULL,                                   /* 0Dh */
3953         NULL,                                   /* 0Eh */
3954         NULL,                                   /* 0Fh */
3955         "INTERMEDIATE",                         /* 10h */
3956         NULL,                                   /* 11h */
3957         NULL,                                   /* 12h */
3958         NULL,                                   /* 13h */
3959         "INTERMEDIATE-CONDITION MET",           /* 14h */
3960         NULL,                                   /* 15h */
3961         NULL,                                   /* 16h */
3962         NULL,                                   /* 17h */
3963         "RESERVATION CONFLICT",                 /* 18h */
3964         NULL,                                   /* 19h */
3965         NULL,                                   /* 1Ah */
3966         NULL,                                   /* 1Bh */
3967         NULL,                                   /* 1Ch */
3968         NULL,                                   /* 1Dh */
3969         NULL,                                   /* 1Eh */
3970         NULL,                                   /* 1Fh */
3971         NULL,                                   /* 20h */
3972         NULL,                                   /* 21h */
3973         "COMMAND TERMINATED",                   /* 22h */
3974         NULL,                                   /* 23h */
3975         NULL,                                   /* 24h */
3976         NULL,                                   /* 25h */
3977         NULL,                                   /* 26h */
3978         NULL,                                   /* 27h */
3979         "TASK SET FULL",                        /* 28h */
3980         NULL,                                   /* 29h */
3981         NULL,                                   /* 2Ah */
3982         NULL,                                   /* 2Bh */
3983         NULL,                                   /* 2Ch */
3984         NULL,                                   /* 2Dh */
3985         NULL,                                   /* 2Eh */
3986         NULL,                                   /* 2Fh */
3987         "ACA ACTIVE",                           /* 30h */
3988         NULL
3989 };
3990
3991 static const char *ScsiCommonOpString[] = {
3992         "TEST UNIT READY",                      /* 00h */
3993         "REZERO UNIT (REWIND)",                 /* 01h */
3994         NULL,                                   /* 02h */
3995         "REQUEST_SENSE",                        /* 03h */
3996         "FORMAT UNIT (MEDIUM)",                 /* 04h */
3997         "READ BLOCK LIMITS",                    /* 05h */
3998         NULL,                                   /* 06h */
3999         "REASSIGN BLOCKS",                      /* 07h */
4000         "READ(6)",                              /* 08h */
4001         NULL,                                   /* 09h */
4002         "WRITE(6)",                             /* 0Ah */
4003         "SEEK(6)",                              /* 0Bh */
4004         NULL,                                   /* 0Ch */
4005         NULL,                                   /* 0Dh */
4006         NULL,                                   /* 0Eh */
4007         "READ REVERSE",                         /* 0Fh */
4008         "WRITE_FILEMARKS",                      /* 10h */
4009         "SPACE(6)",                             /* 11h */
4010         "INQUIRY",                              /* 12h */
4011         NULL
4012 };
4013
4014 static const char *SenseKeyString[] = {
4015         "NO SENSE",                             /* 0h */
4016         "RECOVERED ERROR",                      /* 1h */
4017         "NOT READY",                            /* 2h */
4018         "MEDIUM ERROR",                         /* 3h */
4019         "HARDWARE ERROR",                       /* 4h */
4020         "ILLEGAL REQUEST",                      /* 5h */
4021         "UNIT ATTENTION",                       /* 6h */
4022         "DATA PROTECT",                         /* 7h */
4023         "BLANK CHECK",                          /* 8h */
4024         "VENDOR-SPECIFIC",                      /* 9h */
4025         "ABORTED COPY",                         /* Ah */
4026         "ABORTED COMMAND",                      /* Bh */
4027         "EQUAL (obsolete)",                     /* Ch */
4028         "VOLUME OVERFLOW",                      /* Dh */
4029         "MISCOMPARE",                           /* Eh */
4030         "RESERVED",                             /* Fh */
4031         NULL
4032 };
4033
4034 #define SPECIAL_ASCQ(c,q) \
4035         (((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
4036
4037 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4038 static int dump_cdb(char *foo, unsigned char *cdb)
4039 {
4040         int i, grpCode, cdbLen;
4041         int l = 0;
4042
4043         grpCode = cdb[0] >> 5;
4044         if (grpCode < 1)
4045                 cdbLen = 6;
4046         else if (grpCode < 3)
4047                 cdbLen = 10;
4048         else if (grpCode == 5)
4049                 cdbLen = 12;
4050         else
4051                 cdbLen = 16;
4052
4053         for (i=0; i < cdbLen; i++)
4054                 l += sprintf(foo+l, " %02X", cdb[i]);
4055
4056         return l;
4057 }
4058
4059 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4060 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4061 /*  Do ASC/ASCQ lookup/grindage to English readable string(s)  */
4062 static const char * ascq_set_strings_4max(
4063                 u8 ASC, u8 ASCQ,
4064                 const char **s1, const char **s2, const char **s3, const char **s4)
4065 {
4066         static const char *asc_04_part1_string = "LOGICAL UNIT ";
4067         static const char *asc_04_part2a_string = "NOT READY, ";
4068         static const char *asc_04_part2b_string = "IS ";
4069         static const char *asc_04_ascq_NN_part3_strings[] = {   /* ASC ASCQ (hex) */
4070           "CAUSE NOT REPORTABLE",                               /* 04 00 */
4071           "IN PROCESS OF BECOMING READY",                       /* 04 01 */
4072           "INITIALIZING CMD. REQUIRED",                         /* 04 02 */
4073           "MANUAL INTERVENTION REQUIRED",                       /* 04 03 */
4074           /* Add        " IN PROGRESS" to all the following... */
4075           "FORMAT",                                             /* 04 04 */
4076           "REBUILD",                                            /* 04 05 */
4077           "RECALCULATION",                                      /* 04 06 */
4078           "OPERATION",                                          /* 04 07 */
4079           "LONG WRITE",                                         /* 04 08 */
4080           "SELF-TEST",                                          /* 04 09 */
4081           NULL
4082         };
4083         static char *asc_04_part4_string = " IN PROGRESS";
4084
4085         static char *asc_29_ascq_NN_strings[] = {               /* ASC ASCQ (hex) */
4086           "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED",      /* 29 00 */
4087           "POWER ON OCCURRED",                                  /* 29 01 */
4088           "SCSI BUS RESET OCCURRED",                            /* 29 02 */
4089           "BUS DEVICE RESET FUNCTION OCCURRED",                 /* 29 03 */
4090           "DEVICE INTERNAL RESET",                              /* 29 04 */
4091           "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED",           /* 29 05 */
4092           "TRANSCEIVER MODE CHANGED TO LVD",                    /* 29 06 */
4093           NULL
4094         };
4095         static char *ascq_vendor_uniq = "(Vendor Unique)";
4096         static char *ascq_noone = "(no matching ASC/ASCQ description found)";
4097         int idx;
4098
4099         *s1 = *s2 = *s3 = *s4 = "";             /* set'em all to the empty "" string */
4100
4101         /* CHECKME! Need lock/sem?
4102          *  Update and examine for isense module presense.
4103          */
4104         mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
4105
4106         if (mptscsih_ASCQ_TablePtr == NULL) {
4107                 /* 2nd chances... */
4108                 if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
4109                         *s1 = asc_04_part1_string;
4110                         *s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
4111                         *s3 = asc_04_ascq_NN_part3_strings[ASCQ];
4112                         /* check for " IN PROGRESS" ones */
4113                         if (ASCQ >= 0x04)
4114                                 *s4 = asc_04_part4_string;
4115                 } else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
4116                         *s1 = asc_29_ascq_NN_strings[ASCQ];
4117                 /*
4118                  *      Else { leave all *s[1-4] values pointing to the empty "" string }
4119                  */
4120                 return *s1;
4121         }
4122
4123         /*
4124          * Need to check ASC here; if it is "special," then
4125          * the ASCQ is variable, and indicates failed component number.
4126          * We must treat the ASCQ as a "don't care" while searching the
4127          * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
4128          * on when we actually need to identify the failed component.
4129          */
4130         if (SPECIAL_ASCQ(ASC,ASCQ))
4131                 ASCQ = 0xFF;
4132
4133         /* OK, now search mptscsih_ASCQ_Table[] for a matching entry */
4134         for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
4135                 if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) {
4136                         *s1 = mptscsih_ASCQ_TablePtr[idx].Description;
4137                         return *s1;
4138                 }
4139
4140         if ((ASC >= 0x80) || (ASCQ >= 0x80))
4141                 *s1 = ascq_vendor_uniq;
4142         else
4143                 *s1 = ascq_noone;
4144
4145         return *s1;
4146 }
4147
4148 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4149 /*
4150  *  SCSI Information Report; desired output format...
4151  *---
4152 SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION)
4153   Key=6h (UNIT ATTENTION); FRU=03h
4154   ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4155   CDB: 00 00 00 00 00 00 - TestUnitReady
4156  *---
4157  */
4158 /*
4159  *  SCSI Error Report; desired output format...
4160  *---
4161 SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
4162   SCSI_Status=02h (CHECK CONDITION)
4163   Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
4164   SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
4165   SenseKey=6h (UNIT ATTENTION); FRU=03h
4166   ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4167  *---
4168  */
4169
4170 int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
4171 {
4172         char             foo[512];
4173         char             buf2[32];
4174         char            *statstr;
4175         const char      *opstr;
4176         int              sk             = SD_Sense_Key(ioop->sensePtr);
4177         const char      *skstr          = SenseKeyString[sk];
4178         unsigned char    asc            = SD_ASC(ioop->sensePtr);
4179         unsigned char    ascq           = SD_ASCQ(ioop->sensePtr);
4180         int              l;
4181
4182         /* Change the error logging to only report errors on
4183          * read and write commands. Ignore errors on other commands.
4184          * Should this be configurable via proc?
4185          */
4186         switch (ioop->cdbPtr[0]) {
4187         case READ_6:
4188         case WRITE_6:
4189         case READ_10:
4190         case WRITE_10:
4191         case READ_12:
4192         case WRITE_12:
4193         case READ_16:
4194         case WRITE_16:
4195                 break;
4196         default:
4197                 return 0;
4198         }
4199
4200         /*
4201          *  More quiet mode.
4202          *  Filter out common, repetitive, warning-type errors...  like:
4203          *    POWER ON (06,29/00 or 06,29/01),
4204          *    SPINNING UP (02,04/01),
4205          *    LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
4206          */
4207         if (sk == SK_NO_SENSE) {
4208                 return 0;
4209         }
4210
4211         if (    (sk==SK_UNIT_ATTENTION  && asc==0x29 && (ascq==0x00 || ascq==0x01))
4212              || (sk==SK_NOT_READY       && asc==0x04 && (ascq==0x01 || ascq==0x02))
4213              || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
4214            )
4215         {
4216                 /* Do nothing! */
4217                 return 0;
4218         }
4219
4220         /* Prevent the system from continually writing to the log
4221          * if a medium is not found: 02 3A 00
4222          * Changer issues: TUR, Read Capacity, Table of Contents continually
4223          */
4224         if (sk==SK_NOT_READY && asc==0x3A) {
4225                 if (ioop->cdbPtr == NULL) {
4226                         return 0;
4227                 } else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
4228                         (ioop->cdbPtr[0] == CMD_ReadCapacity) ||
4229                         (ioop->cdbPtr[0] == 0x43)) {
4230                         return 0;
4231                 }
4232         }
4233         if (sk==SK_UNIT_ATTENTION) {
4234                 if (ioop->cdbPtr == NULL)
4235                         return 0;
4236                 else if (ioop->cdbPtr[0] == CMD_TestUnitReady)
4237                         return 0;
4238         }
4239
4240         /*
4241          *  Protect ourselves...
4242          */
4243         if (ioop->cdbPtr == NULL)
4244                 ioop->cdbPtr = dummyCDB;
4245         if (ioop->sensePtr == NULL)
4246                 ioop->sensePtr = dummySenseData;
4247         if (ioop->inqPtr == NULL)
4248                 ioop->inqPtr = dummyInqData;
4249         if (ioop->dataPtr == NULL)
4250                 ioop->dataPtr = dummyScsiData;
4251
4252         statstr = NULL;
4253         if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
4254             ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
4255                 (void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
4256                 statstr = buf2;
4257         }
4258
4259         opstr = NULL;
4260         if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
4261                 opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
4262         else if (mpt_ScsiOpcodesPtr)
4263                 opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
4264
4265         l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n",
4266                           ioop->DevIDStr,
4267                           ioop->SCSIStatus,
4268                           statstr);
4269         l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh",
4270                   sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
4271         {
4272                 const char      *x1, *x2, *x3, *x4;
4273                 x1 = x2 = x3 = x4 = "";
4274                 x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
4275                 if (x1 != NULL) {
4276                         if (x1[0] != '(')
4277                                 l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
4278                         else
4279                                 l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
4280                 }
4281         }
4282         l += sprintf(foo+l, "\n CDB:");
4283         l += dump_cdb(foo+l, ioop->cdbPtr);
4284         if (opstr)
4285                 l += sprintf(foo+l, " - \"%s\"", opstr);
4286         l += sprintf(foo+l, "\n");
4287
4288         PrintF(("%s\n", foo));
4289
4290         return l;
4291 }
4292
4293 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4294
4295 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4296 /*
4297  *      mptscsih_initTarget - Target, LUN alloc/free functionality.
4298  *      @hd: Pointer to MPT_SCSI_HOST structure
4299  *      @bus_id: Bus number (?)
4300  *      @target_id: SCSI target id
4301  *      @lun: SCSI LUN id
4302  *      @data: Pointer to data
4303  *      @dlen: Number of INQUIRY bytes
4304  *
4305  *      NOTE: It's only SAFE to call this routine if data points to
4306  *      sane & valid STANDARD INQUIRY data!
4307  *
4308  *      Allocate and initialize memory for this target.
4309  *      Save inquiry data.
4310  *
4311  */
4312 static void
4313 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
4314 {
4315         int             indexed_lun, lun_index;
4316         VirtDevice      *vdev;
4317         char            data_56;
4318
4319         dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
4320                         hd->ioc->name, bus_id, target_id, lun, hd));
4321
4322         /* Is LUN supported? If so, upper 3 bits will be 0
4323         * in first byte of inquiry data.
4324         */
4325         if (data[0] & 0xe0)
4326                 return;
4327
4328         vdev = hd->Targets[target_id];
4329
4330         lun_index = (lun >> 5);  /* 32 luns per lun_index */
4331         indexed_lun = (lun % 32);
4332         vdev->luns[lun_index] |= (1 << indexed_lun);
4333
4334         vdev->raidVolume = 0;
4335         if (hd->is_spi) {
4336                 if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
4337                         vdev->raidVolume = 1;
4338                         ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
4339                 }
4340         }
4341
4342         if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
4343                 if ( dlen > 8 ) {
4344                         memcpy (vdev->inq_data, data, 8);
4345                 } else {
4346                         memcpy (vdev->inq_data, data, dlen);
4347                 }
4348                 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4349
4350                 /* If LUN 0, tape and have not done DV, set the DV flag.
4351                  */
4352                 if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) {
4353                         ScsiCfgData *pSpi = &hd->ioc->spi_data;
4354                         if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
4355                                 pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
4356                 }
4357
4358                 if ( (data[0] == SCSI_TYPE_PROC) &&
4359                         !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
4360                         if ( dlen > 49 ) {
4361                                 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4362                                 if ( data[44] == 'S' &&
4363                                      data[45] == 'A' &&
4364                                      data[46] == 'F' &&
4365                                      data[47] == '-' &&
4366                                      data[48] == 'T' &&
4367                                      data[49] == 'E' ) {
4368                                         vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4369                                         mptscsih_writeIOCPage4(hd, target_id, bus_id);
4370                                 }
4371                         } else {
4372                                 /* Treat all Processors as SAF-TE if
4373                                  * command line option is set */
4374                                 if ( hd->ioc->spi_data.Saf_Te ) {
4375                                         vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4376                                         mptscsih_writeIOCPage4(hd, target_id, bus_id);
4377                                 }
4378                         }
4379                 }
4380
4381                 data_56 = 0;
4382                 if (dlen > 56) {
4383                         if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
4384                         /* Update the target capabilities
4385                          */
4386                                 data_56 = data[56];
4387                                 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
4388                         }
4389                 }
4390                 mptscsih_setTargetNegoParms(hd, vdev, data_56);
4391         }
4392
4393         dprintk((KERN_INFO "  target = %p\n", vdev));
4394         return;
4395 }
4396
4397 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4398 /*
4399  *  Update the target negotiation parameters based on the
4400  *  the Inquiry data, adapter capabilities, and NVRAM settings.
4401  *
4402  */
4403 void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
4404 {
4405         ScsiCfgData *pspi_data = &hd->ioc->spi_data;
4406         int  id = (int) target->target_id;
4407         int  nvram;
4408         char canQ = 0;
4409         VirtDevice      *vdev;
4410         int ii;
4411         u8 width = MPT_NARROW;
4412         u8 factor = MPT_ASYNC;
4413         u8 offset = 0;
4414         u8 version, nfactor;
4415         u8 noQas = 1;
4416
4417         if (!hd->is_spi) {
4418                 if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
4419                         if (target->inq_data[7] & 0x02)
4420                                 target->tflags |= MPT_TARGET_FLAGS_Q_YES;
4421                 }
4422                 return;
4423         }
4424
4425         target->negoFlags = pspi_data->noQas;
4426
4427         /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
4428          * support. If available, default QAS to off and allow enabling.
4429          * If not available, default QAS to on, turn off for non-disks.
4430          */
4431
4432         /* Set flags based on Inquiry data
4433          */
4434         if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
4435                 version = target->inq_data[2] & 0x07;
4436                 if (version < 2) {
4437                         width = 0;
4438                         factor = MPT_ULTRA2;
4439                         offset = pspi_data->maxSyncOffset;
4440                 } else {
4441                         if (target->inq_data[7] & 0x20) {
4442                                 width = 1;
4443                         }
4444
4445                         if (target->inq_data[7] & 0x10) {
4446                                 /* bits 2 & 3 show DT support
4447                                  */
4448                                 if ((byte56 & 0x04) == 0)
4449                                         factor = MPT_ULTRA2;
4450                                 else if ((byte56 & 0x03) == 0)
4451                                         factor = MPT_ULTRA160;
4452                                 else
4453                                         factor = MPT_ULTRA320;
4454                                 offset = pspi_data->maxSyncOffset;
4455
4456                                 /* If RAID, never disable QAS
4457                                  * else if non RAID, do not disable
4458                                  *   QAS if bit 1 is set
4459                                  * bit 1 QAS support, non-raid only
4460                                  * bit 0 IU support
4461                                  */
4462                                 if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
4463                                         noQas = 0;
4464                         } else {
4465                                 factor = MPT_ASYNC;
4466                                 offset = 0;
4467                         }
4468                 }
4469
4470                 if (target->inq_data[7] & 0x02) {
4471                         canQ = 1;
4472                 }
4473
4474                 /* Update tflags based on NVRAM settings. (SCSI only)
4475                  */
4476                 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4477                         nvram = pspi_data->nvram[id];
4478                         nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
4479
4480                         if (width)
4481                                 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
4482
4483                         if (offset > 0) {
4484                                 /* Ensure factor is set to the
4485                                  * maximum of: adapter, nvram, inquiry
4486                                  */
4487                                 if (nfactor) {
4488                                         if (nfactor < pspi_data->minSyncFactor )
4489                                                 nfactor = pspi_data->minSyncFactor;
4490
4491                                         factor = max(factor, nfactor);
4492                                         if (factor == MPT_ASYNC)
4493                                                 offset = 0;
4494                                 } else {
4495                                         offset = 0;
4496                                         factor = MPT_ASYNC;
4497                                 }
4498                         } else {
4499                                 factor = MPT_ASYNC;
4500                         }
4501                 }
4502
4503                 /* Make sure data is consistent
4504                  */
4505                 if ((!width) && (factor < MPT_ULTRA2)) {
4506                         factor = MPT_ULTRA2;
4507                 }
4508
4509                 /* Save the data to the target structure.
4510                  */
4511                 target->minSyncFactor = factor;
4512                 target->maxOffset = offset;
4513                 target->maxWidth = width;
4514                 if (canQ) {
4515                         target->tflags |= MPT_TARGET_FLAGS_Q_YES;
4516                 }
4517
4518                 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
4519
4520                 /* Disable unused features.
4521                  */
4522                 if (!width)
4523                         target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
4524
4525                 if (!offset)
4526                         target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
4527
4528                 /* GEM, processor WORKAROUND
4529                  */
4530                 if (((target->inq_data[0] & 0x1F) == 0x03)
4531                         || ((target->inq_data[0] & 0x1F) > 0x08)) {
4532                         target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
4533                         pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
4534                 } else {
4535                         if (noQas && (pspi_data->noQas == 0)) {
4536                                 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
4537                                 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4538
4539                                 /* Disable QAS in a mixed configuration case
4540                                 */
4541
4542 //                              ddvtprintk((KERN_INFO "Disabling QAS!\n"));
4543                                 for (ii = 0; ii < id; ii++) {
4544                                         if ( (vdev = hd->Targets[ii]) ) {
4545                                                 vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4546                                         }
4547                                 }
4548                         }
4549                 }
4550         }
4551
4552         return;
4553 }
4554
4555 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4556 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
4557  * Else set the NEED_DV flag after Read Capacity Issued (disks)
4558  * or Mode Sense (cdroms).
4559  *
4560  * Tapes, initTarget will set this flag on completion of Inquiry command.
4561  * Called only if DV_NOT_DONE flag is set
4562  */
4563 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
4564 {
4565         u8 cmd;
4566
4567         if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
4568                 return;
4569
4570         cmd = pReq->CDB[0];
4571
4572         if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
4573                 ScsiCfgData *pSpi = &hd->ioc->spi_data;
4574                 if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
4575                         /* Set NEED_DV for all hidden disks
4576                          */
4577                         Ioc3PhysDisk_t *pPDisk =  pSpi->pIocPg3->PhysDisk;
4578                         int             numPDisk = pSpi->pIocPg3->NumPhysDisks;
4579
4580                         while (numPDisk) {
4581                                 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4582                                 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
4583                                 pPDisk++;
4584                                 numPDisk--;
4585                         }
4586                 }
4587                 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
4588                 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
4589         }
4590 }
4591
4592 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4593 /*
4594  * If no Target, bus reset on 1st I/O. Set the flag to
4595  * prevent any future negotiations to this device.
4596  */
4597 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
4598 {
4599
4600         if ((hd->Targets) && (hd->Targets[target_id] == NULL))
4601                 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
4602
4603         return;
4604 }
4605
4606 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4607 /*
4608  *  SCSI Config Page functionality ...
4609  */
4610 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4611 /*      mptscsih_setDevicePage1Flags  - add Requested and Configuration fields flags
4612  *      based on width, factor and offset parameters.
4613  *      @width: bus width
4614  *      @factor: sync factor
4615  *      @offset: sync offset
4616  *      @requestedPtr: pointer to requested values (updated)
4617  *      @configurationPtr: pointer to configuration values (updated)
4618  *      @flags: flags to block WDTR or SDTR negotiation
4619  *
4620  *      Return: None.
4621  *
4622  *      Remark: Called by writeSDP1 and _dv_params
4623  */
4624 static void
4625 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
4626 {
4627         u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
4628         u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
4629
4630         *configurationPtr = 0;
4631         *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
4632         *requestedPtr |= (offset << 16) | (factor << 8);
4633
4634         if (width && offset && !nowide && !nosync) {
4635                 if (factor < MPT_ULTRA160) {
4636                         *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
4637                         if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
4638                                 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
4639                 } else if (factor < MPT_ULTRA2) {
4640                         *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
4641                 }
4642         }
4643
4644         if (nowide)
4645                 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
4646
4647         if (nosync)
4648                 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
4649
4650         return;
4651 }
4652
4653 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4654 /*      mptscsih_writeSDP1  - write SCSI Device Page 1
4655  *      @hd: Pointer to a SCSI Host Strucutre
4656  *      @portnum: IOC port number
4657  *      @target_id: writeSDP1 for single ID
4658  *      @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
4659  *
4660  *      Return: -EFAULT if read of config page header fails
4661  *              or 0 if success.
4662  *
4663  *      Remark: If a target has been found, the settings from the
4664  *              target structure are used, else the device is set
4665  *              to async/narrow.
4666  *
4667  *      Remark: Called during init and after a FW reload.
4668  *      Remark: We do not wait for a return, write pages sequentially.
4669  */
4670 static int
4671 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
4672 {
4673         MPT_ADAPTER             *ioc = hd->ioc;
4674         Config_t                *pReq;
4675         SCSIDevicePage1_t       *pData;
4676         VirtDevice              *pTarget;
4677         MPT_FRAME_HDR           *mf;
4678         dma_addr_t               dataDma;
4679         u16                      req_idx;
4680         u32                      frameOffset;
4681         u32                      requested, configuration, flagsLength;
4682         int                      ii, nvram;
4683         int                      id = 0, maxid = 0;
4684         u8                       width;
4685         u8                       factor;
4686         u8                       offset;
4687         u8                       bus = 0;
4688         u8                       negoFlags;
4689         u8                       maxwidth, maxoffset, maxfactor;
4690
4691         if (ioc->spi_data.sdp1length == 0)
4692                 return 0;
4693
4694         if (flags & MPT_SCSICFG_ALL_IDS) {
4695                 id = 0;
4696                 maxid = ioc->sh->max_id - 1;
4697         } else if (ioc->sh) {
4698                 id = target_id;
4699                 maxid = min_t(int, id, ioc->sh->max_id - 1);
4700         }
4701
4702         for (; id <= maxid; id++) {
4703
4704                 if (id == ioc->pfacts[portnum].PortSCSIID)
4705                         continue;
4706
4707                 /* Use NVRAM to get adapter and target maximums
4708                  * Data over-riden by target structure information, if present
4709                  */
4710                 maxwidth = ioc->spi_data.maxBusWidth;
4711                 maxoffset = ioc->spi_data.maxSyncOffset;
4712                 maxfactor = ioc->spi_data.minSyncFactor;
4713                 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4714                         nvram = ioc->spi_data.nvram[id];
4715
4716                         if (maxwidth)
4717                                 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
4718
4719                         if (maxoffset > 0) {
4720                                 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
4721                                 if (maxfactor == 0) {
4722                                         /* Key for async */
4723                                         maxfactor = MPT_ASYNC;
4724                                         maxoffset = 0;
4725                                 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
4726                                         maxfactor = ioc->spi_data.minSyncFactor;
4727                                 }
4728                         } else
4729                                 maxfactor = MPT_ASYNC;
4730                 }
4731
4732                 /* Set the negotiation flags.
4733                  */
4734                 negoFlags = ioc->spi_data.noQas;
4735                 if (!maxwidth)
4736                         negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
4737
4738                 if (!maxoffset)
4739                         negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
4740
4741                 if (flags & MPT_SCSICFG_USE_NVRAM) {
4742                         width = maxwidth;
4743                         factor = maxfactor;
4744                         offset = maxoffset;
4745                 } else {
4746                         width = 0;
4747                         factor = MPT_ASYNC;
4748                         offset = 0;
4749                         //negoFlags = 0;
4750                         //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
4751                 }
4752
4753 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4754                 /* Force to async and narrow if DV has not been executed
4755                  * for this ID
4756                  */
4757                 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
4758                         width = 0;
4759                         factor = MPT_ASYNC;
4760                         offset = 0;
4761                 }
4762 #endif
4763
4764                 /* If id is not a raid volume, get the updated
4765                  * transmission settings from the target structure.
4766                  */
4767                 if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
4768                         width = pTarget->maxWidth;
4769                         factor = pTarget->minSyncFactor;
4770                         offset = pTarget->maxOffset;
4771                         negoFlags = pTarget->negoFlags;
4772                 }
4773
4774                 if (flags & MPT_SCSICFG_BLK_NEGO)
4775                         negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
4776
4777                 mptscsih_setDevicePage1Flags(width, factor, offset,
4778                                         &requested, &configuration, negoFlags);
4779
4780                 /* Get a MF for this command.
4781                  */
4782                 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
4783                         dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
4784                                                 ioc->name));
4785                         return -EAGAIN;
4786                 }
4787
4788                 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
4789                         hd->ioc->name, mf, id, requested, configuration));
4790
4791
4792                 /* Set the request and the data pointers.
4793                  * Request takes: 36 bytes (32 bit SGE)
4794                  * SCSI Device Page 1 requires 16 bytes
4795                  * 40 + 16 <= size of SCSI IO Request = 56 bytes
4796                  * and MF size >= 64 bytes.
4797                  * Place data at end of MF.
4798                  */
4799                 pReq = (Config_t *)mf;
4800
4801                 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
4802                 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
4803
4804                 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
4805                 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
4806
4807                 /* Complete the request frame (same for all requests).
4808                  */
4809                 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4810                 pReq->Reserved = 0;
4811                 pReq->ChainOffset = 0;
4812                 pReq->Function = MPI_FUNCTION_CONFIG;
4813                 pReq->ExtPageLength = 0;
4814                 pReq->ExtPageType = 0;
4815                 pReq->MsgFlags = 0;
4816                 for (ii=0; ii < 8; ii++) {
4817                         pReq->Reserved2[ii] = 0;
4818                 }
4819                 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
4820                 pReq->Header.PageLength = ioc->spi_data.sdp1length;
4821                 pReq->Header.PageNumber = 1;
4822                 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4823                 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
4824
4825                 /* Add a SGE to the config request.
4826                  */
4827                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
4828
4829                 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
4830
4831                 /* Set up the common data portion
4832                  */
4833                 pData->Header.PageVersion = pReq->Header.PageVersion;
4834                 pData->Header.PageLength = pReq->Header.PageLength;
4835                 pData->Header.PageNumber = pReq->Header.PageNumber;
4836                 pData->Header.PageType = pReq->Header.PageType;
4837                 pData->RequestedParameters = cpu_to_le32(requested);
4838                 pData->Reserved = 0;
4839                 pData->Configuration = cpu_to_le32(configuration);
4840
4841                 dprintk((MYIOC_s_INFO_FMT
4842                         "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
4843                                 ioc->name, id, (id | (bus<<8)),
4844                                 requested, configuration));
4845
4846                 mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
4847         }
4848
4849         return 0;
4850 }
4851
4852 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4853 /*      mptscsih_writeIOCPage4  - write IOC Page 4
4854  *      @hd: Pointer to a SCSI Host Structure
4855  *      @target_id: write IOC Page4 for this ID & Bus
4856  *
4857  *      Return: -EAGAIN if unable to obtain a Message Frame
4858  *              or 0 if success.
4859  *
4860  *      Remark: We do not wait for a return, write pages sequentially.
4861  */
4862 static int
4863 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
4864 {
4865         MPT_ADAPTER             *ioc = hd->ioc;
4866         Config_t                *pReq;
4867         IOCPage4_t              *IOCPage4Ptr;
4868         MPT_FRAME_HDR           *mf;
4869         dma_addr_t               dataDma;
4870         u16                      req_idx;
4871         u32                      frameOffset;
4872         u32                      flagsLength;
4873         int                      ii;
4874
4875         /* Get a MF for this command.
4876          */
4877         if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
4878                 dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
4879                                         ioc->name));
4880                 return -EAGAIN;
4881         }
4882
4883         ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n",
4884                 ioc->name, mf, target_id));
4885
4886         /* Set the request and the data pointers.
4887          * Place data at end of MF.
4888          */
4889         pReq = (Config_t *)mf;
4890
4891         req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
4892         frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
4893
4894         /* Complete the request frame (same for all requests).
4895          */
4896         pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4897         pReq->Reserved = 0;
4898         pReq->ChainOffset = 0;
4899         pReq->Function = MPI_FUNCTION_CONFIG;
4900         pReq->ExtPageLength = 0;
4901         pReq->ExtPageType = 0;
4902         pReq->MsgFlags = 0;
4903         for (ii=0; ii < 8; ii++) {
4904                 pReq->Reserved2[ii] = 0;
4905         }
4906
4907         IOCPage4Ptr = ioc->spi_data.pIocPg4;
4908         dataDma = ioc->spi_data.IocPg4_dma;
4909         ii = IOCPage4Ptr->ActiveSEP++;
4910         IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
4911         IOCPage4Ptr->SEP[ii].SEPBus = bus;
4912         pReq->Header = IOCPage4Ptr->Header;
4913         pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
4914
4915         /* Add a SGE to the config request.
4916          */
4917         flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
4918                 (IOCPage4Ptr->Header.PageLength + ii) * 4;
4919
4920         mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
4921
4922         dsprintk((MYIOC_s_INFO_FMT
4923                 "writeIOCPage4: pgaddr 0x%x\n",
4924                         ioc->name, (target_id | (bus<<8))));
4925
4926         mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
4927
4928         return 0;
4929 }
4930
4931 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4932 /*      mptscsih_taskmgmt_timeout - Call back for timeout on a
4933  *      task management request.
4934  *      @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
4935  *
4936  */
4937 static void mptscsih_taskmgmt_timeout(unsigned long data)
4938 {
4939         MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
4940
4941         dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
4942                    "TM request timed out!\n", hd->ioc->name));
4943
4944         /* Delete the timer that triggered this callback.
4945          * Remark: del_timer checks to make sure timer is active
4946          * before deleting.
4947          */
4948         del_timer(&hd->TMtimer);
4949
4950         /* Call the reset handler. Already had a TM request
4951          * timeout - so issue a diagnostic reset
4952          */
4953         MPT_INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
4954         SCHEDULE_TASK(&mptscsih_rstTask);
4955         return;
4956 }
4957
4958 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4959 /*      mptscsih_schedule_reset - Call back for timeout on a
4960  *      task management request.
4961  *      @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
4962  *
4963  */
4964 static void
4965 mptscsih_schedule_reset(void *arg)
4966 {
4967         MPT_SCSI_HOST           *hd;
4968         hd = (MPT_SCSI_HOST *) arg;
4969
4970         if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
4971                 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
4972         } else {
4973                 /* Because we have reset the IOC, no TM requests can be
4974                  * pending.  So let's make sure the tmPending flag is reset.
4975                  */
4976                 dtmprintk((KERN_WARNING MYNAM
4977                            ": %s: mptscsih_taskmgmt_timeout\n",
4978                            hd->ioc->name));
4979                 hd->tmPending = 0;
4980         }
4981
4982         return;
4983 }
4984
4985 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4986 /*
4987  *  Bus Scan and Domain Validation functionality ...
4988  */
4989
4990 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4991 /*
4992  *      mptscsih_scandv_complete - Scan and DV callback routine registered
4993  *      to Fustion MPT (base) driver.
4994  *
4995  *      @ioc: Pointer to MPT_ADAPTER structure
4996  *      @mf: Pointer to original MPT request frame
4997  *      @mr: Pointer to MPT reply frame (NULL if TurboReply)
4998  *
4999  *      This routine is called from mpt.c::mpt_interrupt() at the completion
5000  *      of any SCSI IO request.
5001  *      This routine is registered with the Fusion MPT (base) driver at driver
5002  *      load/init time via the mpt_register() API call.
5003  *
5004  *      Returns 1 indicating alloc'd request frame ptr should be freed.
5005  *
5006  *      Remark: Sets a completion code and (possibly) saves sense data
5007  *      in the IOC member localReply structure.
5008  *      Used ONLY for DV and other internal commands.
5009  */
5010 static int
5011 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
5012 {
5013         MPT_SCSI_HOST   *hd;
5014         SCSIIORequest_t *pReq;
5015         int              completionCode;
5016         u16              req_idx;
5017
5018         if ((mf == NULL) ||
5019             (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
5020                 printk(MYIOC_s_ERR_FMT
5021                         "ScanDvComplete, %s req frame ptr! (=%p)\n",
5022                                 ioc->name, mf?"BAD":"NULL", (void *) mf);
5023                 goto wakeup;
5024         }
5025
5026         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
5027         del_timer(&hd->timer);
5028         req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5029         hd->ScsiLookup[req_idx] = NULL;
5030         pReq = (SCSIIORequest_t *) mf;
5031
5032         if (mf != hd->cmdPtr) {
5033                 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
5034                                 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
5035         }
5036         hd->cmdPtr = NULL;
5037
5038         ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
5039                         hd->ioc->name, mf, mr, req_idx));
5040
5041         hd->pLocal = &hd->localReply;
5042         hd->pLocal->scsiStatus = 0;
5043
5044         /* If target struct exists, clear sense valid flag.
5045          */
5046         if (mr == NULL) {
5047                 completionCode = MPT_SCANDV_GOOD;
5048         } else {
5049                 SCSIIOReply_t   *pReply;
5050                 u16              status;
5051
5052                 pReply = (SCSIIOReply_t *) mr;
5053
5054                 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
5055
5056                 ddvtprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
5057                              status, pReply->SCSIState, pReply->SCSIStatus,
5058                              le32_to_cpu(pReply->IOCLogInfo)));
5059
5060                 switch(status) {
5061
5062                 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
5063                         completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
5064                         break;
5065
5066                 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
5067                 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
5068                 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
5069                 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
5070                         completionCode = MPT_SCANDV_DID_RESET;
5071                         break;
5072
5073                 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
5074                 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
5075                 case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
5076                         if (pReply->Function == MPI_FUNCTION_CONFIG) {
5077                                 ConfigReply_t *pr = (ConfigReply_t *)mr;
5078                                 completionCode = MPT_SCANDV_GOOD;
5079                                 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
5080                                 hd->pLocal->header.PageLength = pr->Header.PageLength;
5081                                 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
5082                                 hd->pLocal->header.PageType = pr->Header.PageType;
5083
5084                         } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
5085                                 /* If the RAID Volume request is successful,
5086                                  * return GOOD, else indicate that
5087                                  * some type of error occurred.
5088                                  */
5089                                 MpiRaidActionReply_t    *pr = (MpiRaidActionReply_t *)mr;
5090                                 if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
5091                                         completionCode = MPT_SCANDV_GOOD;
5092                                 else
5093                                         completionCode = MPT_SCANDV_SOME_ERROR;
5094
5095                         } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
5096                                 u8              *sense_data;
5097                                 int              sz;
5098
5099                                 /* save sense data in global structure
5100                                  */
5101                                 completionCode = MPT_SCANDV_SENSE;
5102                                 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5103                                 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
5104                                         (req_idx * MPT_SENSE_BUFFER_ALLOC));
5105
5106                                 sz = min_t(int, pReq->SenseBufferLength,
5107                                                         SCSI_STD_SENSE_BYTES);
5108                                 memcpy(hd->pLocal->sense, sense_data, sz);
5109
5110                                 ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
5111                                                 sense_data));
5112                         } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
5113                                 if (pReq->CDB[0] == CMD_Inquiry)
5114                                         completionCode = MPT_SCANDV_ISSUE_SENSE;
5115                                 else
5116                                         completionCode = MPT_SCANDV_DID_RESET;
5117                         }
5118                         else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
5119                                 completionCode = MPT_SCANDV_DID_RESET;
5120                         else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5121                                 completionCode = MPT_SCANDV_DID_RESET;
5122                         else {
5123                                 /* If no error, this will be equivalent
5124                                  * to MPT_SCANDV_GOOD
5125                                  */
5126                                 completionCode = MPT_SCANDV_GOOD;
5127                                 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5128                         }
5129                         break;
5130
5131                 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:         /* 0x0047 */
5132                         if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5133                                 completionCode = MPT_SCANDV_DID_RESET;
5134                         else
5135                                 completionCode = MPT_SCANDV_SOME_ERROR;
5136                         break;
5137
5138                 default:
5139                         completionCode = MPT_SCANDV_SOME_ERROR;
5140                         break;
5141
5142                 }       /* switch(status) */
5143
5144                 ddvtprintk((KERN_NOTICE "  completionCode set to %08xh\n",
5145                                 completionCode));
5146         } /* end of address reply case */
5147
5148         hd->pLocal->completion = completionCode;
5149
5150         /* MF and RF are freed in mpt_interrupt
5151          */
5152 wakeup:
5153         /* Free Chain buffers (will never chain) in scan or dv */
5154         //mptscsih_freeChainBuffers(hd, req_idx);
5155
5156         /*
5157          * Wake up the original calling thread
5158          */
5159         scandv_wait_done = 1;
5160         wake_up(&scandv_waitq);
5161
5162         return 1;
5163 }
5164
5165 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5166 /*      mptscsih_timer_expired - Call back for timer process.
5167  *      Used only for dv functionality.
5168  *      @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5169  *
5170  */
5171 static void mptscsih_timer_expired(unsigned long data)
5172 {
5173         MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
5174
5175         ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
5176
5177         if (hd->cmdPtr) {
5178                 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
5179
5180                 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
5181                         /* Desire to issue a task management request here.
5182                          * TM requests MUST be single threaded.
5183                          * If old eh code and no TM current, issue request.
5184                          * If new eh code, do nothing. Wait for OS cmd timeout
5185                          *      for bus reset.
5186                          */
5187                         ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
5188                 } else {
5189                         /* Perform a FW reload */
5190                         if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
5191                                 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
5192                         }
5193                 }
5194         } else {
5195                 /* This should NEVER happen */
5196                 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
5197         }
5198
5199         /* No more processing.
5200          * TM call will generate an interrupt for SCSI TM Management.
5201          * The FW will reply to all outstanding commands, callback will finish cleanup.
5202          * Hard reset clean-up will free all resources.
5203          */
5204         ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
5205
5206         return;
5207 }
5208
5209 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
5210 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5211 /*      mptscsih_do_raid - Format and Issue a RAID volume request message.
5212  *      @hd: Pointer to scsi host structure
5213  *      @action: What do be done.
5214  *      @id: Logical target id.
5215  *      @bus: Target locations bus.
5216  *
5217  *      Returns: < 0 on a fatal error
5218  *              0 on success
5219  *
5220  *      Remark: Wait to return until reply processed by the ISR.
5221  */
5222 static int
5223 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
5224 {
5225         MpiRaidActionRequest_t  *pReq;
5226         MPT_FRAME_HDR           *mf;
5227         int                     in_isr;
5228
5229         in_isr = in_interrupt();
5230         if (in_isr) {
5231                 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
5232                                 hd->ioc->name));
5233                 return -EPERM;
5234         }
5235
5236         /* Get and Populate a free Frame
5237          */
5238         if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
5239                 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
5240                                         hd->ioc->name));
5241                 return -EAGAIN;
5242         }
5243         pReq = (MpiRaidActionRequest_t *)mf;
5244         pReq->Action = action;
5245         pReq->Reserved1 = 0;
5246         pReq->ChainOffset = 0;
5247         pReq->Function = MPI_FUNCTION_RAID_ACTION;
5248         pReq->VolumeID = io->id;
5249         pReq->VolumeBus = io->bus;
5250         pReq->PhysDiskNum = io->physDiskNum;
5251         pReq->MsgFlags = 0;
5252         pReq->Reserved2 = 0;
5253         pReq->ActionDataWord = 0; /* Reserved for this action */
5254         //pReq->ActionDataSGE = 0;
5255
5256         mpt_add_sge((char *)&pReq->ActionDataSGE,
5257                 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
5258
5259         ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
5260                         hd->ioc->name, action, io->id));
5261
5262         hd->pLocal = NULL;
5263         hd->timer.expires = jiffies + HZ*2; /* 2 second timeout */
5264         scandv_wait_done = 0;
5265
5266         /* Save cmd pointer, for resource free if timeout or
5267          * FW reload occurs
5268          */
5269         hd->cmdPtr = mf;
5270
5271         add_timer(&hd->timer);
5272         mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
5273         wait_event(scandv_waitq, scandv_wait_done);
5274
5275         if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
5276                 return -1;
5277
5278         return 0;
5279 }
5280 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5281
5282 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5283 /**
5284  *      mptscsih_do_cmd - Do internal command.
5285  *      @hd: MPT_SCSI_HOST pointer
5286  *      @io: INTERNAL_CMD pointer.
5287  *
5288  *      Issue the specified internally generated command and do command
5289  *      specific cleanup. For bus scan / DV only.
5290  *      NOTES: If command is Inquiry and status is good,
5291  *      initialize a target structure, save the data
5292  *
5293  *      Remark: Single threaded access only.
5294  *
5295  *      Return:
5296  *              < 0 if an illegal command or no resources
5297  *
5298  *                 0 if good
5299  *
5300  *               > 0 if command complete but some type of completion error.
5301  */
5302 static int
5303 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
5304 {
5305         MPT_FRAME_HDR   *mf;
5306         SCSIIORequest_t *pScsiReq;
5307         SCSIIORequest_t  ReqCopy;
5308         int              my_idx, ii, dir;
5309         int              rc, cmdTimeout;
5310         int             in_isr;
5311         char             cmdLen;
5312         char             CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
5313         char             cmd = io->cmd;
5314
5315         in_isr = in_interrupt();
5316         if (in_isr) {
5317                 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
5318                                 hd->ioc->name));
5319                 return -EPERM;
5320         }
5321
5322
5323         /* Set command specific information
5324          */
5325         switch (cmd) {
5326         case CMD_Inquiry:
5327                 cmdLen = 6;
5328                 dir = MPI_SCSIIO_CONTROL_READ;
5329                 CDB[0] = cmd;
5330                 CDB[4] = io->size;
5331                 cmdTimeout = 10;
5332                 break;
5333
5334         case CMD_TestUnitReady:
5335                 cmdLen = 6;
5336                 dir = MPI_SCSIIO_CONTROL_READ;
5337                 cmdTimeout = 10;
5338                 break;
5339
5340         case CMD_StartStopUnit:
5341                 cmdLen = 6;
5342                 dir = MPI_SCSIIO_CONTROL_READ;
5343                 CDB[0] = cmd;
5344                 CDB[4] = 1;     /*Spin up the disk */
5345                 cmdTimeout = 15;
5346                 break;
5347
5348         case CMD_RequestSense:
5349                 cmdLen = 6;
5350                 CDB[0] = cmd;
5351                 CDB[4] = io->size;
5352                 dir = MPI_SCSIIO_CONTROL_READ;
5353                 cmdTimeout = 10;
5354                 break;
5355
5356         case CMD_ReadBuffer:
5357                 cmdLen = 10;
5358                 dir = MPI_SCSIIO_CONTROL_READ;
5359                 CDB[0] = cmd;
5360                 if (io->flags & MPT_ICFLAG_ECHO) {
5361                         CDB[1] = 0x0A;
5362                 } else {
5363                         CDB[1] = 0x02;
5364                 }
5365
5366                 if (io->flags & MPT_ICFLAG_BUF_CAP) {
5367                         CDB[1] |= 0x01;
5368                 }
5369                 CDB[6] = (io->size >> 16) & 0xFF;
5370                 CDB[7] = (io->size >>  8) & 0xFF;
5371                 CDB[8] = io->size & 0xFF;
5372                 cmdTimeout = 10;
5373                 break;
5374
5375         case CMD_WriteBuffer:
5376                 cmdLen = 10;
5377                 dir = MPI_SCSIIO_CONTROL_WRITE;
5378                 CDB[0] = cmd;
5379                 if (io->flags & MPT_ICFLAG_ECHO) {
5380                         CDB[1] = 0x0A;
5381                 } else {
5382                         CDB[1] = 0x02;
5383                 }
5384                 CDB[6] = (io->size >> 16) & 0xFF;
5385                 CDB[7] = (io->size >>  8) & 0xFF;
5386                 CDB[8] = io->size & 0xFF;
5387                 cmdTimeout = 10;
5388                 break;
5389
5390         case CMD_Reserve6:
5391                 cmdLen = 6;
5392                 dir = MPI_SCSIIO_CONTROL_READ;
5393                 CDB[0] = cmd;
5394                 cmdTimeout = 10;
5395                 break;
5396
5397         case CMD_Release6:
5398                 cmdLen = 6;
5399                 dir = MPI_SCSIIO_CONTROL_READ;
5400                 CDB[0] = cmd;
5401                 cmdTimeout = 10;
5402                 break;
5403
5404         case CMD_SynchronizeCache:
5405                 cmdLen = 10;
5406                 dir = MPI_SCSIIO_CONTROL_READ;
5407                 CDB[0] = cmd;
5408 //              CDB[1] = 0x02;  /* set immediate bit */
5409                 cmdTimeout = 10;
5410                 break;
5411
5412         default:
5413                 /* Error Case */
5414                 return -EFAULT;
5415         }
5416
5417         /* Get and Populate a free Frame
5418          */
5419         if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
5420                 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
5421                                         hd->ioc->name));
5422                 return -EBUSY;
5423         }
5424
5425         pScsiReq = (SCSIIORequest_t *) mf;
5426
5427         /* Get the request index */
5428         my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5429         ADD_INDEX_LOG(my_idx); /* for debug */
5430
5431         if (io->flags & MPT_ICFLAG_PHYS_DISK) {
5432                 pScsiReq->TargetID = io->physDiskNum;
5433                 pScsiReq->Bus = 0;
5434                 pScsiReq->ChainOffset = 0;
5435                 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
5436         } else {
5437                 pScsiReq->TargetID = io->id;
5438                 pScsiReq->Bus = io->bus;
5439                 pScsiReq->ChainOffset = 0;
5440                 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
5441         }
5442
5443         pScsiReq->CDBLength = cmdLen;
5444         pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
5445
5446         pScsiReq->Reserved = 0;
5447
5448         pScsiReq->MsgFlags = mpt_msg_flags();
5449         /* MsgContext set in mpt_get_msg_fram call  */
5450
5451         for (ii=0; ii < 8; ii++)
5452                 pScsiReq->LUN[ii] = 0;
5453         pScsiReq->LUN[1] = io->lun;
5454
5455         if (io->flags & MPT_ICFLAG_TAGGED_CMD)
5456                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
5457         else
5458                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
5459
5460         if (cmd == CMD_RequestSense) {
5461                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
5462                 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
5463                         hd->ioc->name, cmd));
5464         }
5465
5466         for (ii=0; ii < 16; ii++)
5467                 pScsiReq->CDB[ii] = CDB[ii];
5468
5469         pScsiReq->DataLength = cpu_to_le32(io->size);
5470         pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
5471                                            + (my_idx * MPT_SENSE_BUFFER_ALLOC));
5472
5473         ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
5474                         hd->ioc->name, cmd, io->bus, io->id, io->lun));
5475
5476         if (dir == MPI_SCSIIO_CONTROL_READ) {
5477                 mpt_add_sge((char *) &pScsiReq->SGL,
5478                         MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
5479                         io->data_dma);
5480         } else {
5481                 mpt_add_sge((char *) &pScsiReq->SGL,
5482                         MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
5483                         io->data_dma);
5484         }
5485
5486         /* The ISR will free the request frame, but we need
5487          * the information to initialize the target. Duplicate.
5488          */
5489         memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
5490
5491         /* Issue this command after:
5492          *      finish init
5493          *      add timer
5494          * Wait until the reply has been received
5495          *  ScsiScanDvCtx callback function will
5496          *      set hd->pLocal;
5497          *      set scandv_wait_done and call wake_up
5498          */
5499         hd->pLocal = NULL;
5500         hd->timer.expires = jiffies + HZ*cmdTimeout;
5501         scandv_wait_done = 0;
5502
5503         /* Save cmd pointer, for resource free if timeout or
5504          * FW reload occurs
5505          */
5506         hd->cmdPtr = mf;
5507
5508         add_timer(&hd->timer);
5509         mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
5510         wait_event(scandv_waitq, scandv_wait_done);
5511
5512         if (hd->pLocal) {
5513                 rc = hd->pLocal->completion;
5514                 hd->pLocal->skip = 0;
5515
5516                 /* Always set fatal error codes in some cases.
5517                  */
5518                 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
5519                         rc = -ENXIO;
5520                 else if (rc == MPT_SCANDV_SOME_ERROR)
5521                         rc =  -rc;
5522         } else {
5523                 rc = -EFAULT;
5524                 /* This should never happen. */
5525                 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
5526                                 hd->ioc->name));
5527         }
5528
5529         return rc;
5530 }
5531
5532 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5533 /**
5534  *      mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
5535  *      @hd: Pointer to MPT_SCSI_HOST structure
5536  *      @portnum: IOC port number
5537  *
5538  *      Uses the ISR, but with special processing.
5539  *      MUST be single-threaded.
5540  *
5541  *      Return: 0 on completion
5542  */
5543 static int
5544 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
5545 {
5546         MPT_ADAPTER             *ioc= hd->ioc;
5547         VirtDevice              *pTarget;
5548         SCSIDevicePage1_t       *pcfg1Data = NULL;
5549         INTERNAL_CMD             iocmd;
5550         CONFIGPARMS              cfg;
5551         dma_addr_t               cfg1_dma_addr = -1;
5552         ConfigPageHeader_t       header1;
5553         int                      bus = 0;
5554         int                      id = 0;
5555         int                      lun;
5556         int                      indexed_lun, lun_index;
5557         int                      hostId = ioc->pfacts[portnum].PortSCSIID;
5558         int                      max_id;
5559         int                      requested, configuration, data;
5560         int                      doConfig = 0;
5561         u8                       flags, factor;
5562
5563         max_id = ioc->sh->max_id - 1;
5564
5565         /* Following parameters will not change
5566          * in this routine.
5567          */
5568         iocmd.cmd = CMD_SynchronizeCache;
5569         iocmd.flags = 0;
5570         iocmd.physDiskNum = -1;
5571         iocmd.data = NULL;
5572         iocmd.data_dma = -1;
5573         iocmd.size = 0;
5574         iocmd.rsvd = iocmd.rsvd2 = 0;
5575
5576         /* No SCSI hosts
5577          */
5578         if (hd->Targets == NULL)
5579                 return 0;
5580
5581         /* Skip the host
5582          */
5583         if (id == hostId)
5584                 id++;
5585
5586         /* Write SDP1 for all SCSI devices
5587          * Alloc memory and set up config buffer
5588          */
5589         if (hd->is_spi) {
5590                 if (ioc->spi_data.sdp1length > 0) {
5591                         pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
5592                                          ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
5593
5594                         if (pcfg1Data != NULL) {
5595                                 doConfig = 1;
5596                                 header1.PageVersion = ioc->spi_data.sdp1version;
5597                                 header1.PageLength = ioc->spi_data.sdp1length;
5598                                 header1.PageNumber = 1;
5599                                 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5600                                 cfg.hdr = &header1;
5601                                 cfg.physAddr = cfg1_dma_addr;
5602                                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5603                                 cfg.dir = 1;
5604                                 cfg.timeout = 0;
5605                         }
5606                 }
5607         }
5608
5609         /* loop through all devices on this port
5610          */
5611         while (bus < MPT_MAX_BUS) {
5612                 iocmd.bus = bus;
5613                 iocmd.id = id;
5614                 pTarget = hd->Targets[(int)id];
5615
5616                 if (doConfig) {
5617
5618                         /* Set the negotiation flags */
5619                         if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
5620                                 flags = pTarget->negoFlags;
5621                         } else {
5622                                 flags = hd->ioc->spi_data.noQas;
5623                                 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5624                                         data = hd->ioc->spi_data.nvram[id];
5625
5626                                         if (data & MPT_NVRAM_WIDE_DISABLE)
5627                                                 flags |= MPT_TARGET_NO_NEGO_WIDE;
5628
5629                                         factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5630                                         if ((factor == 0) || (factor == MPT_ASYNC))
5631                                                 flags |= MPT_TARGET_NO_NEGO_SYNC;
5632                                 }
5633                         }
5634
5635                         /* Force to async, narrow */
5636                         mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
5637                                         &configuration, flags);
5638                         pcfg1Data->RequestedParameters = le32_to_cpu(requested);
5639                         pcfg1Data->Reserved = 0;
5640                         pcfg1Data->Configuration = le32_to_cpu(configuration);
5641                         cfg.pageAddr = (bus<<8) | id;
5642                         mpt_config(hd->ioc, &cfg);
5643                 }
5644
5645                 /* If target Ptr NULL or if this target is NOT a disk, skip.
5646                  */
5647                 if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
5648                         for (lun=0; lun <= MPT_LAST_LUN; lun++) {
5649                                 /* If LUN present, issue the command
5650                                  */
5651                                 lun_index = (lun >> 5);  /* 32 luns per lun_index */
5652                                 indexed_lun = (lun % 32);
5653                                 if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
5654                                         iocmd.lun = lun;
5655                                         (void) mptscsih_do_cmd(hd, &iocmd);
5656                                 }
5657                         }
5658                 }
5659
5660                 /* get next relevant device */
5661                 id++;
5662
5663                 if (id == hostId)
5664                         id++;
5665
5666                 if (id > max_id) {
5667                         id = 0;
5668                         bus++;
5669                 }
5670         }
5671
5672         if (pcfg1Data) {
5673                 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
5674         }
5675
5676         return 0;
5677 }
5678
5679 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
5680 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5681 /**
5682  *      mptscsih_domainValidation - Top level handler for domain validation.
5683  *      @hd: Pointer to MPT_SCSI_HOST structure.
5684  *
5685  *      Uses the ISR, but with special processing.
5686  *      Called from schedule, should not be in interrupt mode.
5687  *      While thread alive, do dv for all devices needing dv
5688  *
5689  *      Return: None.
5690  */
5691 static void
5692 mptscsih_domainValidation(void *arg)
5693 {
5694         MPT_SCSI_HOST           *hd;
5695         MPT_ADAPTER             *ioc;
5696         unsigned long            flags;
5697         int                      id, maxid, dvStatus, did;
5698         int                      ii, isPhysDisk;
5699
5700         spin_lock_irqsave(&dvtaskQ_lock, flags);
5701         dvtaskQ_active = 1;
5702         if (dvtaskQ_release) {
5703                 dvtaskQ_active = 0;
5704                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5705                 return;
5706         }
5707         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5708
5709         /* For this ioc, loop through all devices and do dv to each device.
5710          * When complete with this ioc, search through the ioc list, and
5711          * for each scsi ioc found, do dv for all devices. Exit when no
5712          * device needs dv.
5713          */
5714         did = 1;
5715         while (did) {
5716                 did = 0;
5717                 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
5718                         spin_lock_irqsave(&dvtaskQ_lock, flags);
5719                         if (dvtaskQ_release) {
5720                                 dvtaskQ_active = 0;
5721                                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5722                                 return;
5723                         }
5724                         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5725
5726                         set_current_state(TASK_INTERRUPTIBLE);
5727                         schedule_timeout(HZ/4);
5728
5729                         /* DV only to SCSI adapters */
5730                         if ((int)ioc->chip_type <= (int)FC929)
5731                                 continue;
5732
5733                         /* Make sure everything looks ok */
5734                         if (ioc->sh == NULL)
5735                                 continue;
5736
5737                         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
5738                         if (hd == NULL)
5739                                 continue;
5740
5741                         if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
5742                                 mpt_read_ioc_pg_3(ioc);
5743                                 if (ioc->spi_data.pIocPg3) {
5744                                         Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
5745                                         int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
5746
5747                                         while (numPDisk) {
5748                                                 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
5749                                                         ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
5750
5751                                                 pPDisk++;
5752                                                 numPDisk--;
5753                                         }
5754                                 }
5755                                 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
5756                         }
5757
5758                         maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
5759
5760                         for (id = 0; id < maxid; id++) {
5761                                 spin_lock_irqsave(&dvtaskQ_lock, flags);
5762                                 if (dvtaskQ_release) {
5763                                         dvtaskQ_active = 0;
5764                                         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5765                                         return;
5766                                 }
5767                                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5768                                 dvStatus = hd->ioc->spi_data.dvStatus[id];
5769
5770                                 if (dvStatus & MPT_SCSICFG_NEED_DV) {
5771                                         did++;
5772                                         hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
5773                                         hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
5774
5775                                         set_current_state(TASK_INTERRUPTIBLE);
5776                                         schedule_timeout(HZ/4);
5777
5778                                         /* If hidden phys disk, block IO's to all
5779                                          *      raid volumes
5780                                          * else, process normally
5781                                          */
5782                                         isPhysDisk = mptscsih_is_phys_disk(ioc, id);
5783                                         if (isPhysDisk) {
5784                                                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5785                                                         if (hd->ioc->spi_data.isRaid & (1 << ii)) {
5786                                                                 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
5787                                                         }
5788                                                 }
5789                                         }
5790
5791                                         if (mptscsih_doDv(hd, 0, id) == 1) {
5792                                                 /* Untagged device was busy, try again
5793                                                  */
5794                                                 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
5795                                                 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
5796                                         } else {
5797                                                 /* DV is complete. Clear flags.
5798                                                  */
5799                                                 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
5800                                         }
5801
5802                                         if (isPhysDisk) {
5803                                                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5804                                                         if (hd->ioc->spi_data.isRaid & (1 << ii)) {
5805                                                                 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
5806                                                         }
5807                                                 }
5808                                         }
5809
5810                                         /* Post OS IOs that were pended while
5811                                          * DV running.
5812                                          */
5813                                         post_pendingQ_commands(hd);
5814
5815                                         if (hd->ioc->spi_data.noQas)
5816                                                 mptscsih_qas_check(hd, id);
5817                                 }
5818                         }
5819                 }
5820         }
5821
5822         spin_lock_irqsave(&dvtaskQ_lock, flags);
5823         dvtaskQ_active = 0;
5824         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5825
5826         return;
5827 }
5828
5829 /* Search IOC page 3 to determine if this is hidden physical disk
5830  */
5831 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
5832 {
5833         if (ioc->spi_data.pIocPg3) {
5834                 Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
5835                 int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
5836
5837                 while (numPDisk) {
5838                         if (pPDisk->PhysDiskID == id) {
5839                                 return 1;
5840                         }
5841                         pPDisk++;
5842                         numPDisk--;
5843                 }
5844         }
5845         return 0;
5846 }
5847
5848 /* Write SDP1 if no QAS has been enabled
5849  */
5850 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
5851 {
5852         VirtDevice *pTarget;
5853         int ii;
5854
5855         if (hd->Targets == NULL)
5856                 return;
5857
5858         for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5859                 if (ii == id)
5860                         continue;
5861
5862                 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
5863                         continue;
5864
5865                 pTarget = hd->Targets[ii];
5866
5867                 if ((pTarget != NULL) && (!pTarget->raidVolume)) {
5868                         if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
5869                                 pTarget->negoFlags |= hd->ioc->spi_data.noQas;
5870                                 mptscsih_writeSDP1(hd, 0, ii, 0);
5871                         }
5872                 } else {
5873                         if (mptscsih_is_phys_disk(hd->ioc, ii) == 1)
5874                                 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
5875                 }
5876         }
5877         return;
5878 }
5879
5880
5881
5882 #define MPT_GET_NVRAM_VALS      0x01
5883 #define MPT_UPDATE_MAX          0x02
5884 #define MPT_SET_MAX             0x04
5885 #define MPT_SET_MIN             0x08
5886 #define MPT_FALLBACK            0x10
5887 #define MPT_SAVE                0x20
5888
5889 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5890 /**
5891  *      mptscsih_doDv - Perform domain validation to a target.
5892  *      @hd: Pointer to MPT_SCSI_HOST structure.
5893  *      @portnum: IOC port number.
5894  *      @target: Physical ID of this target
5895  *
5896  *      Uses the ISR, but with special processing.
5897  *      MUST be single-threaded.
5898  *      Test will exit if target is at async & narrow.
5899  *
5900  *      Return: None.
5901  */
5902 static int
5903 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
5904 {
5905         MPT_ADAPTER             *ioc = hd->ioc;
5906         VirtDevice              *pTarget;
5907         SCSIDevicePage1_t       *pcfg1Data;
5908         SCSIDevicePage0_t       *pcfg0Data;
5909         u8                      *pbuf1;
5910         u8                      *pbuf2;
5911         u8                      *pDvBuf;
5912         dma_addr_t               dvbuf_dma = -1;
5913         dma_addr_t               buf1_dma = -1;
5914         dma_addr_t               buf2_dma = -1;
5915         dma_addr_t               cfg1_dma_addr = -1;
5916         dma_addr_t               cfg0_dma_addr = -1;
5917         ConfigPageHeader_t       header1;
5918         ConfigPageHeader_t       header0;
5919         DVPARAMETERS             dv;
5920         INTERNAL_CMD             iocmd;
5921         CONFIGPARMS              cfg;
5922         int                      dv_alloc = 0;
5923         int                      rc, sz = 0;
5924         int                      bufsize = 0;
5925         int                      dataBufSize = 0;
5926         int                      echoBufSize = 0;
5927         int                      notDone;
5928         int                      patt;
5929         int                      repeat;
5930         int                      retcode = 0;
5931         int                      nfactor =  MPT_ULTRA320;
5932         char                     firstPass = 1;
5933         char                     doFallback = 0;
5934         char                     readPage0;
5935         char                     bus, lun;
5936         char                     inq0 = 0;
5937
5938         if (ioc->spi_data.sdp1length == 0)
5939                 return 0;
5940
5941         if (ioc->spi_data.sdp0length == 0)
5942                 return 0;
5943
5944         /* If multiple buses are used, require that the initiator
5945          * id be the same on all buses.
5946          */
5947         if (id == ioc->pfacts[0].PortSCSIID)
5948                 return 0;
5949
5950         lun = 0;
5951         bus = (u8) bus_number;
5952         ddvtprintk((MYIOC_s_NOTE_FMT
5953                         "DV started: bus=%d, id %d dv @ %p\n",
5954                         ioc->name, bus, id, &dv));
5955
5956         /* Prep DV structure
5957          */
5958         memset (&dv, 0, sizeof(DVPARAMETERS));
5959         dv.id = id;
5960
5961         /* Populate tmax with the current maximum
5962          * transfer parameters for this target.
5963          * Exit if narrow and async.
5964          */
5965         dv.cmd = MPT_GET_NVRAM_VALS;
5966         mptscsih_dv_parms(hd, &dv, NULL);
5967         if ((!dv.max.width) && (!dv.max.offset))
5968                 return 0;
5969
5970         /* Prep SCSI IO structure
5971          */
5972         iocmd.id = id;
5973         iocmd.bus = bus;
5974         iocmd.lun = lun;
5975         iocmd.flags = 0;
5976         iocmd.physDiskNum = -1;
5977         iocmd.rsvd = iocmd.rsvd2 = 0;
5978
5979         pTarget = hd->Targets[id];
5980         if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
5981                 /* Another GEM workaround. Check peripheral device type,
5982                  * if PROCESSOR, quit DV.
5983                  */
5984                 if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
5985                         pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
5986                         return 0;
5987                 }
5988         }
5989
5990         /* Use tagged commands if possible.
5991          */
5992         if (pTarget) {
5993                 if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
5994                         iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
5995                 else {
5996                         if (hd->ioc->facts.FWVersion.Word < 0x01000600)
5997                                 return 0;
5998
5999                         if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
6000                                 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
6001                                 return 0;
6002                 }
6003         }
6004
6005         /* Prep cfg structure
6006          */
6007         cfg.pageAddr = (bus<<8) | id;
6008         cfg.hdr = NULL;
6009
6010         /* Prep SDP0 header
6011          */
6012         header0.PageVersion = ioc->spi_data.sdp0version;
6013         header0.PageLength = ioc->spi_data.sdp0length;
6014         header0.PageNumber = 0;
6015         header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6016
6017         /* Prep SDP1 header
6018          */
6019         header1.PageVersion = ioc->spi_data.sdp1version;
6020         header1.PageLength = ioc->spi_data.sdp1length;
6021         header1.PageNumber = 1;
6022         header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6023
6024         if (header0.PageLength & 1)
6025                 dv_alloc = (header0.PageLength * 4) + 4;
6026
6027         dv_alloc +=  (2048 + (header1.PageLength * 4));
6028
6029         pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
6030         if (pDvBuf == NULL)
6031                 return 0;
6032
6033         sz = 0;
6034         pbuf1 = (u8 *)pDvBuf;
6035         buf1_dma = dvbuf_dma;
6036         sz +=1024;
6037
6038         pbuf2 = (u8 *) (pDvBuf + sz);
6039         buf2_dma = dvbuf_dma + sz;
6040         sz +=1024;
6041
6042         pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
6043         cfg0_dma_addr = dvbuf_dma + sz;
6044         sz += header0.PageLength * 4;
6045
6046         /* 8-byte alignment
6047          */
6048         if (header0.PageLength & 1)
6049                 sz += 4;
6050
6051         pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
6052         cfg1_dma_addr = dvbuf_dma + sz;
6053
6054         /* Skip this ID? Set cfg.hdr to force config page write
6055          */
6056         {
6057                 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
6058                 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6059                         /* Set the factor from nvram */
6060                         nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
6061                         if (nfactor < pspi_data->minSyncFactor )
6062                                 nfactor = pspi_data->minSyncFactor;
6063
6064                         if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
6065                                 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
6066
6067                                 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
6068                                         ioc->name, bus, id, lun));
6069
6070                                 dv.cmd = MPT_SET_MAX;
6071                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6072                                 cfg.hdr = &header1;
6073
6074                                 /* Save the final negotiated settings to
6075                                  * SCSI device page 1.
6076                                  */
6077                                 cfg.physAddr = cfg1_dma_addr;
6078                                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6079                                 cfg.dir = 1;
6080                                 mpt_config(hd->ioc, &cfg);
6081                                 goto target_done;
6082                         }
6083                 }
6084         }
6085
6086         /* Finish iocmd inititialization - hidden or visible disk? */
6087         if (ioc->spi_data.pIocPg3) {
6088                 /* Searc IOC page 3 for matching id
6089                  */
6090                 Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
6091                 int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
6092
6093                 while (numPDisk) {
6094                         if (pPDisk->PhysDiskID == id) {
6095                                 /* match */
6096                                 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
6097                                 iocmd.physDiskNum = pPDisk->PhysDiskNum;
6098
6099                                 /* Quiesce the IM
6100                                  */
6101                                 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
6102                                         ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
6103                                         goto target_done;
6104                                 }
6105                                 break;
6106                         }
6107                         pPDisk++;
6108                         numPDisk--;
6109                 }
6110         }
6111
6112         /* RAID Volume ID's may double for a physical device. If RAID but
6113          * not a physical ID as well, skip DV.
6114          */
6115         if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
6116                 goto target_done;
6117
6118
6119         /* Basic Test.
6120          * Async & Narrow - Inquiry
6121          * Async & Narrow - Inquiry
6122          * Maximum transfer rate - Inquiry
6123          * Compare buffers:
6124          *      If compare, test complete.
6125          *      If miscompare and first pass, repeat
6126          *      If miscompare and not first pass, fall back and repeat
6127          */
6128         hd->pLocal = NULL;
6129         readPage0 = 0;
6130         sz = SCSI_STD_INQUIRY_BYTES;
6131         rc = MPT_SCANDV_GOOD;
6132         while (1) {
6133                 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
6134                 retcode = 0;
6135                 dv.cmd = MPT_SET_MIN;
6136                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6137
6138                 cfg.hdr = &header1;
6139                 cfg.physAddr = cfg1_dma_addr;
6140                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6141                 cfg.dir = 1;
6142                 if (mpt_config(hd->ioc, &cfg) != 0)
6143                         goto target_done;
6144
6145                 /* Wide - narrow - wide workaround case
6146                  */
6147                 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
6148                         /* Send an untagged command to reset disk Qs corrupted
6149                          * when a parity error occurs on a Request Sense.
6150                          */
6151                         if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
6152                                 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
6153                                 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
6154
6155                                 iocmd.cmd = CMD_RequestSense;
6156                                 iocmd.data_dma = buf1_dma;
6157                                 iocmd.data = pbuf1;
6158                                 iocmd.size = 0x12;
6159                                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6160                                         goto target_done;
6161                                 else {
6162                                         if (hd->pLocal == NULL)
6163                                                 goto target_done;
6164                                         rc = hd->pLocal->completion;
6165                                         if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
6166                                                 dv.max.width = 0;
6167                                                 doFallback = 0;
6168                                         } else
6169                                                 goto target_done;
6170                                 }
6171                         } else
6172                                 goto target_done;
6173                 }
6174
6175                 iocmd.cmd = CMD_Inquiry;
6176                 iocmd.data_dma = buf1_dma;
6177                 iocmd.data = pbuf1;
6178                 iocmd.size = sz;
6179                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6180                         goto target_done;
6181                 else {
6182                         if (hd->pLocal == NULL)
6183                                 goto target_done;
6184                         rc = hd->pLocal->completion;
6185                         if (rc == MPT_SCANDV_GOOD) {
6186                                 if (hd->pLocal->scsiStatus == STS_BUSY) {
6187                                         if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
6188                                                 retcode = 1;
6189                                         else
6190                                                 retcode = 0;
6191
6192                                         goto target_done;
6193                                 }
6194                         } else if  (rc == MPT_SCANDV_SENSE) {
6195                                 ;
6196                         } else {
6197                                 /* If first command doesn't complete
6198                                  * with a good status or with a check condition,
6199                                  * exit.
6200                                  */
6201                                 goto target_done;
6202                         }
6203                 }
6204
6205                 /* Reset the size for disks
6206                  */
6207                 inq0 = (*pbuf1) & 0x1F;
6208                 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
6209                         sz = 0x40;
6210                         iocmd.size = sz;
6211                 }
6212
6213                 /* Another GEM workaround. Check peripheral device type,
6214                  * if PROCESSOR, quit DV.
6215                  */
6216                 if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08))
6217                         goto target_done;
6218
6219                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6220                         goto target_done;
6221
6222                 if (sz == 0x40) {
6223                         if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
6224                                 && (pTarget->minSyncFactor > 0x09)) {
6225                                 if ((pbuf1[56] & 0x04) == 0)
6226                                         ;
6227                                 else if ((pbuf1[56] & 0x01) == 1) {
6228                                         pTarget->minSyncFactor =
6229                                             nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
6230                                 } else {
6231                                         pTarget->minSyncFactor =
6232                                             nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
6233                                 }
6234
6235                                 dv.max.factor = pTarget->minSyncFactor;
6236
6237                                 if ((pbuf1[56] & 0x02) == 0) {
6238                                         pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
6239                                         hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
6240                                 }
6241                         }
6242                 }
6243
6244                 if (doFallback)
6245                         dv.cmd = MPT_FALLBACK;
6246                 else
6247                         dv.cmd = MPT_SET_MAX;
6248
6249                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6250                 if (mpt_config(hd->ioc, &cfg) != 0)
6251                         goto target_done;
6252
6253                 if ((!dv.now.width) && (!dv.now.offset))
6254                         goto target_done;
6255
6256                 iocmd.cmd = CMD_Inquiry;
6257                 iocmd.data_dma = buf2_dma;
6258                 iocmd.data = pbuf2;
6259                 iocmd.size = sz;
6260                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6261                         goto target_done;
6262                 else if (hd->pLocal == NULL)
6263                         goto target_done;
6264                 else {
6265                         /* Save the return code.
6266                          * If this is the first pass,
6267                          * read SCSI Device Page 0
6268                          * and update the target max parameters.
6269                          */
6270                         rc = hd->pLocal->completion;
6271                         doFallback = 0;
6272                         if (rc == MPT_SCANDV_GOOD) {
6273                                 if (!readPage0) {
6274                                         u32 sdp0_info;
6275                                         u32 sdp0_nego;
6276
6277                                         cfg.hdr = &header0;
6278                                         cfg.physAddr = cfg0_dma_addr;
6279                                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6280                                         cfg.dir = 0;
6281
6282                                         if (mpt_config(hd->ioc, &cfg) != 0)
6283                                                 goto target_done;
6284
6285                                         sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
6286                                         sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
6287
6288                                         /* Quantum and Fujitsu workarounds.
6289                                          * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
6290                                          * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
6291                                          * Resetart with a request for U160.
6292                                          */
6293                                         if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
6294                                                         doFallback = 1;
6295                                         } else {
6296                                                 dv.cmd = MPT_UPDATE_MAX;
6297                                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
6298                                                 /* Update the SCSI device page 1 area
6299                                                  */
6300                                                 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
6301                                                 readPage0 = 1;
6302                                         }
6303                                 }
6304
6305                                 /* Quantum workaround. Restart this test will the fallback
6306                                  * flag set.
6307                                  */
6308                                 if (doFallback == 0) {
6309                                         if (memcmp(pbuf1, pbuf2, sz) != 0) {
6310                                                 if (!firstPass)
6311                                                         doFallback = 1;
6312                                         } else
6313                                                 break;  /* test complete */
6314                                 }
6315
6316
6317                         } else if (rc == MPT_SCANDV_ISSUE_SENSE)
6318                                 doFallback = 1; /* set fallback flag */
6319                         else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE))
6320                                 doFallback = 1; /* set fallback flag */
6321                         else
6322                                 goto target_done;
6323
6324                         firstPass = 0;
6325                 }
6326         }
6327         ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
6328         inq0 = (*pbuf1) & 0x1F;
6329
6330         /* Continue only for disks
6331          */
6332         if (inq0 != 0)
6333                 goto target_done;
6334
6335         if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
6336                 goto target_done;
6337
6338         /* Start the Enhanced Test.
6339          * 0) issue TUR to clear out check conditions
6340          * 1) read capacity of echo (regular) buffer
6341          * 2) reserve device
6342          * 3) do write-read-compare data pattern test
6343          * 4) release
6344          * 5) update nego parms to target struct
6345          */
6346         cfg.hdr = &header1;
6347         cfg.physAddr = cfg1_dma_addr;
6348         cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6349         cfg.dir = 1;
6350
6351         iocmd.cmd = CMD_TestUnitReady;
6352         iocmd.data_dma = -1;
6353         iocmd.data = NULL;
6354         iocmd.size = 0;
6355         notDone = 1;
6356         while (notDone) {
6357                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6358                         goto target_done;
6359
6360                 if (hd->pLocal == NULL)
6361                         goto target_done;
6362
6363                 rc = hd->pLocal->completion;
6364                 if (rc == MPT_SCANDV_GOOD)
6365                         notDone = 0;
6366                 else if (rc == MPT_SCANDV_SENSE) {
6367                         u8 skey = hd->pLocal->sense[2] & 0x0F;
6368                         u8 asc = hd->pLocal->sense[12];
6369                         u8 ascq = hd->pLocal->sense[13];
6370                         ddvprintk((MYIOC_s_INFO_FMT
6371                                 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6372                                 ioc->name, skey, asc, ascq));
6373
6374                         if (skey == SK_UNIT_ATTENTION)
6375                                 notDone++; /* repeat */
6376                         else if ((skey == SK_NOT_READY) &&
6377                                         (asc == 0x04)&&(ascq == 0x01)) {
6378                                 /* wait then repeat */
6379                                 mdelay (2000);
6380                                 notDone++;
6381                         } else if ((skey == SK_NOT_READY) && (asc == 0x3A)) {
6382                                 /* no medium, try read test anyway */
6383                                 notDone = 0;
6384                         } else {
6385                                 /* All other errors are fatal.
6386                                  */
6387                                 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
6388                                                 ioc->name));
6389                                 goto target_done;
6390                         }
6391                 } else
6392                         goto target_done;
6393         }
6394
6395         iocmd.cmd = CMD_ReadBuffer;
6396         iocmd.data_dma = buf1_dma;
6397         iocmd.data = pbuf1;
6398         iocmd.size = 4;
6399         iocmd.flags |= MPT_ICFLAG_BUF_CAP;
6400
6401         dataBufSize = 0;
6402         echoBufSize = 0;
6403         for (patt = 0; patt < 2; patt++) {
6404                 if (patt == 0)
6405                         iocmd.flags |= MPT_ICFLAG_ECHO;
6406                 else
6407                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
6408
6409                 notDone = 1;
6410                 while (notDone) {
6411                         bufsize = 0;
6412
6413                         /* If not ready after 8 trials,
6414                          * give up on this device.
6415                          */
6416                         if (notDone > 8)
6417                                 goto target_done;
6418
6419                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
6420                                 goto target_done;
6421                         else if (hd->pLocal == NULL)
6422                                 goto target_done;
6423                         else {
6424                                 rc = hd->pLocal->completion;
6425                                 ddvprintk(("ReadBuffer Comp Code %d", rc));
6426                                 ddvprintk(("  buff: %0x %0x %0x %0x\n",
6427                                         pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
6428
6429                                 if (rc == MPT_SCANDV_GOOD) {
6430                                         notDone = 0;
6431                                         if (iocmd.flags & MPT_ICFLAG_ECHO) {
6432                                                 bufsize =  ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
6433                                         } else {
6434                                                 bufsize =  pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
6435                                         }
6436                                 } else if (rc == MPT_SCANDV_SENSE) {
6437                                         u8 skey = hd->pLocal->sense[2] & 0x0F;
6438                                         u8 asc = hd->pLocal->sense[12];
6439                                         u8 ascq = hd->pLocal->sense[13];
6440                                         ddvprintk((MYIOC_s_INFO_FMT
6441                                                 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6442                                                 ioc->name, skey, asc, ascq));
6443                                         if (skey == SK_ILLEGAL_REQUEST) {
6444                                                 notDone = 0;
6445                                         } else if (skey == SK_UNIT_ATTENTION) {
6446                                                 notDone++; /* repeat */
6447                                         } else if ((skey == SK_NOT_READY) &&
6448                                                 (asc == 0x04)&&(ascq == 0x01)) {
6449                                                 /* wait then repeat */
6450                                                 mdelay (2000);
6451                                                 notDone++;
6452                                         } else {
6453                                                 /* All other errors are fatal.
6454                                                  */
6455                                                 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
6456                                                         ioc->name));
6457                                                 goto target_done;
6458                                         }
6459                                 } else {
6460                                         /* All other errors are fatal
6461                                          */
6462                                         goto target_done;
6463                                 }
6464                         }
6465                 }
6466
6467                 if (iocmd.flags & MPT_ICFLAG_ECHO)
6468                         echoBufSize = bufsize;
6469                 else
6470                         dataBufSize = bufsize;
6471         }
6472         sz = 0;
6473         iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
6474
6475         /* Use echo buffers if possible,
6476          * Exit if both buffers are 0.
6477          */
6478         if (echoBufSize > 0) {
6479                 iocmd.flags |= MPT_ICFLAG_ECHO;
6480                 if (dataBufSize > 0)
6481                         bufsize = min(echoBufSize, dataBufSize);
6482                 else
6483                         bufsize = echoBufSize;
6484         } else if (dataBufSize == 0)
6485                 goto target_done;
6486
6487         ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
6488                 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
6489
6490         /* Data buffers for write-read-compare test max 1K.
6491          */
6492         sz = min(bufsize, 1024);
6493
6494         /* --- loop ----
6495          * On first pass, always issue a reserve.
6496          * On additional loops, only if a reset has occurred.
6497          * iocmd.flags indicates if echo or regular buffer
6498          */
6499         for (patt = 0; patt < 4; patt++) {
6500                 ddvprintk(("Pattern %d\n", patt));
6501                 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
6502                         iocmd.cmd = CMD_TestUnitReady;
6503                         iocmd.data_dma = -1;
6504                         iocmd.data = NULL;
6505                         iocmd.size = 0;
6506                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
6507                                 goto target_done;
6508
6509                         iocmd.cmd = CMD_Release6;
6510                         iocmd.data_dma = -1;
6511                         iocmd.data = NULL;
6512                         iocmd.size = 0;
6513                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
6514                                 goto target_done;
6515                         else if (hd->pLocal == NULL)
6516                                 goto target_done;
6517                         else {
6518                                 rc = hd->pLocal->completion;
6519                                 ddvprintk(("Release rc %d\n", rc));
6520                                 if (rc == MPT_SCANDV_GOOD)
6521                                         iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6522                                 else
6523                                         goto target_done;
6524                         }
6525                         iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6526                 }
6527                 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
6528
6529                 repeat = 5;
6530                 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
6531                         iocmd.cmd = CMD_Reserve6;
6532                         iocmd.data_dma = -1;
6533                         iocmd.data = NULL;
6534                         iocmd.size = 0;
6535                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
6536                                 goto target_done;
6537                         else if (hd->pLocal == NULL)
6538                                 goto target_done;
6539                         else {
6540                                 rc = hd->pLocal->completion;
6541                                 if (rc == MPT_SCANDV_GOOD) {
6542                                         iocmd.flags |= MPT_ICFLAG_RESERVED;
6543                                 } else if (rc == MPT_SCANDV_SENSE) {
6544                                         /* Wait if coming ready
6545                                          */
6546                                         u8 skey = hd->pLocal->sense[2] & 0x0F;
6547                                         u8 asc = hd->pLocal->sense[12];
6548                                         u8 ascq = hd->pLocal->sense[13];
6549                                         ddvprintk((MYIOC_s_INFO_FMT
6550                                                 "DV: Reserve Failed: ", ioc->name));
6551                                         ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6552                                                         skey, asc, ascq));
6553
6554                                         if ((skey == SK_NOT_READY) && (asc == 0x04)&&
6555                                                                         (ascq == 0x01)) {
6556                                                 /* wait then repeat */
6557                                                 mdelay (2000);
6558                                                 notDone++;
6559                                         } else {
6560                                                 ddvprintk((MYIOC_s_INFO_FMT
6561                                                         "DV: Reserved Failed.", ioc->name));
6562                                                 goto target_done;
6563                                         }
6564                                 } else {
6565                                         ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
6566                                                          ioc->name));
6567                                         goto target_done;
6568                                 }
6569                         }
6570                 }
6571
6572                 mptscsih_fillbuf(pbuf1, sz, patt, 1);
6573                 iocmd.cmd = CMD_WriteBuffer;
6574                 iocmd.data_dma = buf1_dma;
6575                 iocmd.data = pbuf1;
6576                 iocmd.size = sz;
6577                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6578                         goto target_done;
6579                 else if (hd->pLocal == NULL)
6580                         goto target_done;
6581                 else {
6582                         rc = hd->pLocal->completion;
6583                         if (rc == MPT_SCANDV_GOOD)
6584                                 ;               /* Issue read buffer */
6585                         else if (rc == MPT_SCANDV_DID_RESET) {
6586                                 /* If using echo buffers, reset to data buffers.
6587                                  * Else do Fallback and restart
6588                                  * this test (re-issue reserve
6589                                  * because of bus reset).
6590                                  */
6591                                 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
6592                                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
6593                                 } else {
6594                                         dv.cmd = MPT_FALLBACK;
6595                                         mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6596
6597                                         if (mpt_config(hd->ioc, &cfg) != 0)
6598                                                 goto target_done;
6599
6600                                         if ((!dv.now.width) && (!dv.now.offset))
6601                                                 goto target_done;
6602                                 }
6603
6604                                 iocmd.flags |= MPT_ICFLAG_DID_RESET;
6605                                 patt = -1;
6606                                 continue;
6607                         } else if (rc == MPT_SCANDV_SENSE) {
6608                                 /* Restart data test if UA, else quit.
6609                                  */
6610                                 u8 skey = hd->pLocal->sense[2] & 0x0F;
6611                                 ddvprintk((MYIOC_s_INFO_FMT
6612                                         "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
6613                                         hd->pLocal->sense[12], hd->pLocal->sense[13]));
6614                                 if (skey == SK_UNIT_ATTENTION) {
6615                                         patt = -1;
6616                                         continue;
6617                                 } else if (skey == SK_ILLEGAL_REQUEST) {
6618                                         if (iocmd.flags & MPT_ICFLAG_ECHO) {
6619                                                 if (dataBufSize >= bufsize) {
6620                                                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
6621                                                         patt = -1;
6622                                                         continue;
6623                                                 }
6624                                         }
6625                                         goto target_done;
6626                                 }
6627                                 else
6628                                         goto target_done;
6629                         } else {
6630                                 /* fatal error */
6631                                 goto target_done;
6632                         }
6633                 }
6634
6635                 iocmd.cmd = CMD_ReadBuffer;
6636                 iocmd.data_dma = buf2_dma;
6637                 iocmd.data = pbuf2;
6638                 iocmd.size = sz;
6639                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6640                         goto target_done;
6641                 else if (hd->pLocal == NULL)
6642                         goto target_done;
6643                 else {
6644                         rc = hd->pLocal->completion;
6645                         if (rc == MPT_SCANDV_GOOD) {
6646                                  /* If buffers compare,
6647                                   * go to next pattern,
6648                                   * else, do a fallback and restart
6649                                   * data transfer test.
6650                                   */
6651                                 if (memcmp (pbuf1, pbuf2, sz) == 0) {
6652                                         ; /* goto next pattern */
6653                                 } else {
6654                                         /* Miscompare with Echo buffer, go to data buffer,
6655                                          * if that buffer exists.
6656                                          * Miscompare with Data buffer, check first 4 bytes,
6657                                          * some devices return capacity. Exit in this case.
6658                                          */
6659                                         if (iocmd.flags & MPT_ICFLAG_ECHO) {
6660                                                 if (dataBufSize >= bufsize)
6661                                                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
6662                                                 else
6663                                                         goto target_done;
6664                                         } else {
6665                                                 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
6666                                                         /* Argh. Device returning wrong data.
6667                                                          * Quit DV for this device.
6668                                                          */
6669                                                         goto target_done;
6670                                                 }
6671
6672                                                 /* Had an actual miscompare. Slow down.*/
6673                                                 dv.cmd = MPT_FALLBACK;
6674                                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6675
6676                                                 if (mpt_config(hd->ioc, &cfg) != 0)
6677                                                         goto target_done;
6678
6679                                                 if ((!dv.now.width) && (!dv.now.offset))
6680                                                         goto target_done;
6681                                         }
6682
6683                                         patt = -1;
6684                                         continue;
6685                                 }
6686                         } else if (rc == MPT_SCANDV_DID_RESET) {
6687                                 /* Do Fallback and restart
6688                                  * this test (re-issue reserve
6689                                  * because of bus reset).
6690                                  */
6691                                 dv.cmd = MPT_FALLBACK;
6692                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6693
6694                                 if (mpt_config(hd->ioc, &cfg) != 0)
6695                                          goto target_done;
6696
6697                                 if ((!dv.now.width) && (!dv.now.offset))
6698                                         goto target_done;
6699
6700                                 iocmd.flags |= MPT_ICFLAG_DID_RESET;
6701                                 patt = -1;
6702                                 continue;
6703                         } else if (rc == MPT_SCANDV_SENSE) {
6704                                 /* Restart data test if UA, else quit.
6705                                  */
6706                                 u8 skey = hd->pLocal->sense[2] & 0x0F;
6707                                 ddvprintk((MYIOC_s_INFO_FMT
6708                                         "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
6709                                         hd->pLocal->sense[12], hd->pLocal->sense[13]));
6710                                 if (skey == SK_UNIT_ATTENTION) {
6711                                         patt = -1;
6712                                         continue;
6713                                 }
6714                                 else
6715                                         goto target_done;
6716                         } else {
6717                                 /* fatal error */
6718                                 goto target_done;
6719                         }
6720                 }
6721
6722         } /* --- end of patt loop ---- */
6723
6724 target_done:
6725         if (iocmd.flags & MPT_ICFLAG_RESERVED) {
6726                 iocmd.cmd = CMD_Release6;
6727                 iocmd.data_dma = -1;
6728                 iocmd.data = NULL;
6729                 iocmd.size = 0;
6730                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6731                         printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
6732                                         ioc->name, id);
6733                 else if (hd->pLocal) {
6734                         if (hd->pLocal->completion == MPT_SCANDV_GOOD)
6735                                 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6736                 } else {
6737                         printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
6738                                                 ioc->name, id);
6739                 }
6740         }
6741
6742
6743         /* Set if cfg1_dma_addr contents is valid
6744          */
6745         if ((cfg.hdr != NULL) && (retcode == 0)){
6746                 /* If disk, not U320, disable QAS
6747                  */
6748                 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320))
6749                         hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
6750
6751                 dv.cmd = MPT_SAVE;
6752                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6753
6754                 /* Double writes to SDP1 can cause problems,
6755                  * skip save of the final negotiated settings to
6756                  * SCSI device page 1.
6757                  *
6758                 cfg.hdr = &header1;
6759                 cfg.physAddr = cfg1_dma_addr;
6760                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6761                 cfg.dir = 1;
6762                 mpt_config(hd->ioc, &cfg);
6763                  */
6764         }
6765
6766         /* If this is a RAID Passthrough, enable internal IOs
6767          */
6768         if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
6769                 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
6770                         ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
6771         }
6772
6773         /* Done with the DV scan of the current target
6774          */
6775         if (pDvBuf)
6776                 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
6777
6778         ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n",
6779                         ioc->name));
6780
6781         return retcode;
6782 }
6783
6784 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6785 /*      mptscsih_dv_parms - perform a variety of operations on the
6786  *      parameters used for negotiation.
6787  *      @hd: Pointer to a SCSI host.
6788  *      @dv: Pointer to a structure that contains the maximum and current
6789  *              negotiated parameters.
6790  */
6791 static void
6792 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
6793 {
6794         VirtDevice              *pTarget;
6795         SCSIDevicePage0_t       *pPage0;
6796         SCSIDevicePage1_t       *pPage1;
6797         int                     val = 0, data, configuration;
6798         u8                      width = 0;
6799         u8                      offset = 0;
6800         u8                      factor = 0;
6801         u8                      negoFlags = 0;
6802         u8                      cmd = dv->cmd;
6803         u8                      id = dv->id;
6804
6805         switch (cmd) {
6806         case MPT_GET_NVRAM_VALS:
6807                 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
6808                                                          hd->ioc->name));
6809                 /* Get the NVRAM values and save in tmax
6810                  * If not an LVD bus, the adapter minSyncFactor has been
6811                  * already throttled back.
6812                  */
6813                 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
6814                         width = pTarget->maxWidth;
6815                         offset = pTarget->maxOffset;
6816                         factor = pTarget->minSyncFactor;
6817                         negoFlags = pTarget->negoFlags;
6818                 } else {
6819                         if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6820                                 data = hd->ioc->spi_data.nvram[id];
6821                                 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
6822                                 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
6823                                         factor = MPT_ASYNC;
6824                                 else {
6825                                         factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
6826                                         if ((factor == 0) || (factor == MPT_ASYNC)){
6827                                                 factor = MPT_ASYNC;
6828                                                 offset = 0;
6829                                         }
6830                                 }
6831                         } else {
6832                                 width = MPT_NARROW;
6833                                 offset = 0;
6834                                 factor = MPT_ASYNC;
6835                         }
6836
6837                         /* Set the negotiation flags */
6838                         negoFlags = hd->ioc->spi_data.noQas;
6839                         if (!width)
6840                                 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
6841
6842                         if (!offset)
6843                                 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
6844                 }
6845
6846                 /* limit by adapter capabilities */
6847                 width = min(width, hd->ioc->spi_data.maxBusWidth);
6848                 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
6849                 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
6850
6851                 /* Check Consistency */
6852                 if (offset && (factor < MPT_ULTRA2) && !width)
6853                         factor = MPT_ULTRA2;
6854
6855                 dv->max.width = width;
6856                 dv->max.offset = offset;
6857                 dv->max.factor = factor;
6858                 dv->max.flags = negoFlags;
6859                 ddvprintk((" width %d, factor %x, offset %x flags %x\n",
6860                                 width, factor, offset, negoFlags));
6861                 break;
6862
6863         case MPT_UPDATE_MAX:
6864                 ddvprintk((MYIOC_s_NOTE_FMT
6865                         "Updating with SDP0 Data: ", hd->ioc->name));
6866                 /* Update tmax values with those from Device Page 0.*/
6867                 pPage0 = (SCSIDevicePage0_t *) pPage;
6868                 if (pPage0) {
6869                         val = cpu_to_le32(pPage0->NegotiatedParameters);
6870                         dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
6871                         dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
6872                         dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
6873                 }
6874
6875                 dv->now.width = dv->max.width;
6876                 dv->now.offset = dv->max.offset;
6877                 dv->now.factor = dv->max.factor;
6878                 ddvprintk(("width %d, factor %x, offset %x, flags %x\n",
6879                                 dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
6880                 break;
6881
6882         case MPT_SET_MAX:
6883                 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
6884                                                                 hd->ioc->name));
6885                 /* Set current to the max values. Update the config page.*/
6886                 dv->now.width = dv->max.width;
6887                 dv->now.offset = dv->max.offset;
6888                 dv->now.factor = dv->max.factor;
6889                 dv->now.flags = dv->max.flags;
6890
6891                 pPage1 = (SCSIDevicePage1_t *)pPage;
6892                 if (pPage1) {
6893                         mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
6894                                 dv->now.offset, &val, &configuration, dv->now.flags);
6895                         pPage1->RequestedParameters = le32_to_cpu(val);
6896                         pPage1->Reserved = 0;
6897                         pPage1->Configuration = le32_to_cpu(configuration);
6898
6899                 }
6900
6901                 ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n",
6902                                 dv->now.width, dv->now.factor, dv->now.offset, val, configuration));
6903                 break;
6904
6905         case MPT_SET_MIN:
6906                 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
6907                                                                 hd->ioc->name));
6908                 /* Set page to asynchronous and narrow
6909                  * Do not update now, breaks fallback routine. */
6910                 width = MPT_NARROW;
6911                 offset = 0;
6912                 factor = MPT_ASYNC;
6913                 negoFlags = dv->max.flags;
6914
6915                 pPage1 = (SCSIDevicePage1_t *)pPage;
6916                 if (pPage1) {
6917                         mptscsih_setDevicePage1Flags (width, factor,
6918                                 offset, &val, &configuration, negoFlags);
6919                         pPage1->RequestedParameters = le32_to_cpu(val);
6920                         pPage1->Reserved = 0;
6921                         pPage1->Configuration = le32_to_cpu(configuration);
6922                 }
6923                 ddvprintk(("width %d, factor %x, offset %x request %x config %x\n",
6924                                 width, factor, offset, val, configuration));
6925                 break;
6926
6927         case MPT_FALLBACK:
6928                 ddvprintk((MYIOC_s_NOTE_FMT
6929                         "Fallback: Start: offset %d, factor %x, width %d \n",
6930                                 hd->ioc->name, dv->now.offset,
6931                                 dv->now.factor, dv->now.width));
6932                 width = dv->now.width;
6933                 offset = dv->now.offset;
6934                 factor = dv->now.factor;
6935                 if ((offset) && (dv->max.width)) {
6936                         if (factor < MPT_ULTRA160)
6937                                 factor = MPT_ULTRA160;
6938                         else if (factor < MPT_ULTRA2) {
6939                                 factor = MPT_ULTRA2;
6940                                 width = MPT_WIDE;
6941                         } else if ((factor == MPT_ULTRA2) && width) {
6942                                 factor = MPT_ULTRA2;
6943                                 width = MPT_NARROW;
6944                         } else if (factor < MPT_ULTRA) {
6945                                 factor = MPT_ULTRA;
6946                                 width = MPT_WIDE;
6947                         } else if ((factor == MPT_ULTRA) && width) {
6948                                 width = MPT_NARROW;
6949                         } else if (factor < MPT_FAST) {
6950                                 factor = MPT_FAST;
6951                                 width = MPT_WIDE;
6952                         } else if ((factor == MPT_FAST) && width) {
6953                                 factor = MPT_FAST;
6954                                 width = MPT_NARROW;
6955                         } else if (factor < MPT_SCSI) {
6956                                 factor = MPT_SCSI;
6957                                 width = MPT_WIDE;
6958                         } else if ((factor == MPT_SCSI) && width) {
6959                                 factor = MPT_SCSI;
6960                                 width = MPT_NARROW;
6961                         } else {
6962                                 factor = MPT_ASYNC;
6963                                 offset = 0;
6964                         }
6965
6966                 } else if (offset) {
6967                         width = MPT_NARROW;
6968                         if (factor < MPT_ULTRA)
6969                                 factor = MPT_ULTRA;
6970                         else if (factor < MPT_FAST)
6971                                 factor = MPT_FAST;
6972                         else if (factor < MPT_SCSI)
6973                                 factor = MPT_SCSI;
6974                         else {
6975                                 factor = MPT_ASYNC;
6976                                 offset = 0;
6977                         }
6978
6979                 } else {
6980                         width = MPT_NARROW;
6981                         factor = MPT_ASYNC;
6982                 }
6983                 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
6984
6985                 dv->now.width = width;
6986                 dv->now.offset = offset;
6987                 dv->now.factor = factor;
6988                 dv->now.flags = dv->max.flags;
6989
6990                 pPage1 = (SCSIDevicePage1_t *)pPage;
6991                 if (pPage1) {
6992                         mptscsih_setDevicePage1Flags (width, factor, offset, &val,
6993                                                 &configuration, dv->now.flags);
6994
6995                         pPage1->RequestedParameters = le32_to_cpu(val);
6996                         pPage1->Reserved = 0;
6997                         pPage1->Configuration = le32_to_cpu(configuration);
6998                 }
6999
7000                 ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n",
7001                              dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
7002                 break;
7003
7004         case MPT_SAVE:
7005                 ddvprintk((MYIOC_s_NOTE_FMT
7006                         "Saving to Target structure: ", hd->ioc->name));
7007                 ddvprintk(("offset %d, factor %x, width %d \n",
7008                              dv->now.offset, dv->now.factor, dv->now.width));
7009
7010                 /* Save these values to target structures
7011                  * or overwrite nvram (phys disks only).
7012                  */
7013
7014                 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
7015                         pTarget->maxWidth = dv->now.width;
7016                         pTarget->maxOffset = dv->now.offset;
7017                         pTarget->minSyncFactor = dv->now.factor;
7018                         pTarget->negoFlags = dv->now.flags;
7019                 } else {
7020                         /* Preserv all flags, use
7021                          * read-modify-write algorithm
7022                          */
7023                         if (hd->ioc->spi_data.nvram) {
7024                                 data = hd->ioc->spi_data.nvram[id];
7025
7026                                 if (dv->now.width)
7027                                         data &= ~MPT_NVRAM_WIDE_DISABLE;
7028                                 else
7029                                         data |= MPT_NVRAM_WIDE_DISABLE;
7030
7031                                 if (!dv->now.offset)
7032                                         factor = MPT_ASYNC;
7033
7034                                 data &= ~MPT_NVRAM_SYNC_MASK;
7035                                 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
7036
7037                                 hd->ioc->spi_data.nvram[id] = data;
7038                         }
7039                 }
7040                 break;
7041         }
7042 }
7043
7044 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7045 /*      mptscsih_fillbuf - fill a buffer with a special data pattern
7046  *              cleanup. For bus scan only.
7047  *
7048  *      @buffer: Pointer to data buffer to be filled.
7049  *      @size: Number of bytes to fill
7050  *      @index: Pattern index
7051  *      @width: bus width, 0 (8 bits) or 1 (16 bits)
7052  */
7053 static void
7054 mptscsih_fillbuf(char *buffer, int size, int index, int width)
7055 {
7056         char *ptr = buffer;
7057         int ii;
7058         char byte;
7059         short val;
7060
7061         switch (index) {
7062         case 0:
7063
7064                 if (width) {
7065                         /* Pattern:  0000 FFFF 0000 FFFF
7066                          */
7067                         for (ii=0; ii < size; ii++, ptr++) {
7068                                 if (ii & 0x02)
7069                                         *ptr = 0xFF;
7070                                 else
7071                                         *ptr = 0x00;
7072                         }
7073                 } else {
7074                         /* Pattern:  00 FF 00 FF
7075                          */
7076                         for (ii=0; ii < size; ii++, ptr++) {
7077                                 if (ii & 0x01)
7078                                         *ptr = 0xFF;
7079                                 else
7080                                         *ptr = 0x00;
7081                         }
7082                 }
7083                 break;
7084
7085         case 1:
7086                 if (width) {
7087                         /* Pattern:  5555 AAAA 5555 AAAA 5555
7088                          */
7089                         for (ii=0; ii < size; ii++, ptr++) {
7090                                 if (ii & 0x02)
7091                                         *ptr = 0xAA;
7092                                 else
7093                                         *ptr = 0x55;
7094                         }
7095                 } else {
7096                         /* Pattern:  55 AA 55 AA 55
7097                          */
7098                         for (ii=0; ii < size; ii++, ptr++) {
7099                                 if (ii & 0x01)
7100                                         *ptr = 0xAA;
7101                                 else
7102                                         *ptr = 0x55;
7103                         }
7104                 }
7105                 break;
7106
7107         case 2:
7108                 /* Pattern:  00 01 02 03 04 05
7109                  * ... FE FF 00 01..
7110                  */
7111                 for (ii=0; ii < size; ii++, ptr++)
7112                         *ptr = (char) ii;
7113                 break;
7114
7115         case 3:
7116                 if (width) {
7117                         /* Wide Pattern:  FFFE 0001 FFFD 0002
7118                          * ...  4000 DFFF 8000 EFFF
7119                          */
7120                         byte = 0;
7121                         for (ii=0; ii < size/2; ii++) {
7122                                 /* Create the base pattern
7123                                  */
7124                                 val = (1 << byte);
7125                                 /* every 64 (0x40) bytes flip the pattern
7126                                  * since we fill 2 bytes / iteration,
7127                                  * test for ii = 0x20
7128                                  */
7129                                 if (ii & 0x20)
7130                                         val = ~(val);
7131
7132                                 if (ii & 0x01) {
7133                                         *ptr = (char)( (val & 0xFF00) >> 8);
7134                                         ptr++;
7135                                         *ptr = (char)(val & 0xFF);
7136                                         byte++;
7137                                         byte &= 0x0F;
7138                                 } else {
7139                                         val = ~val;
7140                                         *ptr = (char)( (val & 0xFF00) >> 8);
7141                                         ptr++;
7142                                         *ptr = (char)(val & 0xFF);
7143                                 }
7144
7145                                 ptr++;
7146                         }
7147                 } else {
7148                         /* Narrow Pattern:  FE 01 FD 02 FB 04
7149                          * .. 7F 80 01 FE 02 FD ...  80 7F
7150                          */
7151                         byte = 0;
7152                         for (ii=0; ii < size; ii++, ptr++) {
7153                                 /* Base pattern - first 32 bytes
7154                                  */
7155                                 if (ii & 0x01) {
7156                                         *ptr = (1 << byte);
7157                                         byte++;
7158                                         byte &= 0x07;
7159                                 } else {
7160                                         *ptr = (char) (~(1 << byte));
7161                                 }
7162
7163                                 /* Flip the pattern every 32 bytes
7164                                  */
7165                                 if (ii & 0x20)
7166                                         *ptr = ~(*ptr);
7167                         }
7168                 }
7169                 break;
7170         }
7171 }
7172 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
7173
7174 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7175 /* Commandline Parsing routines and defines.
7176  *
7177  * insmod format:
7178  *      insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1"
7179  *  boot format:
7180  *      mptscsih=width:1,dv:n,factor:0x8,saf-te:1
7181  *
7182  */
7183 #ifdef MODULE
7184 #define ARG_SEP ' '
7185 #else
7186 #define ARG_SEP ','
7187 #endif
7188
7189 #ifdef MODULE
7190 static char setup_token[] __initdata =
7191         "dv:"
7192         "width:"
7193         "factor:"
7194         "saf-te:"
7195        ;        /* DO NOT REMOVE THIS ';' */
7196 #endif
7197        
7198 #define OPT_DV                  1
7199 #define OPT_MAX_WIDTH           2
7200 #define OPT_MIN_SYNC_FACTOR     3
7201 #define OPT_SAF_TE              4
7202
7203 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7204 #ifdef MODULE
7205 static int
7206 get_setup_token(char *p)
7207 {
7208         char *cur = setup_token;
7209         char *pc;
7210         int i = 0;
7211
7212         while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7213                 ++pc;
7214                 ++i;
7215                 if (!strncmp(p, cur, pc - cur))
7216                         return i;
7217                 cur = pc;
7218         }
7219         return 0;
7220 }
7221
7222 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7223 static int
7224 mptscsih_setup(char *str)
7225 {
7226         char *cur = str;
7227         char *pc, *pv;
7228         unsigned long val;
7229         int  c;
7230
7231         while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7232                 char *pe;
7233
7234                 val = 0;
7235                 pv = pc;
7236                 c = *++pv;
7237
7238                 if      (c == 'n')
7239                         val = 0;
7240                 else if (c == 'y')
7241                         val = 1;
7242                 else
7243                         val = (int) simple_strtoul(pv, &pe, 0);
7244
7245                 printk("Found Token: %s, value %x\n", cur, (int)val);
7246                 switch (get_setup_token(cur)) {
7247                 case OPT_DV:
7248                         driver_setup.dv = val;
7249                         break;
7250
7251                 case OPT_MAX_WIDTH:
7252                         driver_setup.max_width = val;
7253                         break;
7254
7255                 case OPT_MIN_SYNC_FACTOR:
7256                         driver_setup.min_sync_fac = val;
7257                         break;
7258
7259                 case OPT_SAF_TE:
7260                         driver_setup.saf_te = val;
7261                         break;
7262
7263                 default:
7264                         printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
7265                         break;
7266                 }
7267
7268                 if ((cur = strchr(cur, ARG_SEP)) != NULL)
7269                         ++cur;
7270         }
7271         return 1;
7272 }
7273 #endif
7274 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7275
7276
7277 module_init(mptscsih_init);
7278 module_exit(mptscsih_exit);