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