Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[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 static void
2238 mptscsih_set_queue_depth(struct scsi_device *device, MPT_SCSI_HOST *hd,
2239         VirtDevice *pTarget, int qdepth)
2240 {
2241         int     max_depth;
2242         int     tagged;
2243
2244         if (hd->ioc->bus_type == SCSI) {
2245                 if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
2246                         if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2247                                 max_depth = 1;
2248                         else if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
2249                                  (pTarget->minSyncFactor <= MPT_ULTRA160 ))
2250                                 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2251                         else
2252                                 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2253                 } else {
2254                         /* error case - No Inq. Data */
2255                         max_depth = 1;
2256                 }
2257         } else
2258                 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2259
2260         if (qdepth > max_depth)
2261                 qdepth = max_depth;
2262         if (qdepth == 1)
2263                 tagged = 0;
2264         else
2265                 tagged = MSG_SIMPLE_TAG;
2266
2267         scsi_adjust_queue_depth(device, tagged, qdepth);
2268 }
2269
2270
2271 /*
2272  *      OS entry point to adjust the queue_depths on a per-device basis.
2273  *      Called once per device the bus scan. Use it to force the queue_depth
2274  *      member to 1 if a device does not support Q tags.
2275  *      Return non-zero if fails.
2276  */
2277 int
2278 mptscsih_slave_configure(struct scsi_device *device)
2279 {
2280         struct Scsi_Host        *sh = device->host;
2281         VirtDevice              *pTarget;
2282         MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *)sh->hostdata;
2283
2284         if ((hd == NULL) || (hd->Targets == NULL)) {
2285                 return 0;
2286         }
2287
2288         dsprintk((MYIOC_s_INFO_FMT
2289                 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2290                 hd->ioc->name, device, device->id, device->lun, device->channel));
2291         dsprintk((MYIOC_s_INFO_FMT
2292                 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2293                 hd->ioc->name, device->sdtr, device->wdtr,
2294                 device->ppr, device->inquiry_len));
2295
2296         if (device->id > sh->max_id) {
2297                 /* error case, should never happen */
2298                 scsi_adjust_queue_depth(device, 0, 1);
2299                 goto slave_configure_exit;
2300         }
2301
2302         pTarget = hd->Targets[device->id];
2303
2304         if (pTarget == NULL) {
2305                 /* Driver doesn't know about this device.
2306                  * Kernel may generate a "Dummy Lun 0" which
2307                  * may become a real Lun if a 
2308                  * "scsi add-single-device" command is executed
2309                  * while the driver is active (hot-plug a 
2310                  * device).  LSI Raid controllers need 
2311                  * queue_depth set to DEV_HIGH for this reason.
2312                  */
2313                 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
2314                         MPT_SCSI_CMD_PER_DEV_HIGH);
2315                 goto slave_configure_exit;
2316         }
2317
2318         mptscsih_initTarget(hd, device->channel, device->id, device->lun,
2319                 device->inquiry, device->inquiry_len );
2320         mptscsih_set_queue_depth(device, hd, pTarget, MPT_SCSI_CMD_PER_DEV_HIGH);
2321
2322         dsprintk((MYIOC_s_INFO_FMT
2323                 "Queue depth=%d, tflags=%x\n",
2324                 hd->ioc->name, device->queue_depth, pTarget->tflags));
2325
2326         dsprintk((MYIOC_s_INFO_FMT
2327                 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2328                 hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
2329
2330 slave_configure_exit:
2331
2332         dsprintk((MYIOC_s_INFO_FMT
2333                 "tagged %d, simple %d, ordered %d\n",
2334                 hd->ioc->name,device->tagged_supported, device->simple_tags,
2335                 device->ordered_tags));
2336
2337         return 0;
2338 }
2339
2340 ssize_t
2341 mptscsih_store_queue_depth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
2342 {
2343         int                      depth;
2344         struct scsi_device      *sdev = to_scsi_device(dev);
2345         MPT_SCSI_HOST           *hd = (MPT_SCSI_HOST *) sdev->host->hostdata;
2346         VirtDevice              *pTarget;
2347
2348         depth = simple_strtoul(buf, NULL, 0);
2349         if (depth == 0)
2350                 return -EINVAL;
2351         pTarget = hd->Targets[sdev->id];
2352         if (pTarget == NULL)
2353                 return -EINVAL;
2354         mptscsih_set_queue_depth(sdev, (MPT_SCSI_HOST *) sdev->host->hostdata,
2355                 pTarget, depth);
2356         return count;
2357 }
2358
2359 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2360 /*
2361  *  Private routines...
2362  */
2363
2364 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2365 /* Utility function to copy sense data from the scsi_cmnd buffer
2366  * to the FC and SCSI target structures.
2367  *
2368  */
2369 static void
2370 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2371 {
2372         VirtDevice      *target;
2373         SCSIIORequest_t *pReq;
2374         u32              sense_count = le32_to_cpu(pScsiReply->SenseCount);
2375         int              index;
2376
2377         /* Get target structure
2378          */
2379         pReq = (SCSIIORequest_t *) mf;
2380         index = (int) pReq->TargetID;
2381         target = hd->Targets[index];
2382
2383         if (sense_count) {
2384                 u8 *sense_data;
2385                 int req_index;
2386
2387                 /* Copy the sense received into the scsi command block. */
2388                 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2389                 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2390                 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2391
2392                 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2393                  */
2394                 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2395                         if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
2396                                 int idx;
2397                                 MPT_ADAPTER *ioc = hd->ioc;
2398
2399                                 idx = ioc->eventContext % ioc->eventLogSize;
2400                                 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2401                                 ioc->events[idx].eventContext = ioc->eventContext;
2402
2403                                 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2404                                         (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2405                                         (pReq->Bus << 8) || pReq->TargetID;
2406
2407                                 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2408
2409                                 ioc->eventContext++;
2410                         }
2411                 }
2412         } else {
2413                 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2414                                 hd->ioc->name));
2415         }
2416 }
2417
2418 static u32
2419 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2420 {
2421         MPT_SCSI_HOST *hd;
2422         int i;
2423
2424         hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2425
2426         for (i = 0; i < hd->ioc->req_depth; i++) {
2427                 if (hd->ScsiLookup[i] == sc) {
2428                         return i;
2429                 }
2430         }
2431
2432         return -1;
2433 }
2434
2435 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2436 int
2437 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2438 {
2439         MPT_SCSI_HOST   *hd;
2440         unsigned long    flags;
2441
2442         dtmprintk((KERN_WARNING MYNAM
2443                         ": IOC %s_reset routed to SCSI host driver!\n",
2444                         reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2445                         reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2446
2447         /* If a FW reload request arrives after base installed but
2448          * before all scsi hosts have been attached, then an alt_ioc
2449          * may have a NULL sh pointer.
2450          */
2451         if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2452                 return 0;
2453         else
2454                 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2455
2456         if (reset_phase == MPT_IOC_SETUP_RESET) {
2457                 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2458
2459                 /* Clean Up:
2460                  * 1. Set Hard Reset Pending Flag
2461                  * All new commands go to doneQ
2462                  */
2463                 hd->resetPending = 1;
2464
2465         } else if (reset_phase == MPT_IOC_PRE_RESET) {
2466                 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2467
2468                 /* 2. Flush running commands
2469                  *      Clean ScsiLookup (and associated memory)
2470                  *      AND clean mytaskQ
2471                  */
2472
2473                 /* 2b. Reply to OS all known outstanding I/O commands.
2474                  */
2475                 mptscsih_flush_running_cmds(hd);
2476
2477                 /* 2c. If there was an internal command that
2478                  * has not completed, configuration or io request,
2479                  * free these resources.
2480                  */
2481                 if (hd->cmdPtr) {
2482                         del_timer(&hd->timer);
2483                         mpt_free_msg_frame(ioc, hd->cmdPtr);
2484                 }
2485
2486                 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2487
2488         } else {
2489                 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2490
2491                 /* Once a FW reload begins, all new OS commands are
2492                  * redirected to the doneQ w/ a reset status.
2493                  * Init all control structures.
2494                  */
2495
2496                 /* ScsiLookup initialization
2497                  */
2498                 {
2499                         int ii;
2500                         for (ii=0; ii < hd->ioc->req_depth; ii++)
2501                                 hd->ScsiLookup[ii] = NULL;
2502                 }
2503
2504                 /* 2. Chain Buffer initialization
2505                  */
2506
2507                 /* 4. Renegotiate to all devices, if SCSI
2508                  */
2509                 if (ioc->bus_type == SCSI) {
2510                         dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
2511                         mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
2512                 }
2513
2514                 /* 5. Enable new commands to be posted
2515                  */
2516                 spin_lock_irqsave(&ioc->FreeQlock, flags);
2517                 hd->tmPending = 0;
2518                 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2519                 hd->resetPending = 0;
2520                 hd->tmState = TM_STATE_NONE;
2521
2522                 /* 6. If there was an internal command,
2523                  * wake this process up.
2524                  */
2525                 if (hd->cmdPtr) {
2526                         /*
2527                          * Wake up the original calling thread
2528                          */
2529                         hd->pLocal = &hd->localReply;
2530                         hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2531                         hd->scandv_wait_done = 1;
2532                         wake_up(&hd->scandv_waitq);
2533                         hd->cmdPtr = NULL;
2534                 }
2535
2536                 /* 7. Set flag to force DV and re-read IOC Page 3
2537                  */
2538                 if (ioc->bus_type == SCSI) {
2539                         ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2540                         ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2541                 }
2542
2543                 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2544
2545         }
2546
2547         return 1;               /* currently means nothing really */
2548 }
2549
2550 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2551 int
2552 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2553 {
2554         MPT_SCSI_HOST *hd;
2555         u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2556
2557         devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2558                         ioc->name, event));
2559
2560         switch (event) {
2561         case MPI_EVENT_UNIT_ATTENTION:                  /* 03 */
2562                 /* FIXME! */
2563                 break;
2564         case MPI_EVENT_IOC_BUS_RESET:                   /* 04 */
2565         case MPI_EVENT_EXT_BUS_RESET:                   /* 05 */
2566                 hd = NULL;
2567                 if (ioc->sh) {
2568                         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2569                         if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
2570                                 hd->soft_resets++;
2571                 }
2572                 break;
2573         case MPI_EVENT_LOGOUT:                          /* 09 */
2574                 /* FIXME! */
2575                 break;
2576
2577                 /*
2578                  *  CHECKME! Don't think we need to do
2579                  *  anything for these, but...
2580                  */
2581         case MPI_EVENT_RESCAN:                          /* 06 */
2582         case MPI_EVENT_LINK_STATUS_CHANGE:              /* 07 */
2583         case MPI_EVENT_LOOP_STATE_CHANGE:               /* 08 */
2584                 /*
2585                  *  CHECKME!  Falling thru...
2586                  */
2587                 break;
2588
2589         case MPI_EVENT_INTEGRATED_RAID:                 /* 0B */
2590 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2591                 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
2592                  * if DV disabled. Need to check for target mode.
2593                  */
2594                 hd = NULL;
2595                 if (ioc->sh)
2596                         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2597
2598                 if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) {
2599                         ScsiCfgData     *pSpi;
2600                         Ioc3PhysDisk_t  *pPDisk;
2601                         int              numPDisk;
2602                         u8               reason;
2603                         u8               physDiskNum;
2604
2605                         reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
2606                         if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
2607                                 /* New or replaced disk.
2608                                  * Set DV flag and schedule DV.
2609                                  */
2610                                 pSpi = &ioc->spi_data;
2611                                 physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
2612                                 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
2613                                 if (pSpi->pIocPg3) {
2614                                         pPDisk =  pSpi->pIocPg3->PhysDisk;
2615                                         numPDisk =pSpi->pIocPg3->NumPhysDisks;
2616
2617                                         while (numPDisk) {
2618                                                 if (physDiskNum == pPDisk->PhysDiskNum) {
2619                                                         pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
2620                                                         pSpi->forceDv = MPT_SCSICFG_NEED_DV;
2621                                                         ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
2622                                                         break;
2623                                                 }
2624                                                 pPDisk++;
2625                                                 numPDisk--;
2626                                         }
2627
2628                                         if (numPDisk == 0) {
2629                                                 /* The physical disk that needs DV was not found
2630                                                  * in the stored IOC Page 3. The driver must reload
2631                                                  * this page. DV routine will set the NEED_DV flag for
2632                                                  * all phys disks that have DV_NOT_DONE set.
2633                                                  */
2634                                                 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2635                                                 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
2636                                         }
2637                                 }
2638                         }
2639                 }
2640 #endif
2641
2642 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
2643                 printk("Raid Event RF: ");
2644                 {
2645                         u32 *m = (u32 *)pEvReply;
2646                         int ii;
2647                         int n = (int)pEvReply->MsgLength;
2648                         for (ii=6; ii < n; ii++)
2649                                 printk(" %08x", le32_to_cpu(m[ii]));
2650                         printk("\n");
2651                 }
2652 #endif
2653                 break;
2654
2655         case MPI_EVENT_NONE:                            /* 00 */
2656         case MPI_EVENT_LOG_DATA:                        /* 01 */
2657         case MPI_EVENT_STATE_CHANGE:                    /* 02 */
2658         case MPI_EVENT_EVENT_CHANGE:                    /* 0A */
2659         default:
2660                 dprintk((KERN_INFO "  Ignoring event (=%02Xh)\n", event));
2661                 break;
2662         }
2663
2664         return 1;               /* currently means nothing really */
2665 }
2666
2667 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2668 /*
2669  *      mptscsih_initTarget - Target, LUN alloc/free functionality.
2670  *      @hd: Pointer to MPT_SCSI_HOST structure
2671  *      @bus_id: Bus number (?)
2672  *      @target_id: SCSI target id
2673  *      @lun: SCSI LUN id
2674  *      @data: Pointer to data
2675  *      @dlen: Number of INQUIRY bytes
2676  *
2677  *      NOTE: It's only SAFE to call this routine if data points to
2678  *      sane & valid STANDARD INQUIRY data!
2679  *
2680  *      Allocate and initialize memory for this target.
2681  *      Save inquiry data.
2682  *
2683  */
2684 static void
2685 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
2686 {
2687         int             indexed_lun, lun_index;
2688         VirtDevice      *vdev;
2689         ScsiCfgData     *pSpi;
2690         char            data_56;
2691
2692         dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
2693                         hd->ioc->name, bus_id, target_id, lun, hd));
2694
2695         /*
2696          * If the peripheral qualifier filter is enabled then if the target reports a 0x1
2697          * (i.e. The targer is capable of supporting the specified peripheral device type
2698          * on this logical unit; however, the physical device is not currently connected
2699          * to this logical unit) it will be converted to a 0x3 (i.e. The target is not 
2700          * capable of supporting a physical device on this logical unit). This is to work
2701          * around a bug in th emid-layer in some distributions in which the mid-layer will
2702          * continue to try to communicate to the LUN and evntually create a dummy LUN.
2703         */
2704         if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
2705                 data[0] |= 0x40;
2706
2707         /* Is LUN supported? If so, upper 2 bits will be 0
2708         * in first byte of inquiry data.
2709         */
2710         if (data[0] & 0xe0)
2711                 return;
2712
2713         if ((vdev = hd->Targets[target_id]) == NULL) {
2714                 return;
2715         }
2716
2717         lun_index = (lun >> 5);  /* 32 luns per lun_index */
2718         indexed_lun = (lun % 32);
2719         vdev->luns[lun_index] |= (1 << indexed_lun);
2720
2721         if (hd->ioc->bus_type == SCSI) {
2722                 if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2723                         /* Treat all Processors as SAF-TE if
2724                          * command line option is set */
2725                         vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2726                         mptscsih_writeIOCPage4(hd, target_id, bus_id);
2727                 }else if ((data[0] == TYPE_PROCESSOR) &&
2728                         !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2729                         if ( dlen > 49 ) {
2730                                 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2731                                 if ( data[44] == 'S' &&
2732                                      data[45] == 'A' &&
2733                                      data[46] == 'F' &&
2734                                      data[47] == '-' &&
2735                                      data[48] == 'T' &&
2736                                      data[49] == 'E' ) {
2737                                         vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2738                                         mptscsih_writeIOCPage4(hd, target_id, bus_id);
2739                                 }
2740                         }
2741                 }
2742                 if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
2743                         if ( dlen > 8 ) {
2744                                 memcpy (vdev->inq_data, data, 8);
2745                         } else {
2746                                 memcpy (vdev->inq_data, data, dlen);
2747                         }
2748
2749                         /* If have not done DV, set the DV flag.
2750                          */
2751                         pSpi = &hd->ioc->spi_data;
2752                         if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
2753                                 if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
2754                                         pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
2755                         }
2756
2757                         vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2758
2759
2760                         data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
2761                         if (dlen > 56) {
2762                                 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2763                                 /* Update the target capabilities
2764                                  */
2765                                         data_56 = data[56];
2766                                         vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
2767                                 }
2768                         }
2769                         mptscsih_setTargetNegoParms(hd, vdev, data_56);
2770                 } else {
2771                         /* Initial Inquiry may not request enough data bytes to
2772                          * obtain byte 57.  DV will; if target doesn't return
2773                          * at least 57 bytes, data[56] will be zero. */
2774                         if (dlen > 56) {
2775                                 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2776                                 /* Update the target capabilities
2777                                  */
2778                                         data_56 = data[56];
2779                                         vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
2780                                         mptscsih_setTargetNegoParms(hd, vdev, data_56);
2781                                 }
2782                         }
2783                 }
2784         }
2785 }
2786
2787 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2788 /*
2789  *  Update the target negotiation parameters based on the
2790  *  the Inquiry data, adapter capabilities, and NVRAM settings.
2791  *
2792  */
2793 static void
2794 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
2795 {
2796         ScsiCfgData *pspi_data = &hd->ioc->spi_data;
2797         int  id = (int) target->target_id;
2798         int  nvram;
2799         VirtDevice      *vdev;
2800         int ii;
2801         u8 width = MPT_NARROW;
2802         u8 factor = MPT_ASYNC;
2803         u8 offset = 0;
2804         u8 version, nfactor;
2805         u8 noQas = 1;
2806
2807         target->negoFlags = pspi_data->noQas;
2808
2809         /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
2810          * support. If available, default QAS to off and allow enabling.
2811          * If not available, default QAS to on, turn off for non-disks.
2812          */
2813
2814         /* Set flags based on Inquiry data
2815          */
2816         version = target->inq_data[2] & 0x07;
2817         if (version < 2) {
2818                 width = 0;
2819                 factor = MPT_ULTRA2;
2820                 offset = pspi_data->maxSyncOffset;
2821                 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2822         } else {
2823                 if (target->inq_data[7] & 0x20) {
2824                         width = 1;
2825                 }
2826
2827                 if (target->inq_data[7] & 0x10) {
2828                         factor = pspi_data->minSyncFactor;
2829                         if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
2830                                 /* bits 2 & 3 show Clocking support */
2831                                 if ((byte56 & 0x0C) == 0)
2832                                         factor = MPT_ULTRA2;
2833                                 else {
2834                                         if ((byte56 & 0x03) == 0)
2835                                                 factor = MPT_ULTRA160;
2836                                         else {
2837                                                 factor = MPT_ULTRA320;
2838                                                 if (byte56 & 0x02)
2839                                                 {
2840                                                         ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
2841                                                         noQas = 0;
2842                                                 }
2843                                                 if (target->inq_data[0] == TYPE_TAPE) {
2844                                                         if (byte56 & 0x01)
2845                                                                 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2846                                                 }
2847                                         }
2848                                 }
2849                         } else {
2850                                 ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
2851                                 noQas = 0;
2852                         }
2853
2854                         offset = pspi_data->maxSyncOffset;
2855
2856                         /* If RAID, never disable QAS
2857                          * else if non RAID, do not disable
2858                          *   QAS if bit 1 is set
2859                          * bit 1 QAS support, non-raid only
2860                          * bit 0 IU support
2861                          */
2862                         if (target->raidVolume == 1) {
2863                                 noQas = 0;
2864                         }
2865                 } else {
2866                         factor = MPT_ASYNC;
2867                         offset = 0;
2868                 }
2869         }
2870
2871         if ( (target->inq_data[7] & 0x02) == 0) {
2872                 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2873         }
2874
2875         /* Update tflags based on NVRAM settings. (SCSI only)
2876          */
2877         if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2878                 nvram = pspi_data->nvram[id];
2879                 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2880
2881                 if (width)
2882                         width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2883
2884                 if (offset > 0) {
2885                         /* Ensure factor is set to the
2886                          * maximum of: adapter, nvram, inquiry
2887                          */
2888                         if (nfactor) {
2889                                 if (nfactor < pspi_data->minSyncFactor )
2890                                         nfactor = pspi_data->minSyncFactor;
2891
2892                                 factor = max(factor, nfactor);
2893                                 if (factor == MPT_ASYNC)
2894                                         offset = 0;
2895                         } else {
2896                                 offset = 0;
2897                                 factor = MPT_ASYNC;
2898                 }
2899                 } else {
2900                         factor = MPT_ASYNC;
2901                 }
2902         }
2903
2904         /* Make sure data is consistent
2905          */
2906         if ((!width) && (factor < MPT_ULTRA2)) {
2907                 factor = MPT_ULTRA2;
2908         }
2909
2910         /* Save the data to the target structure.
2911          */
2912         target->minSyncFactor = factor;
2913         target->maxOffset = offset;
2914         target->maxWidth = width;
2915
2916         target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2917
2918         /* Disable unused features.
2919          */
2920         if (!width)
2921                 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2922
2923         if (!offset)
2924                 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2925
2926         if ( factor > MPT_ULTRA320 )
2927                 noQas = 0;
2928
2929         /* GEM, processor WORKAROUND
2930          */
2931         if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
2932                 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
2933                 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
2934         } else {
2935                 if (noQas && (pspi_data->noQas == 0)) {
2936                         pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2937                         target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2938
2939                         /* Disable QAS in a mixed configuration case
2940                         */
2941
2942                         ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2943                         for (ii = 0; ii < id; ii++) {
2944                                 if ( (vdev = hd->Targets[ii]) ) {
2945                                         vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2946                                         mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
2947                                 }
2948                         }
2949                 }
2950         }
2951
2952         /* Write SDP1 on this I/O to this target */
2953         if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
2954                 ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
2955                 mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
2956                 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
2957         } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
2958                 ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
2959                 mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
2960                 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
2961         }
2962 }
2963
2964 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2965 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
2966  * Else set the NEED_DV flag after Read Capacity Issued (disks)
2967  * or Mode Sense (cdroms).
2968  *
2969  * Tapes, initTarget will set this flag on completion of Inquiry command.
2970  * Called only if DV_NOT_DONE flag is set
2971  */
2972 static void
2973 mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
2974 {
2975         u8 cmd;
2976         ScsiCfgData *pSpi;
2977
2978         ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", 
2979                 pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
2980
2981         if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
2982                 return;
2983
2984         cmd = pReq->CDB[0];
2985
2986         if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
2987                 pSpi = &hd->ioc->spi_data;
2988                 if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
2989                         /* Set NEED_DV for all hidden disks
2990                          */
2991                         Ioc3PhysDisk_t *pPDisk =  pSpi->pIocPg3->PhysDisk;
2992                         int             numPDisk = pSpi->pIocPg3->NumPhysDisks;
2993
2994                         while (numPDisk) {
2995                                 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
2996                                 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
2997                                 pPDisk++;
2998                                 numPDisk--;
2999                         }
3000                 }
3001                 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
3002                 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
3003         }
3004 }
3005
3006 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3007 /*
3008  * If no Target, bus reset on 1st I/O. Set the flag to
3009  * prevent any future negotiations to this device.
3010  */
3011 static void
3012 mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
3013 {
3014
3015         if ((hd->Targets) && (hd->Targets[target_id] == NULL))
3016                 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
3017
3018         return;
3019 }
3020
3021 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3022 /*
3023  *  SCSI Config Page functionality ...
3024  */
3025 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3026 /*      mptscsih_setDevicePage1Flags  - add Requested and Configuration fields flags
3027  *      based on width, factor and offset parameters.
3028  *      @width: bus width
3029  *      @factor: sync factor
3030  *      @offset: sync offset
3031  *      @requestedPtr: pointer to requested values (updated)
3032  *      @configurationPtr: pointer to configuration values (updated)
3033  *      @flags: flags to block WDTR or SDTR negotiation
3034  *
3035  *      Return: None.
3036  *
3037  *      Remark: Called by writeSDP1 and _dv_params
3038  */
3039 static void
3040 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
3041 {
3042         u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
3043         u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
3044
3045         *configurationPtr = 0;
3046         *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
3047         *requestedPtr |= (offset << 16) | (factor << 8);
3048
3049         if (width && offset && !nowide && !nosync) {
3050                 if (factor < MPT_ULTRA160) {
3051                         *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
3052                         if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
3053                                 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
3054                         if (flags & MPT_TAPE_NEGO_IDP)
3055                                 *requestedPtr |= 0x08000000;
3056                 } else if (factor < MPT_ULTRA2) {
3057                         *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
3058                 }
3059         }
3060
3061         if (nowide)
3062                 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
3063
3064         if (nosync)
3065                 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
3066
3067         return;
3068 }
3069
3070 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3071 /*      mptscsih_writeSDP1  - write SCSI Device Page 1
3072  *      @hd: Pointer to a SCSI Host Strucutre
3073  *      @portnum: IOC port number
3074  *      @target_id: writeSDP1 for single ID
3075  *      @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
3076  *
3077  *      Return: -EFAULT if read of config page header fails
3078  *              or 0 if success.
3079  *
3080  *      Remark: If a target has been found, the settings from the
3081  *              target structure are used, else the device is set
3082  *              to async/narrow.
3083  *
3084  *      Remark: Called during init and after a FW reload.
3085  *      Remark: We do not wait for a return, write pages sequentially.
3086  */
3087 static int
3088 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
3089 {
3090         MPT_ADAPTER             *ioc = hd->ioc;
3091         Config_t                *pReq;
3092         SCSIDevicePage1_t       *pData;
3093         VirtDevice              *pTarget;
3094         MPT_FRAME_HDR           *mf;
3095         dma_addr_t               dataDma;
3096         u16                      req_idx;
3097         u32                      frameOffset;
3098         u32                      requested, configuration, flagsLength;
3099         int                      ii, nvram;
3100         int                      id = 0, maxid = 0;
3101         u8                       width;
3102         u8                       factor;
3103         u8                       offset;
3104         u8                       bus = 0;
3105         u8                       negoFlags;
3106         u8                       maxwidth, maxoffset, maxfactor;
3107
3108         if (ioc->spi_data.sdp1length == 0)
3109                 return 0;
3110
3111         if (flags & MPT_SCSICFG_ALL_IDS) {
3112                 id = 0;
3113                 maxid = ioc->sh->max_id - 1;
3114         } else if (ioc->sh) {
3115                 id = target_id;
3116                 maxid = min_t(int, id, ioc->sh->max_id - 1);
3117         }
3118
3119         for (; id <= maxid; id++) {
3120
3121                 if (id == ioc->pfacts[portnum].PortSCSIID)
3122                         continue;
3123
3124                 /* Use NVRAM to get adapter and target maximums
3125                  * Data over-riden by target structure information, if present
3126                  */
3127                 maxwidth = ioc->spi_data.maxBusWidth;
3128                 maxoffset = ioc->spi_data.maxSyncOffset;
3129                 maxfactor = ioc->spi_data.minSyncFactor;
3130                 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3131                         nvram = ioc->spi_data.nvram[id];
3132
3133                         if (maxwidth)
3134                                 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
3135
3136                         if (maxoffset > 0) {
3137                                 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
3138                                 if (maxfactor == 0) {
3139                                         /* Key for async */
3140                                         maxfactor = MPT_ASYNC;
3141                                         maxoffset = 0;
3142                                 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
3143                                         maxfactor = ioc->spi_data.minSyncFactor;
3144                                 }
3145                         } else
3146                                 maxfactor = MPT_ASYNC;
3147                 }
3148
3149                 /* Set the negotiation flags.
3150                  */
3151                 negoFlags = ioc->spi_data.noQas;
3152                 if (!maxwidth)
3153                         negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
3154
3155                 if (!maxoffset)
3156                         negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
3157
3158                 if (flags & MPT_SCSICFG_USE_NVRAM) {
3159                         width = maxwidth;
3160                         factor = maxfactor;
3161                         offset = maxoffset;
3162                 } else {
3163                         width = 0;
3164                         factor = MPT_ASYNC;
3165                         offset = 0;
3166                         //negoFlags = 0;
3167                         //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
3168                 }
3169
3170                 /* If id is not a raid volume, get the updated
3171                  * transmission settings from the target structure.
3172                  */
3173                 if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
3174                         width = pTarget->maxWidth;
3175                         factor = pTarget->minSyncFactor;
3176                         offset = pTarget->maxOffset;
3177                         negoFlags = pTarget->negoFlags;
3178                 }
3179
3180 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3181                 /* Force to async and narrow if DV has not been executed
3182                  * for this ID
3183                  */
3184                 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
3185                         width = 0;
3186                         factor = MPT_ASYNC;
3187                         offset = 0;
3188                 }
3189 #endif
3190
3191                 if (flags & MPT_SCSICFG_BLK_NEGO)
3192                         negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
3193
3194                 mptscsih_setDevicePage1Flags(width, factor, offset,
3195                                         &requested, &configuration, negoFlags);
3196                 dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
3197                         target_id, width, factor, offset, negoFlags, requested, configuration));
3198
3199                 /* Get a MF for this command.
3200                  */
3201                 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3202                         dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
3203                                                 ioc->name));
3204                         return -EAGAIN;
3205                 }
3206
3207                 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
3208                         hd->ioc->name, mf, id, requested, configuration));
3209
3210
3211                 /* Set the request and the data pointers.
3212                  * Request takes: 36 bytes (32 bit SGE)
3213                  * SCSI Device Page 1 requires 16 bytes
3214                  * 40 + 16 <= size of SCSI IO Request = 56 bytes
3215                  * and MF size >= 64 bytes.
3216                  * Place data at end of MF.
3217                  */
3218                 pReq = (Config_t *)mf;
3219
3220                 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3221                 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
3222
3223                 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
3224                 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
3225
3226                 /* Complete the request frame (same for all requests).
3227                  */
3228                 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3229                 pReq->Reserved = 0;
3230                 pReq->ChainOffset = 0;
3231                 pReq->Function = MPI_FUNCTION_CONFIG;
3232                 pReq->ExtPageLength = 0;
3233                 pReq->ExtPageType = 0;
3234                 pReq->MsgFlags = 0;
3235                 for (ii=0; ii < 8; ii++) {
3236                         pReq->Reserved2[ii] = 0;
3237                 }
3238                 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
3239                 pReq->Header.PageLength = ioc->spi_data.sdp1length;
3240                 pReq->Header.PageNumber = 1;
3241                 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3242                 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
3243
3244                 /* Add a SGE to the config request.
3245                  */
3246                 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
3247
3248                 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3249
3250                 /* Set up the common data portion
3251                  */
3252                 pData->Header.PageVersion = pReq->Header.PageVersion;
3253                 pData->Header.PageLength = pReq->Header.PageLength;
3254                 pData->Header.PageNumber = pReq->Header.PageNumber;
3255                 pData->Header.PageType = pReq->Header.PageType;
3256                 pData->RequestedParameters = cpu_to_le32(requested);
3257                 pData->Reserved = 0;
3258                 pData->Configuration = cpu_to_le32(configuration);
3259
3260                 dprintk((MYIOC_s_INFO_FMT
3261                         "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
3262                                 ioc->name, id, (id | (bus<<8)),
3263                                 requested, configuration));
3264
3265                 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3266         }
3267
3268         return 0;
3269 }
3270
3271 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3272 /*      mptscsih_writeIOCPage4  - write IOC Page 4
3273  *      @hd: Pointer to a SCSI Host Structure
3274  *      @target_id: write IOC Page4 for this ID & Bus
3275  *
3276  *      Return: -EAGAIN if unable to obtain a Message Frame
3277  *              or 0 if success.
3278  *
3279  *      Remark: We do not wait for a return, write pages sequentially.
3280  */
3281 static int
3282 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
3283 {
3284         MPT_ADAPTER             *ioc = hd->ioc;
3285         Config_t                *pReq;
3286         IOCPage4_t              *IOCPage4Ptr;
3287         MPT_FRAME_HDR           *mf;
3288         dma_addr_t               dataDma;
3289         u16                      req_idx;
3290         u32                      frameOffset;
3291         u32                      flagsLength;
3292         int                      ii;
3293
3294         /* Get a MF for this command.
3295          */
3296         if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3297                 dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
3298                                         ioc->name));
3299                 return -EAGAIN;
3300         }
3301
3302         /* Set the request and the data pointers.
3303          * Place data at end of MF.
3304          */
3305         pReq = (Config_t *)mf;
3306
3307         req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3308         frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
3309
3310         /* Complete the request frame (same for all requests).
3311          */
3312         pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3313         pReq->Reserved = 0;
3314         pReq->ChainOffset = 0;
3315         pReq->Function = MPI_FUNCTION_CONFIG;
3316         pReq->ExtPageLength = 0;
3317         pReq->ExtPageType = 0;
3318         pReq->MsgFlags = 0;
3319         for (ii=0; ii < 8; ii++) {
3320                 pReq->Reserved2[ii] = 0;
3321         }
3322
3323         IOCPage4Ptr = ioc->spi_data.pIocPg4;
3324         dataDma = ioc->spi_data.IocPg4_dma;
3325         ii = IOCPage4Ptr->ActiveSEP++;
3326         IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
3327         IOCPage4Ptr->SEP[ii].SEPBus = bus;
3328         pReq->Header = IOCPage4Ptr->Header;
3329         pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
3330
3331         /* Add a SGE to the config request.
3332          */
3333         flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
3334                 (IOCPage4Ptr->Header.PageLength + ii) * 4;
3335
3336         mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3337
3338         dinitprintk((MYIOC_s_INFO_FMT
3339                 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
3340                         ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
3341
3342         mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3343
3344         return 0;
3345 }
3346
3347 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3348 /*
3349  *  Bus Scan and Domain Validation functionality ...
3350  */
3351
3352 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3353 /*
3354  *      mptscsih_scandv_complete - Scan and DV callback routine registered
3355  *      to Fustion MPT (base) driver.
3356  *
3357  *      @ioc: Pointer to MPT_ADAPTER structure
3358  *      @mf: Pointer to original MPT request frame
3359  *      @mr: Pointer to MPT reply frame (NULL if TurboReply)
3360  *
3361  *      This routine is called from mpt.c::mpt_interrupt() at the completion
3362  *      of any SCSI IO request.
3363  *      This routine is registered with the Fusion MPT (base) driver at driver
3364  *      load/init time via the mpt_register() API call.
3365  *
3366  *      Returns 1 indicating alloc'd request frame ptr should be freed.
3367  *
3368  *      Remark: Sets a completion code and (possibly) saves sense data
3369  *      in the IOC member localReply structure.
3370  *      Used ONLY for DV and other internal commands.
3371  */
3372 int
3373 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3374 {
3375         MPT_SCSI_HOST   *hd;
3376         SCSIIORequest_t *pReq;
3377         int              completionCode;
3378         u16              req_idx;
3379
3380         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3381
3382         if ((mf == NULL) ||
3383             (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
3384                 printk(MYIOC_s_ERR_FMT
3385                         "ScanDvComplete, %s req frame ptr! (=%p)\n",
3386                                 ioc->name, mf?"BAD":"NULL", (void *) mf);
3387                 goto wakeup;
3388         }
3389
3390         del_timer(&hd->timer);
3391         req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3392         hd->ScsiLookup[req_idx] = NULL;
3393         pReq = (SCSIIORequest_t *) mf;
3394
3395         if (mf != hd->cmdPtr) {
3396                 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3397                                 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3398         }
3399         hd->cmdPtr = NULL;
3400
3401         ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3402                         hd->ioc->name, mf, mr, req_idx));
3403
3404         hd->pLocal = &hd->localReply;
3405         hd->pLocal->scsiStatus = 0;
3406
3407         /* If target struct exists, clear sense valid flag.
3408          */
3409         if (mr == NULL) {
3410                 completionCode = MPT_SCANDV_GOOD;
3411         } else {
3412                 SCSIIOReply_t   *pReply;
3413                 u16              status;
3414                 u8               scsi_status;
3415
3416                 pReply = (SCSIIOReply_t *) mr;
3417
3418                 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3419                 scsi_status = pReply->SCSIStatus;
3420
3421                 ddvtprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3422                              status, pReply->SCSIState, scsi_status,
3423                              le32_to_cpu(pReply->IOCLogInfo)));
3424
3425                 switch(status) {
3426
3427                 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE:       /* 0x0043 */
3428                         completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3429                         break;
3430
3431                 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:          /* 0x0046 */
3432                 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED:        /* 0x0048 */
3433                 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED:         /* 0x004B */
3434                 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED:         /* 0x004C */
3435                         completionCode = MPT_SCANDV_DID_RESET;
3436                         break;
3437
3438                 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:          /* 0x0045 */
3439                 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:        /* 0x0040 */
3440                 case MPI_IOCSTATUS_SUCCESS:                     /* 0x0000 */
3441                         if (pReply->Function == MPI_FUNCTION_CONFIG) {
3442                                 ConfigReply_t *pr = (ConfigReply_t *)mr;
3443                                 completionCode = MPT_SCANDV_GOOD;
3444                                 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3445                                 hd->pLocal->header.PageLength = pr->Header.PageLength;
3446                                 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3447                                 hd->pLocal->header.PageType = pr->Header.PageType;
3448
3449                         } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3450                                 /* If the RAID Volume request is successful,
3451                                  * return GOOD, else indicate that
3452                                  * some type of error occurred.
3453                                  */
3454                                 MpiRaidActionReply_t    *pr = (MpiRaidActionReply_t *)mr;
3455                                 if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
3456                                         completionCode = MPT_SCANDV_GOOD;
3457                                 else
3458                                         completionCode = MPT_SCANDV_SOME_ERROR;
3459
3460                         } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3461                                 u8              *sense_data;
3462                                 int              sz;
3463
3464                                 /* save sense data in global structure
3465                                  */
3466                                 completionCode = MPT_SCANDV_SENSE;
3467                                 hd->pLocal->scsiStatus = scsi_status;
3468                                 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3469                                         (req_idx * MPT_SENSE_BUFFER_ALLOC));
3470
3471                                 sz = min_t(int, pReq->SenseBufferLength,
3472                                                         SCSI_STD_SENSE_BYTES);
3473                                 memcpy(hd->pLocal->sense, sense_data, sz);
3474
3475                                 ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
3476                                                 sense_data));
3477                         } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3478                                 if (pReq->CDB[0] == INQUIRY)
3479                                         completionCode = MPT_SCANDV_ISSUE_SENSE;
3480                                 else
3481                                         completionCode = MPT_SCANDV_DID_RESET;
3482                         }
3483                         else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3484                                 completionCode = MPT_SCANDV_DID_RESET;
3485                         else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3486                                 completionCode = MPT_SCANDV_DID_RESET;
3487                         else {
3488                                 completionCode = MPT_SCANDV_GOOD;
3489                                 hd->pLocal->scsiStatus = scsi_status;
3490                         }
3491                         break;
3492
3493                 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR:         /* 0x0047 */
3494                         if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3495                                 completionCode = MPT_SCANDV_DID_RESET;
3496                         else
3497                                 completionCode = MPT_SCANDV_SOME_ERROR;
3498                         break;
3499
3500                 default:
3501                         completionCode = MPT_SCANDV_SOME_ERROR;
3502                         break;
3503
3504                 }       /* switch(status) */
3505
3506                 ddvtprintk((KERN_NOTICE "  completionCode set to %08xh\n",
3507                                 completionCode));
3508         } /* end of address reply case */
3509
3510         hd->pLocal->completion = completionCode;
3511
3512         /* MF and RF are freed in mpt_interrupt
3513          */
3514 wakeup:
3515         /* Free Chain buffers (will never chain) in scan or dv */
3516         //mptscsih_freeChainBuffers(ioc, req_idx);
3517
3518         /*
3519          * Wake up the original calling thread
3520          */
3521         hd->scandv_wait_done = 1;
3522         wake_up(&hd->scandv_waitq);
3523
3524         return 1;
3525 }
3526
3527 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3528 /*      mptscsih_timer_expired - Call back for timer process.
3529  *      Used only for dv functionality.
3530  *      @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3531  *
3532  */
3533 void
3534 mptscsih_timer_expired(unsigned long data)
3535 {
3536         MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3537
3538         ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3539
3540         if (hd->cmdPtr) {
3541                 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3542
3543                 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3544                         /* Desire to issue a task management request here.
3545                          * TM requests MUST be single threaded.
3546                          * If old eh code and no TM current, issue request.
3547                          * If new eh code, do nothing. Wait for OS cmd timeout
3548                          *      for bus reset.
3549                          */
3550                         ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3551                 } else {
3552                         /* Perform a FW reload */
3553                         if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3554                                 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3555                         }
3556                 }
3557         } else {
3558                 /* This should NEVER happen */
3559                 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3560         }
3561
3562         /* No more processing.
3563          * TM call will generate an interrupt for SCSI TM Management.
3564          * The FW will reply to all outstanding commands, callback will finish cleanup.
3565          * Hard reset clean-up will free all resources.
3566          */
3567         ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3568
3569         return;
3570 }
3571
3572 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3573 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3574 /*      mptscsih_do_raid - Format and Issue a RAID volume request message.
3575  *      @hd: Pointer to scsi host structure
3576  *      @action: What do be done.
3577  *      @id: Logical target id.
3578  *      @bus: Target locations bus.
3579  *
3580  *      Returns: < 0 on a fatal error
3581  *              0 on success
3582  *
3583  *      Remark: Wait to return until reply processed by the ISR.
3584  */
3585 static int
3586 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
3587 {
3588         MpiRaidActionRequest_t  *pReq;
3589         MPT_FRAME_HDR           *mf;
3590         int                     in_isr;
3591
3592         in_isr = in_interrupt();
3593         if (in_isr) {
3594                 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
3595                                 hd->ioc->name));
3596                 return -EPERM;
3597         }
3598
3599         /* Get and Populate a free Frame
3600          */
3601         if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3602                 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
3603                                         hd->ioc->name));
3604                 return -EAGAIN;
3605         }
3606         pReq = (MpiRaidActionRequest_t *)mf;
3607         pReq->Action = action;
3608         pReq->Reserved1 = 0;
3609         pReq->ChainOffset = 0;
3610         pReq->Function = MPI_FUNCTION_RAID_ACTION;
3611         pReq->VolumeID = io->id;
3612         pReq->VolumeBus = io->bus;
3613         pReq->PhysDiskNum = io->physDiskNum;
3614         pReq->MsgFlags = 0;
3615         pReq->Reserved2 = 0;
3616         pReq->ActionDataWord = 0; /* Reserved for this action */
3617         //pReq->ActionDataSGE = 0;
3618
3619         mpt_add_sge((char *)&pReq->ActionDataSGE,
3620                 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
3621
3622         ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
3623                         hd->ioc->name, action, io->id));
3624
3625         hd->pLocal = NULL;
3626         hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
3627         hd->scandv_wait_done = 0;
3628
3629         /* Save cmd pointer, for resource free if timeout or
3630          * FW reload occurs
3631          */
3632         hd->cmdPtr = mf;
3633
3634         add_timer(&hd->timer);
3635         mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3636         wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3637
3638         if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
3639                 return -1;
3640
3641         return 0;
3642 }
3643 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3644
3645 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3646 /**
3647  *      mptscsih_do_cmd - Do internal command.
3648  *      @hd: MPT_SCSI_HOST pointer
3649  *      @io: INTERNAL_CMD pointer.
3650  *
3651  *      Issue the specified internally generated command and do command
3652  *      specific cleanup. For bus scan / DV only.
3653  *      NOTES: If command is Inquiry and status is good,
3654  *      initialize a target structure, save the data
3655  *
3656  *      Remark: Single threaded access only.
3657  *
3658  *      Return:
3659  *              < 0 if an illegal command or no resources
3660  *
3661  *                 0 if good
3662  *
3663  *               > 0 if command complete but some type of completion error.
3664  */
3665 static int
3666 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3667 {
3668         MPT_FRAME_HDR   *mf;
3669         SCSIIORequest_t *pScsiReq;
3670         SCSIIORequest_t  ReqCopy;
3671         int              my_idx, ii, dir;
3672         int              rc, cmdTimeout;
3673         int             in_isr;
3674         char             cmdLen;
3675         char             CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3676         char             cmd = io->cmd;
3677
3678         in_isr = in_interrupt();
3679         if (in_isr) {
3680                 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3681                                 hd->ioc->name));
3682                 return -EPERM;
3683         }
3684
3685
3686         /* Set command specific information
3687          */
3688         switch (cmd) {
3689         case INQUIRY:
3690                 cmdLen = 6;
3691                 dir = MPI_SCSIIO_CONTROL_READ;
3692                 CDB[0] = cmd;
3693                 CDB[4] = io->size;
3694                 cmdTimeout = 10;
3695                 break;
3696
3697         case TEST_UNIT_READY:
3698                 cmdLen = 6;
3699                 dir = MPI_SCSIIO_CONTROL_READ;
3700                 cmdTimeout = 10;
3701                 break;
3702
3703         case START_STOP:
3704                 cmdLen = 6;
3705                 dir = MPI_SCSIIO_CONTROL_READ;
3706                 CDB[0] = cmd;
3707                 CDB[4] = 1;     /*Spin up the disk */
3708                 cmdTimeout = 15;
3709                 break;
3710
3711         case REQUEST_SENSE:
3712                 cmdLen = 6;
3713                 CDB[0] = cmd;
3714                 CDB[4] = io->size;
3715                 dir = MPI_SCSIIO_CONTROL_READ;
3716                 cmdTimeout = 10;
3717                 break;
3718
3719         case READ_BUFFER:
3720                 cmdLen = 10;
3721                 dir = MPI_SCSIIO_CONTROL_READ;
3722                 CDB[0] = cmd;
3723                 if (io->flags & MPT_ICFLAG_ECHO) {
3724                         CDB[1] = 0x0A;
3725                 } else {
3726                         CDB[1] = 0x02;
3727                 }
3728
3729                 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3730                         CDB[1] |= 0x01;
3731                 }
3732                 CDB[6] = (io->size >> 16) & 0xFF;
3733                 CDB[7] = (io->size >>  8) & 0xFF;
3734                 CDB[8] = io->size & 0xFF;
3735                 cmdTimeout = 10;
3736                 break;
3737
3738         case WRITE_BUFFER:
3739                 cmdLen = 10;
3740                 dir = MPI_SCSIIO_CONTROL_WRITE;
3741                 CDB[0] = cmd;
3742                 if (io->flags & MPT_ICFLAG_ECHO) {
3743                         CDB[1] = 0x0A;
3744                 } else {
3745                         CDB[1] = 0x02;
3746                 }
3747                 CDB[6] = (io->size >> 16) & 0xFF;
3748                 CDB[7] = (io->size >>  8) & 0xFF;
3749                 CDB[8] = io->size & 0xFF;
3750                 cmdTimeout = 10;
3751                 break;
3752
3753         case RESERVE:
3754                 cmdLen = 6;
3755                 dir = MPI_SCSIIO_CONTROL_READ;
3756                 CDB[0] = cmd;
3757                 cmdTimeout = 10;
3758                 break;
3759
3760         case RELEASE:
3761                 cmdLen = 6;
3762                 dir = MPI_SCSIIO_CONTROL_READ;
3763                 CDB[0] = cmd;
3764                 cmdTimeout = 10;
3765                 break;
3766
3767         case SYNCHRONIZE_CACHE:
3768                 cmdLen = 10;
3769                 dir = MPI_SCSIIO_CONTROL_READ;
3770                 CDB[0] = cmd;
3771 //              CDB[1] = 0x02;  /* set immediate bit */
3772                 cmdTimeout = 10;
3773                 break;
3774
3775         default:
3776                 /* Error Case */
3777                 return -EFAULT;
3778         }
3779
3780         /* Get and Populate a free Frame
3781          */
3782         if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3783                 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3784                                         hd->ioc->name));
3785                 return -EBUSY;
3786         }
3787
3788         pScsiReq = (SCSIIORequest_t *) mf;
3789
3790         /* Get the request index */
3791         my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3792         ADD_INDEX_LOG(my_idx); /* for debug */
3793
3794         if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3795                 pScsiReq->TargetID = io->physDiskNum;
3796                 pScsiReq->Bus = 0;
3797                 pScsiReq->ChainOffset = 0;
3798                 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3799         } else {
3800                 pScsiReq->TargetID = io->id;
3801                 pScsiReq->Bus = io->bus;
3802                 pScsiReq->ChainOffset = 0;
3803                 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3804         }
3805
3806         pScsiReq->CDBLength = cmdLen;
3807         pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3808
3809         pScsiReq->Reserved = 0;
3810
3811         pScsiReq->MsgFlags = mpt_msg_flags();
3812         /* MsgContext set in mpt_get_msg_fram call  */
3813
3814         for (ii=0; ii < 8; ii++)
3815                 pScsiReq->LUN[ii] = 0;
3816         pScsiReq->LUN[1] = io->lun;
3817
3818         if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3819                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3820         else
3821                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3822
3823         if (cmd == REQUEST_SENSE) {
3824                 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3825                 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3826                         hd->ioc->name, cmd));
3827         }
3828
3829         for (ii=0; ii < 16; ii++)
3830                 pScsiReq->CDB[ii] = CDB[ii];
3831
3832         pScsiReq->DataLength = cpu_to_le32(io->size);
3833         pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3834                                            + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3835
3836         ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3837                         hd->ioc->name, cmd, io->bus, io->id, io->lun));
3838
3839         if (dir == MPI_SCSIIO_CONTROL_READ) {
3840                 mpt_add_sge((char *) &pScsiReq->SGL,
3841                         MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3842                         io->data_dma);
3843         } else {
3844                 mpt_add_sge((char *) &pScsiReq->SGL,
3845                         MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3846                         io->data_dma);
3847         }
3848
3849         /* The ISR will free the request frame, but we need
3850          * the information to initialize the target. Duplicate.
3851          */
3852         memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3853
3854         /* Issue this command after:
3855          *      finish init
3856          *      add timer
3857          * Wait until the reply has been received
3858          *  ScsiScanDvCtx callback function will
3859          *      set hd->pLocal;
3860          *      set scandv_wait_done and call wake_up
3861          */
3862         hd->pLocal = NULL;
3863         hd->timer.expires = jiffies + HZ*cmdTimeout;
3864         hd->scandv_wait_done = 0;
3865
3866         /* Save cmd pointer, for resource free if timeout or
3867          * FW reload occurs
3868          */
3869         hd->cmdPtr = mf;
3870
3871         add_timer(&hd->timer);
3872         mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3873         wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3874
3875         if (hd->pLocal) {
3876                 rc = hd->pLocal->completion;
3877                 hd->pLocal->skip = 0;
3878
3879                 /* Always set fatal error codes in some cases.
3880                  */
3881                 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3882                         rc = -ENXIO;
3883                 else if (rc == MPT_SCANDV_SOME_ERROR)
3884                         rc =  -rc;
3885         } else {
3886                 rc = -EFAULT;
3887                 /* This should never happen. */
3888                 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3889                                 hd->ioc->name));
3890         }
3891
3892         return rc;
3893 }
3894
3895 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3896 /**
3897  *      mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3898  *      @hd: Pointer to MPT_SCSI_HOST structure
3899  *      @portnum: IOC port number
3900  *
3901  *      Uses the ISR, but with special processing.
3902  *      MUST be single-threaded.
3903  *
3904  *      Return: 0 on completion
3905  */
3906 static int
3907 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
3908 {
3909         MPT_ADAPTER             *ioc= hd->ioc;
3910         VirtDevice              *pTarget;
3911         SCSIDevicePage1_t       *pcfg1Data = NULL;
3912         INTERNAL_CMD             iocmd;
3913         CONFIGPARMS              cfg;
3914         dma_addr_t               cfg1_dma_addr = -1;
3915         ConfigPageHeader_t       header1;
3916         int                      bus = 0;
3917         int                      id = 0;
3918         int                      lun;
3919         int                      indexed_lun, lun_index;
3920         int                      hostId = ioc->pfacts[portnum].PortSCSIID;
3921         int                      max_id;
3922         int                      requested, configuration, data;
3923         int                      doConfig = 0;
3924         u8                       flags, factor;
3925
3926         max_id = ioc->sh->max_id - 1;
3927
3928         /* Following parameters will not change
3929          * in this routine.
3930          */
3931         iocmd.cmd = SYNCHRONIZE_CACHE;
3932         iocmd.flags = 0;
3933         iocmd.physDiskNum = -1;
3934         iocmd.data = NULL;
3935         iocmd.data_dma = -1;
3936         iocmd.size = 0;
3937         iocmd.rsvd = iocmd.rsvd2 = 0;
3938
3939         /* No SCSI hosts
3940          */
3941         if (hd->Targets == NULL)
3942                 return 0;
3943
3944         /* Skip the host
3945          */
3946         if (id == hostId)
3947                 id++;
3948
3949         /* Write SDP1 for all SCSI devices
3950          * Alloc memory and set up config buffer
3951          */
3952         if (ioc->bus_type == SCSI) {
3953                 if (ioc->spi_data.sdp1length > 0) {
3954                         pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
3955                                          ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
3956
3957                         if (pcfg1Data != NULL) {
3958                                 doConfig = 1;
3959                                 header1.PageVersion = ioc->spi_data.sdp1version;
3960                                 header1.PageLength = ioc->spi_data.sdp1length;
3961                                 header1.PageNumber = 1;
3962                                 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3963                                 cfg.hdr = &header1;
3964                                 cfg.physAddr = cfg1_dma_addr;
3965                                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3966                                 cfg.dir = 1;
3967                                 cfg.timeout = 0;
3968                         }
3969                 }
3970         }
3971
3972         /* loop through all devices on this port
3973          */
3974         while (bus < MPT_MAX_BUS) {
3975                 iocmd.bus = bus;
3976                 iocmd.id = id;
3977                 pTarget = hd->Targets[(int)id];
3978
3979                 if (doConfig) {
3980
3981                         /* Set the negotiation flags */
3982                         if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
3983                                 flags = pTarget->negoFlags;
3984                         } else {
3985                                 flags = hd->ioc->spi_data.noQas;
3986                                 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3987                                         data = hd->ioc->spi_data.nvram[id];
3988
3989                                         if (data & MPT_NVRAM_WIDE_DISABLE)
3990                                                 flags |= MPT_TARGET_NO_NEGO_WIDE;
3991
3992                                         factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
3993                                         if ((factor == 0) || (factor == MPT_ASYNC))
3994                                                 flags |= MPT_TARGET_NO_NEGO_SYNC;
3995                                 }
3996                         }
3997
3998                         /* Force to async, narrow */
3999                         mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
4000                                         &configuration, flags);
4001                         dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
4002                                 "offset=0 negoFlags=%x request=%x config=%x\n",
4003                                 id, flags, requested, configuration));
4004                         pcfg1Data->RequestedParameters = le32_to_cpu(requested);
4005                         pcfg1Data->Reserved = 0;
4006                         pcfg1Data->Configuration = le32_to_cpu(configuration);
4007                         cfg.pageAddr = (bus<<8) | id;
4008                         mpt_config(hd->ioc, &cfg);
4009                 }
4010
4011                 /* If target Ptr NULL or if this target is NOT a disk, skip.
4012                  */
4013                 if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
4014                         for (lun=0; lun <= MPT_LAST_LUN; lun++) {
4015                                 /* If LUN present, issue the command
4016                                  */
4017                                 lun_index = (lun >> 5);  /* 32 luns per lun_index */
4018                                 indexed_lun = (lun % 32);
4019                                 if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
4020                                         iocmd.lun = lun;
4021                                         (void) mptscsih_do_cmd(hd, &iocmd);
4022                                 }
4023                         }
4024                 }
4025
4026                 /* get next relevant device */
4027                 id++;
4028
4029                 if (id == hostId)
4030                         id++;
4031
4032                 if (id > max_id) {
4033                         id = 0;
4034                         bus++;
4035                 }
4036         }
4037
4038         if (pcfg1Data) {
4039                 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
4040         }
4041
4042         return 0;
4043 }
4044
4045 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4046 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4047 /**
4048  *      mptscsih_domainValidation - Top level handler for domain validation.
4049  *      @hd: Pointer to MPT_SCSI_HOST structure.
4050  *
4051  *      Uses the ISR, but with special processing.
4052  *      Called from schedule, should not be in interrupt mode.
4053  *      While thread alive, do dv for all devices needing dv
4054  *
4055  *      Return: None.
4056  */
4057 static void
4058 mptscsih_domainValidation(void *arg)
4059 {
4060         MPT_SCSI_HOST           *hd;
4061         MPT_ADAPTER             *ioc;
4062         unsigned long            flags;
4063         int                      id, maxid, dvStatus, did;
4064         int                      ii, isPhysDisk;
4065
4066         spin_lock_irqsave(&dvtaskQ_lock, flags);
4067         dvtaskQ_active = 1;
4068         if (dvtaskQ_release) {
4069                 dvtaskQ_active = 0;
4070                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4071                 return;
4072         }
4073         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4074
4075         /* For this ioc, loop through all devices and do dv to each device.
4076          * When complete with this ioc, search through the ioc list, and
4077          * for each scsi ioc found, do dv for all devices. Exit when no
4078          * device needs dv.
4079          */
4080         did = 1;
4081         while (did) {
4082                 did = 0;
4083                 list_for_each_entry(ioc, &ioc_list, list) {
4084                         spin_lock_irqsave(&dvtaskQ_lock, flags);
4085                         if (dvtaskQ_release) {
4086                                 dvtaskQ_active = 0;
4087                                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4088                                 return;
4089                         }
4090                         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4091
4092                         msleep(250);
4093
4094                         /* DV only to SCSI adapters */
4095                         if (ioc->bus_type != SCSI)
4096                                 continue;
4097
4098                         /* Make sure everything looks ok */
4099                         if (ioc->sh == NULL)
4100                                 continue;
4101
4102                         hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4103                         if (hd == NULL)
4104                                 continue;
4105
4106                         if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
4107                                 mpt_read_ioc_pg_3(ioc);
4108                                 if (ioc->spi_data.pIocPg3) {
4109                                         Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4110                                         int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4111
4112                                         while (numPDisk) {
4113                                                 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
4114                                                         ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4115
4116                                                 pPDisk++;
4117                                                 numPDisk--;
4118                                         }
4119                                 }
4120                                 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
4121                         }
4122
4123                         maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
4124
4125                         for (id = 0; id < maxid; id++) {
4126                                 spin_lock_irqsave(&dvtaskQ_lock, flags);
4127                                 if (dvtaskQ_release) {
4128                                         dvtaskQ_active = 0;
4129                                         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4130                                         return;
4131                                 }
4132                                 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4133                                 dvStatus = hd->ioc->spi_data.dvStatus[id];
4134
4135                                 if (dvStatus & MPT_SCSICFG_NEED_DV) {
4136                                         did++;
4137                                         hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
4138                                         hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
4139
4140                                         msleep(250);
4141
4142                                         /* If hidden phys disk, block IO's to all
4143                                          *      raid volumes
4144                                          * else, process normally
4145                                          */
4146                                         isPhysDisk = mptscsih_is_phys_disk(ioc, id);
4147                                         if (isPhysDisk) {
4148                                                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4149                                                         if (hd->ioc->spi_data.isRaid & (1 << ii)) {
4150                                                                 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
4151                                                         }
4152                                                 }
4153                                         }
4154
4155                                         if (mptscsih_doDv(hd, 0, id) == 1) {
4156                                                 /* Untagged device was busy, try again
4157                                                  */
4158                                                 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
4159                                                 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
4160                                         } else {
4161                                                 /* DV is complete. Clear flags.
4162                                                  */
4163                                                 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
4164                                         }
4165
4166                                         if (isPhysDisk) {
4167                                                 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4168                                                         if (hd->ioc->spi_data.isRaid & (1 << ii)) {
4169                                                                 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
4170                                                         }
4171                                                 }
4172                                         }
4173
4174                                         if (hd->ioc->spi_data.noQas)
4175                                                 mptscsih_qas_check(hd, id);
4176                                 }
4177                         }
4178                 }
4179         }
4180
4181         spin_lock_irqsave(&dvtaskQ_lock, flags);
4182         dvtaskQ_active = 0;
4183         spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4184
4185         return;
4186 }
4187
4188 /* Search IOC page 3 to determine if this is hidden physical disk
4189  */
4190 static int 
4191 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
4192 {
4193         if (ioc->spi_data.pIocPg3) {
4194                 Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
4195                 int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4196
4197                 while (numPDisk) {
4198                         if (pPDisk->PhysDiskID == id) {
4199                                 return 1;
4200                         }
4201                         pPDisk++;
4202                         numPDisk--;
4203                 }
4204         }
4205         return 0;
4206 }
4207
4208 /* Write SDP1 if no QAS has been enabled
4209  */
4210 static void
4211 mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
4212 {
4213         VirtDevice *pTarget;
4214         int ii;
4215
4216         if (hd->Targets == NULL)
4217                 return;
4218
4219         for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4220                 if (ii == id)
4221                         continue;
4222
4223                 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
4224                         continue;
4225
4226                 pTarget = hd->Targets[ii];
4227
4228                 if ((pTarget != NULL) && (!pTarget->raidVolume)) {
4229                         if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
4230                                 pTarget->negoFlags |= hd->ioc->spi_data.noQas;
4231                                 dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
4232                                 mptscsih_writeSDP1(hd, 0, ii, 0);
4233                         }
4234                 } else {
4235                         if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
4236                                 dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
4237                                 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
4238                         }
4239                 }
4240         }
4241         return;
4242 }
4243
4244
4245
4246 #define MPT_GET_NVRAM_VALS      0x01
4247 #define MPT_UPDATE_MAX          0x02
4248 #define MPT_SET_MAX             0x04
4249 #define MPT_SET_MIN             0x08
4250 #define MPT_FALLBACK            0x10
4251 #define MPT_SAVE                0x20
4252
4253 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4254 /**
4255  *      mptscsih_doDv - Perform domain validation to a target.
4256  *      @hd: Pointer to MPT_SCSI_HOST structure.
4257  *      @portnum: IOC port number.
4258  *      @target: Physical ID of this target
4259  *
4260  *      Uses the ISR, but with special processing.
4261  *      MUST be single-threaded.
4262  *      Test will exit if target is at async & narrow.
4263  *
4264  *      Return: None.
4265  */
4266 static int
4267 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
4268 {
4269         MPT_ADAPTER             *ioc = hd->ioc;
4270         VirtDevice              *pTarget;
4271         SCSIDevicePage1_t       *pcfg1Data;
4272         SCSIDevicePage0_t       *pcfg0Data;
4273         u8                      *pbuf1;
4274         u8                      *pbuf2;
4275         u8                      *pDvBuf;
4276         dma_addr_t               dvbuf_dma = -1;
4277         dma_addr_t               buf1_dma = -1;
4278         dma_addr_t               buf2_dma = -1;
4279         dma_addr_t               cfg1_dma_addr = -1;
4280         dma_addr_t               cfg0_dma_addr = -1;
4281         ConfigPageHeader_t       header1;
4282         ConfigPageHeader_t       header0;
4283         DVPARAMETERS             dv;
4284         INTERNAL_CMD             iocmd;
4285         CONFIGPARMS              cfg;
4286         int                      dv_alloc = 0;
4287         int                      rc, sz = 0;
4288         int                      bufsize = 0;
4289         int                      dataBufSize = 0;
4290         int                      echoBufSize = 0;
4291         int                      notDone;
4292         int                      patt;
4293         int                      repeat;
4294         int                      retcode = 0;
4295         int                      nfactor =  MPT_ULTRA320;
4296         char                     firstPass = 1;
4297         char                     doFallback = 0;
4298         char                     readPage0;
4299         char                     bus, lun;
4300         char                     inq0 = 0;
4301
4302         if (ioc->spi_data.sdp1length == 0)
4303                 return 0;
4304
4305         if (ioc->spi_data.sdp0length == 0)
4306                 return 0;
4307
4308         /* If multiple buses are used, require that the initiator
4309          * id be the same on all buses.
4310          */
4311         if (id == ioc->pfacts[0].PortSCSIID)
4312                 return 0;
4313
4314         lun = 0;
4315         bus = (u8) bus_number;
4316         ddvtprintk((MYIOC_s_NOTE_FMT
4317                         "DV started: bus=%d, id=%d dv @ %p\n",
4318                         ioc->name, bus, id, &dv));
4319
4320         /* Prep DV structure
4321          */
4322         memset (&dv, 0, sizeof(DVPARAMETERS));
4323         dv.id = id;
4324
4325         /* Populate tmax with the current maximum
4326          * transfer parameters for this target.
4327          * Exit if narrow and async.
4328          */
4329         dv.cmd = MPT_GET_NVRAM_VALS;
4330         mptscsih_dv_parms(hd, &dv, NULL);
4331
4332         /* Prep SCSI IO structure
4333          */
4334         iocmd.id = id;
4335         iocmd.bus = bus;
4336         iocmd.lun = lun;
4337         iocmd.flags = 0;
4338         iocmd.physDiskNum = -1;
4339         iocmd.rsvd = iocmd.rsvd2 = 0;
4340
4341         pTarget = hd->Targets[id];
4342
4343         /* Use tagged commands if possible.
4344          */
4345         if (pTarget) {
4346                 if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
4347                         iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
4348                 else {
4349                         if (hd->ioc->facts.FWVersion.Word < 0x01000600)
4350                                 return 0;
4351
4352                         if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4353                                 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
4354                                 return 0;
4355                 }
4356         }
4357
4358         /* Prep cfg structure
4359          */
4360         cfg.pageAddr = (bus<<8) | id;
4361         cfg.hdr = NULL;
4362
4363         /* Prep SDP0 header
4364          */
4365         header0.PageVersion = ioc->spi_data.sdp0version;
4366         header0.PageLength = ioc->spi_data.sdp0length;
4367         header0.PageNumber = 0;
4368         header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4369
4370         /* Prep SDP1 header
4371          */
4372         header1.PageVersion = ioc->spi_data.sdp1version;
4373         header1.PageLength = ioc->spi_data.sdp1length;
4374         header1.PageNumber = 1;
4375         header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4376
4377         if (header0.PageLength & 1)
4378                 dv_alloc = (header0.PageLength * 4) + 4;
4379
4380         dv_alloc +=  (2048 + (header1.PageLength * 4));
4381
4382         pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
4383         if (pDvBuf == NULL)
4384                 return 0;
4385
4386         sz = 0;
4387         pbuf1 = (u8 *)pDvBuf;
4388         buf1_dma = dvbuf_dma;
4389         sz +=1024;
4390
4391         pbuf2 = (u8 *) (pDvBuf + sz);
4392         buf2_dma = dvbuf_dma + sz;
4393         sz +=1024;
4394
4395         pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
4396         cfg0_dma_addr = dvbuf_dma + sz;
4397         sz += header0.PageLength * 4;
4398
4399         /* 8-byte alignment
4400          */
4401         if (header0.PageLength & 1)
4402                 sz += 4;
4403
4404         pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
4405         cfg1_dma_addr = dvbuf_dma + sz;
4406
4407         /* Skip this ID? Set cfg.hdr to force config page write
4408          */
4409         {
4410                 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
4411                 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4412                         /* Set the factor from nvram */
4413                         nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
4414                         if (nfactor < pspi_data->minSyncFactor )
4415                                 nfactor = pspi_data->minSyncFactor;
4416
4417                         if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
4418                                 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
4419
4420                                 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
4421                                         ioc->name, bus, id, lun));
4422
4423                                 dv.cmd = MPT_SET_MAX;
4424                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4425                                 cfg.hdr = &header1;
4426
4427                                 /* Save the final negotiated settings to
4428                                  * SCSI device page 1.
4429                                  */
4430                                 cfg.physAddr = cfg1_dma_addr;
4431                                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4432                                 cfg.dir = 1;
4433                                 mpt_config(hd->ioc, &cfg);
4434                                 goto target_done;
4435                         }
4436                 }
4437         }
4438
4439         /* Finish iocmd inititialization - hidden or visible disk? */
4440         if (ioc->spi_data.pIocPg3) {
4441                 /* Search IOC page 3 for matching id
4442                  */
4443                 Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
4444                 int             numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4445
4446                 while (numPDisk) {
4447                         if (pPDisk->PhysDiskID == id) {
4448                                 /* match */
4449                                 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
4450                                 iocmd.physDiskNum = pPDisk->PhysDiskNum;
4451
4452                                 /* Quiesce the IM
4453                                  */
4454                                 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
4455                                         ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
4456                                         goto target_done;
4457                                 }
4458                                 break;
4459                         }
4460                         pPDisk++;
4461                         numPDisk--;
4462                 }
4463         }
4464
4465         /* RAID Volume ID's may double for a physical device. If RAID but
4466          * not a physical ID as well, skip DV.
4467          */
4468         if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
4469                 goto target_done;
4470
4471
4472         /* Basic Test.
4473          * Async & Narrow - Inquiry
4474          * Async & Narrow - Inquiry
4475          * Maximum transfer rate - Inquiry
4476          * Compare buffers:
4477          *      If compare, test complete.
4478          *      If miscompare and first pass, repeat
4479          *      If miscompare and not first pass, fall back and repeat
4480          */
4481         hd->pLocal = NULL;
4482         readPage0 = 0;
4483         sz = SCSI_MAX_INQUIRY_BYTES;
4484         rc = MPT_SCANDV_GOOD;
4485         while (1) {
4486                 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
4487                 retcode = 0;
4488                 dv.cmd = MPT_SET_MIN;
4489                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4490
4491                 cfg.hdr = &header1;
4492                 cfg.physAddr = cfg1_dma_addr;
4493                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4494                 cfg.dir = 1;
4495                 if (mpt_config(hd->ioc, &cfg) != 0)
4496                         goto target_done;
4497
4498                 /* Wide - narrow - wide workaround case
4499                  */
4500                 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
4501                         /* Send an untagged command to reset disk Qs corrupted
4502                          * when a parity error occurs on a Request Sense.
4503                          */
4504                         if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
4505                                 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4506                                 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
4507
4508                                 iocmd.cmd = REQUEST_SENSE;
4509                                 iocmd.data_dma = buf1_dma;
4510                                 iocmd.data = pbuf1;
4511                                 iocmd.size = 0x12;
4512                                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4513                                         goto target_done;
4514                                 else {
4515                                         if (hd->pLocal == NULL)
4516                                                 goto target_done;
4517                                         rc = hd->pLocal->completion;
4518                                         if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
4519                                                 dv.max.width = 0;
4520                                                 doFallback = 0;
4521                                         } else
4522                                                 goto target_done;
4523                                 }
4524                         } else
4525                                 goto target_done;
4526                 }
4527
4528                 iocmd.cmd = INQUIRY;
4529                 iocmd.data_dma = buf1_dma;
4530                 iocmd.data = pbuf1;
4531                 iocmd.size = sz;
4532                 memset(pbuf1, 0x00, sz);
4533                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4534                         goto target_done;
4535                 else {
4536                         if (hd->pLocal == NULL)
4537                                 goto target_done;
4538                         rc = hd->pLocal->completion;
4539                         if (rc == MPT_SCANDV_GOOD) {
4540                                 if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
4541                                         if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
4542                                                 retcode = 1;
4543                                         else
4544                                                 retcode = 0;
4545
4546                                         goto target_done;
4547                                 }
4548                         } else if  (rc == MPT_SCANDV_SENSE) {
4549                                 ;
4550                         } else {
4551                                 /* If first command doesn't complete
4552                                  * with a good status or with a check condition,
4553                                  * exit.
4554                                  */
4555                                 goto target_done;
4556                         }
4557                 }
4558
4559                 /* Reset the size for disks
4560                  */
4561                 inq0 = (*pbuf1) & 0x1F;
4562                 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
4563                         sz = 0x40;
4564                         iocmd.size = sz;
4565                 }
4566
4567                 /* Another GEM workaround. Check peripheral device type,
4568                  * if PROCESSOR, quit DV.
4569                  */
4570                 if (inq0 == TYPE_PROCESSOR) {
4571                         mptscsih_initTarget(hd,
4572                                 bus,
4573                                 id,
4574                                 lun,
4575                                 pbuf1,
4576                                 sz);
4577                         goto target_done;
4578                 }
4579
4580                 if (inq0 > 0x08)
4581                         goto target_done;
4582
4583                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4584                         goto target_done;
4585
4586                 if (sz == 0x40) {
4587                         if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
4588                                 && (pTarget->minSyncFactor > 0x09)) {
4589                                 if ((pbuf1[56] & 0x04) == 0)
4590                                         ;
4591                                 else if ((pbuf1[56] & 0x01) == 1) {
4592                                         pTarget->minSyncFactor =
4593                                             nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
4594                                 } else {
4595                                         pTarget->minSyncFactor =
4596                                             nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
4597                                 }
4598
4599                                 dv.max.factor = pTarget->minSyncFactor;
4600
4601                                 if ((pbuf1[56] & 0x02) == 0) {
4602                                         pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4603                                         hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
4604                                         ddvprintk((MYIOC_s_NOTE_FMT 
4605                                             "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", 
4606                                             ioc->name, id, pbuf1[56]));
4607                                 }
4608                         }
4609                 }
4610
4611                 if (doFallback)
4612                         dv.cmd = MPT_FALLBACK;
4613                 else
4614                         dv.cmd = MPT_SET_MAX;
4615
4616                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4617                 if (mpt_config(hd->ioc, &cfg) != 0)
4618                         goto target_done;
4619
4620                 if ((!dv.now.width) && (!dv.now.offset))
4621                         goto target_done;
4622
4623                 iocmd.cmd = INQUIRY;
4624                 iocmd.data_dma = buf2_dma;
4625                 iocmd.data = pbuf2;
4626                 iocmd.size = sz;
4627                 memset(pbuf2, 0x00, sz);
4628                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4629                         goto target_done;
4630                 else if (hd->pLocal == NULL)
4631                         goto target_done;
4632                 else {
4633                         /* Save the return code.
4634                          * If this is the first pass,
4635                          * read SCSI Device Page 0
4636                          * and update the target max parameters.
4637                          */
4638                         rc = hd->pLocal->completion;
4639                         doFallback = 0;
4640                         if (rc == MPT_SCANDV_GOOD) {
4641                                 if (!readPage0) {
4642                                         u32 sdp0_info;
4643                                         u32 sdp0_nego;
4644
4645                                         cfg.hdr = &header0;
4646                                         cfg.physAddr = cfg0_dma_addr;
4647                                         cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4648                                         cfg.dir = 0;
4649
4650                                         if (mpt_config(hd->ioc, &cfg) != 0)
4651                                                 goto target_done;
4652
4653                                         sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
4654                                         sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
4655
4656                                         /* Quantum and Fujitsu workarounds.
4657                                          * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
4658                                          * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
4659                                          * Resetart with a request for U160.
4660                                          */
4661                                         if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
4662                                                         doFallback = 1;
4663                                         } else {
4664                                                 dv.cmd = MPT_UPDATE_MAX;
4665                                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
4666                                                 /* Update the SCSI device page 1 area
4667                                                  */
4668                                                 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
4669                                                 readPage0 = 1;
4670                                         }
4671                                 }
4672
4673                                 /* Quantum workaround. Restart this test will the fallback
4674                                  * flag set.
4675                                  */
4676                                 if (doFallback == 0) {
4677                                         if (memcmp(pbuf1, pbuf2, sz) != 0) {
4678                                                 if (!firstPass)
4679                                                         doFallback = 1;
4680                                         } else {
4681                                                 ddvprintk((MYIOC_s_NOTE_FMT 
4682                                                     "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
4683                                                 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
4684                                                 mptscsih_initTarget(hd,
4685                                                         bus,
4686                                                         id,
4687                                                         lun,
4688                                                         pbuf1,
4689                                                         sz);
4690                                                 break;  /* test complete */
4691                                         }
4692                                 }
4693
4694
4695                         } else if (rc == MPT_SCANDV_ISSUE_SENSE)
4696                                 doFallback = 1; /* set fallback flag */
4697                         else if ((rc == MPT_SCANDV_DID_RESET) || 
4698                                  (rc == MPT_SCANDV_SENSE) || 
4699                                  (rc == MPT_SCANDV_FALLBACK))
4700                                 doFallback = 1; /* set fallback flag */
4701                         else
4702                                 goto target_done;
4703
4704                         firstPass = 0;
4705                 }
4706         }
4707         ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
4708
4709         if (ioc->spi_data.mpt_dv == 0)
4710                 goto target_done;
4711
4712         inq0 = (*pbuf1) & 0x1F;
4713
4714         /* Continue only for disks
4715          */
4716         if (inq0 != 0)
4717                 goto target_done;
4718
4719         if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
4720                 goto target_done;
4721
4722         /* Start the Enhanced Test.
4723          * 0) issue TUR to clear out check conditions
4724          * 1) read capacity of echo (regular) buffer
4725          * 2) reserve device
4726          * 3) do write-read-compare data pattern test
4727          * 4) release
4728          * 5) update nego parms to target struct
4729          */
4730         cfg.hdr = &header1;
4731         cfg.physAddr = cfg1_dma_addr;
4732         cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4733         cfg.dir = 1;
4734
4735         iocmd.cmd = TEST_UNIT_READY;
4736         iocmd.data_dma = -1;
4737         iocmd.data = NULL;
4738         iocmd.size = 0;
4739         notDone = 1;
4740         while (notDone) {
4741                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4742                         goto target_done;
4743
4744                 if (hd->pLocal == NULL)
4745                         goto target_done;
4746
4747                 rc = hd->pLocal->completion;
4748                 if (rc == MPT_SCANDV_GOOD)
4749                         notDone = 0;
4750                 else if (rc == MPT_SCANDV_SENSE) {
4751                         u8 skey = hd->pLocal->sense[2] & 0x0F;
4752                         u8 asc = hd->pLocal->sense[12];
4753                         u8 ascq = hd->pLocal->sense[13];
4754                         ddvprintk((MYIOC_s_INFO_FMT
4755                                 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4756                                 ioc->name, skey, asc, ascq));
4757
4758                         if (skey == UNIT_ATTENTION)
4759                                 notDone++; /* repeat */
4760                         else if ((skey == NOT_READY) &&
4761                                         (asc == 0x04)&&(ascq == 0x01)) {
4762                                 /* wait then repeat */
4763                                 mdelay (2000);
4764                                 notDone++;
4765                         } else if ((skey == NOT_READY) && (asc == 0x3A)) {
4766                                 /* no medium, try read test anyway */
4767                                 notDone = 0;
4768                         } else {
4769                                 /* All other errors are fatal.
4770                                  */
4771                                 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4772                                                 ioc->name));
4773                                 goto target_done;
4774                         }
4775                 } else
4776                         goto target_done;
4777         }
4778
4779         iocmd.cmd = READ_BUFFER;
4780         iocmd.data_dma = buf1_dma;
4781         iocmd.data = pbuf1;
4782         iocmd.size = 4;
4783         iocmd.flags |= MPT_ICFLAG_BUF_CAP;
4784
4785         dataBufSize = 0;
4786         echoBufSize = 0;
4787         for (patt = 0; patt < 2; patt++) {
4788                 if (patt == 0)
4789                         iocmd.flags |= MPT_ICFLAG_ECHO;
4790                 else
4791                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
4792
4793                 notDone = 1;
4794                 while (notDone) {
4795                         bufsize = 0;
4796
4797                         /* If not ready after 8 trials,
4798                          * give up on this device.
4799                          */
4800                         if (notDone > 8)
4801                                 goto target_done;
4802
4803                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
4804                                 goto target_done;
4805                         else if (hd->pLocal == NULL)
4806                                 goto target_done;
4807                         else {
4808                                 rc = hd->pLocal->completion;
4809                                 ddvprintk(("ReadBuffer Comp Code %d", rc));
4810                                 ddvprintk(("  buff: %0x %0x %0x %0x\n",
4811                                         pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
4812
4813                                 if (rc == MPT_SCANDV_GOOD) {
4814                                         notDone = 0;
4815                                         if (iocmd.flags & MPT_ICFLAG_ECHO) {
4816                                                 bufsize =  ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
4817                                         } else {
4818                                                 bufsize =  pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
4819                                         }
4820                                 } else if (rc == MPT_SCANDV_SENSE) {
4821                                         u8 skey = hd->pLocal->sense[2] & 0x0F;
4822                                         u8 asc = hd->pLocal->sense[12];
4823                                         u8 ascq = hd->pLocal->sense[13];
4824                                         ddvprintk((MYIOC_s_INFO_FMT
4825                                                 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4826                                                 ioc->name, skey, asc, ascq));
4827                                         if (skey == ILLEGAL_REQUEST) {
4828                                                 notDone = 0;
4829                                         } else if (skey == UNIT_ATTENTION) {
4830                                                 notDone++; /* repeat */
4831                                         } else if ((skey == NOT_READY) &&
4832                                                 (asc == 0x04)&&(ascq == 0x01)) {
4833                                                 /* wait then repeat */
4834                                                 mdelay (2000);
4835                                                 notDone++;
4836                                         } else {
4837                                                 /* All other errors are fatal.
4838                                                  */
4839                                                 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4840                                                         ioc->name));
4841                                                 goto target_done;
4842                                         }
4843                                 } else {
4844                                         /* All other errors are fatal
4845                                          */
4846                                         goto target_done;
4847                                 }
4848                         }
4849                 }
4850
4851                 if (iocmd.flags & MPT_ICFLAG_ECHO)
4852                         echoBufSize = bufsize;
4853                 else
4854                         dataBufSize = bufsize;
4855         }
4856         sz = 0;
4857         iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
4858
4859         /* Use echo buffers if possible,
4860          * Exit if both buffers are 0.
4861          */
4862         if (echoBufSize > 0) {
4863                 iocmd.flags |= MPT_ICFLAG_ECHO;
4864                 if (dataBufSize > 0)
4865                         bufsize = min(echoBufSize, dataBufSize);
4866                 else
4867                         bufsize = echoBufSize;
4868         } else if (dataBufSize == 0)
4869                 goto target_done;
4870
4871         ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
4872                 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
4873
4874         /* Data buffers for write-read-compare test max 1K.
4875          */
4876         sz = min(bufsize, 1024);
4877
4878         /* --- loop ----
4879          * On first pass, always issue a reserve.
4880          * On additional loops, only if a reset has occurred.
4881          * iocmd.flags indicates if echo or regular buffer
4882          */
4883         for (patt = 0; patt < 4; patt++) {
4884                 ddvprintk(("Pattern %d\n", patt));
4885                 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
4886                         iocmd.cmd = TEST_UNIT_READY;
4887                         iocmd.data_dma = -1;
4888                         iocmd.data = NULL;
4889                         iocmd.size = 0;
4890                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
4891                                 goto target_done;
4892
4893                         iocmd.cmd = RELEASE;
4894                         iocmd.data_dma = -1;
4895                         iocmd.data = NULL;
4896                         iocmd.size = 0;
4897                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
4898                                 goto target_done;
4899                         else if (hd->pLocal == NULL)
4900                                 goto target_done;
4901                         else {
4902                                 rc = hd->pLocal->completion;
4903                                 ddvprintk(("Release rc %d\n", rc));
4904                                 if (rc == MPT_SCANDV_GOOD)
4905                                         iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4906                                 else
4907                                         goto target_done;
4908                         }
4909                         iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4910                 }
4911                 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
4912
4913                 repeat = 5;
4914                 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
4915                         iocmd.cmd = RESERVE;
4916                         iocmd.data_dma = -1;
4917                         iocmd.data = NULL;
4918                         iocmd.size = 0;
4919                         if (mptscsih_do_cmd(hd, &iocmd) < 0)
4920                                 goto target_done;
4921                         else if (hd->pLocal == NULL)
4922                                 goto target_done;
4923                         else {
4924                                 rc = hd->pLocal->completion;
4925                                 if (rc == MPT_SCANDV_GOOD) {
4926                                         iocmd.flags |= MPT_ICFLAG_RESERVED;
4927                                 } else if (rc == MPT_SCANDV_SENSE) {
4928                                         /* Wait if coming ready
4929                                          */
4930                                         u8 skey = hd->pLocal->sense[2] & 0x0F;
4931                                         u8 asc = hd->pLocal->sense[12];
4932                                         u8 ascq = hd->pLocal->sense[13];
4933                                         ddvprintk((MYIOC_s_INFO_FMT
4934                                                 "DV: Reserve Failed: ", ioc->name));
4935                                         ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4936                                                         skey, asc, ascq));
4937
4938                                         if ((skey == NOT_READY) && (asc == 0x04)&&
4939                                                                         (ascq == 0x01)) {
4940                                                 /* wait then repeat */
4941                                                 mdelay (2000);
4942                                                 notDone++;
4943                                         } else {
4944                                                 ddvprintk((MYIOC_s_INFO_FMT
4945                                                         "DV: Reserved Failed.", ioc->name));
4946                                                 goto target_done;
4947                                         }
4948                                 } else {
4949                                         ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
4950                                                          ioc->name));
4951                                         goto target_done;
4952                                 }
4953                         }
4954                 }
4955
4956                 mptscsih_fillbuf(pbuf1, sz, patt, 1);
4957                 iocmd.cmd = WRITE_BUFFER;
4958                 iocmd.data_dma = buf1_dma;
4959                 iocmd.data = pbuf1;
4960                 iocmd.size = sz;
4961                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4962                         goto target_done;
4963                 else if (hd->pLocal == NULL)
4964                         goto target_done;
4965                 else {
4966                         rc = hd->pLocal->completion;
4967                         if (rc == MPT_SCANDV_GOOD)
4968                                 ;               /* Issue read buffer */
4969                         else if (rc == MPT_SCANDV_DID_RESET) {
4970                                 /* If using echo buffers, reset to data buffers.
4971                                  * Else do Fallback and restart
4972                                  * this test (re-issue reserve
4973                                  * because of bus reset).
4974                                  */
4975                                 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
4976                                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
4977                                 } else {
4978                                         dv.cmd = MPT_FALLBACK;
4979                                         mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4980
4981                                         if (mpt_config(hd->ioc, &cfg) != 0)
4982                                                 goto target_done;
4983
4984                                         if ((!dv.now.width) && (!dv.now.offset))
4985                                                 goto target_done;
4986                                 }
4987
4988                                 iocmd.flags |= MPT_ICFLAG_DID_RESET;
4989                                 patt = -1;
4990                                 continue;
4991                         } else if (rc == MPT_SCANDV_SENSE) {
4992                                 /* Restart data test if UA, else quit.
4993                                  */
4994                                 u8 skey = hd->pLocal->sense[2] & 0x0F;
4995                                 ddvprintk((MYIOC_s_INFO_FMT
4996                                         "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
4997                                         hd->pLocal->sense[12], hd->pLocal->sense[13]));
4998                                 if (skey == UNIT_ATTENTION) {
4999                                         patt = -1;
5000                                         continue;
5001                                 } else if (skey == ILLEGAL_REQUEST) {
5002                                         if (iocmd.flags & MPT_ICFLAG_ECHO) {
5003                                                 if (dataBufSize >= bufsize) {
5004                                                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
5005                                                         patt = -1;
5006                                                         continue;
5007                                                 }
5008                                         }
5009                                         goto target_done;
5010                                 }
5011                                 else
5012                                         goto target_done;
5013                         } else {
5014                                 /* fatal error */
5015                                 goto target_done;
5016                         }
5017                 }
5018
5019                 iocmd.cmd = READ_BUFFER;
5020                 iocmd.data_dma = buf2_dma;
5021                 iocmd.data = pbuf2;
5022                 iocmd.size = sz;
5023                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5024                         goto target_done;
5025                 else if (hd->pLocal == NULL)
5026                         goto target_done;
5027                 else {
5028                         rc = hd->pLocal->completion;
5029                         if (rc == MPT_SCANDV_GOOD) {
5030                                  /* If buffers compare,
5031                                   * go to next pattern,
5032                                   * else, do a fallback and restart
5033                                   * data transfer test.
5034                                   */
5035                                 if (memcmp (pbuf1, pbuf2, sz) == 0) {
5036                                         ; /* goto next pattern */
5037                                 } else {
5038                                         /* Miscompare with Echo buffer, go to data buffer,
5039                                          * if that buffer exists.
5040                                          * Miscompare with Data buffer, check first 4 bytes,
5041                                          * some devices return capacity. Exit in this case.
5042                                          */
5043                                         if (iocmd.flags & MPT_ICFLAG_ECHO) {
5044                                                 if (dataBufSize >= bufsize)
5045                                                         iocmd.flags &= ~MPT_ICFLAG_ECHO;
5046                                                 else
5047                                                         goto target_done;
5048                                         } else {
5049                                                 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
5050                                                         /* Argh. Device returning wrong data.
5051                                                          * Quit DV for this device.
5052                                                          */
5053                                                         goto target_done;
5054                                                 }
5055
5056                                                 /* Had an actual miscompare. Slow down.*/
5057                                                 dv.cmd = MPT_FALLBACK;
5058                                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5059
5060                                                 if (mpt_config(hd->ioc, &cfg) != 0)
5061                                                         goto target_done;
5062
5063                                                 if ((!dv.now.width) && (!dv.now.offset))
5064                                                         goto target_done;
5065                                         }
5066
5067                                         patt = -1;
5068                                         continue;
5069                                 }
5070                         } else if (rc == MPT_SCANDV_DID_RESET) {
5071                                 /* Do Fallback and restart
5072                                  * this test (re-issue reserve
5073                                  * because of bus reset).
5074                                  */
5075                                 dv.cmd = MPT_FALLBACK;
5076                                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5077
5078                                 if (mpt_config(hd->ioc, &cfg) != 0)
5079                                          goto target_done;
5080
5081                                 if ((!dv.now.width) && (!dv.now.offset))
5082                                         goto target_done;
5083
5084                                 iocmd.flags |= MPT_ICFLAG_DID_RESET;
5085                                 patt = -1;
5086                                 continue;
5087                         } else if (rc == MPT_SCANDV_SENSE) {
5088                                 /* Restart data test if UA, else quit.
5089                                  */
5090                                 u8 skey = hd->pLocal->sense[2] & 0x0F;
5091                                 ddvprintk((MYIOC_s_INFO_FMT
5092                                         "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
5093                                         hd->pLocal->sense[12], hd->pLocal->sense[13]));
5094                                 if (skey == UNIT_ATTENTION) {
5095                                         patt = -1;
5096                                         continue;
5097                                 }
5098                                 else
5099                                         goto target_done;
5100                         } else {
5101                                 /* fatal error */
5102                                 goto target_done;
5103                         }
5104                 }
5105
5106         } /* --- end of patt loop ---- */
5107
5108 target_done:
5109         if (iocmd.flags & MPT_ICFLAG_RESERVED) {
5110                 iocmd.cmd = RELEASE;
5111                 iocmd.data_dma = -1;
5112                 iocmd.data = NULL;
5113                 iocmd.size = 0;
5114                 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5115                         printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5116                                         ioc->name, id);
5117                 else if (hd->pLocal) {
5118                         if (hd->pLocal->completion == MPT_SCANDV_GOOD)
5119                                 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
5120                 } else {
5121                         printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5122                                                 ioc->name, id);
5123                 }
5124         }
5125
5126
5127         /* Set if cfg1_dma_addr contents is valid
5128          */
5129         if ((cfg.hdr != NULL) && (retcode == 0)){
5130                 /* If disk, not U320, disable QAS
5131                  */
5132                 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
5133                         hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
5134                         ddvprintk((MYIOC_s_NOTE_FMT 
5135                             "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
5136                 }
5137
5138                 dv.cmd = MPT_SAVE;
5139                 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5140
5141                 /* Double writes to SDP1 can cause problems,
5142                  * skip save of the final negotiated settings to
5143                  * SCSI device page 1.
5144                  *
5145                 cfg.hdr = &header1;
5146                 cfg.physAddr = cfg1_dma_addr;
5147                 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5148                 cfg.dir = 1;
5149                 mpt_config(hd->ioc, &cfg);
5150                  */
5151         }
5152
5153         /* If this is a RAID Passthrough, enable internal IOs
5154          */
5155         if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
5156                 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
5157                         ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
5158         }
5159
5160         /* Done with the DV scan of the current target
5161          */
5162         if (pDvBuf)
5163                 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
5164
5165         ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
5166                         ioc->name, id));
5167
5168         return retcode;
5169 }
5170
5171 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5172 /*      mptscsih_dv_parms - perform a variety of operations on the
5173  *      parameters used for negotiation.
5174  *      @hd: Pointer to a SCSI host.
5175  *      @dv: Pointer to a structure that contains the maximum and current
5176  *              negotiated parameters.
5177  */
5178 static void
5179 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
5180 {
5181         VirtDevice              *pTarget;
5182         SCSIDevicePage0_t       *pPage0;
5183         SCSIDevicePage1_t       *pPage1;
5184         int                     val = 0, data, configuration;
5185         u8                      width = 0;
5186         u8                      offset = 0;
5187         u8                      factor = 0;
5188         u8                      negoFlags = 0;
5189         u8                      cmd = dv->cmd;
5190         u8                      id = dv->id;
5191
5192         switch (cmd) {
5193         case MPT_GET_NVRAM_VALS:
5194                 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
5195                                                          hd->ioc->name));
5196                 /* Get the NVRAM values and save in tmax
5197                  * If not an LVD bus, the adapter minSyncFactor has been
5198                  * already throttled back.
5199                  */
5200                 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
5201                         width = pTarget->maxWidth;
5202                         offset = pTarget->maxOffset;
5203                         factor = pTarget->minSyncFactor;
5204                         negoFlags = pTarget->negoFlags;
5205                 } else {
5206                         if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5207                                 data = hd->ioc->spi_data.nvram[id];
5208                                 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
5209                                 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
5210                                         factor = MPT_ASYNC;
5211                                 else {
5212                                         factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5213                                         if ((factor == 0) || (factor == MPT_ASYNC)){
5214                                                 factor = MPT_ASYNC;
5215                                                 offset = 0;
5216                                         }
5217                                 }
5218                         } else {
5219                                 width = MPT_NARROW;
5220                                 offset = 0;
5221                                 factor = MPT_ASYNC;
5222                         }
5223
5224                         /* Set the negotiation flags */
5225                         negoFlags = hd->ioc->spi_data.noQas;
5226                         if (!width)
5227                                 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5228
5229                         if (!offset)
5230                                 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
5231                 }
5232
5233                 /* limit by adapter capabilities */
5234                 width = min(width, hd->ioc->spi_data.maxBusWidth);
5235                 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
5236                 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
5237
5238                 /* Check Consistency */
5239                 if (offset && (factor < MPT_ULTRA2) && !width)
5240                         factor = MPT_ULTRA2;
5241
5242                 dv->max.width = width;
5243                 dv->max.offset = offset;
5244                 dv->max.factor = factor;
5245                 dv->max.flags = negoFlags;
5246                 ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
5247                                 id, width, factor, offset, negoFlags));
5248                 break;
5249
5250         case MPT_UPDATE_MAX:
5251                 ddvprintk((MYIOC_s_NOTE_FMT
5252                         "Updating with SDP0 Data: ", hd->ioc->name));
5253                 /* Update tmax values with those from Device Page 0.*/
5254                 pPage0 = (SCSIDevicePage0_t *) pPage;
5255                 if (pPage0) {
5256                         val = cpu_to_le32(pPage0->NegotiatedParameters);
5257                         dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
5258                         dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
5259                         dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
5260                 }
5261
5262                 dv->now.width = dv->max.width;
5263                 dv->now.offset = dv->max.offset;
5264                 dv->now.factor = dv->max.factor;
5265                 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
5266                                 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5267                 break;
5268
5269         case MPT_SET_MAX:
5270                 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
5271                                                                 hd->ioc->name));
5272                 /* Set current to the max values. Update the config page.*/
5273                 dv->now.width = dv->max.width;
5274                 dv->now.offset = dv->max.offset;
5275                 dv->now.factor = dv->max.factor;
5276                 dv->now.flags = dv->max.flags;
5277
5278                 pPage1 = (SCSIDevicePage1_t *)pPage;
5279                 if (pPage1) {
5280                         mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
5281                                 dv->now.offset, &val, &configuration, dv->now.flags);
5282                         dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5283                                 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5284                         pPage1->RequestedParameters = le32_to_cpu(val);
5285                         pPage1->Reserved = 0;
5286                         pPage1->Configuration = le32_to_cpu(configuration);
5287                 }
5288
5289                 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
5290                                 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5291                 break;
5292
5293         case MPT_SET_MIN:
5294                 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
5295                                                                 hd->ioc->name));
5296                 /* Set page to asynchronous and narrow
5297                  * Do not update now, breaks fallback routine. */
5298                 width = MPT_NARROW;
5299                 offset = 0;
5300                 factor = MPT_ASYNC;
5301                 negoFlags = dv->max.flags;
5302
5303                 pPage1 = (SCSIDevicePage1_t *)pPage;
5304                 if (pPage1) {
5305                         mptscsih_setDevicePage1Flags (width, factor,
5306                                 offset, &val, &configuration, negoFlags);
5307                         dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5308                                 id, width, factor, offset, negoFlags, val, configuration));
5309                         pPage1->RequestedParameters = le32_to_cpu(val);
5310                         pPage1->Reserved = 0;
5311                         pPage1->Configuration = le32_to_cpu(configuration);
5312                 }
5313                 ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
5314                                 id, width, factor, offset, val, configuration, negoFlags));
5315                 break;
5316
5317         case MPT_FALLBACK:
5318                 ddvprintk((MYIOC_s_NOTE_FMT
5319                         "Fallback: Start: offset %d, factor %x, width %d \n",
5320                                 hd->ioc->name, dv->now.offset,
5321                                 dv->now.factor, dv->now.width));
5322                 width = dv->now.width;
5323                 offset = dv->now.offset;
5324                 factor = dv->now.factor;
5325                 if ((offset) && (dv->max.width)) {
5326                         if (factor < MPT_ULTRA160)
5327                                 factor = MPT_ULTRA160;
5328                         else if (factor < MPT_ULTRA2) {
5329                                 factor = MPT_ULTRA2;
5330                                 width = MPT_WIDE;
5331                         } else if ((factor == MPT_ULTRA2) && width) {
5332                                 factor = MPT_ULTRA2;
5333                                 width = MPT_NARROW;
5334                         } else if (factor < MPT_ULTRA) {
5335                                 factor = MPT_ULTRA;
5336                                 width = MPT_WIDE;
5337                         } else if ((factor == MPT_ULTRA) && width) {
5338                                 width = MPT_NARROW;
5339                         } else if (factor < MPT_FAST) {
5340                                 factor = MPT_FAST;
5341                                 width = MPT_WIDE;
5342                         } else if ((factor == MPT_FAST) && width) {
5343                                 factor = MPT_FAST;
5344                                 width = MPT_NARROW;
5345                         } else if (factor < MPT_SCSI) {
5346                                 factor = MPT_SCSI;
5347                                 width = MPT_WIDE;
5348                         } else if ((factor == MPT_SCSI) && width) {
5349                                 factor = MPT_SCSI;
5350                                 width = MPT_NARROW;
5351                         } else {
5352                                 factor = MPT_ASYNC;
5353                                 offset = 0;
5354                         }
5355
5356                 } else if (offset) {
5357                         width = MPT_NARROW;
5358                         if (factor < MPT_ULTRA)
5359                                 factor = MPT_ULTRA;
5360                         else if (factor < MPT_FAST)
5361                                 factor = MPT_FAST;
5362                         else if (factor < MPT_SCSI)
5363                                 factor = MPT_SCSI;
5364                         else {
5365                                 factor = MPT_ASYNC;
5366                                 offset = 0;
5367                         }
5368
5369                 } else {
5370                         width = MPT_NARROW;
5371                         factor = MPT_ASYNC;
5372                 }
5373                 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
5374                 dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
5375
5376                 dv->now.width = width;
5377                 dv->now.offset = offset;
5378                 dv->now.factor = factor;
5379                 dv->now.flags = dv->max.flags;
5380
5381                 pPage1 = (SCSIDevicePage1_t *)pPage;
5382                 if (pPage1) {
5383                         mptscsih_setDevicePage1Flags (width, factor, offset, &val,
5384                                                 &configuration, dv->now.flags);
5385                         dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
5386                              id, width, offset, factor, dv->now.flags, val, configuration));
5387
5388                         pPage1->RequestedParameters = le32_to_cpu(val);
5389                         pPage1->Reserved = 0;
5390                         pPage1->Configuration = le32_to_cpu(configuration);
5391                 }
5392
5393                 ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
5394                              id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
5395                 break;
5396
5397         case MPT_SAVE:
5398                 ddvprintk((MYIOC_s_NOTE_FMT
5399                         "Saving to Target structure: ", hd->ioc->name));
5400                 ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
5401                              id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5402
5403                 /* Save these values to target structures
5404                  * or overwrite nvram (phys disks only).
5405                  */
5406
5407                 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
5408                         pTarget->maxWidth = dv->now.width;
5409                         pTarget->maxOffset = dv->now.offset;
5410                         pTarget->minSyncFactor = dv->now.factor;
5411                         pTarget->negoFlags = dv->now.flags;
5412                 } else {
5413                         /* Preserv all flags, use
5414                          * read-modify-write algorithm
5415                          */
5416                         if (hd->ioc->spi_data.nvram) {
5417                                 data = hd->ioc->spi_data.nvram[id];
5418
5419                                 if (dv->now.width)
5420                                         data &= ~MPT_NVRAM_WIDE_DISABLE;
5421                                 else
5422                                         data |= MPT_NVRAM_WIDE_DISABLE;
5423
5424                                 if (!dv->now.offset)
5425                                         factor = MPT_ASYNC;
5426
5427                                 data &= ~MPT_NVRAM_SYNC_MASK;
5428                                 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
5429
5430                                 hd->ioc->spi_data.nvram[id] = data;
5431                         }
5432                 }
5433                 break;
5434         }
5435 }
5436
5437 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5438 /*      mptscsih_fillbuf - fill a buffer with a special data pattern
5439  *              cleanup. For bus scan only.
5440  *
5441  *      @buffer: Pointer to data buffer to be filled.
5442  *      @size: Number of bytes to fill
5443  *      @index: Pattern index
5444  *      @width: bus width, 0 (8 bits) or 1 (16 bits)
5445  */
5446 static void
5447 mptscsih_fillbuf(char *buffer, int size, int index, int width)
5448 {
5449         char *ptr = buffer;
5450         int ii;
5451         char byte;
5452         short val;
5453
5454         switch (index) {
5455         case 0:
5456
5457                 if (width) {
5458                         /* Pattern:  0000 FFFF 0000 FFFF
5459                          */
5460                         for (ii=0; ii < size; ii++, ptr++) {
5461                                 if (ii & 0x02)
5462                                         *ptr = 0xFF;
5463                                 else
5464                                         *ptr = 0x00;
5465                         }
5466                 } else {
5467                         /* Pattern:  00 FF 00 FF
5468                          */
5469                         for (ii=0; ii < size; ii++, ptr++) {
5470                                 if (ii & 0x01)
5471                                         *ptr = 0xFF;
5472                                 else
5473                                         *ptr = 0x00;
5474                         }
5475                 }
5476                 break;
5477
5478         case 1:
5479                 if (width) {
5480                         /* Pattern:  5555 AAAA 5555 AAAA 5555
5481                          */
5482                         for (ii=0; ii < size; ii++, ptr++) {
5483                                 if (ii & 0x02)
5484                                         *ptr = 0xAA;
5485                                 else
5486                                         *ptr = 0x55;
5487                         }
5488                 } else {
5489                         /* Pattern:  55 AA 55 AA 55
5490                          */
5491                         for (ii=0; ii < size; ii++, ptr++) {
5492                                 if (ii & 0x01)
5493                                         *ptr = 0xAA;
5494                                 else
5495                                         *ptr = 0x55;
5496                         }
5497                 }
5498                 break;
5499
5500         case 2:
5501                 /* Pattern:  00 01 02 03 04 05
5502                  * ... FE FF 00 01..
5503                  */
5504                 for (ii=0; ii < size; ii++, ptr++)
5505                         *ptr = (char) ii;
5506                 break;
5507
5508         case 3:
5509                 if (width) {
5510                         /* Wide Pattern:  FFFE 0001 FFFD 0002
5511                          * ...  4000 DFFF 8000 EFFF
5512                          */
5513                         byte = 0;
5514                         for (ii=0; ii < size/2; ii++) {
5515                                 /* Create the base pattern
5516                                  */
5517                                 val = (1 << byte);
5518                                 /* every 64 (0x40) bytes flip the pattern
5519                                  * since we fill 2 bytes / iteration,
5520                                  * test for ii = 0x20
5521                                  */
5522                                 if (ii & 0x20)
5523                                         val = ~(val);
5524
5525                                 if (ii & 0x01) {
5526                                         *ptr = (char)( (val & 0xFF00) >> 8);
5527                                         ptr++;
5528                                         *ptr = (char)(val & 0xFF);
5529                                         byte++;
5530                                         byte &= 0x0F;
5531                                 } else {
5532                                         val = ~val;
5533                                         *ptr = (char)( (val & 0xFF00) >> 8);
5534                                         ptr++;
5535                                         *ptr = (char)(val & 0xFF);
5536                                 }
5537
5538                                 ptr++;
5539                         }
5540                 } else {
5541                         /* Narrow Pattern:  FE 01 FD 02 FB 04
5542                          * .. 7F 80 01 FE 02 FD ...  80 7F
5543                          */
5544                         byte = 0;
5545                         for (ii=0; ii < size; ii++, ptr++) {
5546                                 /* Base pattern - first 32 bytes
5547                                  */
5548                                 if (ii & 0x01) {
5549                                         *ptr = (1 << byte);
5550                                         byte++;
5551                                         byte &= 0x07;
5552                                 } else {
5553                                         *ptr = (char) (~(1 << byte));
5554                                 }
5555
5556                                 /* Flip the pattern every 32 bytes
5557                                  */
5558                                 if (ii & 0x20)
5559                                         *ptr = ~(*ptr);
5560                         }
5561                 }
5562                 break;
5563         }
5564 }
5565 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5566
5567 EXPORT_SYMBOL(mptscsih_remove);
5568 EXPORT_SYMBOL(mptscsih_shutdown);
5569 #ifdef CONFIG_PM
5570 EXPORT_SYMBOL(mptscsih_suspend);
5571 EXPORT_SYMBOL(mptscsih_resume);
5572 #endif
5573 EXPORT_SYMBOL(mptscsih_proc_info);
5574 EXPORT_SYMBOL(mptscsih_info);
5575 EXPORT_SYMBOL(mptscsih_qcmd);
5576 EXPORT_SYMBOL(mptscsih_slave_alloc);
5577 EXPORT_SYMBOL(mptscsih_slave_destroy);
5578 EXPORT_SYMBOL(mptscsih_slave_configure);
5579 EXPORT_SYMBOL(mptscsih_abort);
5580 EXPORT_SYMBOL(mptscsih_dev_reset);
5581 EXPORT_SYMBOL(mptscsih_bus_reset);
5582 EXPORT_SYMBOL(mptscsih_host_reset);
5583 EXPORT_SYMBOL(mptscsih_bios_param);
5584 EXPORT_SYMBOL(mptscsih_io_done);
5585 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
5586 EXPORT_SYMBOL(mptscsih_scandv_complete);
5587 EXPORT_SYMBOL(mptscsih_event_process);
5588 EXPORT_SYMBOL(mptscsih_ioc_reset);
5589 EXPORT_SYMBOL(mptscsih_store_queue_depth);
5590 EXPORT_SYMBOL(mptscsih_timer_expired);
5591
5592 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/