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