[SCSI] - mptfusion - convert to new change_queue_depth API
[linux-2.6] / drivers / message / fusion / mptscsih.c
1 /*
2  *  linux/drivers/message/fusion/mptscsih.c
3  *      For use with LSI Logic PCI chip/adapter(s)
4  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5  *
6  *  Copyright (c) 1999-2005 LSI Logic Corporation
7  *  (mailto:mpt_linux_developer@lsil.com)
8  *
9  */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11 /*
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; version 2 of the License.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     NO WARRANTY
22     THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23     CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24     LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26     solely responsible for determining the appropriateness of using and
27     distributing the Program and assumes all risks associated with its
28     exercise of rights under this Agreement, including but not limited to
29     the risks and costs of program errors, damage to or loss of data,
30     programs or equipment, and unavailability or interruption of operations.
31
32     DISCLAIMER OF LIABILITY
33     NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34     DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35     DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37     TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38     USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39     HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41     You should have received a copy of the GNU General Public License
42     along with this program; if not, write to the Free Software
43     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44 */
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47 #include "linux_compat.h"       /* linux-2.6 tweaks */
48 #include <linux/module.h>
49 #include <linux/kernel.h>
50 #include <linux/init.h>
51 #include <linux/errno.h>
52 #include <linux/kdev_t.h>
53 #include <linux/blkdev.h>
54 #include <linux/delay.h>        /* for mdelay */
55 #include <linux/interrupt.h>    /* needed for in_interrupt() proto */
56 #include <linux/reboot.h>       /* notifier code */
57 #include <linux/sched.h>
58 #include <linux/workqueue.h>
59
60 #include <scsi/scsi.h>
61 #include <scsi/scsi_cmnd.h>
62 #include <scsi/scsi_device.h>
63 #include <scsi/scsi_host.h>
64 #include <scsi/scsi_tcq.h>
65
66 #include "mptbase.h"
67 #include "mptscsih.h"
68
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME         "Fusion MPT SCSI Host driver"
71 #define my_VERSION      MPT_LINUX_VERSION_COMMON
72 #define MYNAM           "mptscsih"
73
74 MODULE_AUTHOR(MODULEAUTHOR);
75 MODULE_DESCRIPTION(my_NAME);
76 MODULE_LICENSE("GPL");
77
78 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
79
80 typedef struct _BIG_SENSE_BUF {
81         u8              data[MPT_SENSE_BUFFER_ALLOC];
82 } BIG_SENSE_BUF;
83
84 #define MPT_SCANDV_GOOD                 (0x00000000) /* must be 0 */
85 #define MPT_SCANDV_DID_RESET            (0x00000001)
86 #define MPT_SCANDV_SENSE                (0x00000002)
87 #define MPT_SCANDV_SOME_ERROR           (0x00000004)
88 #define MPT_SCANDV_SELECTION_TIMEOUT    (0x00000008)
89 #define MPT_SCANDV_ISSUE_SENSE          (0x00000010)
90 #define MPT_SCANDV_FALLBACK             (0x00000020)
91
92 #define MPT_SCANDV_MAX_RETRIES          (10)
93
94 #define MPT_ICFLAG_BUF_CAP      0x01    /* ReadBuffer Read Capacity format */
95 #define MPT_ICFLAG_ECHO         0x02    /* ReadBuffer Echo buffer format */
96 #define MPT_ICFLAG_PHYS_DISK    0x04    /* Any SCSI IO but do Phys Disk Format */
97 #define MPT_ICFLAG_TAGGED_CMD   0x08    /* Do tagged IO */
98 #define MPT_ICFLAG_DID_RESET    0x20    /* Bus Reset occurred with this command */
99 #define MPT_ICFLAG_RESERVED     0x40    /* Reserved has been issued */
100
101 typedef struct _internal_cmd {
102         char            *data;          /* data pointer */
103         dma_addr_t      data_dma;       /* data dma address */
104         int             size;           /* transfer size */
105         u8              cmd;            /* SCSI Op Code */
106         u8              bus;            /* bus number */
107         u8              id;             /* SCSI ID (virtual) */
108         u8              lun;
109         u8              flags;          /* Bit Field - See above */
110         u8              physDiskNum;    /* Phys disk number, -1 else */
111         u8              rsvd2;
112         u8              rsvd;
113 } INTERNAL_CMD;
114
115 typedef struct _negoparms {
116         u8 width;
117         u8 offset;
118         u8 factor;
119         u8 flags;
120 } NEGOPARMS;
121
122 typedef struct _dv_parameters {
123         NEGOPARMS        max;
124         NEGOPARMS        now;
125         u8               cmd;
126         u8               id;
127         u16              pad1;
128 } DVPARAMETERS;
129
130 /*
131  *  Other private/forward protos...
132  */
133 int             mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
134 static void     mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
135 int             mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
136
137 static int      mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
138                                  SCSIIORequest_t *pReq, int req_idx);
139 static void     mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
140 static void     mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
141 static int      mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
142 static int      mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
143 static u32      SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
144
145 static int      mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
146 static int      mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
147
148 int             mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
149 int             mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
150
151 static void     mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
152 static void     mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
153 static void     mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
154 static void     mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
155 static void     mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
156 static int      mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
157 static int      mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
158 int             mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
159 static int      mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
160 static int      mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
161
162 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
163 static int      mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
164 static void     mptscsih_domainValidation(void *hd);
165 static int      mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
166 static void     mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
167 static int      mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
168 static void     mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
169 static void     mptscsih_fillbuf(char *buffer, int size, int index, int width);
170 #endif
171
172 void            mptscsih_remove(struct pci_dev *);
173 void            mptscsih_shutdown(struct device *);
174 #ifdef CONFIG_PM
175 int             mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
176 int             mptscsih_resume(struct pci_dev *pdev);
177 #endif
178
179 #define SNS_LEN(scp)    sizeof((scp)->sense_buffer)
180
181 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
182 /*
183  * Domain Validation task structure
184  */
185 static DEFINE_SPINLOCK(dvtaskQ_lock);
186 static int dvtaskQ_active = 0;
187 static int dvtaskQ_release = 0;
188 static struct work_struct       dvTaskQ_task;
189 #endif
190
191 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
192 /**
193  *      mptscsih_add_sge - Place a simple SGE at address pAddr.
194  *      @pAddr: virtual address for SGE
195  *      @flagslength: SGE flags and data transfer length
196  *      @dma_addr: Physical address
197  *
198  *      This routine places a MPT request frame back on the MPT adapter's
199  *      FreeQ.
200  */
201 static inline void
202 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
203 {
204         if (sizeof(dma_addr_t) == sizeof(u64)) {
205                 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
206                 u32 tmp = dma_addr & 0xFFFFFFFF;
207
208                 pSge->FlagsLength = cpu_to_le32(flagslength);
209                 pSge->Address.Low = cpu_to_le32(tmp);
210                 tmp = (u32) ((u64)dma_addr >> 32);
211                 pSge->Address.High = cpu_to_le32(tmp);
212
213         } else {
214                 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
215                 pSge->FlagsLength = cpu_to_le32(flagslength);
216                 pSge->Address = cpu_to_le32(dma_addr);
217         }
218 } /* mptscsih_add_sge() */
219
220 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
221 /**
222  *      mptscsih_add_chain - Place a chain SGE at address pAddr.
223  *      @pAddr: virtual address for SGE
224  *      @next: nextChainOffset value (u32's)
225  *      @length: length of next SGL segment
226  *      @dma_addr: Physical address
227  *
228  *      This routine places a MPT request frame back on the MPT adapter's
229  *      FreeQ.
230  */
231 static inline void
232 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
233 {
234         if (sizeof(dma_addr_t) == sizeof(u64)) {
235                 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
236                 u32 tmp = dma_addr & 0xFFFFFFFF;
237
238                 pChain->Length = cpu_to_le16(length);
239                 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
240
241                 pChain->NextChainOffset = next;
242
243                 pChain->Address.Low = cpu_to_le32(tmp);
244                 tmp = (u32) ((u64)dma_addr >> 32);
245                 pChain->Address.High = cpu_to_le32(tmp);
246         } else {
247                 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
248                 pChain->Length = cpu_to_le16(length);
249                 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
250                 pChain->NextChainOffset = next;
251                 pChain->Address = cpu_to_le32(dma_addr);
252         }
253 } /* mptscsih_add_chain() */
254
255 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
256 /*
257  *      mptscsih_getFreeChainBuffer - Function to get a free chain
258  *      from the MPT_SCSI_HOST FreeChainQ.
259  *      @ioc: Pointer to MPT_ADAPTER structure
260  *      @req_idx: Index of the SCSI IO request frame. (output)
261  *
262  *      return SUCCESS or FAILED
263  */
264 static inline int
265 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
266 {
267         MPT_FRAME_HDR *chainBuf;
268         unsigned long flags;
269         int rc;
270         int chain_idx;
271
272         dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
273                         ioc->name));
274         spin_lock_irqsave(&ioc->FreeQlock, flags);
275         if (!list_empty(&ioc->FreeChainQ)) {
276                 int offset;
277
278                 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
279                                 u.frame.linkage.list);
280                 list_del(&chainBuf->u.frame.linkage.list);
281                 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
282                 chain_idx = offset / ioc->req_sz;
283                 rc = SUCCESS;
284                 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
285                         ioc->name, *retIndex, chainBuf));
286         } else {
287                 rc = FAILED;
288                 chain_idx = MPT_HOST_NO_CHAIN;
289                 dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
290                         ioc->name));
291         }
292         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
293
294         *retIndex = chain_idx;
295         return rc;
296 } /* mptscsih_getFreeChainBuffer() */
297
298 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
299 /*
300  *      mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
301  *      SCSIIORequest_t Message Frame.
302  *      @ioc: Pointer to MPT_ADAPTER structure
303  *      @SCpnt: Pointer to scsi_cmnd structure
304  *      @pReq: Pointer to SCSIIORequest_t structure
305  *
306  *      Returns ...
307  */
308 static int
309 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
310                 SCSIIORequest_t *pReq, int req_idx)
311 {
312         char    *psge;
313         char    *chainSge;
314         struct scatterlist *sg;
315         int      frm_sz;
316         int      sges_left, sg_done;
317         int      chain_idx = MPT_HOST_NO_CHAIN;
318         int      sgeOffset;
319         int      numSgeSlots, numSgeThisFrame;
320         u32      sgflags, sgdir, thisxfer = 0;
321         int      chain_dma_off = 0;
322         int      newIndex;
323         int      ii;
324         dma_addr_t v2;
325         u32     RequestNB;
326
327         sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
328         if (sgdir == MPI_SCSIIO_CONTROL_WRITE)  {
329                 sgdir = MPT_TRANSFER_HOST_TO_IOC;
330         } else {
331                 sgdir = MPT_TRANSFER_IOC_TO_HOST;
332         }
333
334         psge = (char *) &pReq->SGL;
335         frm_sz = ioc->req_sz;
336
337         /* Map the data portion, if any.
338          * sges_left  = 0 if no data transfer.
339          */
340         if ( (sges_left = SCpnt->use_sg) ) {
341                 sges_left = pci_map_sg(ioc->pcidev,
342                                (struct scatterlist *) SCpnt->request_buffer,
343                                SCpnt->use_sg,
344                                SCpnt->sc_data_direction);
345                 if (sges_left == 0)
346                         return FAILED;
347         } else if (SCpnt->request_bufflen) {
348                 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
349                                       SCpnt->request_buffer,
350                                       SCpnt->request_bufflen,
351                                       SCpnt->sc_data_direction);
352                 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
353                                 ioc->name, SCpnt, SCpnt->request_bufflen));
354                 mptscsih_add_sge((char *) &pReq->SGL,
355                         0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
356                         SCpnt->SCp.dma_handle);
357
358                 return SUCCESS;
359         }
360
361         /* Handle the SG case.
362          */
363         sg = (struct scatterlist *) SCpnt->request_buffer;
364         sg_done  = 0;
365         sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
366         chainSge = NULL;
367
368         /* Prior to entering this loop - the following must be set
369          * current MF:  sgeOffset (bytes)
370          *              chainSge (Null if original MF is not a chain buffer)
371          *              sg_done (num SGE done for this MF)
372          */
373
374 nextSGEset:
375         numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
376         numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
377
378         sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
379
380         /* Get first (num - 1) SG elements
381          * Skip any SG entries with a length of 0
382          * NOTE: at finish, sg and psge pointed to NEXT data/location positions
383          */
384         for (ii=0; ii < (numSgeThisFrame-1); ii++) {
385                 thisxfer = sg_dma_len(sg);
386                 if (thisxfer == 0) {
387                         sg ++; /* Get next SG element from the OS */
388                         sg_done++;
389                         continue;
390                 }
391
392                 v2 = sg_dma_address(sg);
393                 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
394
395                 sg++;           /* Get next SG element from the OS */
396                 psge += (sizeof(u32) + sizeof(dma_addr_t));
397                 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
398                 sg_done++;
399         }
400
401         if (numSgeThisFrame == sges_left) {
402                 /* Add last element, end of buffer and end of list flags.
403                  */
404                 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
405                                 MPT_SGE_FLAGS_END_OF_BUFFER |
406                                 MPT_SGE_FLAGS_END_OF_LIST;
407
408                 /* Add last SGE and set termination flags.
409                  * Note: Last SGE may have a length of 0 - which should be ok.
410                  */
411                 thisxfer = sg_dma_len(sg);
412
413                 v2 = sg_dma_address(sg);
414                 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
415                 /*
416                 sg++;
417                 psge += (sizeof(u32) + sizeof(dma_addr_t));
418                 */
419                 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
420                 sg_done++;
421
422                 if (chainSge) {
423                         /* The current buffer is a chain buffer,
424                          * but there is not another one.
425                          * Update the chain element
426                          * Offset and Length fields.
427                          */
428                         mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
429                 } else {
430                         /* The current buffer is the original MF
431                          * and there is no Chain buffer.
432                          */
433                         pReq->ChainOffset = 0;
434                         RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
435                         dsgprintk((MYIOC_s_ERR_FMT 
436                             "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
437                         ioc->RequestNB[req_idx] = RequestNB;
438                 }
439         } else {
440                 /* At least one chain buffer is needed.
441                  * Complete the first MF
442                  *  - last SGE element, set the LastElement bit
443                  *  - set ChainOffset (words) for orig MF
444                  *             (OR finish previous MF chain buffer)
445                  *  - update MFStructPtr ChainIndex
446                  *  - Populate chain element
447                  * Also
448                  * Loop until done.
449                  */
450
451                 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
452                                 ioc->name, sg_done));
453
454                 /* Set LAST_ELEMENT flag for last non-chain element
455                  * in the buffer. Since psge points at the NEXT
456                  * SGE element, go back one SGE element, update the flags
457                  * and reset the pointer. (Note: sgflags & thisxfer are already
458                  * set properly).
459                  */
460                 if (sg_done) {
461                         u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
462                         sgflags = le32_to_cpu(*ptmp);
463                         sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
464                         *ptmp = cpu_to_le32(sgflags);
465                 }
466
467                 if (chainSge) {
468                         /* The current buffer is a chain buffer.
469                          * chainSge points to the previous Chain Element.
470                          * Update its chain element Offset and Length (must
471                          * include chain element size) fields.
472                          * Old chain element is now complete.
473                          */
474                         u8 nextChain = (u8) (sgeOffset >> 2);
475                         sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
476                         mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
477                 } else {
478                         /* The original MF buffer requires a chain buffer -
479                          * set the offset.
480                          * Last element in this MF is a chain element.
481                          */
482                         pReq->ChainOffset = (u8) (sgeOffset >> 2);
483                         RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
484                         dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
485                         ioc->RequestNB[req_idx] = RequestNB;
486                 }
487
488                 sges_left -= sg_done;
489
490
491                 /* NOTE: psge points to the beginning of the chain element
492                  * in current buffer. Get a chain buffer.
493                  */
494                 dsgprintk((MYIOC_s_INFO_FMT 
495                     "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n",
496                     ioc->name, pReq->CDB[0], SCpnt));
497                 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED)
498                         return FAILED;
499
500                 /* Update the tracking arrays.
501                  * If chainSge == NULL, update ReqToChain, else ChainToChain
502                  */
503                 if (chainSge) {
504                         ioc->ChainToChain[chain_idx] = newIndex;
505                 } else {
506                         ioc->ReqToChain[req_idx] = newIndex;
507                 }
508                 chain_idx = newIndex;
509                 chain_dma_off = ioc->req_sz * chain_idx;
510
511                 /* Populate the chainSGE for the current buffer.
512                  * - Set chain buffer pointer to psge and fill
513                  *   out the Address and Flags fields.
514                  */
515                 chainSge = (char *) psge;
516                 dsgprintk((KERN_INFO "  Current buff @ %p (index 0x%x)",
517                                 psge, req_idx));
518
519                 /* Start the SGE for the next buffer
520                  */
521                 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
522                 sgeOffset = 0;
523                 sg_done = 0;
524
525                 dsgprintk((KERN_INFO "  Chain buff @ %p (index 0x%x)\n",
526                                 psge, chain_idx));
527
528                 /* Start the SGE for the next buffer
529                  */
530
531                 goto nextSGEset;
532         }
533
534         return SUCCESS;
535 } /* mptscsih_AddSGE() */
536
537 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
538 /*
539  *      mptscsih_io_done - Main SCSI IO callback routine registered to
540  *      Fusion MPT (base) driver
541  *      @ioc: Pointer to MPT_ADAPTER structure
542  *      @mf: Pointer to original MPT request frame
543  *      @r: Pointer to MPT reply frame (NULL if TurboReply)
544  *
545  *      This routine is called from mpt.c::mpt_interrupt() at the completion
546  *      of any SCSI IO request.
547  *      This routine is registered with the Fusion MPT (base) driver at driver
548  *      load/init time via the mpt_register() API call.
549  *
550  *      Returns 1 indicating alloc'd request frame ptr should be freed.
551  */
552 int
553 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
554 {
555         struct scsi_cmnd        *sc;
556         MPT_SCSI_HOST   *hd;
557         SCSIIORequest_t *pScsiReq;
558         SCSIIOReply_t   *pScsiReply;
559         u16              req_idx;
560
561         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
562
563         req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
564         sc = hd->ScsiLookup[req_idx];
565         if (sc == NULL) {
566                 MPIHeader_t *hdr = (MPIHeader_t *)mf;
567
568                 /* Remark: writeSDP1 will use the ScsiDoneCtx
569                  * If a SCSI I/O cmd, device disabled by OS and
570                  * completion done. Cannot touch sc struct. Just free mem.
571                  */
572                 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
573                         printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
574                         ioc->name);
575
576                 mptscsih_freeChainBuffers(ioc, req_idx);
577                 return 1;
578         }
579
580         dmfprintk((MYIOC_s_INFO_FMT
581                 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
582                 ioc->name, mf, mr, sc, req_idx));
583
584         sc->result = DID_OK << 16;              /* Set default reply as OK */
585         pScsiReq = (SCSIIORequest_t *) mf;
586         pScsiReply = (SCSIIOReply_t *) mr;
587
588         if (pScsiReply == NULL) {
589                 /* special context reply handling */
590                 ;
591         } else {
592                 u32      xfer_cnt;
593                 u16      status;
594                 u8       scsi_state, scsi_status;
595
596                 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
597                 scsi_state = pScsiReply->SCSIState;
598                 scsi_status = pScsiReply->SCSIStatus;
599                 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
600                 sc->resid = sc->request_bufflen - xfer_cnt;
601
602                 dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
603                         "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
604                         "resid=%d bufflen=%d xfer_cnt=%d\n",
605                         ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
606                         status, scsi_state, scsi_status, sc->resid, 
607                         sc->request_bufflen, xfer_cnt));
608
609                 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
610                         mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
611
612                 /*
613                  *  Look for + dump FCP ResponseInfo[]!
614                  */
615                 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
616                         printk(KERN_NOTICE "  FCP_ResponseInfo=%08xh\n",
617                         le32_to_cpu(pScsiReply->ResponseInfo));
618                 }
619
620                 switch(status) {
621                 case MPI_IOCSTATUS_BUSY:                        /* 0x0002 */
622                         /* CHECKME!
623                          * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
624                          * But not: DID_BUS_BUSY lest one risk
625                          * killing interrupt handler:-(
626                          */
627                         sc->result = SAM_STAT_BUSY;
628                         break;
629
630                 case MPI_IOCSTATUS_SCSI_INVALID_BUS:            /* 0x0041 */
631                 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID:       /* 0x0042 */
632                         sc->result = DID_BAD_TARGET << 16;
633                         break;
634
635                 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
636                         /* Spoof to SCSI Selection Timeout! */
637                         sc->result = DID_NO_CONNECT << 16;
638
639                         if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
640                                 hd->sel_timeout[pScsiReq->TargetID]++;
641                         break;
642
643                 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
644                 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
645                 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
646                         /* Linux handles an unsolicited DID_RESET better
647                          * than an unsolicited DID_ABORT.
648                          */
649                         sc->result = DID_RESET << 16;
650
651                         /* GEM Workaround. */
652                         if (ioc->bus_type == SCSI)
653                                 mptscsih_no_negotiate(hd, sc->device->id);
654                         break;
655
656                 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:      /* 0x0049 */
657                         if ( xfer_cnt >= sc->underflow ) {
658                                 /* Sufficient data transfer occurred */
659                                 sc->result = (DID_OK << 16) | scsi_status;
660                         } else if ( xfer_cnt == 0 ) {
661                                 /* A CRC Error causes this condition; retry */ 
662                                 sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | 
663                                         (CHECK_CONDITION << 1);
664                                 sc->sense_buffer[0] = 0x70;
665                                 sc->sense_buffer[2] = NO_SENSE;
666                                 sc->sense_buffer[12] = 0;
667                                 sc->sense_buffer[13] = 0;
668                         } else {
669                                 sc->result = DID_SOFT_ERROR << 16;
670                         }
671                         dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
672                         break;
673
674                 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
675                         /*
676                          *  Do upfront check for valid SenseData and give it
677                          *  precedence!
678                          */
679                         sc->result = (DID_OK << 16) | scsi_status;
680                         if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
681                                 /* Have already saved the status and sense data
682                                  */
683                                 ;
684                         } else {
685                                 if (xfer_cnt < sc->underflow) {
686                                         sc->result = DID_SOFT_ERROR << 16;
687                                 }
688                                 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
689                                         /* What to do?
690                                         */
691                                         sc->result = DID_SOFT_ERROR << 16;
692                                 }
693                                 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
694                                         /*  Not real sure here either...  */
695                                         sc->result = DID_RESET << 16;
696                                 }
697                         }
698
699                         dreplyprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
700                                         sc->underflow));
701                         dreplyprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
702                         /* Report Queue Full
703                          */
704                         if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
705                                 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
706
707                         break;
708
709                 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
710                 case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
711                         scsi_status = pScsiReply->SCSIStatus;
712                         sc->result = (DID_OK << 16) | scsi_status;
713                         if (scsi_state == 0) {
714                                 ;
715                         } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
716                                 /*
717                                  * If running against circa 200003dd 909 MPT f/w,
718                                  * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
719                                  * (QUEUE_FULL) returned from device! --> get 0x0000?128
720                                  * and with SenseBytes set to 0.
721                                  */
722                                 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
723                                         mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
724
725                         }
726                         else if (scsi_state &
727                                  (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
728                            ) {
729                                 /*
730                                  * What to do?
731                                  */
732                                 sc->result = DID_SOFT_ERROR << 16;
733                         }
734                         else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
735                                 /*  Not real sure here either...  */
736                                 sc->result = DID_RESET << 16;
737                         }
738                         else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
739                                 /* Device Inq. data indicates that it supports
740                                  * QTags, but rejects QTag messages.
741                                  * This command completed OK.
742                                  *
743                                  * Not real sure here either so do nothing...  */
744                         }
745
746                         if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
747                                 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
748
749                         /* Add handling of:
750                          * Reservation Conflict, Busy,
751                          * Command Terminated, CHECK
752                          */
753                         break;
754
755                 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:         /* 0x0047 */
756                         sc->result = DID_SOFT_ERROR << 16;
757                         break;
758
759                 case MPI_IOCSTATUS_INVALID_FUNCTION:            /* 0x0001 */
760                 case MPI_IOCSTATUS_INVALID_SGL:                 /* 0x0003 */
761                 case MPI_IOCSTATUS_INTERNAL_ERROR:              /* 0x0004 */
762                 case MPI_IOCSTATUS_RESERVED:                    /* 0x0005 */
763                 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES:      /* 0x0006 */
764                 case MPI_IOCSTATUS_INVALID_FIELD:               /* 0x0007 */
765                 case MPI_IOCSTATUS_INVALID_STATE:               /* 0x0008 */
766                 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:           /* 0x0044 */
767                 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
768                 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:       /* 0x004A */
769                 default:
770                         /*
771                          * What to do?
772                          */
773                         sc->result = DID_SOFT_ERROR << 16;
774                         break;
775
776                 }       /* switch(status) */
777
778                 dreplyprintk((KERN_NOTICE "  sc->result is %08xh\n", sc->result));
779         } /* end of address reply case */
780
781         /* Unmap the DMA buffers, if any. */
782         if (sc->use_sg) {
783                 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
784                             sc->use_sg, sc->sc_data_direction);
785         } else if (sc->request_bufflen) {
786                 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
787                                 sc->request_bufflen, sc->sc_data_direction);
788         }
789
790         hd->ScsiLookup[req_idx] = NULL;
791
792         sc->scsi_done(sc);              /* Issue the command callback */
793
794         /* Free Chain buffers */
795         mptscsih_freeChainBuffers(ioc, req_idx);
796         return 1;
797 }
798
799
800 /*
801  *      mptscsih_flush_running_cmds - For each command found, search
802  *              Scsi_Host instance taskQ and reply to OS.
803  *              Called only if recovering from a FW reload.
804  *      @hd: Pointer to a SCSI HOST structure
805  *
806  *      Returns: None.
807  *
808  *      Must be called while new I/Os are being queued.
809  */
810 static void
811 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
812 {
813         MPT_ADAPTER *ioc = hd->ioc;
814         struct scsi_cmnd        *SCpnt;
815         MPT_FRAME_HDR   *mf;
816         int              ii;
817         int              max = ioc->req_depth;
818
819         dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
820         for (ii= 0; ii < max; ii++) {
821                 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
822
823                         /* Command found.
824                          */
825
826                         /* Null ScsiLookup index
827                          */
828                         hd->ScsiLookup[ii] = NULL;
829
830                         mf = MPT_INDEX_2_MFPTR(ioc, ii);
831                         dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
832                                         mf, SCpnt));
833
834                         /* Set status, free OS resources (SG DMA buffers)
835                          * Do OS callback
836                          * Free driver resources (chain, msg buffers)
837                          */
838                         if (SCpnt->use_sg) {
839                                 pci_unmap_sg(ioc->pcidev,
840                                         (struct scatterlist *) SCpnt->request_buffer,
841                                         SCpnt->use_sg,
842                                         SCpnt->sc_data_direction);
843                         } else if (SCpnt->request_bufflen) {
844                                 pci_unmap_single(ioc->pcidev,
845                                         SCpnt->SCp.dma_handle,
846                                         SCpnt->request_bufflen,
847                                         SCpnt->sc_data_direction);
848                         }
849                         SCpnt->result = DID_RESET << 16;
850                         SCpnt->host_scribble = NULL;
851
852                         /* Free Chain buffers */
853                         mptscsih_freeChainBuffers(ioc, ii);
854
855                         /* Free Message frames */
856                         mpt_free_msg_frame(ioc, mf);
857
858                         SCpnt->scsi_done(SCpnt);        /* Issue the command callback */
859                 }
860         }
861
862         return;
863 }
864
865 /*
866  *      mptscsih_search_running_cmds - Delete any commands associated
867  *              with the specified target and lun. Function called only
868  *              when a lun is disable by mid-layer.
869  *              Do NOT access the referenced scsi_cmnd structure or
870  *              members. Will cause either a paging or NULL ptr error.
871  *      @hd: Pointer to a SCSI HOST structure
872  *      @target: target id
873  *      @lun: lun
874  *
875  *      Returns: None.
876  *
877  *      Called from slave_destroy.
878  */
879 static void
880 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
881 {
882         SCSIIORequest_t *mf = NULL;
883         int              ii;
884         int              max = hd->ioc->req_depth;
885
886         dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
887                         target, lun, max));
888
889         for (ii=0; ii < max; ii++) {
890                 if (hd->ScsiLookup[ii] != NULL) {
891
892                         mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
893
894                         dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
895                                         hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
896
897                         if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
898                                 continue;
899
900                         /* Cleanup
901                          */
902                         hd->ScsiLookup[ii] = NULL;
903                         mptscsih_freeChainBuffers(hd->ioc, ii);
904                         mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
905                 }
906         }
907
908         return;
909 }
910
911 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
912
913 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
914 /*
915  *      mptscsih_report_queue_full - Report QUEUE_FULL status returned
916  *      from a SCSI target device.
917  *      @sc: Pointer to scsi_cmnd structure
918  *      @pScsiReply: Pointer to SCSIIOReply_t
919  *      @pScsiReq: Pointer to original SCSI request
920  *
921  *      This routine periodically reports QUEUE_FULL status returned from a
922  *      SCSI target device.  It reports this to the console via kernel
923  *      printk() API call, not more than once every 10 seconds.
924  */
925 static void
926 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
927 {
928         long time = jiffies;
929         MPT_SCSI_HOST           *hd;
930
931         if (sc->device == NULL)
932                 return;
933         if (sc->device->host == NULL)
934                 return;
935         if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
936                 return;
937
938         if (time - hd->last_queue_full > 10 * HZ) {
939                 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
940                                 hd->ioc->name, 0, sc->device->id, sc->device->lun));
941                 hd->last_queue_full = time;
942         }
943 }
944
945 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
946 /*
947  *      mptscsih_remove - Removed scsi devices
948  *      @pdev: Pointer to pci_dev structure
949  *
950  *
951  */
952 void
953 mptscsih_remove(struct pci_dev *pdev)
954 {
955         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
956         struct Scsi_Host        *host = ioc->sh;
957         MPT_SCSI_HOST           *hd;
958         int                     count;
959         unsigned long           flags;
960         int sz1;
961
962         if(!host)
963                 return;
964
965         scsi_remove_host(host);
966
967         if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
968                 return;
969
970 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
971         /* Check DV thread active */
972         count = 10 * HZ;
973         spin_lock_irqsave(&dvtaskQ_lock, flags);
974         if (dvtaskQ_active) {
975                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
976                 while(dvtaskQ_active && --count) {
977                         set_current_state(TASK_INTERRUPTIBLE);
978                         schedule_timeout(1);
979                 }
980         } else {
981                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
982         }
983         if (!count)
984                 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
985 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
986         else
987                 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
988 #endif
989 #endif
990
991         mptscsih_shutdown(&pdev->dev);
992
993         sz1=0;
994
995         if (hd->ScsiLookup != NULL) {
996                 sz1 = hd->ioc->req_depth * sizeof(void *);
997                 kfree(hd->ScsiLookup);
998                 hd->ScsiLookup = NULL;
999         }
1000
1001         /*
1002          * Free pointer array.
1003          */
1004         kfree(hd->Targets);
1005         hd->Targets = NULL;
1006
1007         dprintk((MYIOC_s_INFO_FMT
1008             "Free'd ScsiLookup (%d) memory\n",
1009             hd->ioc->name, sz1));
1010
1011         kfree(hd->info_kbuf);
1012
1013         /* NULL the Scsi_Host pointer
1014          */
1015         hd->ioc->sh = NULL;
1016
1017         scsi_host_put(host);
1018
1019         mpt_detach(pdev);
1020         
1021 }
1022
1023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1024 /*
1025  *      mptscsih_shutdown - reboot notifier
1026  *
1027  */
1028 void
1029 mptscsih_shutdown(struct device * dev)
1030 {
1031         MPT_ADAPTER             *ioc = pci_get_drvdata(to_pci_dev(dev));
1032         struct Scsi_Host        *host = ioc->sh;
1033         MPT_SCSI_HOST           *hd;
1034
1035         if(!host)
1036                 return;
1037
1038         hd = (MPT_SCSI_HOST *)host->hostdata;
1039
1040         /* Flush the cache of this adapter
1041          */
1042         if(hd != NULL)
1043                 mptscsih_synchronize_cache(hd, 0);
1044
1045 }
1046
1047 #ifdef CONFIG_PM
1048 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1049 /*
1050  *      mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1051  *
1052  *
1053  */
1054 int
1055 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1056 {
1057         mptscsih_shutdown(&pdev->dev);
1058         return mpt_suspend(pdev,state);
1059 }
1060
1061 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1062 /*
1063  *      mptscsih_resume - Fusion MPT scsi driver resume routine.
1064  *
1065  *
1066  */
1067 int
1068 mptscsih_resume(struct pci_dev *pdev)
1069 {
1070         MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
1071         struct Scsi_Host        *host = ioc->sh;
1072         MPT_SCSI_HOST           *hd;
1073
1074         mpt_resume(pdev);
1075         
1076         if(!host)
1077                 return 0;
1078
1079         hd = (MPT_SCSI_HOST *)host->hostdata;
1080         if(!hd)
1081                 return 0;
1082
1083 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1084         {
1085         unsigned long lflags;
1086         spin_lock_irqsave(&dvtaskQ_lock, lflags);
1087         if (!dvtaskQ_active) {
1088                 dvtaskQ_active = 1;
1089                 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1090                 INIT_WORK(&dvTaskQ_task,
1091                   mptscsih_domainValidation, (void *) hd);
1092                 schedule_work(&dvTaskQ_task);
1093         } else {
1094                 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1095         }
1096         }
1097 #endif
1098         return 0;
1099 }
1100
1101 #endif
1102
1103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1104 /**
1105  *      mptscsih_info - Return information about MPT adapter
1106  *      @SChost: Pointer to Scsi_Host structure
1107  *
1108  *      (linux scsi_host_template.info routine)
1109  *
1110  *      Returns pointer to buffer where information was written.
1111  */
1112 const char *
1113 mptscsih_info(struct Scsi_Host *SChost)
1114 {
1115         MPT_SCSI_HOST *h;
1116         int size = 0;
1117
1118         h = (MPT_SCSI_HOST *)SChost->hostdata;
1119
1120         if (h) {
1121                 if (h->info_kbuf == NULL)
1122                         if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1123                                 return h->info_kbuf;
1124                 h->info_kbuf[0] = '\0';
1125
1126                 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1127                 h->info_kbuf[size-1] = '\0';
1128         }
1129
1130         return h->info_kbuf;
1131 }
1132
1133 struct info_str {
1134         char *buffer;
1135         int   length;
1136         int   offset;
1137         int   pos;
1138 };
1139
1140 static void
1141 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1142 {
1143         if (info->pos + len > info->length)
1144                 len = info->length - info->pos;
1145
1146         if (info->pos + len < info->offset) {
1147                 info->pos += len;
1148                 return;
1149         }
1150
1151         if (info->pos < info->offset) {
1152                 data += (info->offset - info->pos);
1153                 len  -= (info->offset - info->pos);
1154         }
1155
1156         if (len > 0) {
1157                 memcpy(info->buffer + info->pos, data, len);
1158                 info->pos += len;
1159         }
1160 }
1161
1162 static int
1163 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1164 {
1165         va_list args;
1166         char buf[81];
1167         int len;
1168
1169         va_start(args, fmt);
1170         len = vsprintf(buf, fmt, args);
1171         va_end(args);
1172
1173         mptscsih_copy_mem_info(info, buf, len);
1174         return len;
1175 }
1176
1177 static int
1178 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1179 {
1180         struct info_str info;
1181
1182         info.buffer     = pbuf;
1183         info.length     = len;
1184         info.offset     = offset;
1185         info.pos        = 0;
1186
1187         mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1188         mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1189         mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1190         mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1191
1192         return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1193 }
1194
1195 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1196 /**
1197  *      mptscsih_proc_info - Return information about MPT adapter
1198  *
1199  *      (linux scsi_host_template.info routine)
1200  *
1201  *      buffer: if write, user data; if read, buffer for user
1202  *      length: if write, return length;
1203  *      offset: if write, 0; if read, the current offset into the buffer from
1204  *              the previous read.
1205  *      hostno: scsi host number
1206  *      func:   if write = 1; if read = 0
1207  */
1208 int
1209 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1210                         int length, int func)
1211 {
1212         MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)host->hostdata;
1213         MPT_ADAPTER     *ioc = hd->ioc;
1214         int size = 0;
1215
1216         if (func) {
1217                 /* 
1218                  * write is not supported 
1219                  */
1220         } else {
1221                 if (start)
1222                         *start = buffer;
1223
1224                 size = mptscsih_host_info(ioc, buffer, offset, length);
1225         }
1226
1227         return size;
1228 }
1229
1230 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1231 #define ADD_INDEX_LOG(req_ent)  do { } while(0)
1232
1233 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1234 /**
1235  *      mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1236  *      @SCpnt: Pointer to scsi_cmnd structure
1237  *      @done: Pointer SCSI mid-layer IO completion function
1238  *
1239  *      (linux scsi_host_template.queuecommand routine)
1240  *      This is the primary SCSI IO start routine.  Create a MPI SCSIIORequest
1241  *      from a linux scsi_cmnd request and send it to the IOC.
1242  *
1243  *      Returns 0. (rtn value discarded by linux scsi mid-layer)
1244  */
1245 int
1246 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1247 {
1248         MPT_SCSI_HOST           *hd;
1249         MPT_FRAME_HDR           *mf;
1250         SCSIIORequest_t         *pScsiReq;
1251         VirtDevice              *pTarget;
1252         int      target;
1253         int      lun;
1254         u32      datalen;
1255         u32      scsictl;
1256         u32      scsidir;
1257         u32      cmd_len;
1258         int      my_idx;
1259         int      ii;
1260
1261         hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1262         target = SCpnt->device->id;
1263         lun = SCpnt->device->lun;
1264         SCpnt->scsi_done = done;
1265
1266         pTarget = hd->Targets[target];
1267
1268         dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1269                         (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1270
1271         if (hd->resetPending) {
1272                 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1273                         (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1274                 return SCSI_MLQUEUE_HOST_BUSY;
1275         }
1276
1277         /*
1278          *  Put together a MPT SCSI request...
1279          */
1280         if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1281                 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1282                                 hd->ioc->name));
1283                 return SCSI_MLQUEUE_HOST_BUSY;
1284         }
1285
1286         pScsiReq = (SCSIIORequest_t *) mf;
1287
1288         my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1289
1290         ADD_INDEX_LOG(my_idx);
1291
1292         /*    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1293          *    Seems we may receive a buffer (datalen>0) even when there
1294          *    will be no data transfer!  GRRRRR...
1295          */
1296         if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1297                 datalen = SCpnt->request_bufflen;
1298                 scsidir = MPI_SCSIIO_CONTROL_READ;      /* DATA IN  (host<--ioc<--dev) */
1299         } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1300                 datalen = SCpnt->request_bufflen;
1301                 scsidir = MPI_SCSIIO_CONTROL_WRITE;     /* DATA OUT (host-->ioc-->dev) */
1302         } else {
1303                 datalen = 0;
1304                 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1305         }
1306
1307         /* Default to untagged. Once a target structure has been allocated,
1308          * use the Inquiry data to determine if device supports tagged.
1309          */
1310         if (   pTarget
1311             && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1312             && (SCpnt->device->tagged_supported)) {
1313                 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1314         } else {
1315                 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1316         }
1317
1318         /* Use the above information to set up the message frame
1319          */
1320         pScsiReq->TargetID = (u8) target;
1321         pScsiReq->Bus = (u8) SCpnt->device->channel;
1322         pScsiReq->ChainOffset = 0;
1323         pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1324         pScsiReq->CDBLength = SCpnt->cmd_len;
1325         pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1326         pScsiReq->Reserved = 0;
1327         pScsiReq->MsgFlags = mpt_msg_flags();
1328         pScsiReq->LUN[0] = 0;
1329         pScsiReq->LUN[1] = lun;
1330         pScsiReq->LUN[2] = 0;
1331         pScsiReq->LUN[3] = 0;
1332         pScsiReq->LUN[4] = 0;
1333         pScsiReq->LUN[5] = 0;
1334         pScsiReq->LUN[6] = 0;
1335         pScsiReq->LUN[7] = 0;
1336         pScsiReq->Control = cpu_to_le32(scsictl);
1337
1338         /*
1339          *  Write SCSI CDB into the message
1340          */
1341         cmd_len = SCpnt->cmd_len;
1342         for (ii=0; ii < cmd_len; ii++)
1343                 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1344
1345         for (ii=cmd_len; ii < 16; ii++)
1346                 pScsiReq->CDB[ii] = 0;
1347
1348         /* DataLength */
1349         pScsiReq->DataLength = cpu_to_le32(datalen);
1350
1351         /* SenseBuffer low address */
1352         pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1353                                            + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1354
1355         /* Now add the SG list
1356          * Always have a SGE even if null length.
1357          */
1358         if (datalen == 0) {
1359                 /* Add a NULL SGE */
1360                 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1361                         (dma_addr_t) -1);
1362         } else {
1363                 /* Add a 32 or 64 bit SGE */
1364                 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1365                         goto fail;
1366         }
1367
1368         hd->ScsiLookup[my_idx] = SCpnt;
1369         SCpnt->host_scribble = NULL;
1370
1371 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1372         if (hd->ioc->bus_type == SCSI) {
1373                 int dvStatus = hd->ioc->spi_data.dvStatus[target];
1374                 int issueCmd = 1;
1375
1376                 if (dvStatus || hd->ioc->spi_data.forceDv) {
1377
1378                         if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
1379                                 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
1380                                 unsigned long lflags;
1381                                 /* Schedule DV if necessary */
1382                                 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1383                                 if (!dvtaskQ_active) {
1384                                         dvtaskQ_active = 1;
1385                                         spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1386                                         INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
1387
1388                                         schedule_work(&dvTaskQ_task);
1389                                 } else {
1390                                         spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1391                                 }
1392                                 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
1393                         }
1394
1395                         /* Trying to do DV to this target, extend timeout.
1396                          * Wait to issue until flag is clear
1397                          */
1398                         if (dvStatus & MPT_SCSICFG_DV_PENDING) {
1399                                 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
1400                                 issueCmd = 0;
1401                         }
1402
1403                         /* Set the DV flags.
1404                          */
1405                         if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
1406                                 mptscsih_set_dvflags(hd, pScsiReq);
1407
1408                         if (!issueCmd)
1409                                 goto fail;
1410                 }
1411         }
1412 #endif
1413
1414         mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1415         dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1416                         hd->ioc->name, SCpnt, mf, my_idx));
1417         DBG_DUMP_REQUEST_FRAME(mf)
1418         return 0;
1419
1420  fail:
1421         mptscsih_freeChainBuffers(hd->ioc, my_idx);
1422         mpt_free_msg_frame(hd->ioc, mf);
1423         return SCSI_MLQUEUE_HOST_BUSY;
1424 }
1425
1426 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1427 /*
1428  *      mptscsih_freeChainBuffers - Function to free chain buffers associated
1429  *      with a SCSI IO request
1430  *      @hd: Pointer to the MPT_SCSI_HOST instance
1431  *      @req_idx: Index of the SCSI IO request frame.
1432  *
1433  *      Called if SG chain buffer allocation fails and mptscsih callbacks.
1434  *      No return.
1435  */
1436 static void
1437 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1438 {
1439         MPT_FRAME_HDR *chain;
1440         unsigned long flags;
1441         int chain_idx;
1442         int next;
1443
1444         /* Get the first chain index and reset
1445          * tracker state.
1446          */
1447         chain_idx = ioc->ReqToChain[req_idx];
1448         ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1449
1450         while (chain_idx != MPT_HOST_NO_CHAIN) {
1451
1452                 /* Save the next chain buffer index */
1453                 next = ioc->ChainToChain[chain_idx];
1454
1455                 /* Free this chain buffer and reset
1456                  * tracker
1457                  */
1458                 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1459
1460                 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1461                                         + (chain_idx * ioc->req_sz));
1462
1463                 spin_lock_irqsave(&ioc->FreeQlock, flags);
1464                 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1465                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1466
1467                 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1468                                 ioc->name, chain_idx));
1469
1470                 /* handle next */
1471                 chain_idx = next;
1472         }
1473         return;
1474 }
1475
1476 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1477 /*
1478  *      Reset Handling
1479  */
1480
1481 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1482 /*
1483  *      mptscsih_TMHandler - Generic handler for SCSI Task Management.
1484  *      Fall through to mpt_HardResetHandler if: not operational, too many
1485  *      failed TM requests or handshake failure.
1486  *
1487  *      @ioc: Pointer to MPT_ADAPTER structure
1488  *      @type: Task Management type
1489  *      @target: Logical Target ID for reset (if appropriate)
1490  *      @lun: Logical Unit for reset (if appropriate)
1491  *      @ctx2abort: Context for the task to be aborted (if appropriate)
1492  *
1493  *      Remark: Currently invoked from a non-interrupt thread (_bh).
1494  *
1495  *      Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1496  *      will be active.
1497  *
1498  *      Returns 0 for SUCCESS or -1 if FAILED.
1499  */
1500 static int
1501 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1502 {
1503         MPT_ADAPTER     *ioc;
1504         int              rc = -1;
1505         int              doTask = 1;
1506         u32              ioc_raw_state;
1507         unsigned long    flags;
1508
1509         /* If FW is being reloaded currently, return success to
1510          * the calling function.
1511          */
1512         if (hd == NULL)
1513                 return 0;
1514
1515         ioc = hd->ioc;
1516         if (ioc == NULL) {
1517                 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1518                 return FAILED;
1519         }
1520         dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1521
1522         // SJR - CHECKME - Can we avoid this here?
1523         // (mpt_HardResetHandler has this check...)
1524         spin_lock_irqsave(&ioc->diagLock, flags);
1525         if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1526                 spin_unlock_irqrestore(&ioc->diagLock, flags);
1527                 return FAILED;
1528         }
1529         spin_unlock_irqrestore(&ioc->diagLock, flags);
1530
1531         /*  Wait a fixed amount of time for the TM pending flag to be cleared.
1532          *  If we time out and not bus reset, then we return a FAILED status to the caller.
1533          *  The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1534          *  successful. Otherwise, reload the FW.
1535          */
1536         if (mptscsih_tm_pending_wait(hd) == FAILED) {
1537                 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1538                         dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
1539                            "Timed out waiting for last TM (%d) to complete! \n",
1540                            hd->ioc->name, hd->tmPending));
1541                         return FAILED;
1542                 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1543                         dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
1544                            "Timed out waiting for last TM (%d) to complete! \n",
1545                            hd->ioc->name, hd->tmPending));
1546                         return FAILED;
1547                 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1548                         dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
1549                            "Timed out waiting for last TM (%d) to complete! \n",
1550                            hd->ioc->name, hd->tmPending));
1551                         if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1552                                 return FAILED;
1553
1554                         doTask = 0;
1555                 }
1556         } else {
1557                 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1558                 hd->tmPending |=  (1 << type);
1559                 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1560         }
1561
1562         /* Is operational?
1563          */
1564         ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1565
1566 #ifdef MPT_DEBUG_RESET
1567         if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1568                 printk(MYIOC_s_WARN_FMT
1569                         "TM Handler: IOC Not operational(0x%x)!\n",
1570                         hd->ioc->name, ioc_raw_state);
1571         }
1572 #endif
1573
1574         if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1575                                 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1576
1577                 /* Isse the Task Mgmt request.
1578                  */
1579                 if (hd->hard_resets < -1)
1580                         hd->hard_resets++;
1581                 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
1582                 if (rc) {
1583                         printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1584                 } else {
1585                         dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1586                 }
1587         }
1588
1589         /* Only fall through to the HRH if this is a bus reset
1590          */
1591         if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1592                 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1593                 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1594                          hd->ioc->name));
1595                 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1596         }
1597
1598         dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1599
1600         return rc;
1601 }
1602
1603
1604 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1605 /*
1606  *      mptscsih_IssueTaskMgmt - Generic send Task Management function.
1607  *      @hd: Pointer to MPT_SCSI_HOST structure
1608  *      @type: Task Management type
1609  *      @target: Logical Target ID for reset (if appropriate)
1610  *      @lun: Logical Unit for reset (if appropriate)
1611  *      @ctx2abort: Context for the task to be aborted (if appropriate)
1612  *
1613  *      Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1614  *      or a non-interrupt thread.  In the former, must not call schedule().
1615  *
1616  *      Not all fields are meaningfull for all task types.
1617  *
1618  *      Returns 0 for SUCCESS, -999 for "no msg frames",
1619  *      else other non-zero value returned.
1620  */
1621 static int
1622 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1623 {
1624         MPT_FRAME_HDR   *mf;
1625         SCSITaskMgmt_t  *pScsiTm;
1626         int              ii;
1627         int              retval;
1628
1629         /* Return Fail to calling function if no message frames available.
1630          */
1631         if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1632                 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1633                                 hd->ioc->name));
1634                 //return FAILED;
1635                 return -999;
1636         }
1637         dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1638                         hd->ioc->name, mf));
1639
1640         /* Format the Request
1641          */
1642         pScsiTm = (SCSITaskMgmt_t *) mf;
1643         pScsiTm->TargetID = target;
1644         pScsiTm->Bus = channel;
1645         pScsiTm->ChainOffset = 0;
1646         pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1647
1648         pScsiTm->Reserved = 0;
1649         pScsiTm->TaskType = type;
1650         pScsiTm->Reserved1 = 0;
1651         pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1652                     ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1653
1654         for (ii= 0; ii < 8; ii++) {
1655                 pScsiTm->LUN[ii] = 0;
1656         }
1657         pScsiTm->LUN[1] = lun;
1658
1659         for (ii=0; ii < 7; ii++)
1660                 pScsiTm->Reserved2[ii] = 0;
1661
1662         pScsiTm->TaskMsgContext = ctx2abort;
1663
1664         dtmprintk((MYIOC_s_INFO_FMT
1665                 "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1666                 hd->ioc->name, ctx2abort, type));
1667
1668         DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1669
1670         if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1671                 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1672                 CAN_SLEEP)) != 0) {
1673                 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1674                         " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1675                         hd->ioc, mf));
1676                 mpt_free_msg_frame(hd->ioc, mf);
1677                 return retval;
1678         }
1679
1680         if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1681                 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1682                         " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1683                         hd->ioc, mf));
1684                 mpt_free_msg_frame(hd->ioc, mf);
1685                 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1686                          hd->ioc->name));
1687                 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1688         }
1689
1690         return retval;
1691 }
1692
1693 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1694 /**
1695  *      mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1696  *      @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1697  *
1698  *      (linux scsi_host_template.eh_abort_handler routine)
1699  *
1700  *      Returns SUCCESS or FAILED.
1701  */
1702 int
1703 mptscsih_abort(struct scsi_cmnd * SCpnt)
1704 {
1705         MPT_SCSI_HOST   *hd;
1706         MPT_ADAPTER     *ioc;
1707         MPT_FRAME_HDR   *mf;
1708         u32              ctx2abort;
1709         int              scpnt_idx;
1710
1711         /* If we can't locate our host adapter structure, return FAILED status.
1712          */
1713         if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1714                 SCpnt->result = DID_RESET << 16;
1715                 SCpnt->scsi_done(SCpnt);
1716                 dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
1717                            "Can't locate host! (sc=%p)\n",
1718                            SCpnt));
1719                 return FAILED;
1720         }
1721
1722         ioc = hd->ioc;
1723         if (hd->resetPending)
1724                 return FAILED;
1725
1726         printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
1727                hd->ioc->name, SCpnt);
1728
1729         if (hd->timeouts < -1)
1730                 hd->timeouts++;
1731
1732         /* Find this command
1733          */
1734         if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1735                 /* Cmd not found in ScsiLookup. 
1736                  * Do OS callback.
1737                  */
1738                 SCpnt->result = DID_RESET << 16;
1739                 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
1740                            "Command not in the active list! (sc=%p)\n",
1741                            hd->ioc->name, SCpnt));
1742                 return SUCCESS;
1743         }
1744
1745         /* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
1746          * (the IO to be ABORT'd)
1747          *
1748          * NOTE: Since we do not byteswap MsgContext, we do not
1749          *       swap it here either.  It is an opaque cookie to
1750          *       the controller, so it does not matter. -DaveM
1751          */
1752         mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1753         ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1754
1755         hd->abortSCpnt = SCpnt;
1756
1757         if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1758                 SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
1759                 ctx2abort, 2 /* 2 second timeout */)
1760                 < 0) {
1761
1762                 /* The TM request failed and the subsequent FW-reload failed!
1763                  * Fatal error case.
1764                  */
1765                 printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
1766                        hd->ioc->name, SCpnt);
1767
1768                 /* We must clear our pending flag before clearing our state.
1769                  */
1770                 hd->tmPending = 0;
1771                 hd->tmState = TM_STATE_NONE;
1772
1773                 /* Unmap the DMA buffers, if any. */
1774                 if (SCpnt->use_sg) {
1775                         pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
1776                                     SCpnt->use_sg, SCpnt->sc_data_direction);
1777                 } else if (SCpnt->request_bufflen) {
1778                         pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle,
1779                                 SCpnt->request_bufflen, SCpnt->sc_data_direction);
1780                 }
1781                 hd->ScsiLookup[scpnt_idx] = NULL;
1782                 SCpnt->result = DID_RESET << 16;
1783                 SCpnt->scsi_done(SCpnt);                /* Issue the command callback */
1784                 mptscsih_freeChainBuffers(ioc, scpnt_idx);
1785                 mpt_free_msg_frame(ioc, mf);
1786                 return FAILED;
1787         }
1788         return SUCCESS;
1789 }
1790
1791 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1792 /**
1793  *      mptscsih_dev_reset - Perform a SCSI TARGET_RESET!  new_eh variant
1794  *      @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1795  *
1796  *      (linux scsi_host_template.eh_dev_reset_handler routine)
1797  *
1798  *      Returns SUCCESS or FAILED.
1799  */
1800 int
1801 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1802 {
1803         MPT_SCSI_HOST   *hd;
1804
1805         /* If we can't locate our host adapter structure, return FAILED status.
1806          */
1807         if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1808                 dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
1809                            "Can't locate host! (sc=%p)\n",
1810                            SCpnt));
1811                 return FAILED;
1812         }
1813
1814         if (hd->resetPending)
1815                 return FAILED;
1816
1817         printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
1818                hd->ioc->name, SCpnt);
1819
1820         if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1821                 SCpnt->device->channel, SCpnt->device->id,
1822                 0, 0, 5 /* 5 second timeout */)
1823                 < 0){
1824                 /* The TM request failed and the subsequent FW-reload failed!
1825                  * Fatal error case.
1826                  */
1827                 printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
1828                                 hd->ioc->name, SCpnt);
1829                 hd->tmPending = 0;
1830                 hd->tmState = TM_STATE_NONE;
1831                 return FAILED;
1832         }
1833
1834         return SUCCESS;
1835 }
1836
1837 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1838 /**
1839  *      mptscsih_bus_reset - Perform a SCSI BUS_RESET!  new_eh variant
1840  *      @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1841  *
1842  *      (linux scsi_host_template.eh_bus_reset_handler routine)
1843  *
1844  *      Returns SUCCESS or FAILED.
1845  */
1846 int
1847 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1848 {
1849         MPT_SCSI_HOST   *hd;
1850         spinlock_t      *host_lock = SCpnt->device->host->host_lock;
1851
1852         /* If we can't locate our host adapter structure, return FAILED status.
1853          */
1854         if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1855                 dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
1856                            "Can't locate host! (sc=%p)\n",
1857                            SCpnt ) );
1858                 return FAILED;
1859         }
1860
1861         printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
1862                hd->ioc->name, SCpnt);
1863
1864         if (hd->timeouts < -1)
1865                 hd->timeouts++;
1866
1867         /* We are now ready to execute the task management request. */
1868         if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1869                 SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
1870             < 0){
1871
1872                 /* The TM request failed and the subsequent FW-reload failed!
1873                  * Fatal error case.
1874                  */
1875                 printk(MYIOC_s_WARN_FMT
1876                        "Error processing TaskMgmt request (sc=%p)\n",
1877                        hd->ioc->name, SCpnt);
1878                 hd->tmPending = 0;
1879                 hd->tmState = TM_STATE_NONE;
1880                 spin_lock_irq(host_lock);
1881                 return FAILED;
1882         }
1883
1884         return SUCCESS;
1885 }
1886
1887 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1888 /**
1889  *      mptscsih_host_reset - Perform a SCSI host adapter RESET!
1890  *      new_eh variant
1891  *      @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1892  *
1893  *      (linux scsi_host_template.eh_host_reset_handler routine)
1894  *
1895  *      Returns SUCCESS or FAILED.
1896  */
1897 int
1898 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1899 {
1900         MPT_SCSI_HOST *  hd;
1901         int              status = SUCCESS;
1902
1903         /*  If we can't locate the host to reset, then we failed. */
1904         if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1905                 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
1906                              "Can't locate host! (sc=%p)\n",
1907                              SCpnt ) );
1908                 return FAILED;
1909         }
1910
1911         printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
1912                hd->ioc->name, SCpnt);
1913
1914         /*  If our attempts to reset the host failed, then return a failed
1915          *  status.  The host will be taken off line by the SCSI mid-layer.
1916          */
1917         if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1918                 status = FAILED;
1919         } else {
1920                 /*  Make sure TM pending is cleared and TM state is set to
1921                  *  NONE.
1922                  */
1923                 hd->tmPending = 0;
1924                 hd->tmState = TM_STATE_NONE;
1925         }
1926
1927         dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
1928                      "Status = %s\n",
1929                      (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1930
1931         return status;
1932 }
1933
1934 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1935 /**
1936  *      mptscsih_tm_pending_wait - wait for pending task management request to
1937  *              complete.
1938  *      @hd: Pointer to MPT host structure.
1939  *
1940  *      Returns {SUCCESS,FAILED}.
1941  */
1942 static int
1943 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1944 {
1945         unsigned long  flags;
1946         int            loop_count = 4 * 10;  /* Wait 10 seconds */
1947         int            status = FAILED;
1948
1949         do {
1950                 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1951                 if (hd->tmState == TM_STATE_NONE) {
1952                         hd->tmState = TM_STATE_IN_PROGRESS;
1953                         hd->tmPending = 1;
1954                         status = SUCCESS;
1955                         spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1956                         break;
1957                 }
1958                 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1959                 msleep(250);
1960         } while (--loop_count);
1961
1962         return status;
1963 }
1964
1965 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1966 /**
1967  *      mptscsih_tm_wait_for_completion - wait for completion of TM task
1968  *      @hd: Pointer to MPT host structure.
1969  *
1970  *      Returns {SUCCESS,FAILED}.
1971  */
1972 static int
1973 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1974 {
1975         unsigned long  flags;
1976         int            loop_count = 4 * timeout;
1977         int            status = FAILED;
1978
1979         do {
1980                 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1981                 if(hd->tmPending == 0) {
1982                         status = SUCCESS;
1983                         spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1984                         break;
1985                 }
1986                 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1987                 msleep_interruptible(250);
1988         } while (--loop_count);
1989
1990         return status;
1991 }
1992
1993 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1994 /**
1995  *      mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
1996  *      @ioc: Pointer to MPT_ADAPTER structure
1997  *      @mf: Pointer to SCSI task mgmt request frame
1998  *      @mr: Pointer to SCSI task mgmt reply frame
1999  *
2000  *      This routine is called from mptbase.c::mpt_interrupt() at the completion
2001  *      of any SCSI task management request.
2002  *      This routine is registered with the MPT (base) driver at driver
2003  *      load/init time via the mpt_register() API call.
2004  *
2005  *      Returns 1 indicating alloc'd request frame ptr should be freed.
2006  */
2007 int
2008 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2009 {
2010         SCSITaskMgmtReply_t     *pScsiTmReply;
2011         SCSITaskMgmt_t          *pScsiTmReq;
2012         MPT_SCSI_HOST           *hd;
2013         unsigned long            flags;
2014         u16                      iocstatus;
2015         u8                       tmType;
2016
2017         dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2018                         ioc->name, mf, mr));
2019         if (ioc->sh) {
2020                 /* Depending on the thread, a timer is activated for
2021                  * the TM request.  Delete this timer on completion of TM.
2022                  * Decrement count of outstanding TM requests.
2023                  */
2024                 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2025         } else {
2026                 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2027                         ioc->name));
2028                 return 1;
2029         }
2030
2031         if (mr == NULL) {
2032                 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2033                         ioc->name, mf));
2034                 return 1;
2035         } else {
2036                 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2037                 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2038
2039                 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2040                 tmType = pScsiTmReq->TaskType;
2041
2042                 dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
2043                                 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2044                 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2045
2046                 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2047                 dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2048                         ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2049                 /* Error?  (anything non-zero?) */
2050                 if (iocstatus) {
2051
2052                         /* clear flags and continue.
2053                          */
2054                         if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2055                                 hd->abortSCpnt = NULL;
2056
2057                         /* If an internal command is present
2058                          * or the TM failed - reload the FW.
2059                          * FC FW may respond FAILED to an ABORT
2060                          */
2061                         if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2062                                 if ((hd->cmdPtr) ||
2063                                     (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2064                                         if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2065                                                 printk((KERN_WARNING
2066                                                         " Firmware Reload FAILED!!\n"));
2067                                         }
2068                                 }
2069                         }
2070                 } else {
2071                         dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2072
2073                         hd->abortSCpnt = NULL;
2074
2075                 }
2076         }
2077
2078         spin_lock_irqsave(&ioc->FreeQlock, flags);
2079         hd->tmPending = 0;
2080         spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2081         hd->tmState = TM_STATE_NONE;
2082
2083         return 1;
2084 }
2085
2086 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2087 /*
2088  *      This is anyones guess quite frankly.
2089  */
2090 int
2091 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2092                 sector_t capacity, int geom[])
2093 {
2094         int             heads;
2095         int             sectors;
2096         sector_t        cylinders;
2097         ulong           dummy;
2098
2099         heads = 64;
2100         sectors = 32;
2101
2102         dummy = heads * sectors;
2103         cylinders = capacity;
2104         sector_div(cylinders,dummy);
2105
2106         /*
2107          * Handle extended translation size for logical drives
2108          * > 1Gb
2109          */
2110         if ((ulong)capacity >= 0x200000) {
2111                 heads = 255;
2112                 sectors = 63;
2113                 dummy = heads * sectors;
2114                 cylinders = capacity;
2115                 sector_div(cylinders,dummy);
2116         }
2117
2118         /* return result */
2119         geom[0] = heads;
2120         geom[1] = sectors;
2121         geom[2] = cylinders;
2122
2123         dprintk((KERN_NOTICE
2124                 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2125                 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
2126
2127         return 0;
2128 }
2129
2130 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2131 /*
2132  *      OS entry point to allow host driver to alloc memory
2133  *      for each scsi device. Called once per device the bus scan.
2134  *      Return non-zero if allocation fails.
2135  *      Init memory once per id (not LUN).
2136  */
2137 int
2138 mptscsih_slave_alloc(struct scsi_device *device)
2139 {
2140         struct Scsi_Host        *host = device->host;
2141         MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
2142         VirtDevice              *vdev;
2143         uint                    target = device->id;
2144
2145         if (hd == NULL)
2146                 return -ENODEV;
2147
2148         if ((vdev = hd->Targets[target]) != NULL)
2149                 goto out;
2150
2151         vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
2152         if (!vdev) {
2153                 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2154                                 hd->ioc->name, sizeof(VirtDevice));
2155                 return -ENOMEM;
2156         }
2157
2158         memset(vdev, 0, sizeof(VirtDevice));
2159         vdev->tflags = MPT_TARGET_FLAGS_Q_YES;
2160         vdev->ioc_id = hd->ioc->id;
2161         vdev->target_id = device->id;
2162         vdev->bus_id = device->channel;
2163         vdev->raidVolume = 0;
2164         hd->Targets[device->id] = vdev;
2165         if (hd->ioc->bus_type == SCSI) {
2166                 if (hd->ioc->spi_data.isRaid & (1 << device->id)) {
2167                         vdev->raidVolume = 1;
2168                         ddvtprintk((KERN_INFO
2169                             "RAID Volume @ id %d\n", device->id));
2170                 }
2171         } else {
2172                 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2173         }
2174
2175  out:
2176         vdev->num_luns++;
2177         return 0;
2178 }
2179
2180 static int 
2181 mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
2182 {
2183         int i;
2184
2185         if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3)
2186                 return 0;
2187
2188         for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) {
2189                 if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID)
2190                         return 1;
2191         }
2192
2193         return 0;
2194 }
2195
2196 /*
2197  *      OS entry point to allow for host driver to free allocated memory
2198  *      Called if no device present or device being unloaded
2199  */
2200 void
2201 mptscsih_slave_destroy(struct scsi_device *device)
2202 {
2203         struct Scsi_Host        *host = device->host;
2204         MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)host->hostdata;
2205         VirtDevice              *vdev;
2206         uint                    target = device->id;
2207         uint                    lun = device->lun;
2208
2209         if (hd == NULL)
2210                 return;
2211
2212         mptscsih_search_running_cmds(hd, target, lun);
2213
2214         vdev = hd->Targets[target];
2215         vdev->luns[0] &= ~(1 << lun);
2216         if (--vdev->num_luns)
2217                 return;
2218
2219         kfree(hd->Targets[target]);
2220         hd->Targets[target] = NULL;
2221
2222         if (hd->ioc->bus_type == SCSI) {
2223                 if (mptscsih_is_raid_volume(hd, target)) {
2224                         hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
2225                 } else {
2226                         hd->ioc->spi_data.dvStatus[target] =
2227                                 MPT_SCSICFG_NEGOTIATE;
2228
2229                         if (!hd->negoNvram) {
2230                                 hd->ioc->spi_data.dvStatus[target] |=
2231                                         MPT_SCSICFG_DV_NOT_DONE;
2232                         }
2233                 }
2234         }
2235 }
2236
2237 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2238 /*
2239  *      mptscsih_change_queue_depth - This function will set a devices queue depth
2240  *      @sdev: per scsi_device pointer
2241  *      @qdepth: requested queue depth
2242  *
2243  *      Adding support for new 'change_queue_depth' api.
2244 */
2245 int
2246 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2247 {
2248         MPT_SCSI_HOST   *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2249         VirtDevice *pTarget;
2250         int     max_depth;
2251         int     tagged;
2252
2253         if (hd == NULL)
2254                 return 0;
2255         if (!(pTarget = hd->Targets[sdev->id]))
2256                 return 0;
2257
2258         if (hd->ioc->bus_type == SCSI) {
2259                 if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
2260                         if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2261                                 max_depth = 1;
2262                         else if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
2263                                  (pTarget->minSyncFactor <= MPT_ULTRA160 ))
2264                                 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2265                         else
2266                                 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2267                 } else {
2268                         /* error case - No Inq. Data */
2269                         max_depth = 1;
2270                 }
2271         } else
2272                 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2273
2274         if (qdepth > max_depth)
2275                 qdepth = max_depth;
2276         if (qdepth == 1)
2277                 tagged = 0;
2278         else
2279                 tagged = MSG_SIMPLE_TAG;
2280
2281         scsi_adjust_queue_depth(sdev, tagged, qdepth);
2282         return sdev->queue_depth;
2283 }
2284
2285 /*
2286  *      OS entry point to adjust the queue_depths on a per-device basis.
2287  *      Called once per device the bus scan. Use it to force the queue_depth
2288  *      member to 1 if a device does not support Q tags.
2289  *      Return non-zero if fails.
2290  */
2291 int
2292 mptscsih_slave_configure(struct scsi_device *device)
2293 {
2294         struct Scsi_Host        *sh = device->host;
2295         VirtDevice              *pTarget;
2296         MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sh->hostdata;
2297
2298         if ((hd == NULL) || (hd->Targets == NULL)) {
2299                 return 0;
2300         }
2301
2302         dsprintk((MYIOC_s_INFO_FMT
2303                 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2304                 hd->ioc->name, device, device->id, device->lun, device->channel));
2305         dsprintk((MYIOC_s_INFO_FMT
2306                 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2307                 hd->ioc->name, device->sdtr, device->wdtr,
2308                 device->ppr, device->inquiry_len));
2309
2310         if (device->id > sh->max_id) {
2311                 /* error case, should never happen */
2312                 scsi_adjust_queue_depth(device, 0, 1);
2313                 goto slave_configure_exit;
2314         }
2315
2316         pTarget = hd->Targets[device->id];
2317
2318         if (pTarget == NULL) {
2319                 /* Driver doesn't know about this device.
2320                  * Kernel may generate a "Dummy Lun 0" which
2321                  * may become a real Lun if a 
2322                  * "scsi add-single-device" command is executed
2323                  * while the driver is active (hot-plug a 
2324                  * device).  LSI Raid controllers need 
2325                  * queue_depth set to DEV_HIGH for this reason.
2326                  */
2327                 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
2328                         MPT_SCSI_CMD_PER_DEV_HIGH);
2329                 goto slave_configure_exit;
2330         }
2331
2332         mptscsih_initTarget(hd, device->channel, device->id, device->lun,
2333                 device->inquiry, device->inquiry_len );
2334         mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH);
2335
2336         dsprintk((MYIOC_s_INFO_FMT
2337                 "Queue depth=%d, tflags=%x\n",
2338                 hd->ioc->name, device->queue_depth, pTarget->tflags));
2339
2340         dsprintk((MYIOC_s_INFO_FMT
2341                 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2342                 hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
2343
2344 slave_configure_exit:
2345
2346         dsprintk((MYIOC_s_INFO_FMT
2347                 "tagged %d, simple %d, ordered %d\n",
2348                 hd->ioc->name,device->tagged_supported, device->simple_tags,
2349                 device->ordered_tags));
2350
2351         return 0;
2352 }
2353
2354 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2355 /*
2356  *  Private routines...
2357  */
2358
2359 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2360 /* Utility function to copy sense data from the scsi_cmnd buffer
2361  * to the FC and SCSI target structures.
2362  *
2363  */
2364 static void
2365 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2366 {
2367         VirtDevice      *target;
2368         SCSIIORequest_t *pReq;
2369         u32              sense_count = le32_to_cpu(pScsiReply->SenseCount);
2370         int              index;
2371
2372         /* Get target structure
2373          */
2374         pReq = (SCSIIORequest_t *) mf;
2375         index = (int) pReq->TargetID;
2376         target = hd->Targets[index];
2377
2378         if (sense_count) {
2379                 u8 *sense_data;
2380                 int req_index;
2381
2382                 /* Copy the sense received into the scsi command block. */
2383                 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2384                 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2385                 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2386
2387                 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2388                  */
2389                 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2390                         if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
2391                                 int idx;
2392                                 MPT_ADAPTER *ioc = hd->ioc;
2393
2394                                 idx = ioc->eventContext % ioc->eventLogSize;
2395                                 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2396                                 ioc->events[idx].eventContext = ioc->eventContext;
2397
2398                                 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2399                                         (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2400                                         (pReq->Bus << 8) || pReq->TargetID;
2401
2402                                 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2403
2404                                 ioc->eventContext++;
2405                         }
2406                 }
2407         } else {
2408                 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2409                                 hd->ioc->name));
2410         }
2411 }
2412
2413 static u32
2414 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2415 {
2416         MPT_SCSI_HOST *hd;
2417         int i;
2418
2419         hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2420
2421         for (i = 0; i < hd->ioc->req_depth; i++) {
2422                 if (hd->ScsiLookup[i] == sc) {
2423                         return i;
2424                 }
2425         }
2426
2427         return -1;
2428 }
2429
2430 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2431 int
2432 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2433 {
2434         MPT_SCSI_HOST   *hd;
2435         unsigned long    flags;
2436
2437         dtmprintk((KERN_WARNING MYNAM
2438                         ": IOC %s_reset routed to SCSI host driver!\n",
2439                         reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2440                         reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2441
2442         /* If a FW reload request arrives after base installed but
2443          * before all scsi hosts have been attached, then an alt_ioc
2444          * may have a NULL sh pointer.
2445          */
2446         if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2447                 return 0;
2448         else
2449                 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2450
2451         if (reset_phase == MPT_IOC_SETUP_RESET) {
2452                 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2453
2454                 /* Clean Up:
2455                  * 1. Set Hard Reset Pending Flag
2456                  * All new commands go to doneQ
2457                  */
2458                 hd->resetPending = 1;
2459
2460         } else if (reset_phase == MPT_IOC_PRE_RESET) {
2461                 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2462
2463                 /* 2. Flush running commands
2464                  *      Clean ScsiLookup (and associated memory)
2465                  *      AND clean mytaskQ
2466                  */
2467
2468                 /* 2b. Reply to OS all known outstanding I/O commands.
2469                  */
2470                 mptscsih_flush_running_cmds(hd);
2471
2472                 /* 2c. If there was an internal command that
2473                  * has not completed, configuration or io request,
2474                  * free these resources.
2475                  */
2476                 if (hd->cmdPtr) {
2477                         del_timer(&hd->timer);
2478                         mpt_free_msg_frame(ioc, hd->cmdPtr);
2479                 }
2480
2481                 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2482
2483         } else {
2484                 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2485
2486                 /* Once a FW reload begins, all new OS commands are
2487                  * redirected to the doneQ w/ a reset status.
2488                  * Init all control structures.
2489                  */
2490
2491                 /* ScsiLookup initialization
2492                  */
2493                 {
2494                         int ii;
2495                         for (ii=0; ii < hd->ioc->req_depth; ii++)
2496                                 hd->ScsiLookup[ii] = NULL;
2497                 }
2498
2499                 /* 2. Chain Buffer initialization
2500                  */
2501
2502                 /* 4. Renegotiate to all devices, if SCSI
2503                  */
2504                 if (ioc->bus_type == SCSI) {
2505                         dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
2506                         mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
2507                 }
2508
2509                 /* 5. Enable new commands to be posted
2510                  */
2511                 spin_lock_irqsave(&ioc->FreeQlock, flags);
2512                 hd->tmPending = 0;
2513                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2514                 hd->resetPending = 0;
2515                 hd->tmState = TM_STATE_NONE;
2516
2517                 /* 6. If there was an internal command,
2518                  * wake this process up.
2519                  */
2520                 if (hd->cmdPtr) {
2521                         /*
2522                          * Wake up the original calling thread
2523                          */
2524                         hd->pLocal = &hd->localReply;
2525                         hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2526                         hd->scandv_wait_done = 1;
2527                         wake_up(&hd->scandv_waitq);
2528                         hd->cmdPtr = NULL;
2529                 }
2530
2531                 /* 7. Set flag to force DV and re-read IOC Page 3
2532                  */
2533                 if (ioc->bus_type == SCSI) {
2534                         ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2535                         ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2536                 }
2537
2538                 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2539
2540         }
2541
2542         return 1;               /* currently means nothing really */
2543 }
2544
2545 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2546 int
2547 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2548 {
2549         MPT_SCSI_HOST *hd;
2550         u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2551
2552         devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2553                         ioc->name, event));
2554
2555         switch (event) {
2556         case MPI_EVENT_UNIT_ATTENTION:                  /* 03 */
2557                 /* FIXME! */
2558                 break;
2559         case MPI_EVENT_IOC_BUS_RESET:                   /* 04 */
2560         case MPI_EVENT_EXT_BUS_RESET:                   /* 05 */
2561                 hd = NULL;
2562                 if (ioc->sh) {
2563                         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2564                         if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
2565                                 hd->soft_resets++;
2566                 }
2567                 break;
2568         case MPI_EVENT_LOGOUT:                          /* 09 */
2569                 /* FIXME! */
2570                 break;
2571
2572                 /*
2573                  *  CHECKME! Don't think we need to do
2574                  *  anything for these, but...
2575                  */
2576         case MPI_EVENT_RESCAN:                          /* 06 */
2577         case MPI_EVENT_LINK_STATUS_CHANGE:              /* 07 */
2578         case MPI_EVENT_LOOP_STATE_CHANGE:               /* 08 */
2579                 /*
2580                  *  CHECKME!  Falling thru...
2581                  */
2582                 break;
2583
2584         case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
2585 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2586                 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
2587                  * if DV disabled. Need to check for target mode.
2588                  */
2589                 hd = NULL;
2590                 if (ioc->sh)
2591                         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2592
2593                 if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) {
2594                         ScsiCfgData     *pSpi;
2595                         Ioc3PhysDisk_t  *pPDisk;
2596                         int              numPDisk;
2597                         u8               reason;
2598                         u8               physDiskNum;
2599
2600                         reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
2601                         if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
2602                                 /* New or replaced disk.
2603                                  * Set DV flag and schedule DV.
2604                                  */
2605                                 pSpi = &ioc->spi_data;
2606                                 physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
2607                                 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
2608                                 if (pSpi->pIocPg3) {
2609                                         pPDisk =  pSpi->pIocPg3->PhysDisk;
2610                                         numPDisk =pSpi->pIocPg3->NumPhysDisks;
2611
2612                                         while (numPDisk) {
2613                                                 if (physDiskNum == pPDisk->PhysDiskNum) {
2614                                                         pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
2615                                                         pSpi->forceDv = MPT_SCSICFG_NEED_DV;
2616                                                         ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
2617                                                         break;
2618                                                 }
2619                                                 pPDisk++;
2620                                                 numPDisk--;
2621                                         }
2622
2623                                         if (numPDisk == 0) {
2624                                                 /* The physical disk that needs DV was not found
2625                                                  * in the stored IOC Page 3. The driver must reload
2626                                                  * this page. DV routine will set the NEED_DV flag for
2627                                                  * all phys disks that have DV_NOT_DONE set.
2628                                                  */
2629                                                 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2630                                                 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
2631                                         }
2632                                 }
2633                         }
2634                 }
2635 #endif
2636
2637 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
2638                 printk("Raid Event RF: ");
2639                 {
2640                         u32 *m = (u32 *)pEvReply;
2641                         int ii;
2642                         int n = (int)pEvReply->MsgLength;
2643                         for (ii=6; ii < n; ii++)
2644                                 printk(" %08x", le32_to_cpu(m[ii]));
2645                         printk("\n");
2646                 }
2647 #endif
2648                 break;
2649
2650         case MPI_EVENT_NONE:                            /* 00 */
2651         case MPI_EVENT_LOG_DATA:                        /* 01 */
2652         case MPI_EVENT_STATE_CHANGE:                    /* 02 */
2653         case MPI_EVENT_EVENT_CHANGE:                    /* 0A */
2654         default:
2655                 dprintk((KERN_INFO "  Ignoring event (=%02Xh)\n", event));
2656                 break;
2657         }
2658
2659         return 1;               /* currently means nothing really */
2660 }
2661
2662 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2663 /*
2664  *      mptscsih_initTarget - Target, LUN alloc/free functionality.
2665  *      @hd: Pointer to MPT_SCSI_HOST structure
2666  *      @bus_id: Bus number (?)
2667  *      @target_id: SCSI target id
2668  *      @lun: SCSI LUN id
2669  *      @data: Pointer to data
2670  *      @dlen: Number of INQUIRY bytes
2671  *
2672  *      NOTE: It's only SAFE to call this routine if data points to
2673  *      sane & valid STANDARD INQUIRY data!
2674  *
2675  *      Allocate and initialize memory for this target.
2676  *      Save inquiry data.
2677  *
2678  */
2679 static void
2680 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
2681 {
2682         int             indexed_lun, lun_index;
2683         VirtDevice      *vdev;
2684         ScsiCfgData     *pSpi;
2685         char            data_56;
2686
2687         dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
2688                         hd->ioc->name, bus_id, target_id, lun, hd));
2689
2690         /*
2691          * If the peripheral qualifier filter is enabled then if the target reports a 0x1
2692          * (i.e. The targer is capable of supporting the specified peripheral device type
2693          * on this logical unit; however, the physical device is not currently connected
2694          * to this logical unit) it will be converted to a 0x3 (i.e. The target is not 
2695          * capable of supporting a physical device on this logical unit). This is to work
2696          * around a bug in th emid-layer in some distributions in which the mid-layer will
2697          * continue to try to communicate to the LUN and evntually create a dummy LUN.
2698         */
2699         if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
2700                 data[0] |= 0x40;
2701
2702         /* Is LUN supported? If so, upper 2 bits will be 0
2703         * in first byte of inquiry data.
2704         */
2705         if (data[0] & 0xe0)
2706                 return;
2707
2708         if ((vdev = hd->Targets[target_id]) == NULL) {
2709                 return;
2710         }
2711
2712         lun_index = (lun >> 5);  /* 32 luns per lun_index */
2713         indexed_lun = (lun % 32);
2714         vdev->luns[lun_index] |= (1 << indexed_lun);
2715
2716         if (hd->ioc->bus_type == SCSI) {
2717                 if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2718                         /* Treat all Processors as SAF-TE if
2719                          * command line option is set */
2720                         vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2721                         mptscsih_writeIOCPage4(hd, target_id, bus_id);
2722                 }else if ((data[0] == TYPE_PROCESSOR) &&
2723                         !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2724                         if ( dlen > 49 ) {
2725                                 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2726                                 if ( data[44] == 'S' &&
2727                                      data[45] == 'A' &&
2728                                      data[46] == 'F' &&
2729                                      data[47] == '-' &&
2730                                      data[48] == 'T' &&
2731                                      data[49] == 'E' ) {
2732                                         vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2733                                         mptscsih_writeIOCPage4(hd, target_id, bus_id);
2734                                 }
2735                         }
2736                 }
2737                 if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
2738                         if ( dlen > 8 ) {
2739                                 memcpy (vdev->inq_data, data, 8);
2740                         } else {
2741                                 memcpy (vdev->inq_data, data, dlen);
2742                         }
2743
2744                         /* If have not done DV, set the DV flag.
2745                          */
2746                         pSpi = &hd->ioc->spi_data;
2747                         if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
2748                                 if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
2749                                         pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
2750                         }
2751
2752                         vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2753
2754
2755                         data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
2756                         if (dlen > 56) {
2757                                 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2758                                 /* Update the target capabilities
2759                                  */
2760                                         data_56 = data[56];
2761                                         vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
2762                                 }
2763                         }
2764                         mptscsih_setTargetNegoParms(hd, vdev, data_56);
2765                 } else {
2766                         /* Initial Inquiry may not request enough data bytes to
2767                          * obtain byte 57.  DV will; if target doesn't return
2768                          * at least 57 bytes, data[56] will be zero. */
2769                         if (dlen > 56) {
2770                                 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2771                                 /* Update the target capabilities
2772                                  */
2773                                         data_56 = data[56];
2774                                         vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
2775                                         mptscsih_setTargetNegoParms(hd, vdev, data_56);
2776                                 }
2777                         }
2778                 }
2779         }
2780 }
2781
2782 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2783 /*
2784  *  Update the target negotiation parameters based on the
2785  *  the Inquiry data, adapter capabilities, and NVRAM settings.
2786  *
2787  */
2788 static void
2789 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
2790 {
2791         ScsiCfgData *pspi_data = &hd->ioc->spi_data;
2792         int  id = (int) target->target_id;
2793         int  nvram;
2794         VirtDevice      *vdev;
2795         int ii;
2796         u8 width = MPT_NARROW;
2797         u8 factor = MPT_ASYNC;
2798         u8 offset = 0;
2799         u8 version, nfactor;
2800         u8 noQas = 1;
2801
2802         target->negoFlags = pspi_data->noQas;
2803
2804         /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
2805          * support. If available, default QAS to off and allow enabling.
2806          * If not available, default QAS to on, turn off for non-disks.
2807          */
2808
2809         /* Set flags based on Inquiry data
2810          */
2811         version = target->inq_data[2] & 0x07;
2812         if (version < 2) {
2813                 width = 0;
2814                 factor = MPT_ULTRA2;
2815                 offset = pspi_data->maxSyncOffset;
2816                 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2817         } else {
2818                 if (target->inq_data[7] & 0x20) {
2819                         width = 1;
2820                 }
2821
2822                 if (target->inq_data[7] & 0x10) {
2823                         factor = pspi_data->minSyncFactor;
2824                         if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
2825                                 /* bits 2 & 3 show Clocking support */
2826                                 if ((byte56 & 0x0C) == 0)
2827                                         factor = MPT_ULTRA2;
2828                                 else {
2829                                         if ((byte56 & 0x03) == 0)
2830                                                 factor = MPT_ULTRA160;
2831                                         else {
2832                                                 factor = MPT_ULTRA320;
2833                                                 if (byte56 & 0x02)
2834                                                 {
2835                                                         ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
2836                                                         noQas = 0;
2837                                                 }
2838                                                 if (target->inq_data[0] == TYPE_TAPE) {
2839                                                         if (byte56 & 0x01)
2840                                                                 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2841                                                 }
2842                                         }
2843                                 }
2844                         } else {
2845                                 ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
2846                                 noQas = 0;
2847                         }
2848
2849                         offset = pspi_data->maxSyncOffset;
2850
2851                         /* If RAID, never disable QAS
2852                          * else if non RAID, do not disable
2853                          *   QAS if bit 1 is set
2854                          * bit 1 QAS support, non-raid only
2855                          * bit 0 IU support
2856                          */
2857                         if (target->raidVolume == 1) {
2858                                 noQas = 0;
2859                         }
2860                 } else {
2861                         factor = MPT_ASYNC;
2862                         offset = 0;
2863                 }
2864         }
2865
2866         if ( (target->inq_data[7] & 0x02) == 0) {
2867                 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2868         }
2869
2870         /* Update tflags based on NVRAM settings. (SCSI only)
2871          */
2872         if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2873                 nvram = pspi_data->nvram[id];
2874                 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2875
2876                 if (width)
2877                         width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2878
2879                 if (offset > 0) {
2880                         /* Ensure factor is set to the
2881                          * maximum of: adapter, nvram, inquiry
2882                          */
2883                         if (nfactor) {
2884                                 if (nfactor < pspi_data->minSyncFactor )
2885                                         nfactor = pspi_data->minSyncFactor;
2886
2887                                 factor = max(factor, nfactor);
2888                                 if (factor == MPT_ASYNC)
2889                                         offset = 0;
2890                         } else {
2891                                 offset = 0;
2892                                 factor = MPT_ASYNC;
2893                 }
2894                 } else {
2895                         factor = MPT_ASYNC;
2896                 }
2897         }
2898
2899         /* Make sure data is consistent
2900          */
2901         if ((!width) && (factor < MPT_ULTRA2)) {
2902                 factor = MPT_ULTRA2;
2903         }
2904
2905         /* Save the data to the target structure.
2906          */
2907         target->minSyncFactor = factor;
2908         target->maxOffset = offset;
2909         target->maxWidth = width;
2910
2911         target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2912
2913         /* Disable unused features.
2914          */
2915         if (!width)
2916                 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2917
2918         if (!offset)
2919                 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2920
2921         if ( factor > MPT_ULTRA320 )
2922                 noQas = 0;
2923
2924         /* GEM, processor WORKAROUND
2925          */
2926         if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
2927                 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
2928                 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
2929         } else {
2930                 if (noQas && (pspi_data->noQas == 0)) {
2931                         pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2932                         target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2933
2934                         /* Disable QAS in a mixed configuration case
2935                         */
2936
2937                         ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2938                         for (ii = 0; ii < id; ii++) {
2939                                 if ( (vdev = hd->Targets[ii]) ) {
2940                                         vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2941                                         mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
2942                                 }
2943                         }
2944                 }
2945         }
2946
2947         /* Write SDP1 on this I/O to this target */
2948         if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
2949                 ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
2950                 mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
2951                 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
2952         } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
2953                 ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
2954                 mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
2955                 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
2956         }
2957 }
2958
2959 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2960 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
2961  * Else set the NEED_DV flag after Read Capacity Issued (disks)
2962  * or Mode Sense (cdroms).
2963  *
2964  * Tapes, initTarget will set this flag on completion of Inquiry command.
2965  * Called only if DV_NOT_DONE flag is set
2966  */
2967 static void
2968 mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
2969 {
2970         u8 cmd;
2971         ScsiCfgData *pSpi;
2972
2973         ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", 
2974                 pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
2975
2976         if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
2977                 return;
2978
2979         cmd = pReq->CDB[0];
2980
2981         if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
2982                 pSpi = &hd->ioc->spi_data;
2983                 if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
2984                         /* Set NEED_DV for all hidden disks
2985                          */
2986                         Ioc3PhysDisk_t *pPDisk =  pSpi->pIocPg3->PhysDisk;
2987                         int             numPDisk = pSpi->pIocPg3->NumPhysDisks;
2988
2989                         while (numPDisk) {
2990                                 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
2991                                 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
2992                                 pPDisk++;
2993                                 numPDisk--;
2994                         }
2995                 }
2996                 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
2997                 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
2998         }
2999 }
3000
3001 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3002 /*
3003  * If no Target, bus reset on 1st I/O. Set the flag to
3004  * prevent any future negotiations to this device.
3005  */
3006 static void
3007 mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
3008 {
3009
3010         if ((hd->Targets) && (hd->Targets[target_id] == NULL))
3011                 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
3012
3013         return;
3014 }
3015
3016 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3017 /*
3018  *  SCSI Config Page functionality ...
3019  */
3020 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3021 /*      mptscsih_setDevicePage1Flags  - add Requested and Configuration fields flags
3022  *      based on width, factor and offset parameters.
3023  *      @width: bus width
3024  *      @factor: sync factor
3025  *      @offset: sync offset
3026  *      @requestedPtr: pointer to requested values (updated)
3027  *      @configurationPtr: pointer to configuration values (updated)
3028  *      @flags: flags to block WDTR or SDTR negotiation
3029  *
3030  *      Return: None.
3031  *
3032  *      Remark: Called by writeSDP1 and _dv_params
3033  */
3034 static void
3035 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
3036 {
3037         u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
3038         u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
3039
3040         *configurationPtr = 0;
3041         *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
3042         *requestedPtr |= (offset << 16) | (factor << 8);
3043
3044         if (width && offset && !nowide && !nosync) {
3045                 if (factor < MPT_ULTRA160) {
3046                         *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
3047                         if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
3048                                 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
3049                         if (flags & MPT_TAPE_NEGO_IDP)
3050                                 *requestedPtr |= 0x08000000;
3051                 } else if (factor < MPT_ULTRA2) {
3052                         *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
3053                 }
3054         }
3055
3056         if (nowide)
3057                 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
3058
3059         if (nosync)
3060                 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
3061
3062         return;
3063 }
3064
3065 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3066 /*      mptscsih_writeSDP1  - write SCSI Device Page 1
3067  *      @hd: Pointer to a SCSI Host Strucutre
3068  *      @portnum: IOC port number
3069  *      @target_id: writeSDP1 for single ID
3070  *      @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
3071  *
3072  *      Return: -EFAULT if read of config page header fails
3073  *              or 0 if success.
3074  *
3075  *      Remark: If a target has been found, the settings from the
3076  *              target structure are used, else the device is set
3077  *              to async/narrow.
3078  *
3079  *      Remark: Called during init and after a FW reload.
3080  *      Remark: We do not wait for a return, write pages sequentially.
3081  */
3082 static int
3083 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
3084 {
3085         MPT_ADAPTER             *ioc = hd->ioc;
3086         Config_t                *pReq;
3087         SCSIDevicePage1_t       *pData;
3088         VirtDevice              *pTarget;
3089         MPT_FRAME_HDR           *mf;
3090         dma_addr_t               dataDma;
3091         u16                      req_idx;
3092         u32                      frameOffset;
3093         u32                      requested, configuration, flagsLength;
3094         int                      ii, nvram;
3095         int                      id = 0, maxid = 0;
3096         u8                       width;
3097         u8                       factor;
3098         u8                       offset;
3099         u8                       bus = 0;
3100         u8                       negoFlags;
3101         u8                       maxwidth, maxoffset, maxfactor;
3102
3103         if (ioc->spi_data.sdp1length == 0)
3104                 return 0;
3105
3106         if (flags & MPT_SCSICFG_ALL_IDS) {
3107                 id = 0;
3108                 maxid = ioc->sh->max_id - 1;
3109         } else if (ioc->sh) {
3110                 id = target_id;
3111                 maxid = min_t(int, id, ioc->sh->max_id - 1);
3112         }
3113
3114         for (; id <= maxid; id++) {
3115
3116                 if (id == ioc->pfacts[portnum].PortSCSIID)
3117                         continue;
3118
3119                 /* Use NVRAM to get adapter and target maximums
3120                  * Data over-riden by target structure information, if present
3121                  */
3122                 maxwidth = ioc->spi_data.maxBusWidth;
3123                 maxoffset = ioc->spi_data.maxSyncOffset;
3124                 maxfactor = ioc->spi_data.minSyncFactor;
3125                 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3126                         nvram = ioc->spi_data.nvram[id];
3127
3128                         if (maxwidth)
3129                                 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
3130
3131                         if (maxoffset > 0) {
3132                                 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
3133                                 if (maxfactor == 0) {
3134                                         /* Key for async */
3135                                         maxfactor = MPT_ASYNC;
3136                                         maxoffset = 0;
3137                                 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
3138                                         maxfactor = ioc->spi_data.minSyncFactor;
3139                                 }
3140                         } else
3141                                 maxfactor = MPT_ASYNC;
3142                 }
3143
3144                 /* Set the negotiation flags.
3145                  */
3146                 negoFlags = ioc->spi_data.noQas;
3147                 if (!maxwidth)
3148                         negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
3149
3150                 if (!maxoffset)
3151                         negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
3152
3153                 if (flags & MPT_SCSICFG_USE_NVRAM) {
3154                         width = maxwidth;
3155                         factor = maxfactor;
3156                         offset = maxoffset;
3157                 } else {
3158                         width = 0;
3159                         factor = MPT_ASYNC;
3160                         offset = 0;
3161                         //negoFlags = 0;
3162                         //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
3163                 }
3164
3165                 /* If id is not a raid volume, get the updated
3166                  * transmission settings from the target structure.
3167                  */
3168                 if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
3169                         width = pTarget->maxWidth;
3170                         factor = pTarget->minSyncFactor;
3171                         offset = pTarget->maxOffset;
3172                         negoFlags = pTarget->negoFlags;
3173                 }
3174
3175 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3176                 /* Force to async and narrow if DV has not been executed
3177                  * for this ID
3178                  */
3179                 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
3180                         width = 0;
3181                         factor = MPT_ASYNC;
3182                         offset = 0;
3183                 }
3184 #endif
3185
3186                 if (flags & MPT_SCSICFG_BLK_NEGO)
3187                         negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
3188
3189                 mptscsih_setDevicePage1Flags(width, factor, offset,
3190                                         &requested, &configuration, negoFlags);
3191                 dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
3192                         target_id, width, factor, offset, negoFlags, requested, configuration));
3193
3194                 /* Get a MF for this command.
3195                  */
3196                 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3197                         dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
3198                                                 ioc->name));
3199                         return -EAGAIN;
3200                 }
3201
3202                 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
3203                         hd->ioc->name, mf, id, requested, configuration));
3204
3205
3206                 /* Set the request and the data pointers.
3207                  * Request takes: 36 bytes (32 bit SGE)
3208                  * SCSI Device Page 1 requires 16 bytes
3209                  * 40 + 16 <= size of SCSI IO Request = 56 bytes
3210                  * and MF size >= 64 bytes.
3211                  * Place data at end of MF.
3212                  */
3213                 pReq = (Config_t *)mf;
3214
3215                 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3216                 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
3217
3218                 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
3219                 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
3220
3221                 /* Complete the request frame (same for all requests).
3222                  */
3223                 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3224                 pReq->Reserved = 0;
3225                 pReq->ChainOffset = 0;
3226                 pReq->Function = MPI_FUNCTION_CONFIG;
3227                 pReq->ExtPageLength = 0;
3228                 pReq->ExtPageType = 0;
3229                 pReq->MsgFlags = 0;
3230                 for (ii=0; ii < 8; ii++) {
3231                         pReq->Reserved2[ii] = 0;
3232                 }
3233                 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
3234                 pReq->Header.PageLength = ioc->spi_data.sdp1length;
3235                 pReq->Header.PageNumber = 1;
3236                 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3237                 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
3238
3239                 /* Add a SGE to the config request.
3240                  */
3241                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
3242
3243                 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3244
3245                 /* Set up the common data portion
3246                  */
3247                 pData->Header.PageVersion = pReq->Header.PageVersion;
3248                 pData->Header.PageLength = pReq->Header.PageLength;
3249                 pData->Header.PageNumber = pReq->Header.PageNumber;
3250                 pData->Header.PageType = pReq->Header.PageType;
3251                 pData->RequestedParameters = cpu_to_le32(requested);
3252                 pData->Reserved = 0;
3253                 pData->Configuration = cpu_to_le32(configuration);
3254
3255                 dprintk((MYIOC_s_INFO_FMT
3256                         "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
3257                                 ioc->name, id, (id | (bus<<8)),
3258                                 requested, configuration));
3259
3260                 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3261         }
3262
3263         return 0;
3264 }
3265
3266 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3267 /*      mptscsih_writeIOCPage4  - write IOC Page 4
3268  *      @hd: Pointer to a SCSI Host Structure
3269  *      @target_id: write IOC Page4 for this ID & Bus
3270  *
3271  *      Return: -EAGAIN if unable to obtain a Message Frame
3272  *              or 0 if success.
3273  *
3274  *      Remark: We do not wait for a return, write pages sequentially.
3275  */
3276 static int
3277 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
3278 {
3279         MPT_ADAPTER             *ioc = hd->ioc;
3280         Config_t                *pReq;
3281         IOCPage4_t              *IOCPage4Ptr;
3282         MPT_FRAME_HDR           *mf;
3283         dma_addr_t               dataDma;
3284         u16                      req_idx;
3285         u32                      frameOffset;
3286         u32                      flagsLength;
3287         int                      ii;
3288
3289         /* Get a MF for this command.
3290          */
3291         if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3292                 dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
3293                                         ioc->name));
3294                 return -EAGAIN;
3295         }
3296
3297         /* Set the request and the data pointers.
3298          * Place data at end of MF.
3299          */
3300         pReq = (Config_t *)mf;
3301
3302         req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3303         frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
3304
3305         /* Complete the request frame (same for all requests).
3306          */
3307         pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3308         pReq->Reserved = 0;
3309         pReq->ChainOffset = 0;
3310         pReq->Function = MPI_FUNCTION_CONFIG;
3311         pReq->ExtPageLength = 0;
3312         pReq->ExtPageType = 0;
3313         pReq->MsgFlags = 0;
3314         for (ii=0; ii < 8; ii++) {
3315                 pReq->Reserved2[ii] = 0;
3316         }
3317
3318         IOCPage4Ptr = ioc->spi_data.pIocPg4;
3319         dataDma = ioc->spi_data.IocPg4_dma;
3320         ii = IOCPage4Ptr->ActiveSEP++;
3321         IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
3322         IOCPage4Ptr->SEP[ii].SEPBus = bus;
3323         pReq->Header = IOCPage4Ptr->Header;
3324         pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
3325
3326         /* Add a SGE to the config request.
3327          */
3328         flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
3329                 (IOCPage4Ptr->Header.PageLength + ii) * 4;
3330
3331         mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3332
3333         dinitprintk((MYIOC_s_INFO_FMT
3334                 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
3335                         ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
3336
3337         mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3338
3339         return 0;
3340 }
3341
3342 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3343 /*
3344  *  Bus Scan and Domain Validation functionality ...
3345  */
3346
3347 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3348 /*
3349  *      mptscsih_scandv_complete - Scan and DV callback routine registered
3350  *      to Fustion MPT (base) driver.
3351  *
3352  *      @ioc: Pointer to MPT_ADAPTER structure
3353  *      @mf: Pointer to original MPT request frame
3354  *      @mr: Pointer to MPT reply frame (NULL if TurboReply)
3355  *
3356  *      This routine is called from mpt.c::mpt_interrupt() at the completion
3357  *      of any SCSI IO request.
3358  *      This routine is registered with the Fusion MPT (base) driver at driver
3359  *      load/init time via the mpt_register() API call.
3360  *
3361  *      Returns 1 indicating alloc'd request frame ptr should be freed.
3362  *
3363  *      Remark: Sets a completion code and (possibly) saves sense data
3364  *      in the IOC member localReply structure.
3365  *      Used ONLY for DV and other internal commands.
3366  */
3367 int
3368 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3369 {
3370         MPT_SCSI_HOST   *hd;
3371         SCSIIORequest_t *pReq;
3372         int              completionCode;
3373         u16              req_idx;
3374
3375         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3376
3377         if ((mf == NULL) ||
3378             (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
3379                 printk(MYIOC_s_ERR_FMT
3380                         "ScanDvComplete, %s req frame ptr! (=%p)\n",
3381                                 ioc->name, mf?"BAD":"NULL", (void *) mf);
3382                 goto wakeup;
3383         }
3384
3385         del_timer(&hd->timer);
3386         req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3387         hd->ScsiLookup[req_idx] = NULL;
3388         pReq = (SCSIIORequest_t *) mf;
3389
3390         if (mf != hd->cmdPtr) {
3391                 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3392                                 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3393         }
3394         hd->cmdPtr = NULL;
3395
3396         ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3397                         hd->ioc->name, mf, mr, req_idx));
3398
3399         hd->pLocal = &hd->localReply;
3400         hd->pLocal->scsiStatus = 0;
3401
3402         /* If target struct exists, clear sense valid flag.
3403          */
3404         if (mr == NULL) {
3405                 completionCode = MPT_SCANDV_GOOD;
3406         } else {
3407                 SCSIIOReply_t   *pReply;
3408                 u16              status;
3409                 u8               scsi_status;
3410
3411                 pReply = (SCSIIOReply_t *) mr;
3412
3413                 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3414                 scsi_status = pReply->SCSIStatus;
3415
3416                 ddvtprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3417                              status, pReply->SCSIState, scsi_status,
3418                              le32_to_cpu(pReply->IOCLogInfo)));
3419
3420                 switch(status) {
3421
3422                 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
3423                         completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3424                         break;
3425
3426                 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
3427                 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
3428                 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
3429                 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
3430                         completionCode = MPT_SCANDV_DID_RESET;
3431                         break;
3432
3433                 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
3434                 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
3435                 case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
3436                         if (pReply->Function == MPI_FUNCTION_CONFIG) {
3437                                 ConfigReply_t *pr = (ConfigReply_t *)mr;
3438                                 completionCode = MPT_SCANDV_GOOD;
3439                                 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3440                                 hd->pLocal->header.PageLength = pr->Header.PageLength;
3441                                 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3442                                 hd->pLocal->header.PageType = pr->Header.PageType;
3443
3444                         } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3445                                 /* If the RAID Volume request is successful,
3446                                  * return GOOD, else indicate that
3447                                  * some type of error occurred.
3448                                  */
3449                                 MpiRaidActionReply_t    *pr = (MpiRaidActionReply_t *)mr;
3450                                 if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
3451                                         completionCode = MPT_SCANDV_GOOD;
3452                                 else
3453                                         completionCode = MPT_SCANDV_SOME_ERROR;
3454
3455                         } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3456                                 u8              *sense_data;
3457                                 int              sz;
3458
3459                                 /* save sense data in global structure
3460                                  */
3461                                 completionCode = MPT_SCANDV_SENSE;
3462                                 hd->pLocal->scsiStatus = scsi_status;
3463                                 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3464                                         (req_idx * MPT_SENSE_BUFFER_ALLOC));
3465
3466                                 sz = min_t(int, pReq->SenseBufferLength,
3467                                                         SCSI_STD_SENSE_BYTES);
3468                                 memcpy(hd->pLocal->sense, sense_data, sz);
3469
3470                                 ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
3471                                                 sense_data));
3472                         } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3473                                 if (pReq->CDB[0] == INQUIRY)
3474                                         completionCode = MPT_SCANDV_ISSUE_SENSE;
3475                                 else
3476                                         completionCode = MPT_SCANDV_DID_RESET;
3477                         }
3478                         else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3479                                 completionCode = MPT_SCANDV_DID_RESET;
3480                         else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3481                                 completionCode = MPT_SCANDV_DID_RESET;
3482                         else {
3483                                 completionCode = MPT_SCANDV_GOOD;
3484                                 hd->pLocal->scsiStatus = scsi_status;
3485                         }
3486                         break;
3487
3488                 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:         /* 0x0047 */
3489                         if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3490                                 completionCode = MPT_SCANDV_DID_RESET;
3491                         else
3492                                 completionCode = MPT_SCANDV_SOME_ERROR;
3493                         break;
3494
3495                 default:
3496                         completionCode = MPT_SCANDV_SOME_ERROR;
3497                         break;
3498
3499                 }       /* switch(status) */
3500
3501                 ddvtprintk((KERN_NOTICE "  completionCode set to %08xh\n",
3502                                 completionCode));
3503         } /* end of address reply case */
3504
3505         hd->pLocal->completion = completionCode;
3506
3507         /* MF and RF are freed in mpt_interrupt
3508          */
3509 wakeup:
3510         /* Free Chain buffers (will never chain) in scan or dv */
3511         //mptscsih_freeChainBuffers(ioc, req_idx);
3512
3513         /*
3514          * Wake up the original calling thread
3515          */
3516         hd->scandv_wait_done = 1;
3517         wake_up(&hd->scandv_waitq);
3518
3519         return 1;
3520 }
3521
3522 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3523 /*      mptscsih_timer_expired - Call back for timer process.
3524  *      Used only for dv functionality.
3525  *      @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3526  *
3527  */
3528 void
3529 mptscsih_timer_expired(unsigned long data)
3530 {
3531         MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3532
3533         ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3534
3535         if (hd->cmdPtr) {
3536                 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3537
3538                 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3539                         /* Desire to issue a task management request here.
3540                          * TM requests MUST be single threaded.
3541                          * If old eh code and no TM current, issue request.
3542                          * If new eh code, do nothing. Wait for OS cmd timeout
3543                          *      for bus reset.
3544                          */
3545                         ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3546                 } else {
3547                         /* Perform a FW reload */
3548                         if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3549                                 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3550                         }
3551                 }
3552         } else {
3553                 /* This should NEVER happen */
3554                 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3555         }
3556
3557         /* No more processing.
3558          * TM call will generate an interrupt for SCSI TM Management.
3559          * The FW will reply to all outstanding commands, callback will finish cleanup.
3560          * Hard reset clean-up will free all resources.
3561          */
3562         ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3563
3564         return;
3565 }
3566
3567 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3568 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3569 /*      mptscsih_do_raid - Format and Issue a RAID volume request message.
3570  *      @hd: Pointer to scsi host structure
3571  *      @action: What do be done.
3572  *      @id: Logical target id.
3573  *      @bus: Target locations bus.
3574  *
3575  *      Returns: < 0 on a fatal error
3576  *              0 on success
3577  *
3578  *      Remark: Wait to return until reply processed by the ISR.
3579  */
3580 static int
3581 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
3582 {
3583         MpiRaidActionRequest_t  *pReq;
3584         MPT_FRAME_HDR           *mf;
3585         int                     in_isr;
3586
3587         in_isr = in_interrupt();
3588         if (in_isr) {
3589                 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
3590                                 hd->ioc->name));
3591                 return -EPERM;
3592         }
3593
3594         /* Get and Populate a free Frame
3595          */
3596         if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3597                 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
3598                                         hd->ioc->name));
3599                 return -EAGAIN;
3600         }
3601         pReq = (MpiRaidActionRequest_t *)mf;
3602         pReq->Action = action;
3603         pReq->Reserved1 = 0;
3604         pReq->ChainOffset = 0;
3605         pReq->Function = MPI_FUNCTION_RAID_ACTION;
3606         pReq->VolumeID = io->id;
3607         pReq->VolumeBus = io->bus;
3608         pReq->PhysDiskNum = io->physDiskNum;
3609         pReq->MsgFlags = 0;
3610         pReq->Reserved2 = 0;
3611         pReq->ActionDataWord = 0; /* Reserved for this action */
3612         //pReq->ActionDataSGE = 0;
3613
3614         mpt_add_sge((char *)&pReq->ActionDataSGE,
3615                 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
3616
3617         ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
3618                         hd->ioc->name, action, io->id));
3619
3620         hd->pLocal = NULL;
3621         hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
3622         hd->scandv_wait_done = 0;
3623
3624         /* Save cmd pointer, for resource free if timeout or
3625          * FW reload occurs
3626          */
3627         hd->cmdPtr = mf;
3628
3629         add_timer(&hd->timer);
3630         mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3631         wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3632
3633         if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
3634                 return -1;
3635
3636         return 0;
3637 }
3638 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3639
3640 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3641 /**
3642  *      mptscsih_do_cmd - Do internal command.
3643  *      @hd: MPT_SCSI_HOST pointer
3644  *      @io: INTERNAL_CMD pointer.
3645  *
3646  *      Issue the specified internally generated command and do command
3647  *      specific cleanup. For bus scan / DV only.
3648  *      NOTES: If command is Inquiry and status is good,
3649  *      initialize a target structure, save the data
3650  *
3651  *      Remark: Single threaded access only.
3652  *
3653  *      Return:
3654  *              < 0 if an illegal command or no resources
3655  *
3656  *                 0 if good
3657  *
3658  *               > 0 if command complete but some type of completion error.
3659  */
3660 static int
3661 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3662 {
3663         MPT_FRAME_HDR   *mf;
3664         SCSIIORequest_t *pScsiReq;
3665         SCSIIORequest_t  ReqCopy;
3666         int              my_idx, ii, dir;
3667         int              rc, cmdTimeout;
3668         int             in_isr;
3669         char             cmdLen;
3670         char             CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3671         char             cmd = io->cmd;
3672
3673         in_isr = in_interrupt();
3674         if (in_isr) {
3675                 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3676                                 hd->ioc->name));
3677                 return -EPERM;
3678         }
3679
3680
3681         /* Set command specific information
3682          */
3683         switch (cmd) {
3684         case INQUIRY:
3685                 cmdLen = 6;
3686                 dir = MPI_SCSIIO_CONTROL_READ;
3687                 CDB[0] = cmd;
3688                 CDB[4] = io->size;
3689                 cmdTimeout = 10;
3690                 break;
3691
3692         case TEST_UNIT_READY:
3693                 cmdLen = 6;
3694                 dir = MPI_SCSIIO_CONTROL_READ;
3695                 cmdTimeout = 10;
3696                 break;
3697
3698         case START_STOP:
3699                 cmdLen = 6;
3700                 dir = MPI_SCSIIO_CONTROL_READ;
3701                 CDB[0] = cmd;
3702                 CDB[4] = 1;     /*Spin up the disk */
3703                 cmdTimeout = 15;
3704                 break;
3705
3706         case REQUEST_SENSE:
3707                 cmdLen = 6;
3708                 CDB[0] = cmd;
3709                 CDB[4] = io->size;
3710                 dir = MPI_SCSIIO_CONTROL_READ;
3711                 cmdTimeout = 10;
3712                 break;
3713
3714         case READ_BUFFER:
3715                 cmdLen = 10;
3716                 dir = MPI_SCSIIO_CONTROL_READ;
3717                 CDB[0] = cmd;
3718                 if (io->flags & MPT_ICFLAG_ECHO) {
3719                         CDB[1] = 0x0A;
3720                 } else {
3721                         CDB[1] = 0x02;
3722                 }
3723
3724                 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3725                         CDB[1] |= 0x01;
3726                 }
3727                 CDB[6] = (io->size >> 16) & 0xFF;
3728                 CDB[7] = (io->size >>  8) & 0xFF;
3729                 CDB[8] = io->size & 0xFF;
3730                 cmdTimeout = 10;
3731                 break;
3732
3733         case WRITE_BUFFER:
3734                 cmdLen = 10;
3735                 dir = MPI_SCSIIO_CONTROL_WRITE;
3736                 CDB[0] = cmd;
3737                 if (io->flags & MPT_ICFLAG_ECHO) {
3738                         CDB[1] = 0x0A;
3739                 } else {
3740                         CDB[1] = 0x02;
3741                 }
3742                 CDB[6] = (io->size >> 16) & 0xFF;
3743                 CDB[7] = (io->size >>  8) & 0xFF;
3744                 CDB[8] = io->size & 0xFF;
3745                 cmdTimeout = 10;
3746                 break;
3747
3748         case RESERVE:
3749                 cmdLen = 6;
3750                 dir = MPI_SCSIIO_CONTROL_READ;
3751                 CDB[0] = cmd;
3752                 cmdTimeout = 10;
3753                 break;
3754
3755         case RELEASE:
3756                 cmdLen = 6;
3757                 dir = MPI_SCSIIO_CONTROL_READ;
3758                 CDB[0] = cmd;
3759                 cmdTimeout = 10;
3760                 break;
3761
3762         case SYNCHRONIZE_CACHE:
3763                 cmdLen = 10;
3764                 dir = MPI_SCSIIO_CONTROL_READ;
3765                 CDB[0] = cmd;
3766 //              CDB[1] = 0x02;  /* set immediate bit */
3767                 cmdTimeout = 10;
3768                 break;
3769
3770         default:
3771                 /* Error Case */
3772                 return -EFAULT;
3773         }
3774
3775         /* Get and Populate a free Frame
3776          */
3777         if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3778                 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3779                                         hd->ioc->name));
3780                 return -EBUSY;
3781         }
3782
3783         pScsiReq = (SCSIIORequest_t *) mf;
3784
3785         /* Get the request index */
3786         my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3787         ADD_INDEX_LOG(my_idx); /* for debug */
3788
3789         if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3790                 pScsiReq->TargetID = io->physDiskNum;
3791                 pScsiReq->Bus = 0;
3792                 pScsiReq->ChainOffset = 0;
3793                 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3794         } else {
3795                 pScsiReq->TargetID = io->id;
3796                 pScsiReq->Bus = io->bus;
3797                 pScsiReq->ChainOffset = 0;
3798                 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3799         }
3800
3801         pScsiReq->CDBLength = cmdLen;
3802         pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3803
3804         pScsiReq->Reserved = 0;
3805
3806         pScsiReq->MsgFlags = mpt_msg_flags();
3807         /* MsgContext set in mpt_get_msg_fram call  */
3808
3809         for (ii=0; ii < 8; ii++)
3810                 pScsiReq->LUN[ii] = 0;
3811         pScsiReq->LUN[1] = io->lun;
3812
3813         if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3814                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3815         else
3816                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3817
3818         if (cmd == REQUEST_SENSE) {
3819                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3820                 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3821                         hd->ioc->name, cmd));
3822         }
3823
3824         for (ii=0; ii < 16; ii++)
3825                 pScsiReq->CDB[ii] = CDB[ii];
3826
3827         pScsiReq->DataLength = cpu_to_le32(io->size);
3828         pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3829                                            + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3830
3831         ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3832                         hd->ioc->name, cmd, io->bus, io->id, io->lun));
3833
3834         if (dir == MPI_SCSIIO_CONTROL_READ) {
3835                 mpt_add_sge((char *) &pScsiReq->SGL,
3836                         MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3837                         io->data_dma);
3838         } else {
3839                 mpt_add_sge((char *) &pScsiReq->SGL,
3840                         MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3841                         io->data_dma);
3842         }
3843
3844         /* The ISR will free the request frame, but we need
3845          * the information to initialize the target. Duplicate.
3846          */
3847         memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3848
3849         /* Issue this command after:
3850          *      finish init
3851          *      add timer
3852          * Wait until the reply has been received
3853          *  ScsiScanDvCtx callback function will
3854          *      set hd->pLocal;
3855          *      set scandv_wait_done and call wake_up
3856          */
3857         hd->pLocal = NULL;
3858         hd->timer.expires = jiffies + HZ*cmdTimeout;
3859         hd->scandv_wait_done = 0;
3860
3861         /* Save cmd pointer, for resource free if timeout or
3862          * FW reload occurs
3863          */
3864         hd->cmdPtr = mf;
3865
3866         add_timer(&hd->timer);
3867         mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3868         wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3869
3870         if (hd->pLocal) {
3871                 rc = hd->pLocal->completion;
3872                 hd->pLocal->skip = 0;
3873
3874                 /* Always set fatal error codes in some cases.
3875                  */
3876                 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3877                         rc = -ENXIO;
3878                 else if (rc == MPT_SCANDV_SOME_ERROR)
3879                         rc =  -rc;
3880         } else {
3881                 rc = -EFAULT;
3882                 /* This should never happen. */
3883                 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3884                                 hd->ioc->name));
3885         }
3886
3887         return rc;
3888 }
3889
3890 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3891 /**
3892  *      mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3893  *      @hd: Pointer to MPT_SCSI_HOST structure
3894  *      @portnum: IOC port number
3895  *
3896  *      Uses the ISR, but with special processing.
3897  *      MUST be single-threaded.
3898  *
3899  *      Return: 0 on completion
3900  */
3901 static int
3902 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
3903 {
3904         MPT_ADAPTER             *ioc= hd->ioc;
3905         VirtDevice              *pTarget;
3906         SCSIDevicePage1_t       *pcfg1Data = NULL;
3907         INTERNAL_CMD             iocmd;
3908         CONFIGPARMS              cfg;
3909         dma_addr_t               cfg1_dma_addr = -1;
3910         ConfigPageHeader_t       header1;
3911         int                      bus = 0;
3912         int                      id = 0;
3913         int                      lun;
3914         int                      indexed_lun, lun_index;
3915         int                      hostId = ioc->pfacts[portnum].PortSCSIID;
3916         int                      max_id;
3917         int                      requested, configuration, data;
3918         int                      doConfig = 0;
3919         u8                       flags, factor;
3920
3921         max_id = ioc->sh->max_id - 1;
3922
3923         /* Following parameters will not change
3924          * in this routine.
3925          */
3926         iocmd.cmd = SYNCHRONIZE_CACHE;
3927         iocmd.flags = 0;
3928         iocmd.physDiskNum = -1;
3929         iocmd.data = NULL;
3930         iocmd.data_dma = -1;
3931         iocmd.size = 0;
3932         iocmd.rsvd = iocmd.rsvd2 = 0;
3933
3934         /* No SCSI hosts
3935          */
3936         if (hd->Targets == NULL)
3937                 return 0;
3938
3939         /* Skip the host
3940          */
3941         if (id == hostId)
3942                 id++;
3943
3944         /* Write SDP1 for all SCSI devices
3945          * Alloc memory and set up config buffer
3946          */
3947         if (ioc->bus_type == SCSI) {
3948                 if (ioc->spi_data.sdp1length > 0) {
3949                         pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
3950                                          ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
3951
3952                         if (pcfg1Data != NULL) {
3953                                 doConfig = 1;
3954                                 header1.PageVersion = ioc->spi_data.sdp1version;
3955                                 header1.PageLength = ioc->spi_data.sdp1length;
3956                                 header1.PageNumber = 1;
3957                                 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3958                                 cfg.hdr = &header1;
3959                                 cfg.physAddr = cfg1_dma_addr;
3960                                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3961                                 cfg.dir = 1;
3962                                 cfg.timeout = 0;
3963                         }
3964                 }
3965         }
3966
3967         /* loop through all devices on this port
3968          */
3969         while (bus < MPT_MAX_BUS) {
3970                 iocmd.bus = bus;
3971                 iocmd.id = id;
3972                 pTarget = hd->Targets[(int)id];
3973
3974                 if (doConfig) {
3975
3976                         /* Set the negotiation flags */
3977                         if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
3978                                 flags = pTarget->negoFlags;
3979                         } else {
3980                                 flags = hd->ioc->spi_data.noQas;
3981                                 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3982                                         data = hd->ioc->spi_data.nvram[id];
3983
3984                                         if (data & MPT_NVRAM_WIDE_DISABLE)
3985                                                 flags |= MPT_TARGET_NO_NEGO_WIDE;
3986
3987                                         factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
3988                                         if ((factor == 0) || (factor == MPT_ASYNC))
3989                                                 flags |= MPT_TARGET_NO_NEGO_SYNC;
3990                                 }
3991                         }
3992
3993                         /* Force to async, narrow */
3994                         mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
3995                                         &configuration, flags);
3996                         dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
3997                                 "offset=0 negoFlags=%x request=%x config=%x\n",
3998                                 id, flags, requested, configuration));
3999                         pcfg1Data->RequestedParameters = le32_to_cpu(requested);
4000                         pcfg1Data->Reserved = 0;
4001                         pcfg1Data->Configuration = le32_to_cpu(configuration);
4002                         cfg.pageAddr = (bus<<8) | id;
4003                         mpt_config(hd->ioc, &cfg);
4004                 }
4005
4006                 /* If target Ptr NULL or if this target is NOT a disk, skip.
4007                  */
4008                 if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
4009                         for (lun=0; lun <= MPT_LAST_LUN; lun++) {
4010                                 /* If LUN present, issue the command
4011                                  */
4012                                 lun_index = (lun >> 5);  /* 32 luns per lun_index */
4013                                 indexed_lun = (lun % 32);
4014                                 if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
4015                                         iocmd.lun = lun;
4016                                         (void) mptscsih_do_cmd(hd, &iocmd);
4017                                 }
4018                         }
4019                 }
4020
4021                 /* get next relevant device */
4022                 id++;
4023
4024                 if (id == hostId)
4025                         id++;
4026
4027                 if (id > max_id) {
4028                         id = 0;
4029                         bus++;
4030                 }
4031         }
4032
4033         if (pcfg1Data) {
4034                 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
4035         }
4036
4037         return 0;
4038 }
4039
4040 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4041 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4042 /**
4043  *      mptscsih_domainValidation - Top level handler for domain validation.
4044  *      @hd: Pointer to MPT_SCSI_HOST structure.
4045  *
4046  *      Uses the ISR, but with special processing.
4047  *      Called from schedule, should not be in interrupt mode.
4048  *      While thread alive, do dv for all devices needing dv
4049  *
4050  *      Return: None.
4051  */
4052 static void
4053 mptscsih_domainValidation(void *arg)
4054 {
4055         MPT_SCSI_HOST           *hd;
4056         MPT_ADAPTER             *ioc;
4057         unsigned long            flags;
4058         int                      id, maxid, dvStatus, did;
4059         int                      ii, isPhysDisk;
4060
4061         spin_lock_irqsave(&dvtaskQ_lock, flags);
4062         dvtaskQ_active = 1;
4063         if (dvtaskQ_release) {
4064                 dvtaskQ_active = 0;
4065                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4066                 return;
4067         }
4068         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4069
4070         /* For this ioc, loop through all devices and do dv to each device.
4071          * When complete with this ioc, search through the ioc list, and
4072          * for each scsi ioc found, do dv for all devices. Exit when no
4073          * device needs dv.
4074          */
4075         did = 1;
4076         while (did) {
4077                 did = 0;
4078                 list_for_each_entry(ioc, &ioc_list, list) {
4079                         spin_lock_irqsave(&dvtaskQ_lock, flags);
4080                         if (dvtaskQ_release) {
4081                                 dvtaskQ_active = 0;
4082                                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4083                                 return;
4084                         }
4085                         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4086
4087                         msleep(250);
4088
4089                         /* DV only to SCSI adapters */
4090                         if (ioc->bus_type != SCSI)
4091                                 continue;
4092
4093                         /* Make sure everything looks ok */
4094                         if (ioc->sh == NULL)
4095                                 continue;
4096
4097                         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4098                         if (hd == NULL)
4099                                 continue;
4100
4101                         if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
4102                                 mpt_read_ioc_pg_3(ioc);
4103                                 if (ioc->spi_data.pIocPg3) {
4104                                         Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4105                                         int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4106
4107                                         while (numPDisk) {
4108                                                 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
4109                                                         ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4110
4111                                                 pPDisk++;
4112                                                 numPDisk--;
4113                                         }
4114                                 }
4115                                 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
4116                         }
4117
4118                         maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
4119
4120                         for (id = 0; id < maxid; id++) {
4121                                 spin_lock_irqsave(&dvtaskQ_lock, flags);
4122                                 if (dvtaskQ_release) {
4123                                         dvtaskQ_active = 0;
4124                                         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4125                                         return;
4126                                 }
4127                                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4128                                 dvStatus = hd->ioc->spi_data.dvStatus[id];
4129
4130                                 if (dvStatus & MPT_SCSICFG_NEED_DV) {
4131                                         did++;
4132                                         hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
4133                                         hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
4134
4135                                         msleep(250);
4136
4137                                         /* If hidden phys disk, block IO's to all
4138                                          *      raid volumes
4139                                          * else, process normally
4140                                          */
4141                                         isPhysDisk = mptscsih_is_phys_disk(ioc, id);
4142                                         if (isPhysDisk) {
4143                                                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4144                                                         if (hd->ioc->spi_data.isRaid & (1 << ii)) {
4145                                                                 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
4146                                                         }
4147                                                 }
4148                                         }
4149
4150                                         if (mptscsih_doDv(hd, 0, id) == 1) {
4151                                                 /* Untagged device was busy, try again
4152                                                  */
4153                                                 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
4154                                                 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
4155                                         } else {
4156                                                 /* DV is complete. Clear flags.
4157                                                  */
4158                                                 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
4159                                         }
4160
4161                                         if (isPhysDisk) {
4162                                                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4163                                                         if (hd->ioc->spi_data.isRaid & (1 << ii)) {
4164                                                                 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
4165                                                         }
4166                                                 }
4167                                         }
4168
4169                                         if (hd->ioc->spi_data.noQas)
4170                                                 mptscsih_qas_check(hd, id);
4171                                 }
4172                         }
4173                 }
4174         }
4175
4176         spin_lock_irqsave(&dvtaskQ_lock, flags);
4177         dvtaskQ_active = 0;
4178         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4179
4180         return;
4181 }
4182
4183 /* Search IOC page 3 to determine if this is hidden physical disk
4184  */
4185 static int 
4186 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
4187 {
4188         if (ioc->spi_data.pIocPg3) {
4189                 Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
4190                 int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4191
4192                 while (numPDisk) {
4193                         if (pPDisk->PhysDiskID == id) {
4194                                 return 1;
4195                         }
4196                         pPDisk++;
4197                         numPDisk--;
4198                 }
4199         }
4200         return 0;
4201 }
4202
4203 /* Write SDP1 if no QAS has been enabled
4204  */
4205 static void
4206 mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
4207 {
4208         VirtDevice *pTarget;
4209         int ii;
4210
4211         if (hd->Targets == NULL)
4212                 return;
4213
4214         for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4215                 if (ii == id)
4216                         continue;
4217
4218                 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
4219                         continue;
4220
4221                 pTarget = hd->Targets[ii];
4222
4223                 if ((pTarget != NULL) && (!pTarget->raidVolume)) {
4224                         if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
4225                                 pTarget->negoFlags |= hd->ioc->spi_data.noQas;
4226                                 dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
4227                                 mptscsih_writeSDP1(hd, 0, ii, 0);
4228                         }
4229                 } else {
4230                         if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
4231                                 dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
4232                                 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
4233                         }
4234                 }
4235         }
4236         return;
4237 }
4238
4239
4240
4241 #define MPT_GET_NVRAM_VALS      0x01
4242 #define MPT_UPDATE_MAX          0x02
4243 #define MPT_SET_MAX             0x04
4244 #define MPT_SET_MIN             0x08
4245 #define MPT_FALLBACK            0x10
4246 #define MPT_SAVE                0x20
4247
4248 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4249 /**
4250  *      mptscsih_doDv - Perform domain validation to a target.
4251  *      @hd: Pointer to MPT_SCSI_HOST structure.
4252  *      @portnum: IOC port number.
4253  *      @target: Physical ID of this target
4254  *
4255  *      Uses the ISR, but with special processing.
4256  *      MUST be single-threaded.
4257  *      Test will exit if target is at async & narrow.
4258  *
4259  *      Return: None.
4260  */
4261 static int
4262 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
4263 {
4264         MPT_ADAPTER             *ioc = hd->ioc;
4265         VirtDevice              *pTarget;
4266         SCSIDevicePage1_t       *pcfg1Data;
4267         SCSIDevicePage0_t       *pcfg0Data;
4268         u8                      *pbuf1;
4269         u8                      *pbuf2;
4270         u8                      *pDvBuf;
4271         dma_addr_t               dvbuf_dma = -1;
4272         dma_addr_t               buf1_dma = -1;
4273         dma_addr_t               buf2_dma = -1;
4274         dma_addr_t               cfg1_dma_addr = -1;
4275         dma_addr_t               cfg0_dma_addr = -1;
4276         ConfigPageHeader_t       header1;
4277         ConfigPageHeader_t       header0;
4278         DVPARAMETERS             dv;
4279         INTERNAL_CMD             iocmd;
4280         CONFIGPARMS              cfg;
4281         int                      dv_alloc = 0;
4282         int                      rc, sz = 0;
4283         int                      bufsize = 0;
4284         int                      dataBufSize = 0;
4285         int                      echoBufSize = 0;
4286         int                      notDone;
4287         int                      patt;
4288         int                      repeat;
4289         int                      retcode = 0;
4290         int                      nfactor =  MPT_ULTRA320;
4291         char                     firstPass = 1;
4292         char                     doFallback = 0;
4293         char                     readPage0;
4294         char                     bus, lun;
4295         char                     inq0 = 0;
4296
4297         if (ioc->spi_data.sdp1length == 0)
4298                 return 0;
4299
4300         if (ioc->spi_data.sdp0length == 0)
4301                 return 0;
4302
4303         /* If multiple buses are used, require that the initiator
4304          * id be the same on all buses.
4305          */
4306         if (id == ioc->pfacts[0].PortSCSIID)
4307                 return 0;
4308
4309         lun = 0;
4310         bus = (u8) bus_number;
4311         ddvtprintk((MYIOC_s_NOTE_FMT
4312                         "DV started: bus=%d, id=%d dv @ %p\n",
4313                         ioc->name, bus, id, &dv));
4314
4315         /* Prep DV structure
4316          */
4317         memset (&dv, 0, sizeof(DVPARAMETERS));
4318         dv.id = id;
4319
4320         /* Populate tmax with the current maximum
4321          * transfer parameters for this target.
4322          * Exit if narrow and async.
4323          */
4324         dv.cmd = MPT_GET_NVRAM_VALS;
4325         mptscsih_dv_parms(hd, &dv, NULL);
4326
4327         /* Prep SCSI IO structure
4328          */
4329         iocmd.id = id;
4330         iocmd.bus = bus;
4331         iocmd.lun = lun;
4332         iocmd.flags = 0;
4333         iocmd.physDiskNum = -1;
4334         iocmd.rsvd = iocmd.rsvd2 = 0;
4335
4336         pTarget = hd->Targets[id];
4337
4338         /* Use tagged commands if possible.
4339          */
4340         if (pTarget) {
4341                 if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
4342                         iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
4343                 else {
4344                         if (hd->ioc->facts.FWVersion.Word < 0x01000600)
4345                                 return 0;
4346
4347                         if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4348                                 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
4349                                 return 0;
4350                 }
4351         }
4352
4353         /* Prep cfg structure
4354          */
4355         cfg.pageAddr = (bus<<8) | id;
4356         cfg.hdr = NULL;
4357
4358         /* Prep SDP0 header
4359          */
4360         header0.PageVersion = ioc->spi_data.sdp0version;
4361         header0.PageLength = ioc->spi_data.sdp0length;
4362         header0.PageNumber = 0;
4363         header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4364
4365         /* Prep SDP1 header
4366          */
4367         header1.PageVersion = ioc->spi_data.sdp1version;
4368         header1.PageLength = ioc->spi_data.sdp1length;
4369         header1.PageNumber = 1;
4370         header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4371
4372         if (header0.PageLength & 1)
4373                 dv_alloc = (header0.PageLength * 4) + 4;
4374
4375         dv_alloc +=  (2048 + (header1.PageLength * 4));
4376
4377         pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
4378         if (pDvBuf == NULL)
4379                 return 0;
4380
4381         sz = 0;
4382         pbuf1 = (u8 *)pDvBuf;
4383         buf1_dma = dvbuf_dma;
4384         sz +=1024;
4385
4386         pbuf2 = (u8 *) (pDvBuf + sz);
4387         buf2_dma = dvbuf_dma + sz;
4388         sz +=1024;
4389
4390         pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
4391         cfg0_dma_addr = dvbuf_dma + sz;
4392         sz += header0.PageLength * 4;
4393
4394         /* 8-byte alignment
4395          */
4396         if (header0.PageLength & 1)
4397                 sz += 4;
4398
4399         pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
4400         cfg1_dma_addr = dvbuf_dma + sz;
4401
4402         /* Skip this ID? Set cfg.hdr to force config page write
4403          */
4404         {
4405                 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
4406                 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4407                         /* Set the factor from nvram */
4408                         nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
4409                         if (nfactor < pspi_data->minSyncFactor )
4410                                 nfactor = pspi_data->minSyncFactor;
4411
4412                         if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
4413                                 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
4414
4415                                 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
4416                                         ioc->name, bus, id, lun));
4417
4418                                 dv.cmd = MPT_SET_MAX;
4419                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4420                                 cfg.hdr = &header1;
4421
4422                                 /* Save the final negotiated settings to
4423                                  * SCSI device page 1.
4424                                  */
4425                                 cfg.physAddr = cfg1_dma_addr;
4426                                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4427                                 cfg.dir = 1;
4428                                 mpt_config(hd->ioc, &cfg);
4429                                 goto target_done;
4430                         }
4431                 }
4432         }
4433
4434         /* Finish iocmd inititialization - hidden or visible disk? */
4435         if (ioc->spi_data.pIocPg3) {
4436                 /* Search IOC page 3 for matching id
4437                  */
4438                 Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
4439                 int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4440
4441                 while (numPDisk) {
4442                         if (pPDisk->PhysDiskID == id) {
4443                                 /* match */
4444                                 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
4445                                 iocmd.physDiskNum = pPDisk->PhysDiskNum;
4446
4447                                 /* Quiesce the IM
4448                                  */
4449                                 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
4450                                         ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
4451                                         goto target_done;
4452                                 }
4453                                 break;
4454                         }
4455                         pPDisk++;
4456                         numPDisk--;
4457                 }
4458         }
4459
4460         /* RAID Volume ID's may double for a physical device. If RAID but
4461          * not a physical ID as well, skip DV.
4462          */
4463         if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
4464                 goto target_done;
4465
4466
4467         /* Basic Test.
4468          * Async & Narrow - Inquiry
4469          * Async & Narrow - Inquiry
4470          * Maximum transfer rate - Inquiry
4471          * Compare buffers:
4472          *      If compare, test complete.
4473          *      If miscompare and first pass, repeat
4474          *      If miscompare and not first pass, fall back and repeat
4475          */
4476         hd->pLocal = NULL;
4477         readPage0 = 0;
4478         sz = SCSI_MAX_INQUIRY_BYTES;
4479         rc = MPT_SCANDV_GOOD;
4480         while (1) {
4481                 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
4482                 retcode = 0;
4483                 dv.cmd = MPT_SET_MIN;
4484                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4485
4486                 cfg.hdr = &header1;
4487                 cfg.physAddr = cfg1_dma_addr;
4488                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4489                 cfg.dir = 1;
4490                 if (mpt_config(hd->ioc, &cfg) != 0)
4491                         goto target_done;
4492
4493                 /* Wide - narrow - wide workaround case
4494                  */
4495                 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
4496                         /* Send an untagged command to reset disk Qs corrupted
4497                          * when a parity error occurs on a Request Sense.
4498                          */
4499                         if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
4500                                 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4501                                 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
4502
4503                                 iocmd.cmd = REQUEST_SENSE;
4504                                 iocmd.data_dma = buf1_dma;
4505                                 iocmd.data = pbuf1;
4506                                 iocmd.size = 0x12;
4507                                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4508                                         goto target_done;
4509                                 else {
4510                                         if (hd->pLocal == NULL)
4511                                                 goto target_done;
4512                                         rc = hd->pLocal->completion;
4513                                         if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
4514                                                 dv.max.width = 0;
4515                                                 doFallback = 0;
4516                                         } else
4517                                                 goto target_done;
4518                                 }
4519                         } else
4520                                 goto target_done;
4521                 }
4522
4523                 iocmd.cmd = INQUIRY;
4524                 iocmd.data_dma = buf1_dma;
4525                 iocmd.data = pbuf1;
4526                 iocmd.size = sz;
4527                 memset(pbuf1, 0x00, sz);
4528                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4529                         goto target_done;
4530                 else {
4531                         if (hd->pLocal == NULL)
4532                                 goto target_done;
4533                         rc = hd->pLocal->completion;
4534                         if (rc == MPT_SCANDV_GOOD) {
4535                                 if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
4536                                         if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
4537                                                 retcode = 1;
4538                                         else
4539                                                 retcode = 0;
4540
4541                                         goto target_done;
4542                                 }
4543                         } else if  (rc == MPT_SCANDV_SENSE) {
4544                                 ;
4545                         } else {
4546                                 /* If first command doesn't complete
4547                                  * with a good status or with a check condition,
4548                                  * exit.
4549                                  */
4550                                 goto target_done;
4551                         }
4552                 }
4553
4554                 /* Reset the size for disks
4555                  */
4556                 inq0 = (*pbuf1) & 0x1F;
4557                 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
4558                         sz = 0x40;
4559                         iocmd.size = sz;
4560                 }
4561
4562                 /* Another GEM workaround. Check peripheral device type,
4563                  * if PROCESSOR, quit DV.
4564                  */
4565                 if (inq0 == TYPE_PROCESSOR) {
4566                         mptscsih_initTarget(hd,
4567                                 bus,
4568                                 id,
4569                                 lun,
4570                                 pbuf1,
4571                                 sz);
4572                         goto target_done;
4573                 }
4574
4575                 if (inq0 > 0x08)
4576                         goto target_done;
4577
4578                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4579                         goto target_done;
4580
4581                 if (sz == 0x40) {
4582                         if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
4583                                 && (pTarget->minSyncFactor > 0x09)) {
4584                                 if ((pbuf1[56] & 0x04) == 0)
4585                                         ;
4586                                 else if ((pbuf1[56] & 0x01) == 1) {
4587                                         pTarget->minSyncFactor =
4588                                             nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
4589                                 } else {
4590                                         pTarget->minSyncFactor =
4591                                             nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
4592                                 }
4593
4594                                 dv.max.factor = pTarget->minSyncFactor;
4595
4596                                 if ((pbuf1[56] & 0x02) == 0) {
4597                                         pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4598                                         hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
4599                                         ddvprintk((MYIOC_s_NOTE_FMT 
4600                                             "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", 
4601                                             ioc->name, id, pbuf1[56]));
4602                                 }
4603                         }
4604                 }
4605
4606                 if (doFallback)
4607                         dv.cmd = MPT_FALLBACK;
4608                 else
4609                         dv.cmd = MPT_SET_MAX;
4610
4611                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4612                 if (mpt_config(hd->ioc, &cfg) != 0)
4613                         goto target_done;
4614
4615                 if ((!dv.now.width) && (!dv.now.offset))
4616                         goto target_done;
4617
4618                 iocmd.cmd = INQUIRY;
4619                 iocmd.data_dma = buf2_dma;
4620                 iocmd.data = pbuf2;
4621                 iocmd.size = sz;
4622                 memset(pbuf2, 0x00, sz);
4623                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4624                         goto target_done;
4625                 else if (hd->pLocal == NULL)
4626                         goto target_done;
4627                 else {
4628                         /* Save the return code.
4629                          * If this is the first pass,
4630                          * read SCSI Device Page 0
4631                          * and update the target max parameters.
4632                          */
4633                         rc = hd->pLocal->completion;
4634                         doFallback = 0;
4635                         if (rc == MPT_SCANDV_GOOD) {
4636                                 if (!readPage0) {
4637                                         u32 sdp0_info;
4638                                         u32 sdp0_nego;
4639
4640                                         cfg.hdr = &header0;
4641                                         cfg.physAddr = cfg0_dma_addr;
4642                                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4643                                         cfg.dir = 0;
4644
4645                                         if (mpt_config(hd->ioc, &cfg) != 0)
4646                                                 goto target_done;
4647
4648                                         sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
4649                                         sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
4650
4651                                         /* Quantum and Fujitsu workarounds.
4652                                          * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
4653                                          * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
4654                                          * Resetart with a request for U160.
4655                                          */
4656                                         if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
4657                                                         doFallback = 1;
4658                                         } else {
4659                                                 dv.cmd = MPT_UPDATE_MAX;
4660                                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
4661                                                 /* Update the SCSI device page 1 area
4662                                                  */
4663                                                 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
4664                                                 readPage0 = 1;
4665                                         }
4666                                 }
4667
4668                                 /* Quantum workaround. Restart this test will the fallback
4669                                  * flag set.
4670                                  */
4671                                 if (doFallback == 0) {
4672                                         if (memcmp(pbuf1, pbuf2, sz) != 0) {
4673                                                 if (!firstPass)
4674                                                         doFallback = 1;
4675                                         } else {
4676                                                 ddvprintk((MYIOC_s_NOTE_FMT 
4677                                                     "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
4678                                                 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
4679                                                 mptscsih_initTarget(hd,
4680                                                         bus,
4681                                                         id,
4682                                                         lun,
4683                                                         pbuf1,
4684                                                         sz);
4685                                                 break;  /* test complete */
4686                                         }
4687                                 }
4688
4689
4690                         } else if (rc == MPT_SCANDV_ISSUE_SENSE)
4691                                 doFallback = 1; /* set fallback flag */
4692                         else if ((rc == MPT_SCANDV_DID_RESET) || 
4693                                  (rc == MPT_SCANDV_SENSE) || 
4694                                  (rc == MPT_SCANDV_FALLBACK))
4695                                 doFallback = 1; /* set fallback flag */
4696                         else
4697                                 goto target_done;
4698
4699                         firstPass = 0;
4700                 }
4701         }
4702         ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
4703
4704         if (ioc->spi_data.mpt_dv == 0)
4705                 goto target_done;
4706
4707         inq0 = (*pbuf1) & 0x1F;
4708
4709         /* Continue only for disks
4710          */
4711         if (inq0 != 0)
4712                 goto target_done;
4713
4714         if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
4715                 goto target_done;
4716
4717         /* Start the Enhanced Test.
4718          * 0) issue TUR to clear out check conditions
4719          * 1) read capacity of echo (regular) buffer
4720          * 2) reserve device
4721          * 3) do write-read-compare data pattern test
4722          * 4) release
4723          * 5) update nego parms to target struct
4724          */
4725         cfg.hdr = &header1;
4726         cfg.physAddr = cfg1_dma_addr;
4727         cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4728         cfg.dir = 1;
4729
4730         iocmd.cmd = TEST_UNIT_READY;
4731         iocmd.data_dma = -1;
4732         iocmd.data = NULL;
4733         iocmd.size = 0;
4734         notDone = 1;
4735         while (notDone) {
4736                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4737                         goto target_done;
4738
4739                 if (hd->pLocal == NULL)
4740                         goto target_done;
4741
4742                 rc = hd->pLocal->completion;
4743                 if (rc == MPT_SCANDV_GOOD)
4744                         notDone = 0;
4745                 else if (rc == MPT_SCANDV_SENSE) {
4746                         u8 skey = hd->pLocal->sense[2] & 0x0F;
4747                         u8 asc = hd->pLocal->sense[12];
4748                         u8 ascq = hd->pLocal->sense[13];
4749                         ddvprintk((MYIOC_s_INFO_FMT
4750                                 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4751                                 ioc->name, skey, asc, ascq));
4752
4753                         if (skey == UNIT_ATTENTION)
4754                                 notDone++; /* repeat */
4755                         else if ((skey == NOT_READY) &&
4756                                         (asc == 0x04)&&(ascq == 0x01)) {
4757                                 /* wait then repeat */
4758                                 mdelay (2000);
4759                                 notDone++;
4760                         } else if ((skey == NOT_READY) && (asc == 0x3A)) {
4761                                 /* no medium, try read test anyway */
4762                                 notDone = 0;
4763                         } else {
4764                                 /* All other errors are fatal.
4765                                  */
4766                                 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4767                                                 ioc->name));
4768                                 goto target_done;
4769                         }
4770                 } else
4771                         goto target_done;
4772         }
4773
4774         iocmd.cmd = READ_BUFFER;
4775         iocmd.data_dma = buf1_dma;
4776         iocmd.data = pbuf1;
4777         iocmd.size = 4;
4778         iocmd.flags |= MPT_ICFLAG_BUF_CAP;
4779
4780         dataBufSize = 0;
4781         echoBufSize = 0;
4782         for (patt = 0; patt < 2; patt++) {
4783                 if (patt == 0)
4784                         iocmd.flags |= MPT_ICFLAG_ECHO;
4785                 else
4786                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
4787
4788                 notDone = 1;
4789                 while (notDone) {
4790                         bufsize = 0;
4791
4792                         /* If not ready after 8 trials,
4793                          * give up on this device.
4794                          */
4795                         if (notDone > 8)
4796                                 goto target_done;
4797
4798                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
4799                                 goto target_done;
4800                         else if (hd->pLocal == NULL)
4801                                 goto target_done;
4802                         else {
4803                                 rc = hd->pLocal->completion;
4804                                 ddvprintk(("ReadBuffer Comp Code %d", rc));
4805                                 ddvprintk(("  buff: %0x %0x %0x %0x\n",
4806                                         pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
4807
4808                                 if (rc == MPT_SCANDV_GOOD) {
4809                                         notDone = 0;
4810                                         if (iocmd.flags & MPT_ICFLAG_ECHO) {
4811                                                 bufsize =  ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
4812                                         } else {
4813                                                 bufsize =  pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
4814                                         }
4815                                 } else if (rc == MPT_SCANDV_SENSE) {
4816                                         u8 skey = hd->pLocal->sense[2] & 0x0F;
4817                                         u8 asc = hd->pLocal->sense[12];
4818                                         u8 ascq = hd->pLocal->sense[13];
4819                                         ddvprintk((MYIOC_s_INFO_FMT
4820                                                 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4821                                                 ioc->name, skey, asc, ascq));
4822                                         if (skey == ILLEGAL_REQUEST) {
4823                                                 notDone = 0;
4824                                         } else if (skey == UNIT_ATTENTION) {
4825                                                 notDone++; /* repeat */
4826                                         } else if ((skey == NOT_READY) &&
4827                                                 (asc == 0x04)&&(ascq == 0x01)) {
4828                                                 /* wait then repeat */
4829                                                 mdelay (2000);
4830                                                 notDone++;
4831                                         } else {
4832                                                 /* All other errors are fatal.
4833                                                  */
4834                                                 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4835                                                         ioc->name));
4836                                                 goto target_done;
4837                                         }
4838                                 } else {
4839                                         /* All other errors are fatal
4840                                          */
4841                                         goto target_done;
4842                                 }
4843                         }
4844                 }
4845
4846                 if (iocmd.flags & MPT_ICFLAG_ECHO)
4847                         echoBufSize = bufsize;
4848                 else
4849                         dataBufSize = bufsize;
4850         }
4851         sz = 0;
4852         iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
4853
4854         /* Use echo buffers if possible,
4855          * Exit if both buffers are 0.
4856          */
4857         if (echoBufSize > 0) {
4858                 iocmd.flags |= MPT_ICFLAG_ECHO;
4859                 if (dataBufSize > 0)
4860                         bufsize = min(echoBufSize, dataBufSize);
4861                 else
4862                         bufsize = echoBufSize;
4863         } else if (dataBufSize == 0)
4864                 goto target_done;
4865
4866         ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
4867                 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
4868
4869         /* Data buffers for write-read-compare test max 1K.
4870          */
4871         sz = min(bufsize, 1024);
4872
4873         /* --- loop ----
4874          * On first pass, always issue a reserve.
4875          * On additional loops, only if a reset has occurred.
4876          * iocmd.flags indicates if echo or regular buffer
4877          */
4878         for (patt = 0; patt < 4; patt++) {
4879                 ddvprintk(("Pattern %d\n", patt));
4880                 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
4881                         iocmd.cmd = TEST_UNIT_READY;
4882                         iocmd.data_dma = -1;
4883                         iocmd.data = NULL;
4884                         iocmd.size = 0;
4885                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
4886                                 goto target_done;
4887
4888                         iocmd.cmd = RELEASE;
4889                         iocmd.data_dma = -1;
4890                         iocmd.data = NULL;
4891                         iocmd.size = 0;
4892                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
4893                                 goto target_done;
4894                         else if (hd->pLocal == NULL)
4895                                 goto target_done;
4896                         else {
4897                                 rc = hd->pLocal->completion;
4898                                 ddvprintk(("Release rc %d\n", rc));
4899                                 if (rc == MPT_SCANDV_GOOD)
4900                                         iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4901                                 else
4902                                         goto target_done;
4903                         }
4904                         iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4905                 }
4906                 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
4907
4908                 repeat = 5;
4909                 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
4910                         iocmd.cmd = RESERVE;
4911                         iocmd.data_dma = -1;
4912                         iocmd.data = NULL;
4913                         iocmd.size = 0;
4914                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
4915                                 goto target_done;
4916                         else if (hd->pLocal == NULL)
4917                                 goto target_done;
4918                         else {
4919                                 rc = hd->pLocal->completion;
4920                                 if (rc == MPT_SCANDV_GOOD) {
4921                                         iocmd.flags |= MPT_ICFLAG_RESERVED;
4922                                 } else if (rc == MPT_SCANDV_SENSE) {
4923                                         /* Wait if coming ready
4924                                          */
4925                                         u8 skey = hd->pLocal->sense[2] & 0x0F;
4926                                         u8 asc = hd->pLocal->sense[12];
4927                                         u8 ascq = hd->pLocal->sense[13];
4928                                         ddvprintk((MYIOC_s_INFO_FMT
4929                                                 "DV: Reserve Failed: ", ioc->name));
4930                                         ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4931                                                         skey, asc, ascq));
4932
4933                                         if ((skey == NOT_READY) && (asc == 0x04)&&
4934                                                                         (ascq == 0x01)) {
4935                                                 /* wait then repeat */
4936                                                 mdelay (2000);
4937                                                 notDone++;
4938                                         } else {
4939                                                 ddvprintk((MYIOC_s_INFO_FMT
4940                                                         "DV: Reserved Failed.", ioc->name));
4941                                                 goto target_done;
4942                                         }
4943                                 } else {
4944                                         ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
4945                                                          ioc->name));
4946                                         goto target_done;
4947                                 }
4948                         }
4949                 }
4950
4951                 mptscsih_fillbuf(pbuf1, sz, patt, 1);
4952                 iocmd.cmd = WRITE_BUFFER;
4953                 iocmd.data_dma = buf1_dma;
4954                 iocmd.data = pbuf1;
4955                 iocmd.size = sz;
4956                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4957                         goto target_done;
4958                 else if (hd->pLocal == NULL)
4959                         goto target_done;
4960                 else {
4961                         rc = hd->pLocal->completion;
4962                         if (rc == MPT_SCANDV_GOOD)
4963                                 ;               /* Issue read buffer */
4964                         else if (rc == MPT_SCANDV_DID_RESET) {
4965                                 /* If using echo buffers, reset to data buffers.
4966                                  * Else do Fallback and restart
4967                                  * this test (re-issue reserve
4968                                  * because of bus reset).
4969                                  */
4970                                 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
4971                                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
4972                                 } else {
4973                                         dv.cmd = MPT_FALLBACK;
4974                                         mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4975
4976                                         if (mpt_config(hd->ioc, &cfg) != 0)
4977                                                 goto target_done;
4978
4979                                         if ((!dv.now.width) && (!dv.now.offset))
4980                                                 goto target_done;
4981                                 }
4982
4983                                 iocmd.flags |= MPT_ICFLAG_DID_RESET;
4984                                 patt = -1;
4985                                 continue;
4986                         } else if (rc == MPT_SCANDV_SENSE) {
4987                                 /* Restart data test if UA, else quit.
4988                                  */
4989                                 u8 skey = hd->pLocal->sense[2] & 0x0F;
4990                                 ddvprintk((MYIOC_s_INFO_FMT
4991                                         "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
4992                                         hd->pLocal->sense[12], hd->pLocal->sense[13]));
4993                                 if (skey == UNIT_ATTENTION) {
4994                                         patt = -1;
4995                                         continue;
4996                                 } else if (skey == ILLEGAL_REQUEST) {
4997                                         if (iocmd.flags & MPT_ICFLAG_ECHO) {
4998                                                 if (dataBufSize >= bufsize) {
4999                                                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
5000                                                         patt = -1;
5001                                                         continue;
5002                                                 }
5003                                         }
5004                                         goto target_done;
5005                                 }
5006                                 else
5007                                         goto target_done;
5008                         } else {
5009                                 /* fatal error */
5010                                 goto target_done;
5011                         }
5012                 }
5013
5014                 iocmd.cmd = READ_BUFFER;
5015                 iocmd.data_dma = buf2_dma;
5016                 iocmd.data = pbuf2;
5017                 iocmd.size = sz;
5018                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5019                         goto target_done;
5020                 else if (hd->pLocal == NULL)
5021                         goto target_done;
5022                 else {
5023                         rc = hd->pLocal->completion;
5024                         if (rc == MPT_SCANDV_GOOD) {
5025                                  /* If buffers compare,
5026                                   * go to next pattern,
5027                                   * else, do a fallback and restart
5028                                   * data transfer test.
5029                                   */
5030                                 if (memcmp (pbuf1, pbuf2, sz) == 0) {
5031                                         ; /* goto next pattern */
5032                                 } else {
5033                                         /* Miscompare with Echo buffer, go to data buffer,
5034                                          * if that buffer exists.
5035                                          * Miscompare with Data buffer, check first 4 bytes,
5036                                          * some devices return capacity. Exit in this case.
5037                                          */
5038                                         if (iocmd.flags & MPT_ICFLAG_ECHO) {
5039                                                 if (dataBufSize >= bufsize)
5040                                                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
5041                                                 else
5042                                                         goto target_done;
5043                                         } else {
5044                                                 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
5045                                                         /* Argh. Device returning wrong data.
5046                                                          * Quit DV for this device.
5047                                                          */
5048                                                         goto target_done;
5049                                                 }
5050
5051                                                 /* Had an actual miscompare. Slow down.*/
5052                                                 dv.cmd = MPT_FALLBACK;
5053                                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5054
5055                                                 if (mpt_config(hd->ioc, &cfg) != 0)
5056                                                         goto target_done;
5057
5058                                                 if ((!dv.now.width) && (!dv.now.offset))
5059                                                         goto target_done;
5060                                         }
5061
5062                                         patt = -1;
5063                                         continue;
5064                                 }
5065                         } else if (rc == MPT_SCANDV_DID_RESET) {
5066                                 /* Do Fallback and restart
5067                                  * this test (re-issue reserve
5068                                  * because of bus reset).
5069                                  */
5070                                 dv.cmd = MPT_FALLBACK;
5071                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5072
5073                                 if (mpt_config(hd->ioc, &cfg) != 0)
5074                                          goto target_done;
5075
5076                                 if ((!dv.now.width) && (!dv.now.offset))
5077                                         goto target_done;
5078
5079                                 iocmd.flags |= MPT_ICFLAG_DID_RESET;
5080                                 patt = -1;
5081                                 continue;
5082                         } else if (rc == MPT_SCANDV_SENSE) {
5083                                 /* Restart data test if UA, else quit.
5084                                  */
5085                                 u8 skey = hd->pLocal->sense[2] & 0x0F;
5086                                 ddvprintk((MYIOC_s_INFO_FMT
5087                                         "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
5088                                         hd->pLocal->sense[12], hd->pLocal->sense[13]));
5089                                 if (skey == UNIT_ATTENTION) {
5090                                         patt = -1;
5091                                         continue;
5092                                 }
5093                                 else
5094                                         goto target_done;
5095                         } else {
5096                                 /* fatal error */
5097                                 goto target_done;
5098                         }
5099                 }
5100
5101         } /* --- end of patt loop ---- */
5102
5103 target_done:
5104         if (iocmd.flags & MPT_ICFLAG_RESERVED) {
5105                 iocmd.cmd = RELEASE;
5106                 iocmd.data_dma = -1;
5107                 iocmd.data = NULL;
5108                 iocmd.size = 0;
5109                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5110                         printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5111                                         ioc->name, id);
5112                 else if (hd->pLocal) {
5113                         if (hd->pLocal->completion == MPT_SCANDV_GOOD)
5114                                 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
5115                 } else {
5116                         printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5117                                                 ioc->name, id);
5118                 }
5119         }
5120
5121
5122         /* Set if cfg1_dma_addr contents is valid
5123          */
5124         if ((cfg.hdr != NULL) && (retcode == 0)){
5125                 /* If disk, not U320, disable QAS
5126                  */
5127                 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
5128                         hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
5129                         ddvprintk((MYIOC_s_NOTE_FMT 
5130                             "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
5131                 }
5132
5133                 dv.cmd = MPT_SAVE;
5134                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5135
5136                 /* Double writes to SDP1 can cause problems,
5137                  * skip save of the final negotiated settings to
5138                  * SCSI device page 1.
5139                  *
5140                 cfg.hdr = &header1;
5141                 cfg.physAddr = cfg1_dma_addr;
5142                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5143                 cfg.dir = 1;
5144                 mpt_config(hd->ioc, &cfg);
5145                  */
5146         }
5147
5148         /* If this is a RAID Passthrough, enable internal IOs
5149          */
5150         if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
5151                 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
5152                         ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
5153         }
5154
5155         /* Done with the DV scan of the current target
5156          */
5157         if (pDvBuf)
5158                 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
5159
5160         ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
5161                         ioc->name, id));
5162
5163         return retcode;
5164 }
5165
5166 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5167 /*      mptscsih_dv_parms - perform a variety of operations on the
5168  *      parameters used for negotiation.
5169  *      @hd: Pointer to a SCSI host.
5170  *      @dv: Pointer to a structure that contains the maximum and current
5171  *              negotiated parameters.
5172  */
5173 static void
5174 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
5175 {
5176         VirtDevice              *pTarget;
5177         SCSIDevicePage0_t       *pPage0;
5178         SCSIDevicePage1_t       *pPage1;
5179         int                     val = 0, data, configuration;
5180         u8                      width = 0;
5181         u8                      offset = 0;
5182         u8                      factor = 0;
5183         u8                      negoFlags = 0;
5184         u8                      cmd = dv->cmd;
5185         u8                      id = dv->id;
5186
5187         switch (cmd) {
5188         case MPT_GET_NVRAM_VALS:
5189                 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
5190                                                          hd->ioc->name));
5191                 /* Get the NVRAM values and save in tmax
5192                  * If not an LVD bus, the adapter minSyncFactor has been
5193                  * already throttled back.
5194                  */
5195                 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
5196                         width = pTarget->maxWidth;
5197                         offset = pTarget->maxOffset;
5198                         factor = pTarget->minSyncFactor;
5199                         negoFlags = pTarget->negoFlags;
5200                 } else {
5201                         if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5202                                 data = hd->ioc->spi_data.nvram[id];
5203                                 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
5204                                 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
5205                                         factor = MPT_ASYNC;
5206                                 else {
5207                                         factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5208                                         if ((factor == 0) || (factor == MPT_ASYNC)){
5209                                                 factor = MPT_ASYNC;
5210                                                 offset = 0;
5211                                         }
5212                                 }
5213                         } else {
5214                                 width = MPT_NARROW;
5215                                 offset = 0;
5216                                 factor = MPT_ASYNC;
5217                         }
5218
5219                         /* Set the negotiation flags */
5220                         negoFlags = hd->ioc->spi_data.noQas;
5221                         if (!width)
5222                                 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5223
5224                         if (!offset)
5225                                 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
5226                 }
5227
5228                 /* limit by adapter capabilities */
5229                 width = min(width, hd->ioc->spi_data.maxBusWidth);
5230                 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
5231                 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
5232
5233                 /* Check Consistency */
5234                 if (offset && (factor < MPT_ULTRA2) && !width)
5235                         factor = MPT_ULTRA2;
5236
5237                 dv->max.width = width;
5238                 dv->max.offset = offset;
5239                 dv->max.factor = factor;
5240                 dv->max.flags = negoFlags;
5241                 ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
5242                                 id, width, factor, offset, negoFlags));
5243                 break;
5244
5245         case MPT_UPDATE_MAX:
5246                 ddvprintk((MYIOC_s_NOTE_FMT
5247                         "Updating with SDP0 Data: ", hd->ioc->name));
5248                 /* Update tmax values with those from Device Page 0.*/
5249                 pPage0 = (SCSIDevicePage0_t *) pPage;
5250                 if (pPage0) {
5251                         val = cpu_to_le32(pPage0->NegotiatedParameters);
5252                         dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
5253                         dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
5254                         dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
5255                 }
5256
5257                 dv->now.width = dv->max.width;
5258                 dv->now.offset = dv->max.offset;
5259                 dv->now.factor = dv->max.factor;
5260                 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
5261                                 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5262                 break;
5263
5264         case MPT_SET_MAX:
5265                 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
5266                                                                 hd->ioc->name));
5267                 /* Set current to the max values. Update the config page.*/
5268                 dv->now.width = dv->max.width;
5269                 dv->now.offset = dv->max.offset;
5270                 dv->now.factor = dv->max.factor;
5271                 dv->now.flags = dv->max.flags;
5272
5273                 pPage1 = (SCSIDevicePage1_t *)pPage;
5274                 if (pPage1) {
5275                         mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
5276                                 dv->now.offset, &val, &configuration, dv->now.flags);
5277                         dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5278                                 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5279                         pPage1->RequestedParameters = le32_to_cpu(val);
5280                         pPage1->Reserved = 0;
5281                         pPage1->Configuration = le32_to_cpu(configuration);
5282                 }
5283
5284                 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
5285                                 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5286                 break;
5287
5288         case MPT_SET_MIN:
5289                 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
5290                                                                 hd->ioc->name));
5291                 /* Set page to asynchronous and narrow
5292                  * Do not update now, breaks fallback routine. */
5293                 width = MPT_NARROW;
5294                 offset = 0;
5295                 factor = MPT_ASYNC;
5296                 negoFlags = dv->max.flags;
5297
5298                 pPage1 = (SCSIDevicePage1_t *)pPage;
5299                 if (pPage1) {
5300                         mptscsih_setDevicePage1Flags (width, factor,
5301                                 offset, &val, &configuration, negoFlags);
5302                         dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5303                                 id, width, factor, offset, negoFlags, val, configuration));
5304                         pPage1->RequestedParameters = le32_to_cpu(val);
5305                         pPage1->Reserved = 0;
5306                         pPage1->Configuration = le32_to_cpu(configuration);
5307                 }
5308                 ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
5309                                 id, width, factor, offset, val, configuration, negoFlags));
5310                 break;
5311
5312         case MPT_FALLBACK:
5313                 ddvprintk((MYIOC_s_NOTE_FMT
5314                         "Fallback: Start: offset %d, factor %x, width %d \n",
5315                                 hd->ioc->name, dv->now.offset,
5316                                 dv->now.factor, dv->now.width));
5317                 width = dv->now.width;
5318                 offset = dv->now.offset;
5319                 factor = dv->now.factor;
5320                 if ((offset) && (dv->max.width)) {
5321                         if (factor < MPT_ULTRA160)
5322                                 factor = MPT_ULTRA160;
5323                         else if (factor < MPT_ULTRA2) {
5324                                 factor = MPT_ULTRA2;
5325                                 width = MPT_WIDE;
5326                         } else if ((factor == MPT_ULTRA2) && width) {
5327                                 factor = MPT_ULTRA2;
5328                                 width = MPT_NARROW;
5329                         } else if (factor < MPT_ULTRA) {
5330                                 factor = MPT_ULTRA;
5331                                 width = MPT_WIDE;
5332                         } else if ((factor == MPT_ULTRA) && width) {
5333                                 width = MPT_NARROW;
5334                         } else if (factor < MPT_FAST) {
5335                                 factor = MPT_FAST;
5336                                 width = MPT_WIDE;
5337                         } else if ((factor == MPT_FAST) && width) {
5338                                 factor = MPT_FAST;
5339                                 width = MPT_NARROW;
5340                         } else if (factor < MPT_SCSI) {
5341                                 factor = MPT_SCSI;
5342                                 width = MPT_WIDE;
5343                         } else if ((factor == MPT_SCSI) && width) {
5344                                 factor = MPT_SCSI;
5345                                 width = MPT_NARROW;
5346                         } else {
5347                                 factor = MPT_ASYNC;
5348                                 offset = 0;
5349                         }
5350
5351                 } else if (offset) {
5352                         width = MPT_NARROW;
5353                         if (factor < MPT_ULTRA)
5354                                 factor = MPT_ULTRA;
5355                         else if (factor < MPT_FAST)
5356                                 factor = MPT_FAST;
5357                         else if (factor < MPT_SCSI)
5358                                 factor = MPT_SCSI;
5359                         else {
5360                                 factor = MPT_ASYNC;
5361                                 offset = 0;
5362                         }
5363
5364                 } else {
5365                         width = MPT_NARROW;
5366                         factor = MPT_ASYNC;
5367                 }
5368                 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
5369                 dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
5370
5371                 dv->now.width = width;
5372                 dv->now.offset = offset;
5373                 dv->now.factor = factor;
5374                 dv->now.flags = dv->max.flags;
5375
5376                 pPage1 = (SCSIDevicePage1_t *)pPage;
5377                 if (pPage1) {
5378                         mptscsih_setDevicePage1Flags (width, factor, offset, &val,
5379                                                 &configuration, dv->now.flags);
5380                         dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
5381                              id, width, offset, factor, dv->now.flags, val, configuration));
5382
5383                         pPage1->RequestedParameters = le32_to_cpu(val);
5384                         pPage1->Reserved = 0;
5385                         pPage1->Configuration = le32_to_cpu(configuration);
5386                 }
5387
5388                 ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
5389                              id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
5390                 break;
5391
5392         case MPT_SAVE:
5393                 ddvprintk((MYIOC_s_NOTE_FMT
5394                         "Saving to Target structure: ", hd->ioc->name));
5395                 ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
5396                              id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5397
5398                 /* Save these values to target structures
5399                  * or overwrite nvram (phys disks only).
5400                  */
5401
5402                 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
5403                         pTarget->maxWidth = dv->now.width;
5404                         pTarget->maxOffset = dv->now.offset;
5405                         pTarget->minSyncFactor = dv->now.factor;
5406                         pTarget->negoFlags = dv->now.flags;
5407                 } else {
5408                         /* Preserv all flags, use
5409                          * read-modify-write algorithm
5410                          */
5411                         if (hd->ioc->spi_data.nvram) {
5412                                 data = hd->ioc->spi_data.nvram[id];
5413
5414                                 if (dv->now.width)
5415                                         data &= ~MPT_NVRAM_WIDE_DISABLE;
5416                                 else
5417                                         data |= MPT_NVRAM_WIDE_DISABLE;
5418
5419                                 if (!dv->now.offset)
5420                                         factor = MPT_ASYNC;
5421
5422                                 data &= ~MPT_NVRAM_SYNC_MASK;
5423                                 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
5424
5425                                 hd->ioc->spi_data.nvram[id] = data;
5426                         }
5427                 }
5428                 break;
5429         }
5430 }
5431
5432 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5433 /*      mptscsih_fillbuf - fill a buffer with a special data pattern
5434  *              cleanup. For bus scan only.
5435  *
5436  *      @buffer: Pointer to data buffer to be filled.
5437  *      @size: Number of bytes to fill
5438  *      @index: Pattern index
5439  *      @width: bus width, 0 (8 bits) or 1 (16 bits)
5440  */
5441 static void
5442 mptscsih_fillbuf(char *buffer, int size, int index, int width)
5443 {
5444         char *ptr = buffer;
5445         int ii;
5446         char byte;
5447         short val;
5448
5449         switch (index) {
5450         case 0:
5451
5452                 if (width) {
5453                         /* Pattern:  0000 FFFF 0000 FFFF
5454                          */
5455                         for (ii=0; ii < size; ii++, ptr++) {
5456                                 if (ii & 0x02)
5457                                         *ptr = 0xFF;
5458                                 else
5459                                         *ptr = 0x00;
5460                         }
5461                 } else {
5462                         /* Pattern:  00 FF 00 FF
5463                          */
5464                         for (ii=0; ii < size; ii++, ptr++) {
5465                                 if (ii & 0x01)
5466                                         *ptr = 0xFF;
5467                                 else
5468                                         *ptr = 0x00;
5469                         }
5470                 }
5471                 break;
5472
5473         case 1:
5474                 if (width) {
5475                         /* Pattern:  5555 AAAA 5555 AAAA 5555
5476                          */
5477                         for (ii=0; ii < size; ii++, ptr++) {
5478                                 if (ii & 0x02)
5479                                         *ptr = 0xAA;
5480                                 else
5481                                         *ptr = 0x55;
5482                         }
5483                 } else {
5484                         /* Pattern:  55 AA 55 AA 55
5485                          */
5486                         for (ii=0; ii < size; ii++, ptr++) {
5487                                 if (ii & 0x01)
5488                                         *ptr = 0xAA;
5489                                 else
5490                                         *ptr = 0x55;
5491                         }
5492                 }
5493                 break;
5494
5495         case 2:
5496                 /* Pattern:  00 01 02 03 04 05
5497                  * ... FE FF 00 01..
5498                  */
5499                 for (ii=0; ii < size; ii++, ptr++)
5500                         *ptr = (char) ii;
5501                 break;
5502
5503         case 3:
5504                 if (width) {
5505                         /* Wide Pattern:  FFFE 0001 FFFD 0002
5506                          * ...  4000 DFFF 8000 EFFF
5507                          */
5508                         byte = 0;
5509                         for (ii=0; ii < size/2; ii++) {
5510                                 /* Create the base pattern
5511                                  */
5512                                 val = (1 << byte);
5513                                 /* every 64 (0x40) bytes flip the pattern
5514                                  * since we fill 2 bytes / iteration,
5515                                  * test for ii = 0x20
5516                                  */
5517                                 if (ii & 0x20)
5518                                         val = ~(val);
5519
5520                                 if (ii & 0x01) {
5521                                         *ptr = (char)( (val & 0xFF00) >> 8);
5522                                         ptr++;
5523                                         *ptr = (char)(val & 0xFF);
5524                                         byte++;
5525                                         byte &= 0x0F;
5526                                 } else {
5527                                         val = ~val;
5528                                         *ptr = (char)( (val & 0xFF00) >> 8);
5529                                         ptr++;
5530                                         *ptr = (char)(val & 0xFF);
5531                                 }
5532
5533                                 ptr++;
5534                         }
5535                 } else {
5536                         /* Narrow Pattern:  FE 01 FD 02 FB 04
5537                          * .. 7F 80 01 FE 02 FD ...  80 7F
5538                          */
5539                         byte = 0;
5540                         for (ii=0; ii < size; ii++, ptr++) {
5541                                 /* Base pattern - first 32 bytes
5542                                  */
5543                                 if (ii & 0x01) {
5544                                         *ptr = (1 << byte);
5545                                         byte++;
5546                                         byte &= 0x07;
5547                                 } else {
5548                                         *ptr = (char) (~(1 << byte));
5549                                 }
5550
5551                                 /* Flip the pattern every 32 bytes
5552                                  */
5553                                 if (ii & 0x20)
5554                                         *ptr = ~(*ptr);
5555                         }
5556                 }
5557                 break;
5558         }
5559 }
5560 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5561
5562 EXPORT_SYMBOL(mptscsih_remove);
5563 EXPORT_SYMBOL(mptscsih_shutdown);
5564 #ifdef CONFIG_PM
5565 EXPORT_SYMBOL(mptscsih_suspend);
5566 EXPORT_SYMBOL(mptscsih_resume);
5567 #endif
5568 EXPORT_SYMBOL(mptscsih_proc_info);
5569 EXPORT_SYMBOL(mptscsih_info);
5570 EXPORT_SYMBOL(mptscsih_qcmd);
5571 EXPORT_SYMBOL(mptscsih_slave_alloc);
5572 EXPORT_SYMBOL(mptscsih_slave_destroy);
5573 EXPORT_SYMBOL(mptscsih_slave_configure);
5574 EXPORT_SYMBOL(mptscsih_abort);
5575 EXPORT_SYMBOL(mptscsih_dev_reset);
5576 EXPORT_SYMBOL(mptscsih_bus_reset);
5577 EXPORT_SYMBOL(mptscsih_host_reset);
5578 EXPORT_SYMBOL(mptscsih_bios_param);
5579 EXPORT_SYMBOL(mptscsih_io_done);
5580 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
5581 EXPORT_SYMBOL(mptscsih_scandv_complete);
5582 EXPORT_SYMBOL(mptscsih_event_process);
5583 EXPORT_SYMBOL(mptscsih_ioc_reset);
5584 EXPORT_SYMBOL(mptscsih_change_queue_depth);
5585 EXPORT_SYMBOL(mptscsih_timer_expired);
5586
5587 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/