[SCSI] mptfusion: mptscsih Split driver support
[usb.git] / drivers / message / fusion / mptscsih.c
blobcf058a399dab6e558277ad52d6bd3bafef0515d1
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.
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
9 */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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.
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.
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
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
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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>
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>
66 #include "mptbase.h"
67 #include "mptscsih.h"
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME "Fusion MPT SCSI Host driver"
71 #define my_VERSION MPT_LINUX_VERSION_COMMON
72 #define MYNAM "mptscsih"
74 MODULE_AUTHOR(MODULEAUTHOR);
75 MODULE_DESCRIPTION(my_NAME);
76 MODULE_LICENSE("GPL");
78 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
80 typedef struct _BIG_SENSE_BUF {
81 u8 data[MPT_SENSE_BUFFER_ALLOC];
82 } BIG_SENSE_BUF;
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)
92 #define MPT_SCANDV_MAX_RETRIES (10)
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 */
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;
115 typedef struct _negoparms {
116 u8 width;
117 u8 offset;
118 u8 factor;
119 u8 flags;
120 } NEGOPARMS;
122 typedef struct _dv_parameters {
123 NEGOPARMS max;
124 NEGOPARMS now;
125 u8 cmd;
126 u8 id;
127 u16 pad1;
128 } DVPARAMETERS;
131 * Other private/forward protos...
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);
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);
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);
148 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
149 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
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);
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
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
179 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
181 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
183 * Domain Validation task structure
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
191 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
198 * This routine places a MPT request frame back on the MPT adapter's
199 * FreeQ.
201 static inline void
202 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
204 if (sizeof(dma_addr_t) == sizeof(u64)) {
205 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
206 u32 tmp = dma_addr & 0xFFFFFFFF;
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);
213 } else {
214 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
215 pSge->FlagsLength = cpu_to_le32(flagslength);
216 pSge->Address = cpu_to_le32(dma_addr);
218 } /* mptscsih_add_sge() */
220 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
228 * This routine places a MPT request frame back on the MPT adapter's
229 * FreeQ.
231 static inline void
232 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
234 if (sizeof(dma_addr_t) == sizeof(u64)) {
235 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
236 u32 tmp = dma_addr & 0xFFFFFFFF;
238 pChain->Length = cpu_to_le16(length);
239 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
241 pChain->NextChainOffset = next;
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);
253 } /* mptscsih_add_chain() */
255 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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)
262 * return SUCCESS or FAILED
264 static inline int
265 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
267 MPT_FRAME_HDR *chainBuf;
268 unsigned long flags;
269 int rc;
270 int chain_idx;
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;
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));
292 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
294 *retIndex = chain_idx;
295 return rc;
296 } /* mptscsih_getFreeChainBuffer() */
298 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
306 * Returns ...
308 static int
309 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
310 SCSIIORequest_t *pReq, int req_idx)
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;
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;
334 psge = (char *) &pReq->SGL;
335 frm_sz = ioc->req_sz;
337 /* Map the data portion, if any.
338 * sges_left = 0 if no data transfer.
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);
358 return SUCCESS;
361 /* Handle the SG case.
363 sg = (struct scatterlist *) SCpnt->request_buffer;
364 sg_done = 0;
365 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
366 chainSge = NULL;
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)
374 nextSGEset:
375 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
376 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
378 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
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
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;
392 v2 = sg_dma_address(sg);
393 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
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++;
401 if (numSgeThisFrame == sges_left) {
402 /* Add last element, end of buffer and end of list flags.
404 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
405 MPT_SGE_FLAGS_END_OF_BUFFER |
406 MPT_SGE_FLAGS_END_OF_LIST;
408 /* Add last SGE and set termination flags.
409 * Note: Last SGE may have a length of 0 - which should be ok.
411 thisxfer = sg_dma_len(sg);
413 v2 = sg_dma_address(sg);
414 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
416 sg++;
417 psge += (sizeof(u32) + sizeof(dma_addr_t));
419 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
420 sg_done++;
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.
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.
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;
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.
451 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
452 ioc->name, sg_done));
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).
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);
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.
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.
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;
488 sges_left -= sg_done;
491 /* NOTE: psge points to the beginning of the chain element
492 * in current buffer. Get a chain buffer.
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;
500 /* Update the tracking arrays.
501 * If chainSge == NULL, update ReqToChain, else ChainToChain
503 if (chainSge) {
504 ioc->ChainToChain[chain_idx] = newIndex;
505 } else {
506 ioc->ReqToChain[req_idx] = newIndex;
508 chain_idx = newIndex;
509 chain_dma_off = ioc->req_sz * chain_idx;
511 /* Populate the chainSGE for the current buffer.
512 * - Set chain buffer pointer to psge and fill
513 * out the Address and Flags fields.
515 chainSge = (char *) psge;
516 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
517 psge, req_idx));
519 /* Start the SGE for the next buffer
521 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
522 sgeOffset = 0;
523 sg_done = 0;
525 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
526 psge, chain_idx));
528 /* Start the SGE for the next buffer
531 goto nextSGEset;
534 return SUCCESS;
535 } /* mptscsih_AddSGE() */
537 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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)
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.
550 * Returns 1 indicating alloc'd request frame ptr should be freed.
553 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
555 struct scsi_cmnd *sc;
556 MPT_SCSI_HOST *hd;
557 SCSIIORequest_t *pScsiReq;
558 SCSIIOReply_t *pScsiReply;
559 u16 req_idx;
561 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
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;
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.
572 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
573 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
574 ioc->name);
576 mptscsih_freeChainBuffers(ioc, req_idx);
577 return 1;
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));
584 sc->result = DID_OK << 16; /* Set default reply as OK */
585 pScsiReq = (SCSIIORequest_t *) mf;
586 pScsiReply = (SCSIIOReply_t *) mr;
588 if (pScsiReply == NULL) {
589 /* special context reply handling */
591 } else {
592 u32 xfer_cnt;
593 u16 status;
594 u8 scsi_state, scsi_status;
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;
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));
609 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
610 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
613 * Look for + dump FCP ResponseInfo[]!
615 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
616 printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n",
617 le32_to_cpu(pScsiReply->ResponseInfo));
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:-(
627 sc->result = SAM_STAT_BUSY;
628 break;
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;
635 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
636 /* Spoof to SCSI Selection Timeout! */
637 sc->result = DID_NO_CONNECT << 16;
639 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
640 hd->sel_timeout[pScsiReq->TargetID]++;
641 break;
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.
649 sc->result = DID_RESET << 16;
651 /* GEM Workaround. */
652 if (ioc->bus_type == SCSI)
653 mptscsih_no_negotiate(hd, sc->device->id);
654 break;
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;
671 dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
672 break;
674 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
676 * Do upfront check for valid SenseData and give it
677 * precedence!
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
684 } else {
685 if (xfer_cnt < sc->underflow) {
686 sc->result = DID_SOFT_ERROR << 16;
688 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
689 /* What to do?
691 sc->result = DID_SOFT_ERROR << 16;
693 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
694 /* Not real sure here either... */
695 sc->result = DID_RESET << 16;
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
704 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
705 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
707 break;
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) {
715 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
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.
722 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
723 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
726 else if (scsi_state &
727 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
730 * What to do?
732 sc->result = DID_SOFT_ERROR << 16;
734 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
735 /* Not real sure here either... */
736 sc->result = DID_RESET << 16;
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.
743 * Not real sure here either so do nothing... */
746 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
747 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
749 /* Add handling of:
750 * Reservation Conflict, Busy,
751 * Command Terminated, CHECK
753 break;
755 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
756 sc->result = DID_SOFT_ERROR << 16;
757 break;
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:
771 * What to do?
773 sc->result = DID_SOFT_ERROR << 16;
774 break;
776 } /* switch(status) */
778 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
779 } /* end of address reply case */
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);
790 hd->ScsiLookup[req_idx] = NULL;
792 sc->scsi_done(sc); /* Issue the command callback */
794 /* Free Chain buffers */
795 mptscsih_freeChainBuffers(ioc, req_idx);
796 return 1;
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
806 * Returns: None.
808 * Must be called while new I/Os are being queued.
810 static void
811 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
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;
819 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
820 for (ii= 0; ii < max; ii++) {
821 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
823 /* Command found.
826 /* Null ScsiLookup index
828 hd->ScsiLookup[ii] = NULL;
830 mf = MPT_INDEX_2_MFPTR(ioc, ii);
831 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
832 mf, SCpnt));
834 /* Set status, free OS resources (SG DMA buffers)
835 * Do OS callback
836 * Free driver resources (chain, msg buffers)
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);
849 SCpnt->result = DID_RESET << 16;
850 SCpnt->host_scribble = NULL;
852 /* Free Chain buffers */
853 mptscsih_freeChainBuffers(ioc, ii);
855 /* Free Message frames */
856 mpt_free_msg_frame(ioc, mf);
858 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
862 return;
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
875 * Returns: None.
877 * Called from slave_destroy.
879 static void
880 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
882 SCSIIORequest_t *mf = NULL;
883 int ii;
884 int max = hd->ioc->req_depth;
886 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
887 target, lun, max));
889 for (ii=0; ii < max; ii++) {
890 if (hd->ScsiLookup[ii] != NULL) {
892 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
894 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
895 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
897 if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
898 continue;
900 /* Cleanup
902 hd->ScsiLookup[ii] = NULL;
903 mptscsih_freeChainBuffers(hd->ioc, ii);
904 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
908 return;
911 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
913 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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.
925 static void
926 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
928 long time = jiffies;
929 MPT_SCSI_HOST *hd;
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;
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;
945 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
947 * mptscsih_remove - Removed scsi devices
948 * @pdev: Pointer to pci_dev structure
952 void
953 mptscsih_remove(struct pci_dev *pdev)
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;
962 if(!host)
963 return;
965 scsi_remove_host(host);
967 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
968 return;
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);
980 } else {
981 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
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
991 mptscsih_shutdown(&pdev->dev);
993 sz1=0;
995 if (hd->ScsiLookup != NULL) {
996 sz1 = hd->ioc->req_depth * sizeof(void *);
997 kfree(hd->ScsiLookup);
998 hd->ScsiLookup = NULL;
1001 if (hd->Targets != NULL) {
1003 * Free pointer array.
1005 kfree(hd->Targets);
1006 hd->Targets = NULL;
1009 dprintk((MYIOC_s_INFO_FMT
1010 "Free'd ScsiLookup (%d) memory\n",
1011 hd->ioc->name, sz1));
1013 if (hd->info_kbuf != NULL)
1014 kfree(hd->info_kbuf);
1016 /* NULL the Scsi_Host pointer
1018 hd->ioc->sh = NULL;
1020 scsi_host_put(host);
1022 mpt_detach(pdev);
1026 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1028 * mptscsih_shutdown - reboot notifier
1031 void
1032 mptscsih_shutdown(struct device * dev)
1034 MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev));
1035 struct Scsi_Host *host = ioc->sh;
1036 MPT_SCSI_HOST *hd;
1038 if(!host)
1039 return;
1041 hd = (MPT_SCSI_HOST *)host->hostdata;
1043 /* Flush the cache of this adapter
1045 if(hd != NULL)
1046 mptscsih_synchronize_cache(hd, 0);
1050 #ifdef CONFIG_PM
1051 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1053 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1058 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1060 mptscsih_shutdown(&pdev->dev);
1061 return mpt_suspend(pdev,state);
1064 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1066 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1071 mptscsih_resume(struct pci_dev *pdev)
1073 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1074 struct Scsi_Host *host = ioc->sh;
1075 MPT_SCSI_HOST *hd;
1077 mpt_resume(pdev);
1079 if(!host)
1080 return 0;
1082 hd = (MPT_SCSI_HOST *)host->hostdata;
1083 if(!hd)
1084 return 0;
1086 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
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);
1100 #endif
1101 return 0;
1104 #endif
1106 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1108 * mptscsih_info - Return information about MPT adapter
1109 * @SChost: Pointer to Scsi_Host structure
1111 * (linux scsi_host_template.info routine)
1113 * Returns pointer to buffer where information was written.
1115 const char *
1116 mptscsih_info(struct Scsi_Host *SChost)
1118 MPT_SCSI_HOST *h;
1119 int size = 0;
1121 h = (MPT_SCSI_HOST *)SChost->hostdata;
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';
1129 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1130 h->info_kbuf[size-1] = '\0';
1133 return h->info_kbuf;
1136 struct info_str {
1137 char *buffer;
1138 int length;
1139 int offset;
1140 int pos;
1143 static void
1144 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1146 if (info->pos + len > info->length)
1147 len = info->length - info->pos;
1149 if (info->pos + len < info->offset) {
1150 info->pos += len;
1151 return;
1154 if (info->pos < info->offset) {
1155 data += (info->offset - info->pos);
1156 len -= (info->offset - info->pos);
1159 if (len > 0) {
1160 memcpy(info->buffer + info->pos, data, len);
1161 info->pos += len;
1165 static int
1166 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1168 va_list args;
1169 char buf[81];
1170 int len;
1172 va_start(args, fmt);
1173 len = vsprintf(buf, fmt, args);
1174 va_end(args);
1176 mptscsih_copy_mem_info(info, buf, len);
1177 return len;
1180 static int
1181 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1183 struct info_str info;
1185 info.buffer = pbuf;
1186 info.length = len;
1187 info.offset = offset;
1188 info.pos = 0;
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);
1195 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1198 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1200 * mptscsih_proc_info - Return information about MPT adapter
1202 * (linux scsi_host_template.info routine)
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
1212 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1213 int length, int func)
1215 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1216 MPT_ADAPTER *ioc = hd->ioc;
1217 int size = 0;
1219 if (func) {
1221 * write is not supported
1223 } else {
1224 if (start)
1225 *start = buffer;
1227 size = mptscsih_host_info(ioc, buffer, offset, length);
1230 return size;
1233 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1234 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1236 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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.
1246 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1249 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
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;
1264 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1265 target = SCpnt->device->id;
1266 lun = SCpnt->device->lun;
1267 SCpnt->scsi_done = done;
1269 pTarget = hd->Targets[target];
1271 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1272 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
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;
1281 * Put together a MPT SCSI request...
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;
1289 pScsiReq = (SCSIIORequest_t *) mf;
1291 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1293 ADD_INDEX_LOG(my_idx);
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...
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;
1310 /* Default to untagged. Once a target structure has been allocated,
1311 * use the Inquiry data to determine if device supports tagged.
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;
1321 /* Use the above information to set up the message frame
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);
1342 * Write SCSI CDB into the message
1344 cmd_len = SCpnt->cmd_len;
1345 for (ii=0; ii < cmd_len; ii++)
1346 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1348 for (ii=cmd_len; ii < 16; ii++)
1349 pScsiReq->CDB[ii] = 0;
1351 /* DataLength */
1352 pScsiReq->DataLength = cpu_to_le32(datalen);
1354 /* SenseBuffer low address */
1355 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1356 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1358 /* Now add the SG list
1359 * Always have a SGE even if null length.
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;
1371 hd->ScsiLookup[my_idx] = SCpnt;
1372 SCpnt->host_scribble = NULL;
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;
1379 if (dvStatus || hd->ioc->spi_data.forceDv) {
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);
1391 schedule_work(&dvTaskQ_task);
1392 } else {
1393 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1395 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
1398 /* Trying to do DV to this target, extend timeout.
1399 * Wait to issue until flag is clear
1401 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
1402 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
1403 issueCmd = 0;
1406 /* Set the DV flags.
1408 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
1409 mptscsih_set_dvflags(hd, pScsiReq);
1411 if (!issueCmd)
1412 goto fail;
1415 #endif
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;
1423 fail:
1424 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1425 mpt_free_msg_frame(hd->ioc, mf);
1426 return SCSI_MLQUEUE_HOST_BUSY;
1429 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
1436 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1437 * No return.
1439 static void
1440 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1442 MPT_FRAME_HDR *chain;
1443 unsigned long flags;
1444 int chain_idx;
1445 int next;
1447 /* Get the first chain index and reset
1448 * tracker state.
1450 chain_idx = ioc->ReqToChain[req_idx];
1451 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1453 while (chain_idx != MPT_HOST_NO_CHAIN) {
1455 /* Save the next chain buffer index */
1456 next = ioc->ChainToChain[chain_idx];
1458 /* Free this chain buffer and reset
1459 * tracker
1461 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1463 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1464 + (chain_idx * ioc->req_sz));
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);
1470 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1471 ioc->name, chain_idx));
1473 /* handle next */
1474 chain_idx = next;
1476 return;
1479 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1481 * Reset Handling
1484 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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)
1496 * Remark: Currently invoked from a non-interrupt thread (_bh).
1498 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1499 * will be active.
1501 * Returns 0 for SUCCESS or -1 if FAILED.
1503 static int
1504 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1506 MPT_ADAPTER *ioc;
1507 int rc = -1;
1508 int doTask = 1;
1509 u32 ioc_raw_state;
1510 unsigned long flags;
1512 /* If FW is being reloaded currently, return success to
1513 * the calling function.
1515 if (hd == NULL)
1516 return 0;
1518 ioc = hd->ioc;
1519 if (ioc == NULL) {
1520 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1521 return FAILED;
1523 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
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;
1532 spin_unlock_irqrestore(&ioc->diagLock, flags);
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.
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;
1557 doTask = 0;
1559 } else {
1560 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1561 hd->tmPending |= (1 << type);
1562 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1565 /* Is operational?
1567 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
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);
1575 #endif
1577 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1578 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1580 /* Isse the Task Mgmt request.
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));
1592 /* Only fall through to the HRH if this is a bus reset
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);
1601 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1603 return rc;
1607 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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)
1616 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1617 * or a non-interrupt thread. In the former, must not call schedule().
1619 * Not all fields are meaningfull for all task types.
1621 * Returns 0 for SUCCESS, -999 for "no msg frames",
1622 * else other non-zero value returned.
1624 static int
1625 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1627 MPT_FRAME_HDR *mf;
1628 SCSITaskMgmt_t *pScsiTm;
1629 int ii;
1630 int retval;
1632 /* Return Fail to calling function if no message frames available.
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;
1640 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1641 hd->ioc->name, mf));
1643 /* Format the Request
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;
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;
1657 for (ii= 0; ii < 8; ii++) {
1658 pScsiTm->LUN[ii] = 0;
1660 pScsiTm->LUN[1] = lun;
1662 for (ii=0; ii < 7; ii++)
1663 pScsiTm->Reserved2[ii] = 0;
1665 pScsiTm->TaskMsgContext = ctx2abort;
1667 dtmprintk((MYIOC_s_INFO_FMT
1668 "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1669 hd->ioc->name, ctx2abort, type));
1671 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
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;
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);
1693 return retval;
1696 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1698 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1699 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1701 * (linux scsi_host_template.eh_abort_handler routine)
1703 * Returns SUCCESS or FAILED.
1706 mptscsih_abort(struct scsi_cmnd * SCpnt)
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;
1715 /* If we can't locate our host adapter structure, return FAILED status.
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;
1726 ioc = hd->ioc;
1727 if (hd->resetPending)
1728 return FAILED;
1730 printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
1731 hd->ioc->name, SCpnt);
1733 if (hd->timeouts < -1)
1734 hd->timeouts++;
1736 /* Find this command
1738 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1739 /* Cmd not found in ScsiLookup.
1740 * Do OS callback.
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;
1749 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1750 * (the IO to be ABORT'd)
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
1756 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1757 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1759 hd->abortSCpnt = SCpnt;
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) {
1767 /* The TM request failed and the subsequent FW-reload failed!
1768 * Fatal error case.
1770 printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
1771 hd->ioc->name, SCpnt);
1773 /* We must clear our pending flag before clearing our state.
1775 hd->tmPending = 0;
1776 hd->tmState = TM_STATE_NONE;
1778 spin_lock_irq(host_lock);
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);
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;
1795 spin_lock_irq(host_lock);
1796 return SUCCESS;
1799 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
1804 * (linux scsi_host_template.eh_dev_reset_handler routine)
1806 * Returns SUCCESS or FAILED.
1809 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1811 MPT_SCSI_HOST *hd;
1812 spinlock_t *host_lock = SCpnt->device->host->host_lock;
1814 /* If we can't locate our host adapter structure, return FAILED status.
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;
1823 if (hd->resetPending)
1824 return FAILED;
1826 printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
1827 hd->ioc->name, SCpnt);
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.
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;
1844 spin_lock_irq(host_lock);
1845 return SUCCESS;
1849 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
1854 * (linux scsi_host_template.eh_bus_reset_handler routine)
1856 * Returns SUCCESS or FAILED.
1859 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1861 MPT_SCSI_HOST *hd;
1862 spinlock_t *host_lock = SCpnt->device->host->host_lock;
1864 /* If we can't locate our host adapter structure, return FAILED status.
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;
1873 printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
1874 hd->ioc->name, SCpnt);
1876 if (hd->timeouts < -1)
1877 hd->timeouts++;
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){
1885 /* The TM request failed and the subsequent FW-reload failed!
1886 * Fatal error case.
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;
1896 spin_lock_irq(host_lock);
1897 return SUCCESS;
1900 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
1906 * (linux scsi_host_template.eh_host_reset_handler routine)
1908 * Returns SUCCESS or FAILED.
1911 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1913 MPT_SCSI_HOST * hd;
1914 int status = SUCCESS;
1915 spinlock_t *host_lock = SCpnt->device->host->host_lock;
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;
1925 printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
1926 hd->ioc->name, SCpnt);
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.
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.
1938 hd->tmPending = 0;
1939 hd->tmState = TM_STATE_NONE;
1941 spin_lock_irq(host_lock);
1944 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
1945 "Status = %s\n",
1946 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1948 return status;
1951 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1953 * mptscsih_tm_pending_wait - wait for pending task management request to
1954 * complete.
1955 * @hd: Pointer to MPT host structure.
1957 * Returns {SUCCESS,FAILED}.
1959 static int
1960 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1962 unsigned long flags;
1963 int loop_count = 4 * 10; /* Wait 10 seconds */
1964 int status = FAILED;
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;
1975 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1976 msleep(250);
1977 } while (--loop_count);
1979 return status;
1982 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1984 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1985 * @hd: Pointer to MPT host structure.
1987 * Returns {SUCCESS,FAILED}.
1989 static int
1990 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1992 unsigned long flags;
1993 int loop_count = 4 * timeout;
1994 int status = FAILED;
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;
2003 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2004 msleep_interruptible(250);
2005 } while (--loop_count);
2007 return status;
2010 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
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.
2022 * Returns 1 indicating alloc'd request frame ptr should be freed.
2025 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2027 SCSITaskMgmtReply_t *pScsiTmReply;
2028 SCSITaskMgmt_t *pScsiTmReq;
2029 MPT_SCSI_HOST *hd;
2030 unsigned long flags;
2031 u16 iocstatus;
2032 u8 tmType;
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.
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;
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;
2056 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2057 tmType = pScsiTmReq->TaskType;
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);
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) {
2069 /* clear flags and continue.
2071 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2072 hd->abortSCpnt = NULL;
2074 /* If an internal command is present
2075 * or the TM failed - reload the FW.
2076 * FC FW may respond FAILED to an ABORT
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"));
2087 } else {
2088 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2090 hd->abortSCpnt = NULL;
2095 spin_lock_irqsave(&ioc->FreeQlock, flags);
2096 hd->tmPending = 0;
2097 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2098 hd->tmState = TM_STATE_NONE;
2100 return 1;
2103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2105 * This is anyones guess quite frankly.
2108 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2109 sector_t capacity, int geom[])
2111 int heads;
2112 int sectors;
2113 sector_t cylinders;
2114 ulong dummy;
2116 heads = 64;
2117 sectors = 32;
2119 dummy = heads * sectors;
2120 cylinders = capacity;
2121 sector_div(cylinders,dummy);
2124 * Handle extended translation size for logical drives
2125 * > 1Gb
2127 if ((ulong)capacity >= 0x200000) {
2128 heads = 255;
2129 sectors = 63;
2130 dummy = heads * sectors;
2131 cylinders = capacity;
2132 sector_div(cylinders,dummy);
2135 /* return result */
2136 geom[0] = heads;
2137 geom[1] = sectors;
2138 geom[2] = cylinders;
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));
2144 return 0;
2147 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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).
2155 mptscsih_slave_alloc(struct scsi_device *device)
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;
2162 if (hd == NULL)
2163 return -ENODEV;
2165 if ((vdev = hd->Targets[target]) != NULL)
2166 goto out;
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;
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));
2188 } else {
2189 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2192 out:
2193 vdev->num_luns++;
2194 return 0;
2197 static int
2198 mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
2200 int i;
2202 if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3)
2203 return 0;
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;
2210 return 0;
2214 * OS entry point to allow for host driver to free allocated memory
2215 * Called if no device present or device being unloaded
2217 void
2218 mptscsih_slave_destroy(struct scsi_device *device)
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;
2226 if (hd == NULL)
2227 return;
2229 mptscsih_search_running_cmds(hd, target, lun);
2231 vdev = hd->Targets[target];
2232 vdev->luns[0] &= ~(1 << lun);
2233 if (--vdev->num_luns)
2234 return;
2236 kfree(hd->Targets[target]);
2237 hd->Targets[target] = NULL;
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;
2246 if (!hd->negoNvram) {
2247 hd->ioc->spi_data.dvStatus[target] |=
2248 MPT_SCSICFG_DV_NOT_DONE;
2254 static void
2255 mptscsih_set_queue_depth(struct scsi_device *device, MPT_SCSI_HOST *hd,
2256 VirtDevice *pTarget, int qdepth)
2258 int max_depth;
2259 int tagged;
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;
2274 } else
2275 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2277 if (qdepth > max_depth)
2278 qdepth = max_depth;
2279 if (qdepth == 1)
2280 tagged = 0;
2281 else
2282 tagged = MSG_SIMPLE_TAG;
2284 scsi_adjust_queue_depth(device, tagged, qdepth);
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.
2295 mptscsih_slave_configure(struct scsi_device *device)
2297 struct Scsi_Host *sh = device->host;
2298 VirtDevice *pTarget;
2299 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2301 if ((hd == NULL) || (hd->Targets == NULL)) {
2302 return 0;
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));
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;
2319 pTarget = hd->Targets[device->id];
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.
2330 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
2331 MPT_SCSI_CMD_PER_DEV_HIGH);
2332 goto slave_configure_exit;
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);
2339 dsprintk((MYIOC_s_INFO_FMT
2340 "Queue depth=%d, tflags=%x\n",
2341 hd->ioc->name, device->queue_depth, pTarget->tflags));
2343 dsprintk((MYIOC_s_INFO_FMT
2344 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2345 hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
2347 slave_configure_exit:
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));
2354 return 0;
2357 ssize_t
2358 mptscsih_store_queue_depth(struct device *dev, const char *buf, size_t count)
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;
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;
2376 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2378 * Private routines...
2381 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2382 /* Utility function to copy sense data from the scsi_cmnd buffer
2383 * to the FC and SCSI target structures.
2386 static void
2387 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2389 VirtDevice *target;
2390 SCSIIORequest_t *pReq;
2391 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2392 int index;
2394 /* Get target structure
2396 pReq = (SCSIIORequest_t *) mf;
2397 index = (int) pReq->TargetID;
2398 target = hd->Targets[index];
2400 if (sense_count) {
2401 u8 *sense_data;
2402 int req_index;
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));
2409 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
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;
2416 idx = ioc->eventContext % ioc->eventLogSize;
2417 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2418 ioc->events[idx].eventContext = ioc->eventContext;
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;
2424 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2426 ioc->eventContext++;
2429 } else {
2430 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2431 hd->ioc->name));
2435 static u32
2436 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2438 MPT_SCSI_HOST *hd;
2439 int i;
2441 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2443 for (i = 0; i < hd->ioc->req_depth; i++) {
2444 if (hd->ScsiLookup[i] == sc) {
2445 return i;
2449 return -1;
2452 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2454 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2456 MPT_SCSI_HOST *hd;
2457 unsigned long flags;
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")));
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.
2468 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2469 return 0;
2470 else
2471 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2473 if (reset_phase == MPT_IOC_SETUP_RESET) {
2474 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2476 /* Clean Up:
2477 * 1. Set Hard Reset Pending Flag
2478 * All new commands go to doneQ
2480 hd->resetPending = 1;
2482 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2483 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2485 /* 2. Flush running commands
2486 * Clean ScsiLookup (and associated memory)
2487 * AND clean mytaskQ
2490 /* 2b. Reply to OS all known outstanding I/O commands.
2492 mptscsih_flush_running_cmds(hd);
2494 /* 2c. If there was an internal command that
2495 * has not completed, configuration or io request,
2496 * free these resources.
2498 if (hd->cmdPtr) {
2499 del_timer(&hd->timer);
2500 mpt_free_msg_frame(ioc, hd->cmdPtr);
2503 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2505 } else {
2506 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
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.
2513 /* ScsiLookup initialization
2516 int ii;
2517 for (ii=0; ii < hd->ioc->req_depth; ii++)
2518 hd->ScsiLookup[ii] = NULL;
2521 /* 2. Chain Buffer initialization
2524 /* 4. Renegotiate to all devices, if SCSI
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);
2531 /* 5. Enable new commands to be posted
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;
2539 /* 6. If there was an internal command,
2540 * wake this process up.
2542 if (hd->cmdPtr) {
2544 * Wake up the original calling thread
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;
2553 /* 7. Set flag to force DV and re-read IOC Page 3
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"));
2560 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2564 return 1; /* currently means nothing really */
2567 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2569 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2571 MPT_SCSI_HOST *hd;
2572 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2574 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2575 ioc->name, event));
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++;
2589 break;
2590 case MPI_EVENT_LOGOUT: /* 09 */
2591 /* FIXME! */
2592 break;
2595 * CHECKME! Don't think we need to do
2596 * anything for these, but...
2598 case MPI_EVENT_RESCAN: /* 06 */
2599 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2600 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2602 * CHECKME! Falling thru...
2604 break;
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.
2611 hd = NULL;
2612 if (ioc->sh)
2613 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
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;
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.
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;
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;
2641 pPDisk++;
2642 numPDisk--;
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.
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));
2657 #endif
2659 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
2660 printk("Raid Event RF: ");
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");
2669 #endif
2670 break;
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;
2681 return 1; /* currently means nothing really */
2684 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
2694 * NOTE: It's only SAFE to call this routine if data points to
2695 * sane & valid STANDARD INQUIRY data!
2697 * Allocate and initialize memory for this target.
2698 * Save inquiry data.
2701 static void
2702 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
2704 int indexed_lun, lun_index;
2705 VirtDevice *vdev;
2706 ScsiCfgData *pSpi;
2707 char data_56;
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));
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.
2721 if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
2722 data[0] |= 0x40;
2724 /* Is LUN supported? If so, upper 2 bits will be 0
2725 * in first byte of inquiry data.
2727 if (data[0] & 0xe0)
2728 return;
2730 if ((vdev = hd->Targets[target_id]) == NULL) {
2731 return;
2734 lun_index = (lun >> 5); /* 32 luns per lun_index */
2735 indexed_lun = (lun % 32);
2736 vdev->luns[lun_index] |= (1 << indexed_lun);
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);
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);
2766 /* If have not done DV, set the DV flag.
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;
2774 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
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
2782 data_56 = data[56];
2783 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
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
2795 data_56 = data[56];
2796 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
2797 mptscsih_setTargetNegoParms(hd, vdev, data_56);
2804 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2806 * Update the target negotiation parameters based on the
2807 * the Inquiry data, adapter capabilities, and NVRAM settings.
2810 static void
2811 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
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;
2824 target->negoFlags = pspi_data->noQas;
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.
2831 /* Set flags based on Inquiry data
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;
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)
2857 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
2858 noQas = 0;
2860 if (target->inq_data[0] == TYPE_TAPE) {
2861 if (byte56 & 0x01)
2862 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2866 } else {
2867 ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
2868 noQas = 0;
2871 offset = pspi_data->maxSyncOffset;
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
2879 if (target->raidVolume == 1) {
2880 noQas = 0;
2882 } else {
2883 factor = MPT_ASYNC;
2884 offset = 0;
2888 if ( (target->inq_data[7] & 0x02) == 0) {
2889 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2892 /* Update tflags based on NVRAM settings. (SCSI only)
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;
2898 if (width)
2899 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2901 if (offset > 0) {
2902 /* Ensure factor is set to the
2903 * maximum of: adapter, nvram, inquiry
2905 if (nfactor) {
2906 if (nfactor < pspi_data->minSyncFactor )
2907 nfactor = pspi_data->minSyncFactor;
2909 factor = max(factor, nfactor);
2910 if (factor == MPT_ASYNC)
2911 offset = 0;
2912 } else {
2913 offset = 0;
2914 factor = MPT_ASYNC;
2916 } else {
2917 factor = MPT_ASYNC;
2921 /* Make sure data is consistent
2923 if ((!width) && (factor < MPT_ULTRA2)) {
2924 factor = MPT_ULTRA2;
2927 /* Save the data to the target structure.
2929 target->minSyncFactor = factor;
2930 target->maxOffset = offset;
2931 target->maxWidth = width;
2933 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2935 /* Disable unused features.
2937 if (!width)
2938 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2940 if (!offset)
2941 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2943 if ( factor > MPT_ULTRA320 )
2944 noQas = 0;
2946 /* GEM, processor WORKAROUND
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;
2956 /* Disable QAS in a mixed configuration case
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);
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;
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).
2986 * Tapes, initTarget will set this flag on completion of Inquiry command.
2987 * Called only if DV_NOT_DONE flag is set
2989 static void
2990 mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
2992 u8 cmd;
2993 ScsiCfgData *pSpi;
2995 ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
2996 pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
2998 if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
2999 return;
3001 cmd = pReq->CDB[0];
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
3008 Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk;
3009 int numPDisk = pSpi->pIocPg3->NumPhysDisks;
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--;
3018 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
3019 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
3023 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3025 * If no Target, bus reset on 1st I/O. Set the flag to
3026 * prevent any future negotiations to this device.
3028 static void
3029 mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
3032 if ((hd->Targets) && (hd->Targets[target_id] == NULL))
3033 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
3035 return;
3038 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3040 * SCSI Config Page functionality ...
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
3052 * Return: None.
3054 * Remark: Called by writeSDP1 and _dv_params
3056 static void
3057 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
3059 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
3060 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
3062 *configurationPtr = 0;
3063 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
3064 *requestedPtr |= (offset << 16) | (factor << 8);
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;
3078 if (nowide)
3079 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
3081 if (nosync)
3082 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
3084 return;
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
3094 * Return: -EFAULT if read of config page header fails
3095 * or 0 if success.
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.
3101 * Remark: Called during init and after a FW reload.
3102 * Remark: We do not wait for a return, write pages sequentially.
3104 static int
3105 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
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;
3125 if (ioc->spi_data.sdp1length == 0)
3126 return 0;
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);
3136 for (; id <= maxid; id++) {
3138 if (id == ioc->pfacts[portnum].PortSCSIID)
3139 continue;
3141 /* Use NVRAM to get adapter and target maximums
3142 * Data over-riden by target structure information, if present
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];
3150 if (maxwidth)
3151 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
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;
3162 } else
3163 maxfactor = MPT_ASYNC;
3166 /* Set the negotiation flags.
3168 negoFlags = ioc->spi_data.noQas;
3169 if (!maxwidth)
3170 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
3172 if (!maxoffset)
3173 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
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;
3187 /* If id is not a raid volume, get the updated
3188 * transmission settings from the target structure.
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;
3197 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3198 /* Force to async and narrow if DV has not been executed
3199 * for this ID
3201 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
3202 width = 0;
3203 factor = MPT_ASYNC;
3204 offset = 0;
3206 #endif
3208 if (flags & MPT_SCSICFG_BLK_NEGO)
3209 negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
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));
3216 /* Get a MF for this command.
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;
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));
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.
3235 pReq = (Config_t *)mf;
3237 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3238 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
3240 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
3241 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
3243 /* Complete the request frame (same for all requests).
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;
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 ));
3261 /* Add a SGE to the config request.
3263 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
3265 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3267 /* Set up the common data portion
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);
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));
3282 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3285 return 0;
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
3293 * Return: -EAGAIN if unable to obtain a Message Frame
3294 * or 0 if success.
3296 * Remark: We do not wait for a return, write pages sequentially.
3298 static int
3299 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
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;
3311 /* Get a MF for this command.
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;
3319 /* Set the request and the data pointers.
3320 * Place data at end of MF.
3322 pReq = (Config_t *)mf;
3324 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3325 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
3327 /* Complete the request frame (same for all requests).
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;
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 ));
3348 /* Add a SGE to the config request.
3350 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
3351 (IOCPage4Ptr->Header.PageLength + ii) * 4;
3353 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
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));
3359 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3361 return 0;
3364 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3366 * Bus Scan and Domain Validation functionality ...
3369 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3371 * mptscsih_scandv_complete - Scan and DV callback routine registered
3372 * to Fustion MPT (base) driver.
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)
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.
3383 * Returns 1 indicating alloc'd request frame ptr should be freed.
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.
3390 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3392 MPT_SCSI_HOST *hd;
3393 SCSIIORequest_t *pReq;
3394 int completionCode;
3395 u16 req_idx;
3397 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
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;
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;
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);
3416 hd->cmdPtr = NULL;
3418 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3419 hd->ioc->name, mf, mr, req_idx));
3421 hd->pLocal = &hd->localReply;
3422 hd->pLocal->scsiStatus = 0;
3424 /* If target struct exists, clear sense valid flag.
3426 if (mr == NULL) {
3427 completionCode = MPT_SCANDV_GOOD;
3428 } else {
3429 SCSIIOReply_t *pReply;
3430 u16 status;
3431 u8 scsi_status;
3433 pReply = (SCSIIOReply_t *) mr;
3435 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3436 scsi_status = pReply->SCSIStatus;
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)));
3442 switch(status) {
3444 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
3445 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3446 break;
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;
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;
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.
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;
3477 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3478 u8 *sense_data;
3479 int sz;
3481 /* save sense data in global structure
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));
3488 sz = min_t(int, pReq->SenseBufferLength,
3489 SCSI_STD_SENSE_BYTES);
3490 memcpy(hd->pLocal->sense, sense_data, sz);
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;
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;
3508 break;
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;
3517 default:
3518 completionCode = MPT_SCANDV_SOME_ERROR;
3519 break;
3521 } /* switch(status) */
3523 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
3524 completionCode));
3525 } /* end of address reply case */
3527 hd->pLocal->completion = completionCode;
3529 /* MF and RF are freed in mpt_interrupt
3531 wakeup:
3532 /* Free Chain buffers (will never chain) in scan or dv */
3533 //mptscsih_freeChainBuffers(ioc, req_idx);
3536 * Wake up the original calling thread
3538 hd->scandv_wait_done = 1;
3539 wake_up(&hd->scandv_waitq);
3541 return 1;
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
3550 void
3551 mptscsih_timer_expired(unsigned long data)
3553 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3555 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3557 if (hd->cmdPtr) {
3558 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
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.
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);
3574 } else {
3575 /* This should NEVER happen */
3576 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
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.
3584 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3586 return;
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.
3597 * Returns: < 0 on a fatal error
3598 * 0 on success
3600 * Remark: Wait to return until reply processed by the ISR.
3602 static int
3603 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
3605 MpiRaidActionRequest_t *pReq;
3606 MPT_FRAME_HDR *mf;
3607 int in_isr;
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;
3616 /* Get and Populate a free Frame
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;
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;
3636 mpt_add_sge((char *)&pReq->ActionDataSGE,
3637 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
3639 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
3640 hd->ioc->name, action, io->id));
3642 hd->pLocal = NULL;
3643 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
3644 hd->scandv_wait_done = 0;
3646 /* Save cmd pointer, for resource free if timeout or
3647 * FW reload occurs
3649 hd->cmdPtr = mf;
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);
3655 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
3656 return -1;
3658 return 0;
3660 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3662 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3664 * mptscsih_do_cmd - Do internal command.
3665 * @hd: MPT_SCSI_HOST pointer
3666 * @io: INTERNAL_CMD pointer.
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
3673 * Remark: Single threaded access only.
3675 * Return:
3676 * < 0 if an illegal command or no resources
3678 * 0 if good
3680 * > 0 if command complete but some type of completion error.
3682 static int
3683 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
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;
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;
3703 /* Set command specific information
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;
3714 case TEST_UNIT_READY:
3715 cmdLen = 6;
3716 dir = MPI_SCSIIO_CONTROL_READ;
3717 cmdTimeout = 10;
3718 break;
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;
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;
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;
3746 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3747 CDB[1] |= 0x01;
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;
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;
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;
3770 case RESERVE:
3771 cmdLen = 6;
3772 dir = MPI_SCSIIO_CONTROL_READ;
3773 CDB[0] = cmd;
3774 cmdTimeout = 10;
3775 break;
3777 case RELEASE:
3778 cmdLen = 6;
3779 dir = MPI_SCSIIO_CONTROL_READ;
3780 CDB[0] = cmd;
3781 cmdTimeout = 10;
3782 break;
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;
3792 default:
3793 /* Error Case */
3794 return -EFAULT;
3797 /* Get and Populate a free Frame
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;
3805 pScsiReq = (SCSIIORequest_t *) mf;
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 */
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;
3823 pScsiReq->CDBLength = cmdLen;
3824 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3826 pScsiReq->Reserved = 0;
3828 pScsiReq->MsgFlags = mpt_msg_flags();
3829 /* MsgContext set in mpt_get_msg_fram call */
3831 for (ii=0; ii < 8; ii++)
3832 pScsiReq->LUN[ii] = 0;
3833 pScsiReq->LUN[1] = io->lun;
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);
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));
3846 for (ii=0; ii < 16; ii++)
3847 pScsiReq->CDB[ii] = CDB[ii];
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));
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));
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);
3866 /* The ISR will free the request frame, but we need
3867 * the information to initialize the target. Duplicate.
3869 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
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
3879 hd->pLocal = NULL;
3880 hd->timer.expires = jiffies + HZ*cmdTimeout;
3881 hd->scandv_wait_done = 0;
3883 /* Save cmd pointer, for resource free if timeout or
3884 * FW reload occurs
3886 hd->cmdPtr = mf;
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);
3892 if (hd->pLocal) {
3893 rc = hd->pLocal->completion;
3894 hd->pLocal->skip = 0;
3896 /* Always set fatal error codes in some cases.
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));
3909 return rc;
3912 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3914 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3915 * @hd: Pointer to MPT_SCSI_HOST structure
3916 * @portnum: IOC port number
3918 * Uses the ISR, but with special processing.
3919 * MUST be single-threaded.
3921 * Return: 0 on completion
3923 static int
3924 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
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;
3943 max_id = ioc->sh->max_id - 1;
3945 /* Following parameters will not change
3946 * in this routine.
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;
3956 /* No SCSI hosts
3958 if (hd->Targets == NULL)
3959 return 0;
3961 /* Skip the host
3963 if (id == hostId)
3964 id++;
3966 /* Write SDP1 for all SCSI devices
3967 * Alloc memory and set up config buffer
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);
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;
3989 /* loop through all devices on this port
3991 while (bus < MPT_MAX_BUS) {
3992 iocmd.bus = bus;
3993 iocmd.id = id;
3994 pTarget = hd->Targets[(int)id];
3996 if (doConfig) {
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];
4006 if (data & MPT_NVRAM_WIDE_DISABLE)
4007 flags |= MPT_TARGET_NO_NEGO_WIDE;
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;
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);
4028 /* If target Ptr NULL or if this target is NOT a disk, skip.
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
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);
4043 /* get next relevant device */
4044 id++;
4046 if (id == hostId)
4047 id++;
4049 if (id > max_id) {
4050 id = 0;
4051 bus++;
4055 if (pcfg1Data) {
4056 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
4059 return 0;
4062 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4063 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4065 * mptscsih_domainValidation - Top level handler for domain validation.
4066 * @hd: Pointer to MPT_SCSI_HOST structure.
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
4072 * Return: None.
4074 static void
4075 mptscsih_domainValidation(void *arg)
4077 MPT_SCSI_HOST *hd;
4078 MPT_ADAPTER *ioc;
4079 unsigned long flags;
4080 int id, maxid, dvStatus, did;
4081 int ii, isPhysDisk;
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;
4090 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
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.
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;
4107 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4109 msleep(250);
4111 /* DV only to SCSI adapters */
4112 if (ioc->bus_type != SCSI)
4113 continue;
4115 /* Make sure everything looks ok */
4116 if (ioc->sh == NULL)
4117 continue;
4119 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4120 if (hd == NULL)
4121 continue;
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;
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;
4133 pPDisk++;
4134 numPDisk--;
4137 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
4140 maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
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;
4149 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4150 dvStatus = hd->ioc->spi_data.dvStatus[id];
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;
4157 msleep(250);
4159 /* If hidden phys disk, block IO's to all
4160 * raid volumes
4161 * else, process normally
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;
4172 if (mptscsih_doDv(hd, 0, id) == 1) {
4173 /* Untagged device was busy, try again
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.
4180 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
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;
4191 if (hd->ioc->spi_data.noQas)
4192 mptscsih_qas_check(hd, id);
4198 spin_lock_irqsave(&dvtaskQ_lock, flags);
4199 dvtaskQ_active = 0;
4200 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4202 return;
4205 /* Search IOC page 3 to determine if this is hidden physical disk
4207 static int
4208 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
4210 if (ioc->spi_data.pIocPg3) {
4211 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4212 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4214 while (numPDisk) {
4215 if (pPDisk->PhysDiskID == id) {
4216 return 1;
4218 pPDisk++;
4219 numPDisk--;
4222 return 0;
4225 /* Write SDP1 if no QAS has been enabled
4227 static void
4228 mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
4230 VirtDevice *pTarget;
4231 int ii;
4233 if (hd->Targets == NULL)
4234 return;
4236 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4237 if (ii == id)
4238 continue;
4240 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
4241 continue;
4243 pTarget = hd->Targets[ii];
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);
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);
4258 return;
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
4270 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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
4277 * Uses the ISR, but with special processing.
4278 * MUST be single-threaded.
4279 * Test will exit if target is at async & narrow.
4281 * Return: None.
4283 static int
4284 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
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;
4319 if (ioc->spi_data.sdp1length == 0)
4320 return 0;
4322 if (ioc->spi_data.sdp0length == 0)
4323 return 0;
4325 /* If multiple buses are used, require that the initiator
4326 * id be the same on all buses.
4328 if (id == ioc->pfacts[0].PortSCSIID)
4329 return 0;
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));
4337 /* Prep DV structure
4339 memset (&dv, 0, sizeof(DVPARAMETERS));
4340 dv.id = id;
4342 /* Populate tmax with the current maximum
4343 * transfer parameters for this target.
4344 * Exit if narrow and async.
4346 dv.cmd = MPT_GET_NVRAM_VALS;
4347 mptscsih_dv_parms(hd, &dv, NULL);
4349 /* Prep SCSI IO structure
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;
4358 pTarget = hd->Targets[id];
4360 /* Use tagged commands if possible.
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;
4369 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4370 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
4371 return 0;
4375 /* Prep cfg structure
4377 cfg.pageAddr = (bus<<8) | id;
4378 cfg.hdr = NULL;
4380 /* Prep SDP0 header
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;
4387 /* Prep SDP1 header
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;
4394 if (header0.PageLength & 1)
4395 dv_alloc = (header0.PageLength * 4) + 4;
4397 dv_alloc += (2048 + (header1.PageLength * 4));
4399 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
4400 if (pDvBuf == NULL)
4401 return 0;
4403 sz = 0;
4404 pbuf1 = (u8 *)pDvBuf;
4405 buf1_dma = dvbuf_dma;
4406 sz +=1024;
4408 pbuf2 = (u8 *) (pDvBuf + sz);
4409 buf2_dma = dvbuf_dma + sz;
4410 sz +=1024;
4412 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
4413 cfg0_dma_addr = dvbuf_dma + sz;
4414 sz += header0.PageLength * 4;
4416 /* 8-byte alignment
4418 if (header0.PageLength & 1)
4419 sz += 4;
4421 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
4422 cfg1_dma_addr = dvbuf_dma + sz;
4424 /* Skip this ID? Set cfg.hdr to force config page write
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;
4434 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
4435 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
4437 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
4438 ioc->name, bus, id, lun));
4440 dv.cmd = MPT_SET_MAX;
4441 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4442 cfg.hdr = &header1;
4444 /* Save the final negotiated settings to
4445 * SCSI device page 1.
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;
4456 /* Finish iocmd inititialization - hidden or visible disk? */
4457 if (ioc->spi_data.pIocPg3) {
4458 /* Search IOC page 3 for matching id
4460 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4461 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4463 while (numPDisk) {
4464 if (pPDisk->PhysDiskID == id) {
4465 /* match */
4466 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
4467 iocmd.physDiskNum = pPDisk->PhysDiskNum;
4469 /* Quiesce the IM
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;
4475 break;
4477 pPDisk++;
4478 numPDisk--;
4482 /* RAID Volume ID's may double for a physical device. If RAID but
4483 * not a physical ID as well, skip DV.
4485 if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
4486 goto target_done;
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
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);
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;
4515 /* Wide - narrow - wide workaround case
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.
4521 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
4522 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4523 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
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;
4541 } else
4542 goto target_done;
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;
4563 goto target_done;
4565 } else if (rc == MPT_SCANDV_SENSE) {
4567 } else {
4568 /* If first command doesn't complete
4569 * with a good status or with a check condition,
4570 * exit.
4572 goto target_done;
4576 /* Reset the size for disks
4578 inq0 = (*pbuf1) & 0x1F;
4579 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
4580 sz = 0x40;
4581 iocmd.size = sz;
4584 /* Another GEM workaround. Check peripheral device type,
4585 * if PROCESSOR, quit DV.
4587 if (inq0 == TYPE_PROCESSOR) {
4588 mptscsih_initTarget(hd,
4589 bus,
4591 lun,
4592 pbuf1,
4593 sz);
4594 goto target_done;
4597 if (inq0 > 0x08)
4598 goto target_done;
4600 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4601 goto target_done;
4603 if (sz == 0x40) {
4604 if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
4605 && (pTarget->minSyncFactor > 0x09)) {
4606 if ((pbuf1[56] & 0x04) == 0)
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;
4616 dv.max.factor = pTarget->minSyncFactor;
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]));
4628 if (doFallback)
4629 dv.cmd = MPT_FALLBACK;
4630 else
4631 dv.cmd = MPT_SET_MAX;
4633 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4634 if (mpt_config(hd->ioc, &cfg) != 0)
4635 goto target_done;
4637 if ((!dv.now.width) && (!dv.now.offset))
4638 goto target_done;
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.
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;
4662 cfg.hdr = &header0;
4663 cfg.physAddr = cfg0_dma_addr;
4664 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4665 cfg.dir = 0;
4667 if (mpt_config(hd->ioc, &cfg) != 0)
4668 goto target_done;
4670 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
4671 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
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.
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
4685 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
4686 readPage0 = 1;
4690 /* Quantum workaround. Restart this test will the fallback
4691 * flag set.
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,
4704 lun,
4705 pbuf1,
4706 sz);
4707 break; /* test complete */
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;
4721 firstPass = 0;
4724 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
4726 if (ioc->spi_data.mpt_dv == 0)
4727 goto target_done;
4729 inq0 = (*pbuf1) & 0x1F;
4731 /* Continue only for disks
4733 if (inq0 != 0)
4734 goto target_done;
4736 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
4737 goto target_done;
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
4747 cfg.hdr = &header1;
4748 cfg.physAddr = cfg1_dma_addr;
4749 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4750 cfg.dir = 1;
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;
4761 if (hd->pLocal == NULL)
4762 goto target_done;
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));
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.
4788 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4789 ioc->name));
4790 goto target_done;
4792 } else
4793 goto target_done;
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;
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;
4810 notDone = 1;
4811 while (notDone) {
4812 bufsize = 0;
4814 /* If not ready after 8 trials,
4815 * give up on this device.
4817 if (notDone > 8)
4818 goto target_done;
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]));
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];
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.
4856 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4857 ioc->name));
4858 goto target_done;
4860 } else {
4861 /* All other errors are fatal
4863 goto target_done;
4868 if (iocmd.flags & MPT_ICFLAG_ECHO)
4869 echoBufSize = bufsize;
4870 else
4871 dataBufSize = bufsize;
4873 sz = 0;
4874 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
4876 /* Use echo buffers if possible,
4877 * Exit if both buffers are 0.
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;
4888 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
4889 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
4891 /* Data buffers for write-read-compare test max 1K.
4893 sz = min(bufsize, 1024);
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
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;
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;
4926 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4928 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
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
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));
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;
4965 } else {
4966 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
4967 ioc->name));
4968 goto target_done;
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).
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);
4998 if (mpt_config(hd->ioc, &cfg) != 0)
4999 goto target_done;
5001 if ((!dv.now.width) && (!dv.now.offset))
5002 goto target_done;
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.
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;
5026 goto target_done;
5028 else
5029 goto target_done;
5030 } else {
5031 /* fatal error */
5032 goto target_done;
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.
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.
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.
5070 goto target_done;
5073 /* Had an actual miscompare. Slow down.*/
5074 dv.cmd = MPT_FALLBACK;
5075 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5077 if (mpt_config(hd->ioc, &cfg) != 0)
5078 goto target_done;
5080 if ((!dv.now.width) && (!dv.now.offset))
5081 goto target_done;
5084 patt = -1;
5085 continue;
5087 } else if (rc == MPT_SCANDV_DID_RESET) {
5088 /* Do Fallback and restart
5089 * this test (re-issue reserve
5090 * because of bus reset).
5092 dv.cmd = MPT_FALLBACK;
5093 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5095 if (mpt_config(hd->ioc, &cfg) != 0)
5096 goto target_done;
5098 if ((!dv.now.width) && (!dv.now.offset))
5099 goto target_done;
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.
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;
5115 else
5116 goto target_done;
5117 } else {
5118 /* fatal error */
5119 goto target_done;
5123 } /* --- end of patt loop ---- */
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);
5144 /* Set if cfg1_dma_addr contents is valid
5146 if ((cfg.hdr != NULL) && (retcode == 0)){
5147 /* If disk, not U320, disable QAS
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));
5155 dv.cmd = MPT_SAVE;
5156 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5158 /* Double writes to SDP1 can cause problems,
5159 * skip save of the final negotiated settings to
5160 * SCSI device page 1.
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);
5170 /* If this is a RAID Passthrough, enable internal IOs
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));
5177 /* Done with the DV scan of the current target
5179 if (pDvBuf)
5180 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
5182 ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
5183 ioc->name, id));
5185 return retcode;
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.
5195 static void
5196 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
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;
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.
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;
5235 } else {
5236 width = MPT_NARROW;
5237 offset = 0;
5238 factor = MPT_ASYNC;
5241 /* Set the negotiation flags */
5242 negoFlags = hd->ioc->spi_data.noQas;
5243 if (!width)
5244 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5246 if (!offset)
5247 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
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);
5255 /* Check Consistency */
5256 if (offset && (factor < MPT_ULTRA2) && !width)
5257 factor = MPT_ULTRA2;
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;
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;
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;
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;
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);
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;
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;
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);
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;
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;
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;
5386 } else {
5387 width = MPT_NARROW;
5388 factor = MPT_ASYNC;
5390 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
5391 dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
5393 dv->now.width = width;
5394 dv->now.offset = offset;
5395 dv->now.factor = factor;
5396 dv->now.flags = dv->max.flags;
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));
5405 pPage1->RequestedParameters = le32_to_cpu(val);
5406 pPage1->Reserved = 0;
5407 pPage1->Configuration = le32_to_cpu(configuration);
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;
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));
5420 /* Save these values to target structures
5421 * or overwrite nvram (phys disks only).
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
5433 if (hd->ioc->spi_data.nvram) {
5434 data = hd->ioc->spi_data.nvram[id];
5436 if (dv->now.width)
5437 data &= ~MPT_NVRAM_WIDE_DISABLE;
5438 else
5439 data |= MPT_NVRAM_WIDE_DISABLE;
5441 if (!dv->now.offset)
5442 factor = MPT_ASYNC;
5444 data &= ~MPT_NVRAM_SYNC_MASK;
5445 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
5447 hd->ioc->spi_data.nvram[id] = data;
5450 break;
5454 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5455 /* mptscsih_fillbuf - fill a buffer with a special data pattern
5456 * cleanup. For bus scan only.
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)
5463 static void
5464 mptscsih_fillbuf(char *buffer, int size, int index, int width)
5466 char *ptr = buffer;
5467 int ii;
5468 char byte;
5469 short val;
5471 switch (index) {
5472 case 0:
5474 if (width) {
5475 /* Pattern: 0000 FFFF 0000 FFFF
5477 for (ii=0; ii < size; ii++, ptr++) {
5478 if (ii & 0x02)
5479 *ptr = 0xFF;
5480 else
5481 *ptr = 0x00;
5483 } else {
5484 /* Pattern: 00 FF 00 FF
5486 for (ii=0; ii < size; ii++, ptr++) {
5487 if (ii & 0x01)
5488 *ptr = 0xFF;
5489 else
5490 *ptr = 0x00;
5493 break;
5495 case 1:
5496 if (width) {
5497 /* Pattern: 5555 AAAA 5555 AAAA 5555
5499 for (ii=0; ii < size; ii++, ptr++) {
5500 if (ii & 0x02)
5501 *ptr = 0xAA;
5502 else
5503 *ptr = 0x55;
5505 } else {
5506 /* Pattern: 55 AA 55 AA 55
5508 for (ii=0; ii < size; ii++, ptr++) {
5509 if (ii & 0x01)
5510 *ptr = 0xAA;
5511 else
5512 *ptr = 0x55;
5515 break;
5517 case 2:
5518 /* Pattern: 00 01 02 03 04 05
5519 * ... FE FF 00 01..
5521 for (ii=0; ii < size; ii++, ptr++)
5522 *ptr = (char) ii;
5523 break;
5525 case 3:
5526 if (width) {
5527 /* Wide Pattern: FFFE 0001 FFFD 0002
5528 * ... 4000 DFFF 8000 EFFF
5530 byte = 0;
5531 for (ii=0; ii < size/2; ii++) {
5532 /* Create the base pattern
5534 val = (1 << byte);
5535 /* every 64 (0x40) bytes flip the pattern
5536 * since we fill 2 bytes / iteration,
5537 * test for ii = 0x20
5539 if (ii & 0x20)
5540 val = ~(val);
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);
5555 ptr++;
5557 } else {
5558 /* Narrow Pattern: FE 01 FD 02 FB 04
5559 * .. 7F 80 01 FE 02 FD ... 80 7F
5561 byte = 0;
5562 for (ii=0; ii < size; ii++, ptr++) {
5563 /* Base pattern - first 32 bytes
5565 if (ii & 0x01) {
5566 *ptr = (1 << byte);
5567 byte++;
5568 byte &= 0x07;
5569 } else {
5570 *ptr = (char) (~(1 << byte));
5573 /* Flip the pattern every 32 bytes
5575 if (ii & 0x20)
5576 *ptr = ~(*ptr);
5579 break;
5582 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
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);
5609 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/