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