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