2 * linux/drivers/message/fusion/mptscsih.c
3 * High performance SCSI / Fibre Channel SCSI Host device driver.
4 * For use with PCI chip/adapter(s):
5 * LSIFC9xx/LSI409xx Fibre Channel
6 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
9 * This driver would not exist if not for Alan Cox's development
10 * of the linux i2o driver.
12 * A special thanks to Pamela Delaney (LSI Logic) for tons of work
13 * and countless enhancements while adding support for the 1030
14 * chip family. Pam has been instrumental in the development of
15 * of the 2.xx.xx series fusion drivers, and her contributions are
16 * far too numerous to hope to list in one place.
18 * A huge debt of gratitude is owed to David S. Miller (DaveM)
19 * for fixing much of the stupid and broken stuff in the early
20 * driver while porting to sparc64 platform. THANK YOU!
24 * Copyright (c) 1999-2004 LSI Logic Corporation
25 * Original author: Steven J. Ralston
26 * (mailto:sjralston1@netscape.net)
27 * (mailto:mpt_linux_developer@lsil.com)
29 * $Id: mptscsih.c,v 1.104 2002/12/03 21:26:34 pdelaney Exp $
31 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
33 This program is free software; you can redistribute it and/or modify
34 it under the terms of the GNU General Public License as published by
35 the Free Software Foundation; version 2 of the License.
37 This program is distributed in the hope that it will be useful,
38 but WITHOUT ANY WARRANTY; without even the implied warranty of
39 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 GNU General Public License for more details.
43 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
44 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
45 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
46 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
47 solely responsible for determining the appropriateness of using and
48 distributing the Program and assumes all risks associated with its
49 exercise of rights under this Agreement, including but not limited to
50 the risks and costs of program errors, damage to or loss of data,
51 programs or equipment, and unavailability or interruption of operations.
53 DISCLAIMER OF LIABILITY
54 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
55 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
57 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
58 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
59 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
60 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
62 You should have received a copy of the GNU General Public License
63 along with this program; if not, write to the Free Software
64 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
66 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
68 #include <linux/module.h>
69 #include <linux/kernel.h>
70 #include <linux/init.h>
71 #include <linux/errno.h>
72 #include <linux/kdev_t.h>
73 #include <linux/blkdev.h>
74 #include <linux/delay.h> /* for mdelay */
75 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
76 #include <linux/reboot.h> /* notifier code */
77 #include <linux/sched.h>
78 #include <linux/workqueue.h>
79 #include "../../scsi/scsi.h"
80 #include <scsi/scsi_host.h>
87 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
88 #define my_NAME "Fusion MPT SCSI Host driver"
89 #define my_VERSION MPT_LINUX_VERSION_COMMON
90 #define MYNAM "mptscsih"
92 MODULE_AUTHOR(MODULEAUTHOR);
93 MODULE_DESCRIPTION(my_NAME);
94 MODULE_LICENSE("GPL");
96 /* Set string for command line args from insmod */
101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
103 typedef struct _BIG_SENSE_BUF {
104 u8 data[MPT_SENSE_BUFFER_ALLOC];
107 #define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
108 #define MPT_SCANDV_DID_RESET (0x00000001)
109 #define MPT_SCANDV_SENSE (0x00000002)
110 #define MPT_SCANDV_SOME_ERROR (0x00000004)
111 #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
112 #define MPT_SCANDV_ISSUE_SENSE (0x00000010)
114 #define MPT_SCANDV_MAX_RETRIES (10)
116 #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
117 #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
118 #define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */
119 #define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */
120 #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
121 #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
123 typedef struct _internal_cmd {
124 char *data; /* data pointer */
125 dma_addr_t data_dma; /* data dma address */
126 int size; /* transfer size */
127 u8 cmd; /* SCSI Op Code */
128 u8 bus; /* bus number */
129 u8 id; /* SCSI ID (virtual) */
131 u8 flags; /* Bit Field - See above */
132 u8 physDiskNum; /* Phys disk number, -1 else */
137 typedef struct _negoparms {
144 typedef struct _dv_parameters {
154 * Other private/forward protos...
156 static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
157 static void mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
158 static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
160 static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
161 SCSIIORequest_t *pReq, int req_idx);
162 static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
163 static int mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
164 static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
165 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
166 static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
167 static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
168 static void post_pendingQ_commands(MPT_SCSI_HOST *hd);
170 static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
171 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
173 static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
174 static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
176 static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
177 void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
178 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
179 static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
180 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
181 static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
182 static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
183 static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
184 static void mptscsih_timer_expired(unsigned long data);
185 static void mptscsih_taskmgmt_timeout(unsigned long data);
186 static void mptscsih_schedule_reset(void *hd);
187 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
188 static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
190 static struct work_struct mptscsih_rstTask;
192 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
193 static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
194 static void mptscsih_domainValidation(void *hd);
195 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
196 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
197 static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
198 static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
199 static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
202 static int mptscsih_setup(char *str);
204 /* module entry point */
205 static int __init mptscsih_init (void);
206 static void __exit mptscsih_exit (void);
208 static int mptscsih_probe (struct pci_dev *, const struct pci_device_id *);
209 static void mptscsih_remove(struct pci_dev *);
210 static void mptscsih_shutdown(struct device *);
212 static int mptscsih_suspend(struct pci_dev *pdev, u32 state);
213 static int mptscsih_resume(struct pci_dev *pdev);
221 static int mpt_scsi_hosts = 0;
223 static int ScsiDoneCtx = -1;
224 static int ScsiTaskCtx = -1;
225 static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
227 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
229 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
231 * Domain Validation task structure
233 static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
234 static int dvtaskQ_active = 0;
235 static int dvtaskQ_release = 0;
236 static struct work_struct mptscsih_dvTask;
242 static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
243 static int scandv_wait_done = 1;
245 /* Driver default setup
247 static struct mptscsih_driver_setup
248 driver_setup = MPTSCSIH_DRIVER_SETUP;
250 #ifdef MPTSCSIH_DBG_TIMEOUT
251 static Scsi_Cmnd *foo_to[8];
254 static struct scsi_host_template driver_template;
256 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
258 * Private inline routines...
260 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
261 /* 19991030 -sralston
262 * Return absolute SCSI data direction:
267 * Changed: 3-20-2002 pdelaney to use the default data
268 * direction and the defines set up in the
270 * 1 = _DATA_OUT changed to SCSI_DATA_WRITE (1)
271 * 0 = _DIR_NONE changed to SCSI_DATA_NONE (3)
272 * -1 = _DATA_IN changed to SCSI_DATA_READ (2)
273 * If the direction is unknown, fall through to original code.
275 * Mid-layer bug fix(): sg interface generates the wrong data
276 * direction in some cases. Set the direction the hard way for
277 * the most common commands.
280 mptscsih_io_direction(Scsi_Cmnd *cmd)
282 switch (cmd->cmnd[0]) {
286 return SCSI_DATA_WRITE;
291 return SCSI_DATA_READ;
295 if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN)
296 return cmd->sc_data_direction;
298 switch (cmd->cmnd[0]) {
299 /* _DATA_OUT commands */
300 case WRITE_6: case WRITE_10: case WRITE_12:
302 case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
303 case WRITE_VERIFY: case WRITE_VERIFY_12:
304 case COMPARE: case COPY: case COPY_VERIFY:
305 case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
306 case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12:
307 case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT:
308 case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK:
309 case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG:
310 case REASSIGN_BLOCKS:
311 case PERSISTENT_RESERVE_OUT:
314 return SCSI_DATA_WRITE;
316 /* No data transfer commands */
317 case SEEK_6: case SEEK_10:
318 case RESERVE: case RELEASE:
319 case TEST_UNIT_READY:
321 case ALLOW_MEDIUM_REMOVAL:
322 return SCSI_DATA_NONE;
324 /* Conditional data transfer commands */
326 if (cmd->cmnd[1] & 0x10) /* FmtData (data out phase)? */
327 return SCSI_DATA_WRITE;
329 return SCSI_DATA_NONE;
332 if (cmd->cmnd[1] & 0x02) /* VERIFY:BYTCHK (data out phase)? */
333 return SCSI_DATA_WRITE;
335 return SCSI_DATA_NONE;
338 if (cmd->cmnd[1] & 0x03) /* RESERVE:{LongID|Extent} (data out phase)? */
339 return SCSI_DATA_WRITE;
341 return SCSI_DATA_NONE;
343 /* Must be data _IN! */
345 return SCSI_DATA_READ;
347 } /* mptscsih_io_direction() */
349 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
351 * mptscsih_add_sge - Place a simple SGE at address pAddr.
352 * @pAddr: virtual address for SGE
353 * @flagslength: SGE flags and data transfer length
354 * @dma_addr: Physical address
356 * This routine places a MPT request frame back on the MPT adapter's
360 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
362 if (sizeof(dma_addr_t) == sizeof(u64)) {
363 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
364 u32 tmp = dma_addr & 0xFFFFFFFF;
366 pSge->FlagsLength = cpu_to_le32(flagslength);
367 pSge->Address.Low = cpu_to_le32(tmp);
368 tmp = (u32) ((u64)dma_addr >> 32);
369 pSge->Address.High = cpu_to_le32(tmp);
372 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
373 pSge->FlagsLength = cpu_to_le32(flagslength);
374 pSge->Address = cpu_to_le32(dma_addr);
376 } /* mptscsih_add_sge() */
378 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
380 * mptscsih_add_chain - Place a chain SGE at address pAddr.
381 * @pAddr: virtual address for SGE
382 * @next: nextChainOffset value (u32's)
383 * @length: length of next SGL segment
384 * @dma_addr: Physical address
386 * This routine places a MPT request frame back on the MPT adapter's
390 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
392 if (sizeof(dma_addr_t) == sizeof(u64)) {
393 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
394 u32 tmp = dma_addr & 0xFFFFFFFF;
396 pChain->Length = cpu_to_le16(length);
397 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
399 pChain->NextChainOffset = next;
401 pChain->Address.Low = cpu_to_le32(tmp);
402 tmp = (u32) ((u64)dma_addr >> 32);
403 pChain->Address.High = cpu_to_le32(tmp);
405 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
406 pChain->Length = cpu_to_le16(length);
407 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
408 pChain->NextChainOffset = next;
409 pChain->Address = cpu_to_le32(dma_addr);
411 } /* mptscsih_add_chain() */
413 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
415 * mptscsih_getFreeChainBuffes - Function to get a free chain
416 * from the MPT_SCSI_HOST FreeChainQ.
417 * @hd: Pointer to the MPT_SCSI_HOST instance
418 * @req_idx: Index of the SCSI IO request frame. (output)
420 * return SUCCESS or FAILED
423 mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
425 MPT_FRAME_HDR *chainBuf;
430 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
431 if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
435 chainBuf = hd->FreeChainQ.head;
436 Q_DEL_ITEM(&chainBuf->u.frame.linkage);
437 offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
438 chain_idx = offset / hd->ioc->req_sz;
443 chain_idx = MPT_HOST_NO_CHAIN;
445 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
448 *retIndex = chain_idx;
450 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
451 hd->ioc->name, *retIndex, chainBuf));
454 } /* mptscsih_getFreeChainBuffer() */
456 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
458 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
459 * SCSIIORequest_t Message Frame.
460 * @hd: Pointer to MPT_SCSI_HOST structure
461 * @SCpnt: Pointer to Scsi_Cmnd structure
462 * @pReq: Pointer to SCSIIORequest_t structure
467 mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
468 SCSIIORequest_t *pReq, int req_idx)
472 struct scatterlist *sg;
474 int sges_left, sg_done;
475 int chain_idx = MPT_HOST_NO_CHAIN;
477 int numSgeSlots, numSgeThisFrame;
478 u32 sgflags, sgdir, thisxfer = 0;
479 int chain_dma_off = 0;
484 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
485 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
486 sgdir = MPT_TRANSFER_HOST_TO_IOC;
488 sgdir = MPT_TRANSFER_IOC_TO_HOST;
491 psge = (char *) &pReq->SGL;
492 frm_sz = hd->ioc->req_sz;
494 /* Map the data portion, if any.
495 * sges_left = 0 if no data transfer.
497 if ( (sges_left = SCpnt->use_sg) ) {
498 sges_left = pci_map_sg(hd->ioc->pcidev,
499 (struct scatterlist *) SCpnt->request_buffer,
501 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
504 } else if (SCpnt->request_bufflen) {
505 dma_addr_t buf_dma_addr;
508 buf_dma_addr = pci_map_single(hd->ioc->pcidev,
509 SCpnt->request_buffer,
510 SCpnt->request_bufflen,
511 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
513 /* We hide it here for later unmap. */
514 my_priv = (scPrivate *) &SCpnt->SCp;
515 my_priv->p1 = (void *)(ulong) buf_dma_addr;
517 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
518 hd->ioc->name, SCpnt, SCpnt->request_bufflen));
520 mptscsih_add_sge((char *) &pReq->SGL,
521 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
527 /* Handle the SG case.
529 sg = (struct scatterlist *) SCpnt->request_buffer;
531 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
534 /* Prior to entering this loop - the following must be set
535 * current MF: sgeOffset (bytes)
536 * chainSge (Null if original MF is not a chain buffer)
537 * sg_done (num SGE done for this MF)
541 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
542 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
544 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
546 /* Get first (num - 1) SG elements
547 * Skip any SG entries with a length of 0
548 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
550 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
551 thisxfer = sg_dma_len(sg);
553 sg ++; /* Get next SG element from the OS */
558 v2 = sg_dma_address(sg);
559 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
561 sg++; /* Get next SG element from the OS */
562 psge += (sizeof(u32) + sizeof(dma_addr_t));
563 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
567 if (numSgeThisFrame == sges_left) {
568 /* Add last element, end of buffer and end of list flags.
570 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
571 MPT_SGE_FLAGS_END_OF_BUFFER |
572 MPT_SGE_FLAGS_END_OF_LIST;
574 /* Add last SGE and set termination flags.
575 * Note: Last SGE may have a length of 0 - which should be ok.
577 thisxfer = sg_dma_len(sg);
579 v2 = sg_dma_address(sg);
580 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
583 psge += (sizeof(u32) + sizeof(dma_addr_t));
585 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
589 /* The current buffer is a chain buffer,
590 * but there is not another one.
591 * Update the chain element
592 * Offset and Length fields.
594 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
596 /* The current buffer is the original MF
597 * and there is no Chain buffer.
599 pReq->ChainOffset = 0;
602 /* At least one chain buffer is needed.
603 * Complete the first MF
604 * - last SGE element, set the LastElement bit
605 * - set ChainOffset (words) for orig MF
606 * (OR finish previous MF chain buffer)
607 * - update MFStructPtr ChainIndex
608 * - Populate chain element
613 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
614 hd->ioc->name, sg_done));
616 /* Set LAST_ELEMENT flag for last non-chain element
617 * in the buffer. Since psge points at the NEXT
618 * SGE element, go back one SGE element, update the flags
619 * and reset the pointer. (Note: sgflags & thisxfer are already
623 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
624 sgflags = le32_to_cpu(*ptmp);
625 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
626 *ptmp = cpu_to_le32(sgflags);
630 /* The current buffer is a chain buffer.
631 * chainSge points to the previous Chain Element.
632 * Update its chain element Offset and Length (must
633 * include chain element size) fields.
634 * Old chain element is now complete.
636 u8 nextChain = (u8) (sgeOffset >> 2);
637 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
638 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
640 /* The original MF buffer requires a chain buffer -
642 * Last element in this MF is a chain element.
644 pReq->ChainOffset = (u8) (sgeOffset >> 2);
647 sges_left -= sg_done;
650 /* NOTE: psge points to the beginning of the chain element
651 * in current buffer. Get a chain buffer.
653 if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
656 /* Update the tracking arrays.
657 * If chainSge == NULL, update ReqToChain, else ChainToChain
660 hd->ChainToChain[chain_idx] = newIndex;
662 hd->ReqToChain[req_idx] = newIndex;
664 chain_idx = newIndex;
665 chain_dma_off = hd->ioc->req_sz * chain_idx;
667 /* Populate the chainSGE for the current buffer.
668 * - Set chain buffer pointer to psge and fill
669 * out the Address and Flags fields.
671 chainSge = (char *) psge;
672 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
675 /* Start the SGE for the next buffer
677 psge = (char *) (hd->ChainBuffer + chain_dma_off);
681 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
684 /* Start the SGE for the next buffer
691 } /* mptscsih_AddSGE() */
693 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
695 * mptscsih_io_done - Main SCSI IO callback routine registered to
696 * Fusion MPT (base) driver
697 * @ioc: Pointer to MPT_ADAPTER structure
698 * @mf: Pointer to original MPT request frame
699 * @r: Pointer to MPT reply frame (NULL if TurboReply)
701 * This routine is called from mpt.c::mpt_interrupt() at the completion
702 * of any SCSI IO request.
703 * This routine is registered with the Fusion MPT (base) driver at driver
704 * load/init time via the mpt_register() API call.
706 * Returns 1 indicating alloc'd request frame ptr should be freed.
709 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
713 SCSIIORequest_t *pScsiReq;
714 SCSIIOReply_t *pScsiReply;
717 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
719 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
720 sc = hd->ScsiLookup[req_idx];
722 MPIHeader_t *hdr = (MPIHeader_t *)mf;
724 /* Remark: writeSDP1 will use the ScsiDoneCtx
725 * If a SCSI I/O cmd, device disabled by OS and
726 * completion done. Cannot touch sc struct. Just free mem.
728 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
729 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
732 mptscsih_freeChainBuffers(hd, req_idx);
736 dmfprintk((MYIOC_s_INFO_FMT
737 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
738 ioc->name, mf, mr, sc, req_idx));
740 sc->result = DID_OK << 16; /* Set default reply as OK */
741 pScsiReq = (SCSIIORequest_t *) mf;
742 pScsiReply = (SCSIIOReply_t *) mr;
744 #ifdef MPTSCSIH_DBG_TIMEOUT
745 if (ioc->timeout_cnt > 0) {
748 for (ii=0; ii < 8; ii++) {
749 if (sc == foo_to[ii]) {
750 printk(MYIOC_s_INFO_FMT "complete (%p, %ld)\n",
751 ioc->name, sc, jiffies);
754 if (foo_to[ii] != NULL)
759 ioc->timeout_maxcnt = 0;
760 ioc->timeout_cnt = 0;
765 if (pScsiReply == NULL) {
766 /* special context reply handling */
771 u8 scsi_state, scsi_status;
773 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
774 scsi_state = pScsiReply->SCSIState;
776 dprintk((KERN_NOTICE " Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
777 ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
779 dprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh"
780 ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
781 status, scsi_state, pScsiReply->SCSIStatus,
782 le32_to_cpu(pScsiReply->IOCLogInfo)));
784 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
785 copy_sense_data(sc, hd, mf, pScsiReply);
788 * Look for + dump FCP ResponseInfo[]!
790 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
791 printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n",
792 le32_to_cpu(pScsiReply->ResponseInfo));
796 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
798 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
799 * But not: DID_BUS_BUSY lest one risk
800 * killing interrupt handler:-(
802 sc->result = STS_BUSY;
805 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
806 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
807 sc->result = DID_BAD_TARGET << 16;
810 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
811 /* Spoof to SCSI Selection Timeout! */
812 sc->result = DID_NO_CONNECT << 16;
814 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
815 hd->sel_timeout[pScsiReq->TargetID]++;
818 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
819 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
820 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
821 /* Linux handles an unsolicited DID_RESET better
822 * than an unsolicited DID_ABORT.
824 sc->result = DID_RESET << 16;
826 /* GEM Workaround. */
828 mptscsih_no_negotiate(hd, sc->device->id);
831 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
832 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
834 * Do upfront check for valid SenseData and give it
837 scsi_status = pScsiReply->SCSIStatus;
838 sc->result = (DID_OK << 16) | scsi_status;
839 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
840 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
841 /* Have already saved the status and sense data
845 if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) {
846 sc->result = DID_SOFT_ERROR << 16;
848 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
851 sc->result = DID_SOFT_ERROR << 16;
853 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
854 /* Not real sure here either... */
855 sc->result = DID_RESET << 16;
859 /* Give report and update residual count.
861 dprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
863 dprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
865 sc->resid = sc->request_bufflen - xfer_cnt;
866 dprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid));
870 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
871 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
875 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
876 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
877 sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
878 if (scsi_state == 0) {
880 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
882 * If running against circa 200003dd 909 MPT f/w,
883 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
884 * (QUEUE_FULL) returned from device! --> get 0x0000?128
885 * and with SenseBytes set to 0.
887 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
888 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
891 else if (scsi_state &
892 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
897 sc->result = DID_SOFT_ERROR << 16;
899 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
900 /* Not real sure here either... */
901 sc->result = DID_RESET << 16;
903 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
904 /* Device Inq. data indicates that it supports
905 * QTags, but rejects QTag messages.
906 * This command completed OK.
908 * Not real sure here either so do nothing... */
911 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
912 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
915 * Reservation Conflict, Busy,
916 * Command Terminated, CHECK
920 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
921 sc->result = DID_SOFT_ERROR << 16;
924 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
925 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
926 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
927 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
928 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
929 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
930 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
931 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
932 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
933 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
938 sc->result = DID_SOFT_ERROR << 16;
941 } /* switch(status) */
943 dprintk((KERN_NOTICE " sc->result set to %08xh\n", sc->result));
944 } /* end of address reply case */
946 /* Unmap the DMA buffers, if any. */
948 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
949 sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
950 } else if (sc->request_bufflen) {
953 my_priv = (scPrivate *) &sc->SCp;
954 pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
956 scsi_to_pci_dma_dir(sc->sc_data_direction));
959 hd->ScsiLookup[req_idx] = NULL;
961 sc->scsi_done(sc); /* Issue the command callback */
963 /* Free Chain buffers */
964 mptscsih_freeChainBuffers(hd, req_idx);
969 * Flush all commands on the doneQ.
970 * Lock Q when deleting/adding members
971 * Lock io_request_lock for OS callback.
974 flush_doneQ(MPT_SCSI_HOST *hd)
982 dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n"));
984 spin_lock_irqsave(&hd->freedoneQlock, flags);
985 if (Q_IS_EMPTY(&hd->doneQ)) {
986 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
990 buffer = hd->doneQ.head;
995 /* Set the Scsi_Cmnd pointer
997 SCpnt = (Scsi_Cmnd *) buffer->argp;
1002 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1003 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1005 /* Do the OS callback.
1007 SCpnt->scsi_done(SCpnt);
1014 * Search the doneQ for a specific command. If found, delete from Q.
1015 * Calling function will finish processing.
1018 search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt)
1020 unsigned long flags;
1023 spin_lock_irqsave(&hd->freedoneQlock, flags);
1024 if (!Q_IS_EMPTY(&hd->doneQ)) {
1025 buffer = hd->doneQ.head;
1027 Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp;
1030 SCpnt->result = sc->result;
1032 /* Set the Scsi_Cmnd pointer
1034 buffer->argp = NULL;
1038 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1041 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ);
1043 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1048 * mptscsih_flush_running_cmds - For each command found, search
1049 * Scsi_Host instance taskQ and reply to OS.
1050 * Called only if recovering from a FW reload.
1051 * @hd: Pointer to a SCSI HOST structure
1055 * Must be called while new I/Os are being queued.
1058 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
1064 int max = hd->ioc->req_depth;
1065 unsigned long flags;
1067 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
1068 for (ii= 0; ii < max; ii++) {
1069 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
1074 /* Search pendingQ, if found,
1077 mptscsih_search_pendingQ(hd, ii);
1079 /* Null ScsiLookup index
1081 hd->ScsiLookup[ii] = NULL;
1083 mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);
1084 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
1087 /* Set status, free OS resources (SG DMA buffers)
1089 * Free driver resources (chain, msg buffers)
1091 if (scsi_device_online(SCpnt->device)) {
1092 if (SCpnt->use_sg) {
1093 pci_unmap_sg(hd->ioc->pcidev,
1094 (struct scatterlist *) SCpnt->request_buffer,
1096 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1097 } else if (SCpnt->request_bufflen) {
1100 my_priv = (scPrivate *) &SCpnt->SCp;
1101 pci_unmap_single(hd->ioc->pcidev,
1102 (dma_addr_t)(ulong)my_priv->p1,
1103 SCpnt->request_bufflen,
1104 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1107 SCpnt->result = DID_RESET << 16;
1108 SCpnt->host_scribble = NULL;
1110 /* Free Chain buffers */
1111 mptscsih_freeChainBuffers(hd, ii);
1113 /* Free Message frames */
1114 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
1117 /* Post to doneQ, do not reply until POST phase
1118 * of reset handler....prevents new commands from
1121 spin_lock_irqsave(&hd->freedoneQlock, flags);
1122 if (!Q_IS_EMPTY(&hd->freeQ)) {
1123 buffer = hd->freeQ.head;
1126 /* Set the Scsi_Cmnd pointer
1128 buffer->argp = (void *)SCpnt;
1132 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
1133 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1135 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1136 SCpnt->scsi_done(SCpnt);
1139 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
1149 * mptscsih_search_running_cmds - Delete any commands associated
1150 * with the specified target and lun. Function called only
1151 * when a lun is disable by mid-layer.
1152 * Do NOT access the referenced Scsi_Cmnd structure or
1153 * members. Will cause either a paging or NULL ptr error.
1154 * @hd: Pointer to a SCSI HOST structure
1155 * @target: target id
1160 * Called from slave_destroy.
1163 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
1165 SCSIIORequest_t *mf = NULL;
1167 int max = hd->ioc->req_depth;
1169 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
1172 for (ii=0; ii < max; ii++) {
1173 if (hd->ScsiLookup[ii] != NULL) {
1175 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
1177 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
1178 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
1180 if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
1185 hd->ScsiLookup[ii] = NULL;
1186 mptscsih_freeChainBuffers(hd, ii);
1187 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, (MPT_FRAME_HDR *)mf);
1194 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1196 * mptscsih_initChainBuffers - Allocate memory for and initialize
1197 * chain buffers, chain buffer control arrays and spinlock.
1198 * @hd: Pointer to MPT_SCSI_HOST structure
1199 * @init: If set, initialize the spin lock.
1202 mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
1204 MPT_FRAME_HDR *chain;
1206 unsigned long flags;
1207 int sz, ii, num_chain;
1210 /* chain buffer allocation done from PrimeIocFifos */
1211 if (hd->ioc->fifo_pool == NULL)
1214 hd->ChainBuffer = hd->ioc->chain_alloc;
1215 hd->ChainBufferDMA = hd->ioc->chain_alloc_dma;
1217 dprintk((KERN_INFO " ChainBuffer @ %p(%p), sz=%d\n",
1218 hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, hd->ioc->chain_alloc_sz));
1220 /* ReqToChain size must equal the req_depth
1223 if (hd->ReqToChain == NULL) {
1224 sz = hd->ioc->req_depth * sizeof(int);
1225 mem = kmalloc(sz, GFP_ATOMIC);
1229 hd->ReqToChain = (int *) mem;
1231 for (ii = 0; ii < hd->ioc->req_depth; ii++)
1232 hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
1234 /* ChainToChain size must equal the total number
1235 * of chain buffers to be allocated.
1238 * Calculate the number of chain buffers needed(plus 1) per I/O
1239 * then multiply the the maximum number of simultaneous cmds
1241 * num_sge = num sge in request frame + last chain buffer
1242 * scale = num sge per chain buffer if no chain element
1244 scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1245 if (sizeof(dma_addr_t) == sizeof(u64))
1246 num_sge = scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
1248 num_sge = 1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
1251 while (hd->max_sge - num_sge > 0) {
1253 num_sge += (scale - 1);
1257 if ((int) hd->ioc->chip_type > (int) FC929)
1258 num_chain *= MPT_SCSI_CAN_QUEUE;
1260 num_chain *= MPT_FC_CAN_QUEUE;
1262 hd->num_chain = num_chain;
1264 sz = num_chain * sizeof(int);
1265 if (hd->ChainToChain == NULL) {
1266 mem = kmalloc(sz, GFP_ATOMIC);
1270 hd->ChainToChain = (int *) mem;
1272 mem = (u8 *) hd->ChainToChain;
1274 memset(mem, 0xFF, sz);
1277 /* Initialize the free chain Q.
1280 spin_lock_init(&hd->FreeChainQlock);
1283 spin_lock_irqsave (&hd->FreeChainQlock, flags);
1284 Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);
1286 /* Post the chain buffers to the FreeChainQ.
1288 mem = (u8 *)hd->ChainBuffer;
1289 for (ii=0; ii < num_chain; ii++) {
1290 chain = (MPT_FRAME_HDR *) mem;
1291 Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);
1292 mem += hd->ioc->req_sz;
1294 spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
1299 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1301 * Hack! It might be nice to report if a device is returning QUEUE_FULL
1302 * but maybe not each and every time...
1304 static long last_queue_full = 0;
1306 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1308 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1309 * from a SCSI target device.
1310 * @sc: Pointer to Scsi_Cmnd structure
1311 * @pScsiReply: Pointer to SCSIIOReply_t
1312 * @pScsiReq: Pointer to original SCSI request
1314 * This routine periodically reports QUEUE_FULL status returned from a
1315 * SCSI target device. It reports this to the console via kernel
1316 * printk() API call, not more than once every 10 seconds.
1319 mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1321 long time = jiffies;
1323 if (time - last_queue_full > 10 * HZ) {
1324 char *ioc_str = "ioc?";
1326 if (sc->device && sc->device->host != NULL && sc->device->host->hostdata != NULL)
1327 ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name;
1328 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1329 ioc_str, 0, sc->device->id, sc->device->lun));
1330 last_queue_full = time;
1334 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1335 static char *info_kbuf = NULL;
1337 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1338 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1340 * mptscsih_probe - Installs scsi devices per bus.
1341 * @pdev: Pointer to pci_dev structure
1343 * Returns 0 for success, non-zero for failure.
1348 mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1350 struct Scsi_Host *sh;
1352 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1353 MPT_DONE_Q *freedoneQ;
1354 unsigned long flags;
1363 /* 20010202 -sralston
1364 * Added sanity check on readiness of the MPT adapter.
1366 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1367 printk(MYIOC_s_WARN_FMT
1368 "Skipping because it's not operational!\n",
1374 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1379 /* Sanity check - ensure at least 1 port is INITIATOR capable
1382 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1383 if (ioc->pfacts[ii].ProtocolFlags &
1384 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1389 printk(MYIOC_s_WARN_FMT
1390 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1395 sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));
1398 printk(MYIOC_s_WARN_FMT
1399 "Unable to register controller with SCSI subsystem\n",
1404 spin_lock_irqsave(&ioc->FreeQlock, flags);
1406 /* Attach the SCSI Host to the IOC structure
1414 /* set 16 byte cdb's */
1415 sh->max_cmd_len = 16;
1417 /* Yikes! This is important!
1418 * Otherwise, by default, linux
1419 * only scans target IDs 0-7!
1420 * pfactsN->MaxDevices unreliable
1421 * (not supported in early
1422 * versions of the FW).
1423 * max_id = 1 + actual max id,
1424 * max_lun = 1 + actual last lun,
1427 if ((int)ioc->chip_type > (int)FC929) {
1428 sh->max_id = MPT_MAX_SCSI_DEVICES;
1430 /* For FC, increase the queue depth
1431 * from MPT_SCSI_CAN_QUEUE (31)
1432 * to MPT_FC_CAN_QUEUE (63).
1434 sh->can_queue = MPT_FC_CAN_QUEUE;
1436 MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1439 sh->max_lun = MPT_LAST_LUN + 1;
1440 sh->max_channel = 0;
1441 sh->this_id = ioc->pfacts[0].PortSCSIID;
1445 sh->unique_id = ioc->id;
1447 /* Verify that we won't exceed the maximum
1448 * number of chain buffers
1449 * We can optimize: ZZ = req_sz/sizeof(SGE)
1451 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1452 * + (req_sz - 64)/sizeof(SGE)
1453 * A slightly different algorithm is required for
1456 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1457 if (sizeof(dma_addr_t) == sizeof(u64)) {
1458 numSGE = (scale - 1) *
1459 (ioc->facts.MaxChainDepth-1) + scale +
1460 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1463 numSGE = 1 + (scale - 1) *
1464 (ioc->facts.MaxChainDepth-1) + scale +
1465 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1469 if (numSGE < sh->sg_tablesize) {
1470 /* Reset this value */
1471 dprintk((MYIOC_s_INFO_FMT
1472 "Resetting sg_tablesize to %d from %d\n",
1473 ioc->name, numSGE, sh->sg_tablesize));
1474 sh->sg_tablesize = numSGE;
1477 /* Set the pci device pointer in Scsi_Host structure.
1479 scsi_set_device(sh, &ioc->pcidev->dev);
1481 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1483 hd = (MPT_SCSI_HOST *) sh->hostdata;
1485 hd->max_sge = sh->sg_tablesize;
1487 if ((int)ioc->chip_type > (int)FC929)
1490 if (DmpService && (ioc->chip_type == FC919 ||
1491 ioc->chip_type == FC929)) {
1492 hd->is_multipath = 1;
1495 /* SCSI needs Scsi_Cmnd lookup table!
1496 * (with size equal to req_depth*PtrSz!)
1498 sz = hd->ioc->req_depth * sizeof(void *);
1499 mem = kmalloc(sz, GFP_ATOMIC);
1502 goto mptscsih_probe_failed;
1506 hd->ScsiLookup = (struct scsi_cmnd **) mem;
1508 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
1509 ioc->name, hd->ScsiLookup, sz));
1511 if (mptscsih_initChainBuffers(hd, 1) < 0) {
1513 goto mptscsih_probe_failed;
1516 /* Allocate memory for free and doneQ's
1518 sz = sh->can_queue * sizeof(MPT_DONE_Q);
1519 mem = kmalloc(sz, GFP_ATOMIC);
1522 goto mptscsih_probe_failed;
1525 memset(mem, 0xFF, sz);
1528 /* Initialize the free, done and pending Qs.
1530 Q_INIT(&hd->freeQ, MPT_DONE_Q);
1531 Q_INIT(&hd->doneQ, MPT_DONE_Q);
1532 Q_INIT(&hd->pendingQ, MPT_DONE_Q);
1533 spin_lock_init(&hd->freedoneQlock);
1536 for (ii=0; ii < sh->can_queue; ii++) {
1537 freedoneQ = (MPT_DONE_Q *) mem;
1538 Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
1539 mem += sizeof(MPT_DONE_Q);
1542 /* Initialize this Scsi_Host
1545 Q_INIT(&hd->taskQ, MPT_FRAME_HDR);
1548 /* Allocate memory for the device structures.
1549 * A non-Null pointer at an offset
1550 * indicates a device exists.
1551 * max_id = 1 + maximum id (hosts.h)
1553 sz = sh->max_id * sizeof(void *);
1554 mem = kmalloc(sz, GFP_ATOMIC);
1557 goto mptscsih_probe_failed;
1561 hd->Targets = (VirtDevice **) mem;
1564 " Targets @ %p, sz=%d\n", hd->Targets, sz));
1566 /* Clear the TM flags
1569 hd->tmState = TM_STATE_NONE;
1570 hd->resetPending = 0;
1571 hd->abortSCpnt = NULL;
1573 hd->numTMrequests = 0;
1575 /* Clear the pointer used to store
1576 * single-threaded commands, i.e., those
1577 * issued during a bus scan, dv and
1578 * configuration pages.
1582 /* Initialize this SCSI Hosts' timers
1583 * To use, set the timer expires field
1586 init_timer(&hd->timer);
1587 hd->timer.data = (unsigned long) hd;
1588 hd->timer.function = mptscsih_timer_expired;
1590 init_timer(&hd->TMtimer);
1591 hd->TMtimer.data = (unsigned long) hd;
1592 hd->TMtimer.function = mptscsih_taskmgmt_timeout;
1593 hd->qtag_tick = jiffies;
1595 /* Moved Earlier Pam D */
1598 #ifdef MPTSCSIH_DBG_TIMEOUT
1599 hd->ioc->timeout_hard = 0;
1600 hd->ioc->timeout_delta = 30 * HZ;
1601 hd->ioc->timeout_maxcnt = 0;
1602 hd->ioc->timeout_cnt = 0;
1603 for (ii=0; ii < 8; ii++)
1607 /* Update with the driver setup
1610 if (hd->ioc->spi_data.maxBusWidth >
1611 driver_setup.max_width) {
1612 hd->ioc->spi_data.maxBusWidth =
1613 driver_setup.max_width;
1616 if (hd->ioc->spi_data.minSyncFactor <
1617 driver_setup.min_sync_fac) {
1618 hd->ioc->spi_data.minSyncFactor =
1619 driver_setup.min_sync_fac;
1622 if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) {
1623 hd->ioc->spi_data.maxSyncOffset = 0;
1626 hd->ioc->spi_data.Saf_Te = driver_setup.saf_te;
1629 #ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1630 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1632 if (driver_setup.dv == 0) {
1633 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1636 hd->ioc->spi_data.forceDv = 0;
1637 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1638 hd->ioc->spi_data.dvStatus[ii] =
1639 MPT_SCSICFG_NEGOTIATE;
1642 if (hd->negoNvram == 0) {
1643 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
1644 hd->ioc->spi_data.dvStatus[ii] |=
1645 MPT_SCSICFG_DV_NOT_DONE;
1648 ddvprintk((MYIOC_s_INFO_FMT
1649 "dv %x width %x factor %x saf_te %x\n",
1650 hd->ioc->name, driver_setup.dv,
1651 driver_setup.max_width,
1652 driver_setup.min_sync_fac,
1653 driver_setup.saf_te));
1658 error = scsi_add_host (sh, &ioc->pcidev->dev);
1660 dprintk((KERN_ERR MYNAM
1661 "scsi_add_host failed\n"));
1662 goto mptscsih_probe_failed;
1668 mptscsih_probe_failed:
1670 mptscsih_remove(pdev);
1675 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1677 * mptscsih_remove - Removed scsi devices
1678 * @pdev: Pointer to pci_dev structure
1683 mptscsih_remove(struct pci_dev *pdev)
1685 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1686 struct Scsi_Host *host = ioc->sh;
1689 unsigned long flags;
1694 scsi_remove_host(host);
1696 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1697 /* Check DV thread active */
1699 spin_lock_irqsave(&dvtaskQ_lock, flags);
1700 if (dvtaskQ_active) {
1701 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1702 while(dvtaskQ_active && --count) {
1703 set_current_state(TASK_INTERRUPTIBLE);
1704 schedule_timeout(1);
1707 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1710 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
1711 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
1713 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
1717 hd = (MPT_SCSI_HOST *)host->hostdata;
1719 int sz1, sz2, sz3, sztarget=0;
1724 mptscsih_shutdown(&pdev->dev);
1726 sz1 = sz2 = sz3 = 0;
1728 if (hd->ScsiLookup != NULL) {
1729 sz1 = hd->ioc->req_depth * sizeof(void *);
1730 kfree(hd->ScsiLookup);
1731 hd->ScsiLookup = NULL;
1734 if (hd->ReqToChain != NULL) {
1735 szr2chain = hd->ioc->req_depth * sizeof(int);
1736 kfree(hd->ReqToChain);
1737 hd->ReqToChain = NULL;
1740 if (hd->ChainToChain != NULL) {
1741 szc2chain = hd->num_chain * sizeof(int);
1742 kfree(hd->ChainToChain);
1743 hd->ChainToChain = NULL;
1746 if (hd->memQ != NULL) {
1747 szQ = host->can_queue * sizeof(MPT_DONE_Q);
1752 if (hd->Targets != NULL) {
1756 * Free any target structures that were allocated.
1759 max = MPT_MAX_SCSI_DEVICES;
1761 max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1763 for (ii=0; ii < max; ii++) {
1764 if (hd->Targets[ii]) {
1765 kfree(hd->Targets[ii]);
1766 hd->Targets[ii] = NULL;
1767 sztarget += sizeof(VirtDevice);
1772 * Free pointer array.
1774 sz3 = max * sizeof(void *);
1779 dprintk((MYIOC_s_INFO_FMT
1780 "Free'd ScsiLookup (%d) Target (%d+%d) memory\n",
1781 hd->ioc->name, sz1, sz3, sztarget));
1782 dprintk(("Free'd done and free Q (%d) memory\n", szQ));
1784 /* NULL the Scsi_Host pointer
1789 scsi_host_put(host);
1794 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1796 * mptscsih_shutdown - reboot notifier
1800 mptscsih_shutdown(struct device * dev)
1802 MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev));
1803 struct Scsi_Host *host = ioc->sh;
1809 hd = (MPT_SCSI_HOST *)host->hostdata;
1811 /* Flush the cache of this adapter
1814 mptscsih_synchronize_cache(hd, 0);
1819 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1821 * mptscsih_suspend - Fusion MPT scsie driver suspend routine.
1826 mptscsih_suspend(struct pci_dev *pdev, u32 state)
1828 mptscsih_shutdown(&pdev->dev);
1832 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1834 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1839 mptscsih_resume(struct pci_dev *pdev)
1841 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1842 struct Scsi_Host *host = ioc->sh;
1848 hd = (MPT_SCSI_HOST *)host->hostdata;
1852 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1854 unsigned long lflags;
1855 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1856 if (!dvtaskQ_active) {
1858 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1859 INIT_WORK(&mptscsih_dvTask,
1860 mptscsih_domainValidation, (void *) hd);
1861 schedule_work(&mptscsih_dvTask);
1863 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1872 static struct mpt_pci_driver mptscsih_driver = {
1873 .probe = mptscsih_probe,
1874 .remove = mptscsih_remove,
1875 .shutdown = mptscsih_shutdown,
1877 .suspend = mptscsih_suspend,
1878 .resume = mptscsih_resume,
1882 /* SCSI host fops start here... */
1883 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1885 * mptscsih_init - Register MPT adapter(s) as SCSI host(s) with
1886 * linux scsi mid-layer.
1888 * Returns 0 for success, non-zero for failure.
1894 show_mptmod_ver(my_NAME, my_VERSION);
1896 ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
1897 ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
1898 ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
1900 if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
1901 dprintk((KERN_INFO MYNAM
1902 ": Registered for IOC event notifications\n"));
1905 if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
1906 dprintk((KERN_INFO MYNAM
1907 ": Registered for IOC reset notifications\n"));
1911 /* Evaluate the command line arguments, if any */
1913 mptscsih_setup(mptscsih);
1916 if(mpt_device_driver_register(&mptscsih_driver,
1917 MPTSCSIH_DRIVER) != 0 ) {
1918 dprintk((KERN_INFO MYNAM
1919 ": failed to register dd callbacks\n"));
1926 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1927 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1929 * mptscsih_exit - Unregisters MPT adapter(s)
1937 /* removing devices */
1938 for(ioc = mpt_adapter_find_first(); ioc != NULL;
1939 ioc = mpt_adapter_find_next(ioc)) {
1940 if ((ioc->last_state != MPI_IOC_STATE_OPERATIONAL) ||
1943 mptscsih_remove(ioc->pcidev);
1946 mpt_reset_deregister(ScsiDoneCtx);
1947 dprintk((KERN_INFO MYNAM
1948 ": Deregistered for IOC reset notifications\n"));
1950 mpt_event_deregister(ScsiDoneCtx);
1951 dprintk((KERN_INFO MYNAM
1952 ": Deregistered for IOC event notifications\n"));
1954 mpt_device_driver_deregister(MPTSCSIH_DRIVER);
1955 mpt_deregister(ScsiScanDvCtx);
1956 mpt_deregister(ScsiTaskCtx);
1957 mpt_deregister(ScsiDoneCtx);
1959 if (info_kbuf != NULL)
1964 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1966 * mptscsih_info - Return information about MPT adapter
1967 * @SChost: Pointer to Scsi_Host structure
1969 * (linux Scsi_Host_Template.info routine)
1971 * Returns pointer to buffer where information was written.
1974 mptscsih_info(struct Scsi_Host *SChost)
1979 if (info_kbuf == NULL)
1980 if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1983 h = (MPT_SCSI_HOST *)SChost->hostdata;
1984 info_kbuf[0] = '\0';
1986 mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
1987 info_kbuf[size-1] = '\0';
2000 static void copy_mem_info(struct info_str *info, char *data, int len)
2002 if (info->pos + len > info->length)
2003 len = info->length - info->pos;
2005 if (info->pos + len < info->offset) {
2010 if (info->pos < info->offset) {
2011 data += (info->offset - info->pos);
2012 len -= (info->offset - info->pos);
2016 memcpy(info->buffer + info->pos, data, len);
2021 static int copy_info(struct info_str *info, char *fmt, ...)
2027 va_start(args, fmt);
2028 len = vsprintf(buf, fmt, args);
2031 copy_mem_info(info, buf, len);
2035 static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
2037 struct info_str info;
2041 info.offset = offset;
2044 copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
2045 copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
2046 copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
2047 copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
2049 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
2052 #ifndef MPTSCSIH_DBG_TIMEOUT
2053 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len)
2055 /* Not yet implemented */
2059 #define is_digit(c) ((c) >= '0' && (c) <= '9')
2060 #define digit_to_bin(c) ((c) - '0')
2061 #define is_space(c) ((c) == ' ' || (c) == '\t')
2063 #define UC_DBG_TIMEOUT 0x01
2064 #define UC_DBG_HARDRESET 0x02
2066 static int skip_spaces(char *ptr, int len)
2070 for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --);
2075 static int get_int_arg(char *ptr, int len, ulong *pv)
2079 for (v = 0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) {
2080 v = (v * 10) + digit_to_bin(c);
2090 static int is_keyword(char *ptr, int len, char *verb)
2092 int verb_len = strlen(verb);
2094 if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))
2100 #define SKIP_SPACES(min_spaces) \
2101 if ((arg_len = skip_spaces(ptr,len)) < (min_spaces)) \
2106 #define GET_INT_ARG(v) \
2107 if (!(arg_len = get_int_arg(ptr,len, &(v)))) \
2112 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length)
2115 char btmp[24]; /* REMOVE */
2122 if ((len > 0) && (ptr[len -1] == '\n'))
2126 strncpy(btmp, buffer, len);
2129 strncpy(btmp, buffer, 22);
2132 printk("user_command: ioc %d, buffer %s, length %d\n",
2133 ioc->id, btmp, length);
2135 if ((arg_len = is_keyword(ptr, len, "timeout")) != 0)
2136 cmd = UC_DBG_TIMEOUT;
2137 else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0)
2138 cmd = UC_DBG_HARDRESET;
2146 case UC_DBG_TIMEOUT:
2148 GET_INT_ARG(number);
2154 printk("user_command: cnt=%ld delta=%ld\n", number, delta);
2159 if (cmd == UC_DBG_HARDRESET) {
2160 ioc->timeout_hard = 1;
2161 } else if (cmd == UC_DBG_TIMEOUT) {
2162 /* process this command ...
2164 ioc->timeout_maxcnt = 0;
2165 ioc->timeout_delta = delta < 2 ? 2 : delta;
2166 ioc->timeout_cnt = 0;
2167 ioc->timeout_maxcnt = number < 8 ? number: 8;
2170 /* Not yet implemented */
2175 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2177 * mptscsih_proc_info - Return information about MPT adapter
2179 * (linux Scsi_Host_Template.info routine)
2181 * buffer: if write, user data; if read, buffer for user
2182 * length: if write, return length;
2183 * offset: if write, 0; if read, the current offset into the buffer from
2184 * the previous read.
2185 * hostno: scsi host number
2186 * func: if write = 1; if read = 0
2188 int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
2189 int length, int func)
2192 MPT_SCSI_HOST *hd = NULL;
2195 dprintk(("Called mptscsih_proc_info: hostno=%d, func=%d\n", host->host_no, func));
2196 dprintk(("buffer %p, start=%p (%p) offset=%ld length = %d\n",
2197 buffer, start, *start, offset, length));
2199 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
2200 if ((ioc->sh) && (ioc->sh == host)) {
2201 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2205 if ((ioc == NULL) || (ioc->sh == NULL) || (hd == NULL))
2209 size = mptscsih_user_command(ioc, buffer, length);
2214 size = mptscsih_host_info(ioc, buffer, offset, length);
2221 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2222 #define ADD_INDEX_LOG(req_ent) do { } while(0)
2224 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2226 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
2227 * @SCpnt: Pointer to Scsi_Cmnd structure
2228 * @done: Pointer SCSI mid-layer IO completion function
2230 * (linux Scsi_Host_Template.queuecommand routine)
2231 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
2232 * from a linux Scsi_Cmnd request and send it to the IOC.
2234 * Returns 0. (rtn value discarded by linux scsi mid-layer)
2237 mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2241 SCSIIORequest_t *pScsiReq;
2242 VirtDevice *pTarget;
2244 unsigned long flags;
2259 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
2260 target = SCpnt->device->id;
2261 lun = SCpnt->device->lun;
2262 SCpnt->scsi_done = done;
2264 pTarget = hd->Targets[target];
2266 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
2267 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
2269 if (hd->resetPending) {
2270 /* Prevent new commands from being issued
2271 * while reloading the FW. Reset timer to 60 seconds,
2272 * as the FW can take some time to come ready.
2273 * For New EH, cmds on doneQ posted to FW.
2276 mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));
2277 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
2278 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2283 * Put together a MPT SCSI request...
2285 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
2286 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
2292 pScsiReq = (SCSIIORequest_t *) mf;
2294 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2296 ADD_INDEX_LOG(my_idx);
2299 * The scsi layer should be handling this stuff
2300 * (In 2.3.x it does -DaveM)
2303 /* BUG FIX! 19991030 -sralston
2304 * TUR's being issued with scsictl=0x02000000 (DATA_IN)!
2305 * Seems we may receive a buffer (datalen>0) even when there
2306 * will be no data transfer! GRRRRR...
2308 datadir = mptscsih_io_direction(SCpnt);
2309 if (datadir == SCSI_DATA_READ) {
2310 datalen = SCpnt->request_bufflen;
2311 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
2312 } else if (datadir == SCSI_DATA_WRITE) {
2313 datalen = SCpnt->request_bufflen;
2314 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
2317 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
2320 /* Default to untagged. Once a target structure has been allocated,
2321 * use the Inquiry data to determine if device supports tagged.
2324 && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
2325 && (SCpnt->device->tagged_supported)) {
2326 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
2328 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
2331 /* Use the above information to set up the message frame
2333 pScsiReq->TargetID = (u8) target;
2334 pScsiReq->Bus = (u8) SCpnt->device->channel;
2335 pScsiReq->ChainOffset = 0;
2336 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
2337 pScsiReq->CDBLength = SCpnt->cmd_len;
2338 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2339 pScsiReq->Reserved = 0;
2340 pScsiReq->MsgFlags = mpt_msg_flags();
2341 pScsiReq->LUN[0] = 0;
2342 pScsiReq->LUN[1] = lun;
2343 pScsiReq->LUN[2] = 0;
2344 pScsiReq->LUN[3] = 0;
2345 pScsiReq->LUN[4] = 0;
2346 pScsiReq->LUN[5] = 0;
2347 pScsiReq->LUN[6] = 0;
2348 pScsiReq->LUN[7] = 0;
2349 pScsiReq->Control = cpu_to_le32(scsictl);
2352 * Write SCSI CDB into the message
2354 cmd_len = SCpnt->cmd_len;
2355 for (ii=0; ii < cmd_len; ii++)
2356 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
2358 for (ii=cmd_len; ii < 16; ii++)
2359 pScsiReq->CDB[ii] = 0;
2362 pScsiReq->DataLength = cpu_to_le32(datalen);
2364 /* SenseBuffer low address */
2365 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
2366 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
2368 /* Now add the SG list
2369 * Always have a SGE even if null length.
2373 /* Add a NULL SGE */
2374 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
2377 /* Add a 32 or 64 bit SGE */
2378 rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
2382 if (rc == SUCCESS) {
2383 hd->ScsiLookup[my_idx] = SCpnt;
2384 SCpnt->host_scribble = NULL;
2386 /* SCSI specific processing */
2389 int dvStatus = hd->ioc->spi_data.dvStatus[target];
2391 if (dvStatus || hd->ioc->spi_data.forceDv) {
2393 /* Write SDP1 on this I/O to this target */
2394 if (dvStatus & MPT_SCSICFG_NEGOTIATE) {
2395 mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);
2396 dvStatus &= ~MPT_SCSICFG_NEGOTIATE;
2397 hd->ioc->spi_data.dvStatus[target] = dvStatus;
2398 } else if (dvStatus & MPT_SCSICFG_BLK_NEGO) {
2399 mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO);
2400 dvStatus &= ~MPT_SCSICFG_BLK_NEGO;
2401 hd->ioc->spi_data.dvStatus[target] = dvStatus;
2404 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2405 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
2406 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
2407 unsigned long lflags;
2408 /* Schedule DV if necessary */
2409 spin_lock_irqsave(&dvtaskQ_lock, lflags);
2410 if (!dvtaskQ_active) {
2412 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2413 INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
2415 schedule_work(&mptscsih_dvTask);
2417 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2419 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
2422 /* Trying to do DV to this target, extend timeout.
2423 * Wait to issue intil flag is clear
2425 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
2426 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
2430 /* Set the DV flags.
2432 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
2433 mptscsih_set_dvflags(hd, pScsiReq);
2438 #ifdef MPTSCSIH_DBG_TIMEOUT
2439 if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) {
2440 foo_to[hd->ioc->timeout_cnt] = SCpnt;
2441 hd->ioc->timeout_cnt++;
2442 //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta);
2444 printk(MYIOC_s_WARN_FMT
2445 "to pendingQ: (sc=%p, mf=%p, time=%ld)\n",
2446 hd->ioc->name, SCpnt, mf, jiffies);
2451 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2452 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
2453 hd->ioc->name, SCpnt, mf, my_idx));
2455 ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",
2456 hd->ioc->name, SCpnt, my_idx));
2457 /* Place this command on the pendingQ if possible */
2458 spin_lock_irqsave(&hd->freedoneQlock, flags);
2459 if (!Q_IS_EMPTY(&hd->freeQ)) {
2460 buffer = hd->freeQ.head;
2463 /* Save the mf pointer
2465 buffer->argp = (void *)mf;
2467 /* Add to the pendingQ
2469 Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);
2470 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2472 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2473 SCpnt->result = (DID_BUS_BUSY << 16);
2474 SCpnt->scsi_done(SCpnt);
2478 mptscsih_freeChainBuffers(hd, my_idx);
2479 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2487 dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n",
2488 hd->ioc->name, did_errcode, SCpnt));
2489 /* Just wish OS to issue a retry */
2490 SCpnt->result = (DID_BUS_BUSY << 16);
2491 spin_lock_irqsave(&hd->freedoneQlock, flags);
2492 if (!Q_IS_EMPTY(&hd->freeQ)) {
2493 dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n",
2494 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2495 buffer = hd->freeQ.head;
2498 /* Set the Scsi_Cmnd pointer
2500 buffer->argp = (void *)SCpnt;
2504 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
2505 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2507 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2508 SCpnt->scsi_done(SCpnt);
2514 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2516 * mptscsih_freeChainBuffers - Function to free chain buffers associated
2517 * with a SCSI IO request
2518 * @hd: Pointer to the MPT_SCSI_HOST instance
2519 * @req_idx: Index of the SCSI IO request frame.
2521 * Called if SG chain buffer allocation fails and mptscsih callbacks.
2525 mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
2527 MPT_FRAME_HDR *chain;
2528 unsigned long flags;
2532 /* Get the first chain index and reset
2535 chain_idx = hd->ReqToChain[req_idx];
2536 hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
2538 while (chain_idx != MPT_HOST_NO_CHAIN) {
2540 /* Save the next chain buffer index */
2541 next = hd->ChainToChain[chain_idx];
2543 /* Free this chain buffer and reset
2546 hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
2548 chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
2549 + (chain_idx * hd->ioc->req_sz));
2550 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2551 Q_ADD_TAIL(&hd->FreeChainQ.head,
2552 &chain->u.frame.linkage, MPT_FRAME_HDR);
2553 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2555 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
2556 hd->ioc->name, chain_idx));
2564 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2569 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2571 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
2572 * Fall through to mpt_HardResetHandler if: not operational, too many
2573 * failed TM requests or handshake failure.
2575 * @ioc: Pointer to MPT_ADAPTER structure
2576 * @type: Task Management type
2577 * @target: Logical Target ID for reset (if appropriate)
2578 * @lun: Logical Unit for reset (if appropriate)
2579 * @ctx2abort: Context for the task to be aborted (if appropriate)
2580 * @sleepFlag: If set, use udelay instead of schedule in handshake code.
2582 * Remark: Currently invoked from a non-interrupt thread (_bh).
2584 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
2587 * Returns 0 for SUCCESS or -1 if FAILED.
2590 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
2596 unsigned long flags;
2598 /* If FW is being reloaded currently, return success to
2599 * the calling function.
2606 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
2609 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
2611 // SJR - CHECKME - Can we avoid this here?
2612 // (mpt_HardResetHandler has this check...)
2613 spin_lock_irqsave(&ioc->diagLock, flags);
2614 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
2615 spin_unlock_irqrestore(&ioc->diagLock, flags);
2618 spin_unlock_irqrestore(&ioc->diagLock, flags);
2620 /* Do not do a Task Management if there are
2621 * too many failed TMs on this adapter.
2623 if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM)
2626 /* Wait a fixed amount of time for the TM pending flag to be cleared.
2627 * If we time out and not bus reset, then we return a FAILED status to the caller.
2628 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
2629 * successful. Otherwise, reload the FW.
2631 if (mptscsih_tm_pending_wait(hd) == FAILED) {
2632 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
2633 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
2634 "Timed out waiting for last TM (%d) to complete! \n",
2635 hd->ioc->name, hd->tmPending));
2637 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
2638 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
2639 "Timed out waiting for last TM (%d) to complete! \n",
2640 hd->ioc->name, hd->tmPending));
2642 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2643 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
2644 "Timed out waiting for last TM (%d) to complete! \n",
2645 hd->ioc->name, hd->tmPending));
2646 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
2652 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2653 hd->tmPending |= (1 << type);
2654 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2659 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
2661 #ifdef MPT_DEBUG_RESET
2662 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
2663 printk(MYIOC_s_WARN_FMT
2664 "TM Handler: IOC Not operational(0x%x)!\n",
2665 hd->ioc->name, ioc_raw_state);
2669 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
2670 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
2672 /* Isse the Task Mgmt request.
2674 if (hd->hard_resets < -1)
2676 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag);
2678 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
2680 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
2684 #ifdef MPTSCSIH_DBG_TIMEOUT
2685 if (hd->ioc->timeout_hard)
2689 /* Only fall through to the HRH if this is a bus reset
2691 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
2692 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
2693 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
2695 rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
2698 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
2704 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2706 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
2707 * @hd: Pointer to MPT_SCSI_HOST structure
2708 * @type: Task Management type
2709 * @target: Logical Target ID for reset (if appropriate)
2710 * @lun: Logical Unit for reset (if appropriate)
2711 * @ctx2abort: Context for the task to be aborted (if appropriate)
2712 * @sleepFlag: If set, use udelay instead of schedule in handshake code.
2714 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
2715 * or a non-interrupt thread. In the former, must not call schedule().
2717 * Not all fields are meaningfull for all task types.
2719 * Returns 0 for SUCCESS, -999 for "no msg frames",
2720 * else other non-zero value returned.
2723 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
2726 SCSITaskMgmt_t *pScsiTm;
2730 /* Return Fail to calling function if no message frames available.
2732 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
2733 dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
2738 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
2739 hd->ioc->name, mf));
2741 /* Format the Request
2743 pScsiTm = (SCSITaskMgmt_t *) mf;
2744 pScsiTm->TargetID = target;
2745 pScsiTm->Bus = channel;
2746 pScsiTm->ChainOffset = 0;
2747 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
2749 pScsiTm->Reserved = 0;
2750 pScsiTm->TaskType = type;
2751 pScsiTm->Reserved1 = 0;
2752 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
2753 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
2755 for (ii= 0; ii < 8; ii++) {
2756 pScsiTm->LUN[ii] = 0;
2758 pScsiTm->LUN[1] = lun;
2760 for (ii=0; ii < 7; ii++)
2761 pScsiTm->Reserved2[ii] = 0;
2763 pScsiTm->TaskMsgContext = ctx2abort;
2764 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n",
2765 hd->ioc->name, ctx2abort, type));
2767 /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
2768 mpt_put_msg_frame(hd->ioc->id, mf);
2769 * Save the MF pointer in case the request times out.
2772 hd->numTMrequests++;
2773 hd->TMtimer.expires = jiffies + timeout;
2774 add_timer(&hd->TMtimer);
2776 if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
2777 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
2779 dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
2780 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
2781 hd->numTMrequests--;
2783 del_timer(&hd->TMtimer);
2784 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
2790 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2792 * mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
2793 * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
2795 * (linux Scsi_Host_Template.eh_abort_handler routine)
2797 * Returns SUCCESS or FAILED.
2800 mptscsih_abort(Scsi_Cmnd * SCpnt)
2806 spinlock_t *host_lock = SCpnt->device->host->host_lock;
2808 /* If we can't locate our host adapter structure, return FAILED status.
2810 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
2811 SCpnt->result = DID_RESET << 16;
2812 SCpnt->scsi_done(SCpnt);
2813 dtmprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
2814 "Can't locate host! (sc=%p)\n",
2819 if (hd->resetPending)
2822 printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
2823 hd->ioc->name, SCpnt);
2825 if (hd->timeouts < -1)
2828 /* Find this command
2830 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
2831 /* Cmd not found in ScsiLookup. If found in
2832 * doneQ, delete from Q. Do OS callback.
2834 search_doneQ_for_cmd(hd, SCpnt);
2836 SCpnt->result = DID_RESET << 16;
2837 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
2838 "Command not in the active list! (sc=%p)\n",
2839 hd->ioc->name, SCpnt));
2843 /* If this command is pended, then timeout/hang occurred
2844 * during DV. Post command and flush pending Q
2845 * and then following up with the reset request.
2847 if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
2848 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2849 post_pendingQ_commands(hd);
2850 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
2851 "Posting pended cmd! (sc=%p)\n",
2852 hd->ioc->name, SCpnt));
2855 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
2856 * (the IO to be ABORT'd)
2858 * NOTE: Since we do not byteswap MsgContext, we do not
2859 * swap it here either. It is an opaque cookie to
2860 * the controller, so it does not matter. -DaveM
2862 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
2863 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
2865 hd->abortSCpnt = SCpnt;
2867 spin_unlock_irq(host_lock);
2868 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
2869 SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
2870 ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP)
2873 /* The TM request failed and the subsequent FW-reload failed!
2876 printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
2877 hd->ioc->name, SCpnt);
2879 /* We must clear our pending flag before clearing our state.
2882 hd->tmState = TM_STATE_NONE;
2884 spin_lock_irq(host_lock);
2887 spin_lock_irq(host_lock);
2892 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2894 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
2895 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
2897 * (linux Scsi_Host_Template.eh_dev_reset_handler routine)
2899 * Returns SUCCESS or FAILED.
2902 mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
2905 spinlock_t *host_lock = SCpnt->device->host->host_lock;
2907 /* If we can't locate our host adapter structure, return FAILED status.
2909 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2910 dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
2911 "Can't locate host! (sc=%p)\n",
2916 if (hd->resetPending)
2919 printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
2920 hd->ioc->name, SCpnt);
2922 /* Unsupported for SCSI. Supported for FCP
2927 spin_unlock_irq(host_lock);
2928 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
2929 SCpnt->device->channel, SCpnt->device->id,
2930 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
2932 /* The TM request failed and the subsequent FW-reload failed!
2935 printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
2936 hd->ioc->name, SCpnt);
2938 hd->tmState = TM_STATE_NONE;
2939 spin_lock_irq(host_lock);
2942 spin_lock_irq(host_lock);
2947 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2949 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
2950 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
2952 * (linux Scsi_Host_Template.eh_bus_reset_handler routine)
2954 * Returns SUCCESS or FAILED.
2957 mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
2960 spinlock_t *host_lock = SCpnt->device->host->host_lock;
2962 /* If we can't locate our host adapter structure, return FAILED status.
2964 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2965 dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
2966 "Can't locate host! (sc=%p)\n",
2971 printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
2972 hd->ioc->name, SCpnt);
2974 if (hd->timeouts < -1)
2977 /* We are now ready to execute the task management request. */
2978 spin_unlock_irq(host_lock);
2979 // printk("testing start : mptscsih_schedule_reset\n");
2980 // mptscsih_schedule_reset(hd);
2981 // printk("testing end: mptscsih_schedule_reset\n");
2982 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
2983 SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
2986 /* The TM request failed and the subsequent FW-reload failed!
2989 printk(MYIOC_s_WARN_FMT
2990 "Error processing TaskMgmt request (sc=%p)\n",
2991 hd->ioc->name, SCpnt);
2993 hd->tmState = TM_STATE_NONE;
2994 spin_lock_irq(host_lock);
2997 spin_lock_irq(host_lock);
3001 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3003 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
3005 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
3007 * (linux Scsi_Host_Template.eh_host_reset_handler routine)
3009 * Returns SUCCESS or FAILED.
3012 mptscsih_host_reset(Scsi_Cmnd *SCpnt)
3015 int status = SUCCESS;
3016 spinlock_t *host_lock = SCpnt->device->host->host_lock;
3018 /* If we can't locate the host to reset, then we failed. */
3019 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
3020 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3021 "Can't locate host! (sc=%p)\n",
3026 printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
3027 hd->ioc->name, SCpnt);
3029 /* If our attempts to reset the host failed, then return a failed
3030 * status. The host will be taken off line by the SCSI mid-layer.
3032 spin_unlock_irq(host_lock);
3033 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
3036 /* Make sure TM pending is cleared and TM state is set to
3040 hd->tmState = TM_STATE_NONE;
3042 spin_lock_irq(host_lock);
3045 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3047 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
3052 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3054 * mptscsih_tm_pending_wait - wait for pending task management request to
3056 * @hd: Pointer to MPT host structure.
3058 * Returns {SUCCESS,FAILED}.
3061 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
3063 unsigned long flags;
3064 int loop_count = 10 * 4; /* Wait 10 seconds */
3065 int status = FAILED;
3068 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
3069 if (hd->tmState == TM_STATE_NONE) {
3070 hd->tmState = TM_STATE_IN_PROGRESS;
3072 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3076 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3077 set_current_state(TASK_INTERRUPTIBLE);
3078 schedule_timeout(HZ/4);
3079 } while (--loop_count);
3084 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3086 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
3087 * @ioc: Pointer to MPT_ADAPTER structure
3088 * @mf: Pointer to SCSI task mgmt request frame
3089 * @mr: Pointer to SCSI task mgmt reply frame
3091 * This routine is called from mptbase.c::mpt_interrupt() at the completion
3092 * of any SCSI task management request.
3093 * This routine is registered with the MPT (base) driver at driver
3094 * load/init time via the mpt_register() API call.
3096 * Returns 1 indicating alloc'd request frame ptr should be freed.
3099 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3101 SCSITaskMgmtReply_t *pScsiTmReply;
3102 SCSITaskMgmt_t *pScsiTmReq;
3104 unsigned long flags;
3107 dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
3108 ioc->name, mf, mr));
3110 /* Depending on the thread, a timer is activated for
3111 * the TM request. Delete this timer on completion of TM.
3112 * Decrement count of outstanding TM requests.
3114 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
3116 del_timer(&hd->TMtimer);
3118 dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
3119 ioc->name, hd->taskQcnt));
3121 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
3127 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
3131 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
3132 pScsiTmReq = (SCSITaskMgmt_t*)mf;
3134 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
3135 tmType = pScsiTmReq->TaskType;
3137 dtmprintk((KERN_INFO " TaskType = %d, TerminationCount=%d\n",
3138 tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
3140 /* Error? (anything non-zero?) */
3141 if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
3144 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3145 dtmprintk((KERN_INFO " SCSI TaskMgmt (%d) - Oops!\n", tmType));
3146 dtmprintk((KERN_INFO " IOCStatus = %04xh\n", iocstatus));
3147 dtmprintk((KERN_INFO " IOCLogInfo = %08xh\n",
3148 le32_to_cpu(pScsiTmReply->IOCLogInfo)));
3150 /* clear flags and continue.
3152 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
3153 hd->abortSCpnt = NULL;
3155 /* If an internal command is present
3156 * or the TM failed - reload the FW.
3157 * FC FW may respond FAILED to an ABORT
3159 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
3161 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
3162 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
3163 printk((KERN_WARNING
3164 " Firmware Reload FAILED!!\n"));
3169 dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n"));
3171 hd->numTMrequests--;
3172 hd->abortSCpnt = NULL;
3179 spin_lock_irqsave(&ioc->FreeQlock, flags);
3181 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3182 hd->tmState = TM_STATE_NONE;
3187 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3189 * This is anyones guess quite frankly.
3192 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
3193 sector_t capacity, int geom[])
3205 dummy = heads * sectors;
3206 cylinders = capacity;
3207 sector_div(cylinders,dummy);
3209 cylinders = (ulong)capacity / (heads * sectors);
3213 * Handle extended translation size for logical drives
3216 if ((ulong)capacity >= 0x200000) {
3220 dummy = heads * sectors;
3221 cylinders = capacity;
3222 sector_div(cylinders,dummy);
3224 cylinders = (ulong)capacity / (heads * sectors);
3231 geom[2] = cylinders;
3233 dprintk((KERN_NOTICE
3234 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
3235 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
3240 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3242 * OS entry point to allow host driver to alloc memory
3243 * for each scsi device. Called once per device the bus scan.
3244 * Return non-zero if allocation fails.
3245 * Init memory once per id (not LUN).
3248 mptscsih_slave_alloc(Scsi_Device *device)
3250 struct Scsi_Host *host = device->host;
3254 hd = (MPT_SCSI_HOST *)host->hostdata;
3259 if ((vdev = hd->Targets[device->id]) == NULL) {
3260 if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
3261 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%d) FAILED!\n",
3262 hd->ioc->name, (int)sizeof(VirtDevice));
3265 memset(vdev, 0, sizeof(VirtDevice));
3266 rwlock_init(&vdev->VdevLock);
3267 Q_INIT(&vdev->WaitQ, void);
3268 Q_INIT(&vdev->SentQ, void);
3269 Q_INIT(&vdev->DoneQ, void);
3271 vdev->ioc_id = hd->ioc->id;
3272 vdev->target_id = device->id;
3273 vdev->bus_id = hd->port;
3275 hd->Targets[device->id] = vdev;
3284 * OS entry point to allow for host driver to free allocated memory
3285 * Called if no device present or device being unloaded
3288 mptscsih_slave_destroy(Scsi_Device *device)
3290 struct Scsi_Host *host = device->host;
3295 hd = (MPT_SCSI_HOST *)host->hostdata;
3300 mptscsih_search_running_cmds(hd, device->id, device->lun);
3302 /* Free memory and reset all flags for this target
3304 if ((vdev = hd->Targets[device->id]) != NULL) {
3307 if (vdev->luns[0] & (1 << device->lun))
3308 vdev->luns[0] &= ~(1 << device->lun);
3310 /* Free device structure only if number of luns is 0.
3312 if (vdev->num_luns == 0) {
3313 kfree(hd->Targets[device->id]);
3314 hd->Targets[device->id] = NULL;
3319 if((hd->ioc->spi_data.isRaid) && (hd->ioc->spi_data.pIocPg3)) {
3321 for(i=0;i<hd->ioc->spi_data.pIocPg3->NumPhysDisks &&
3325 hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) {
3327 hd->ioc->spi_data.forceDv |=
3328 MPT_SCSICFG_RELOAD_IOC_PG3;
3333 hd->ioc->spi_data.dvStatus[device->id] =
3334 MPT_SCSICFG_NEGOTIATE;
3336 if (hd->negoNvram == 0)
3337 hd->ioc->spi_data.dvStatus[device->id]
3338 |= MPT_SCSICFG_DV_NOT_DONE;
3347 * OS entry point to adjust the queue_depths on a per-device basis.
3348 * Called once per device the bus scan. Use it to force the queue_depth
3349 * member to 1 if a device does not support Q tags.
3350 * Return non-zero if fails.
3353 mptscsih_slave_configure(Scsi_Device *device)
3355 struct Scsi_Host *sh = device->host;
3356 VirtDevice *pTarget;
3357 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
3359 if ((hd == NULL) || (hd->Targets == NULL)) {
3363 dsprintk((MYIOC_s_INFO_FMT
3364 "device @ %p, id=%d, LUN=%d, channel=%d\n",
3365 hd->ioc->name, device, device->id, device->lun, device->channel));
3366 dsprintk((MYIOC_s_INFO_FMT
3367 "sdtr %d wdtr %d ppr %d inq length=%d\n",
3368 hd->ioc->name, device->sdtr, device->wdtr,
3369 device->ppr, device->inquiry_len));
3371 if (device->id > sh->max_id) {
3372 /* error case, should never happen */
3373 scsi_adjust_queue_depth(device, 0, 1);
3374 goto slave_configure_exit;
3377 pTarget = hd->Targets[device->id];
3379 if (pTarget == NULL) {
3380 /* error case - don't know about this device */
3381 scsi_adjust_queue_depth(device, 0, 1);
3382 goto slave_configure_exit;
3385 mptscsih_initTarget(hd, device->channel, device->id, device->lun,
3386 device->inquiry, device->inquiry_len );
3387 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3388 MPT_SCSI_CMD_PER_DEV_HIGH);
3390 if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
3391 if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
3392 scsi_adjust_queue_depth(device, 0, 1);
3393 else if (((pTarget->inq_data[0] & 0x1f) == 0x00)
3394 && (pTarget->minSyncFactor <= MPT_ULTRA160 ))
3395 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3396 MPT_SCSI_CMD_PER_DEV_HIGH);
3398 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3399 MPT_SCSI_CMD_PER_DEV_LOW);
3401 /* error case - No Inq. Data */
3402 scsi_adjust_queue_depth(device, 0, 1);
3406 dsprintk((MYIOC_s_INFO_FMT
3407 "Queue depth=%d, tflags=%x\n",
3408 hd->ioc->name, device->queue_depth, pTarget->tflags));
3410 dsprintk((MYIOC_s_INFO_FMT
3411 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
3412 hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
3414 slave_configure_exit:
3416 dsprintk((MYIOC_s_INFO_FMT
3417 "tagged %d, simple %d, ordered %d\n",
3418 hd->ioc->name,device->tagged_supported, device->simple_tags,
3419 device->ordered_tags));
3425 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3427 * Private routines...
3430 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3431 /* Utility function to copy sense data from the scsi_cmnd buffer
3432 * to the FC and SCSI target structures.
3436 copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
3439 SCSIIORequest_t *pReq;
3440 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
3445 /* Get target structure
3447 pReq = (SCSIIORequest_t *) mf;
3448 index = (int) pReq->TargetID;
3449 target = hd->Targets[index];
3450 if (hd->is_multipath && sc->device->hostdata)
3451 target = (VirtDevice *) sc->device->hostdata;
3457 /* Copy the sense received into the scsi command block. */
3458 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3459 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
3460 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
3462 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
3464 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
3465 if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
3467 MPT_ADAPTER *ioc = hd->ioc;
3469 idx = ioc->eventContext % ioc->eventLogSize;
3470 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
3471 ioc->events[idx].eventContext = ioc->eventContext;
3473 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
3474 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
3475 (pReq->Bus << 8) || pReq->TargetID;
3477 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
3479 ioc->eventContext++;
3483 /* Print an error report for the user.
3485 thisIo.cdbPtr = sc->cmnd;
3486 thisIo.sensePtr = sc->sense_buffer;
3487 thisIo.SCSIStatus = pScsiReply->SCSIStatus;
3488 thisIo.DoDisplay = 1;
3489 if (hd->is_multipath)
3490 sprintf(devFoo, "%d:%d:%d",
3495 sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->device->id, sc->device->lun);
3496 thisIo.DevIDStr = devFoo;
3498 thisIo.dataPtr = NULL;
3499 thisIo.inqPtr = NULL;
3501 thisIo.inqPtr = sc->device->vendor-8; /* FIXME!!! */
3503 (void) mpt_ScsiHost_ErrorReport(&thisIo);
3506 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
3514 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
3519 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
3521 for (i = 0; i < hd->ioc->req_depth; i++) {
3522 if (hd->ScsiLookup[i] == sc) {
3531 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3532 /* Search the pendingQ for a command with specific index.
3533 * If found, delete and return mf pointer
3534 * If not found, return NULL
3536 static MPT_FRAME_HDR *
3537 mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx)
3539 unsigned long flags;
3541 MPT_FRAME_HDR *mf = NULL;
3542 MPT_FRAME_HDR *cmdMfPtr;
3544 ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
3545 cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
3546 spin_lock_irqsave(&hd->freedoneQlock, flags);
3547 if (!Q_IS_EMPTY(&hd->pendingQ)) {
3548 buffer = hd->pendingQ.head;
3550 mf = (MPT_FRAME_HDR *) buffer->argp;
3551 if (mf == cmdMfPtr) {
3554 /* clear the arg pointer
3556 buffer->argp = NULL;
3560 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
3564 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ);
3566 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3567 ddvtprintk((" ...return %p\n", mf));
3571 /* Post all commands on the pendingQ to the FW.
3572 * Lock Q when deleting/adding members
3573 * Lock io_request_lock for OS callback.
3576 post_pendingQ_commands(MPT_SCSI_HOST *hd)
3580 unsigned long flags;
3582 /* Flush the pendingQ.
3584 ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name));
3586 spin_lock_irqsave(&hd->freedoneQlock, flags);
3587 if (Q_IS_EMPTY(&hd->pendingQ)) {
3588 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3592 buffer = hd->pendingQ.head;
3597 mf = (MPT_FRAME_HDR *) buffer->argp;
3598 buffer->argp = NULL;
3602 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
3603 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3606 /* This should never happen */
3607 printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf);
3611 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
3613 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
3615 u16 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3616 Scsi_Cmnd *sc = hd->ScsiLookup[req_idx];
3617 printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
3618 hd->ioc->name, sc, req_idx, mf);
3626 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3628 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
3631 unsigned long flags;
3633 dtmprintk((KERN_WARNING MYNAM
3634 ": IOC %s_reset routed to SCSI host driver!\n",
3635 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
3636 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
3638 /* If a FW reload request arrives after base installed but
3639 * before all scsi hosts have been attached, then an alt_ioc
3640 * may have a NULL sh pointer.
3642 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
3645 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3647 if (reset_phase == MPT_IOC_SETUP_RESET) {
3648 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
3651 * 1. Set Hard Reset Pending Flag
3652 * All new commands go to doneQ
3654 hd->resetPending = 1;
3656 } else if (reset_phase == MPT_IOC_PRE_RESET) {
3657 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
3659 /* 2. Flush running commands
3660 * Clean drop test code - if compiled
3661 * Clean ScsiLookup (and associated memory)
3665 /* 2a. Drop Test Command.
3668 /* 2b. Reply to OS all known outstanding I/O commands.
3670 mptscsih_flush_running_cmds(hd);
3672 /* 2c. If there was an internal command that
3673 * has not completed, configuration or io request,
3674 * free these resources.
3677 del_timer(&hd->timer);
3678 mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr);
3681 /* 2d. If a task management has not completed,
3682 * free resources associated with this request.
3685 del_timer(&hd->TMtimer);
3686 mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr);
3689 #ifdef MPTSCSIH_DBG_TIMEOUT
3690 ioc->timeout_hard = 0;
3693 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
3696 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
3698 /* Once a FW reload begins, all new OS commands are
3699 * redirected to the doneQ w/ a reset status.
3700 * Init all control structures.
3703 /* ScsiLookup initialization
3707 for (ii=0; ii < hd->ioc->req_depth; ii++)
3708 hd->ScsiLookup[ii] = NULL;
3711 /* 2. Chain Buffer initialization
3713 mptscsih_initChainBuffers(hd, 0);
3721 /* 4. Renegotiate to all devices, if SCSI
3724 mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
3726 /* 5. Enable new commands to be posted
3728 spin_lock_irqsave(&ioc->FreeQlock, flags);
3730 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3731 hd->resetPending = 0;
3732 hd->numTMrequests = 0;
3733 hd->tmState = TM_STATE_NONE;
3735 /* 6. If there was an internal command,
3736 * wake this process up.
3740 * Wake up the original calling thread
3742 hd->pLocal = &hd->localReply;
3743 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
3744 scandv_wait_done = 1;
3745 wake_up(&scandv_waitq);
3753 /* 8. Set flag to force DV and re-read IOC Page 3
3756 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
3757 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
3760 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
3764 return 1; /* currently means nothing really */
3767 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3769 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
3772 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
3774 dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
3778 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
3781 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
3782 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
3785 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3786 if (hd && (hd->is_spi) && (hd->soft_resets < -1))
3790 case MPI_EVENT_LOGOUT: /* 09 */
3795 * CHECKME! Don't think we need to do
3796 * anything for these, but...
3798 case MPI_EVENT_RESCAN: /* 06 */
3799 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
3800 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
3802 * CHECKME! Falling thru...
3806 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
3807 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3808 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
3809 * if DV disabled. Need to check for target mode.
3813 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3815 if (hd && (hd->is_spi) && (hd->negoNvram == 0)) {
3817 Ioc3PhysDisk_t *pPDisk;
3822 reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
3823 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
3824 /* New or replaced disk.
3825 * Set DV flag and schedule DV.
3827 pSpi = &ioc->spi_data;
3828 physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
3829 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
3830 if (pSpi->pIocPg3) {
3831 pPDisk = pSpi->pIocPg3->PhysDisk;
3832 numPDisk =pSpi->pIocPg3->NumPhysDisks;
3835 if (physDiskNum == pPDisk->PhysDiskNum) {
3836 pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
3837 pSpi->forceDv = MPT_SCSICFG_NEED_DV;
3838 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
3845 if (numPDisk == 0) {
3846 /* The physical disk that needs DV was not found
3847 * in the stored IOC Page 3. The driver must reload
3848 * this page. DV routine will set the NEED_DV flag for
3849 * all phys disks that have DV_NOT_DONE set.
3851 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
3852 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
3859 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
3860 printk("Raid Event RF: ");
3862 u32 *m = (u32 *)pEvReply;
3864 int n = (int)pEvReply->MsgLength;
3865 for (ii=6; ii < n; ii++)
3866 printk(" %08x", le32_to_cpu(m[ii]));
3872 case MPI_EVENT_NONE: /* 00 */
3873 case MPI_EVENT_LOG_DATA: /* 01 */
3874 case MPI_EVENT_STATE_CHANGE: /* 02 */
3875 case MPI_EVENT_EVENT_CHANGE: /* 0A */
3877 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
3881 return 1; /* currently means nothing really */
3884 static struct scsi_host_template driver_template = {
3885 .proc_name = "mptscsih",
3886 .proc_info = mptscsih_proc_info,
3887 .name = "MPT SCSI Host",
3888 .info = mptscsih_info,
3889 .queuecommand = mptscsih_qcmd,
3890 .slave_alloc = mptscsih_slave_alloc,
3891 .slave_configure = mptscsih_slave_configure,
3892 .slave_destroy = mptscsih_slave_destroy,
3893 .eh_abort_handler = mptscsih_abort,
3894 .eh_device_reset_handler = mptscsih_dev_reset,
3895 .eh_bus_reset_handler = mptscsih_bus_reset,
3896 .eh_host_reset_handler = mptscsih_host_reset,
3897 .bios_param = mptscsih_bios_param,
3898 .can_queue = MPT_SCSI_CAN_QUEUE,
3900 .sg_tablesize = MPT_SCSI_SG_DEPTH,
3901 .max_sectors = 8192,
3903 .use_clustering = ENABLE_CLUSTERING,
3907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3911 static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
3913 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3914 /* old symsense.c stuff... */
3915 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3918 * To protect ourselves against those that would pass us bogus pointers
3920 static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
3921 = { 0x1F, 0x00, 0x00, 0x00,
3922 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3923 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3924 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3925 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3926 static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
3927 = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
3928 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3930 static u8 dummyCDB[16]
3931 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3932 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3933 static u8 dummyScsiData[16]
3934 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3935 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3937 static char *ScsiStatusString[] = {
3940 "CHECK CONDITION", /* 02h */
3942 "CONDITION MET", /* 04h */
3954 "INTERMEDIATE", /* 10h */
3958 "INTERMEDIATE-CONDITION MET", /* 14h */
3962 "RESERVATION CONFLICT", /* 18h */
3972 "COMMAND TERMINATED", /* 22h */
3978 "TASK SET FULL", /* 28h */
3986 "ACA ACTIVE", /* 30h */
3990 static const char *ScsiCommonOpString[] = {
3991 "TEST UNIT READY", /* 00h */
3992 "REZERO UNIT (REWIND)", /* 01h */
3994 "REQUEST_SENSE", /* 03h */
3995 "FORMAT UNIT (MEDIUM)", /* 04h */
3996 "READ BLOCK LIMITS", /* 05h */
3998 "REASSIGN BLOCKS", /* 07h */
3999 "READ(6)", /* 08h */
4001 "WRITE(6)", /* 0Ah */
4002 "SEEK(6)", /* 0Bh */
4006 "READ REVERSE", /* 0Fh */
4007 "WRITE_FILEMARKS", /* 10h */
4008 "SPACE(6)", /* 11h */
4009 "INQUIRY", /* 12h */
4013 static const char *SenseKeyString[] = {
4014 "NO SENSE", /* 0h */
4015 "RECOVERED ERROR", /* 1h */
4016 "NOT READY", /* 2h */
4017 "MEDIUM ERROR", /* 3h */
4018 "HARDWARE ERROR", /* 4h */
4019 "ILLEGAL REQUEST", /* 5h */
4020 "UNIT ATTENTION", /* 6h */
4021 "DATA PROTECT", /* 7h */
4022 "BLANK CHECK", /* 8h */
4023 "VENDOR-SPECIFIC", /* 9h */
4024 "ABORTED COPY", /* Ah */
4025 "ABORTED COMMAND", /* Bh */
4026 "EQUAL (obsolete)", /* Ch */
4027 "VOLUME OVERFLOW", /* Dh */
4028 "MISCOMPARE", /* Eh */
4029 "RESERVED", /* Fh */
4033 #define SPECIAL_ASCQ(c,q) \
4034 (((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
4036 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4037 static int dump_cdb(char *foo, unsigned char *cdb)
4039 int i, grpCode, cdbLen;
4042 grpCode = cdb[0] >> 5;
4045 else if (grpCode < 3)
4047 else if (grpCode == 5)
4052 for (i=0; i < cdbLen; i++)
4053 l += sprintf(foo+l, " %02X", cdb[i]);
4058 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4059 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4060 /* Do ASC/ASCQ lookup/grindage to English readable string(s) */
4061 static const char * ascq_set_strings_4max(
4063 const char **s1, const char **s2, const char **s3, const char **s4)
4065 static const char *asc_04_part1_string = "LOGICAL UNIT ";
4066 static const char *asc_04_part2a_string = "NOT READY, ";
4067 static const char *asc_04_part2b_string = "IS ";
4068 static const char *asc_04_ascq_NN_part3_strings[] = { /* ASC ASCQ (hex) */
4069 "CAUSE NOT REPORTABLE", /* 04 00 */
4070 "IN PROCESS OF BECOMING READY", /* 04 01 */
4071 "INITIALIZING CMD. REQUIRED", /* 04 02 */
4072 "MANUAL INTERVENTION REQUIRED", /* 04 03 */
4073 /* Add " IN PROGRESS" to all the following... */
4074 "FORMAT", /* 04 04 */
4075 "REBUILD", /* 04 05 */
4076 "RECALCULATION", /* 04 06 */
4077 "OPERATION", /* 04 07 */
4078 "LONG WRITE", /* 04 08 */
4079 "SELF-TEST", /* 04 09 */
4082 static char *asc_04_part4_string = " IN PROGRESS";
4084 static char *asc_29_ascq_NN_strings[] = { /* ASC ASCQ (hex) */
4085 "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED", /* 29 00 */
4086 "POWER ON OCCURRED", /* 29 01 */
4087 "SCSI BUS RESET OCCURRED", /* 29 02 */
4088 "BUS DEVICE RESET FUNCTION OCCURRED", /* 29 03 */
4089 "DEVICE INTERNAL RESET", /* 29 04 */
4090 "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED", /* 29 05 */
4091 "TRANSCEIVER MODE CHANGED TO LVD", /* 29 06 */
4094 static char *ascq_vendor_uniq = "(Vendor Unique)";
4095 static char *ascq_noone = "(no matching ASC/ASCQ description found)";
4098 *s1 = *s2 = *s3 = *s4 = ""; /* set'em all to the empty "" string */
4100 /* CHECKME! Need lock/sem?
4101 * Update and examine for isense module presense.
4103 mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
4105 if (mptscsih_ASCQ_TablePtr == NULL) {
4106 /* 2nd chances... */
4107 if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
4108 *s1 = asc_04_part1_string;
4109 *s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
4110 *s3 = asc_04_ascq_NN_part3_strings[ASCQ];
4111 /* check for " IN PROGRESS" ones */
4113 *s4 = asc_04_part4_string;
4114 } else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
4115 *s1 = asc_29_ascq_NN_strings[ASCQ];
4117 * Else { leave all *s[1-4] values pointing to the empty "" string }
4123 * Need to check ASC here; if it is "special," then
4124 * the ASCQ is variable, and indicates failed component number.
4125 * We must treat the ASCQ as a "don't care" while searching the
4126 * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
4127 * on when we actually need to identify the failed component.
4129 if (SPECIAL_ASCQ(ASC,ASCQ))
4132 /* OK, now search mptscsih_ASCQ_Table[] for a matching entry */
4133 for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
4134 if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) {
4135 *s1 = mptscsih_ASCQ_TablePtr[idx].Description;
4139 if ((ASC >= 0x80) || (ASCQ >= 0x80))
4140 *s1 = ascq_vendor_uniq;
4147 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4149 * SCSI Information Report; desired output format...
4151 SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION)
4152 Key=6h (UNIT ATTENTION); FRU=03h
4153 ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4154 CDB: 00 00 00 00 00 00 - TestUnitReady
4158 * SCSI Error Report; desired output format...
4160 SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
4161 SCSI_Status=02h (CHECK CONDITION)
4162 Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
4163 SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
4164 SenseKey=6h (UNIT ATTENTION); FRU=03h
4165 ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4169 int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
4175 int sk = SD_Sense_Key(ioop->sensePtr);
4176 const char *skstr = SenseKeyString[sk];
4177 unsigned char asc = SD_ASC(ioop->sensePtr);
4178 unsigned char ascq = SD_ASCQ(ioop->sensePtr);
4181 /* Change the error logging to only report errors on
4182 * read and write commands. Ignore errors on other commands.
4183 * Should this be configurable via proc?
4185 switch (ioop->cdbPtr[0]) {
4201 * Filter out common, repetitive, warning-type errors... like:
4202 * POWER ON (06,29/00 or 06,29/01),
4203 * SPINNING UP (02,04/01),
4204 * LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
4206 if (sk == SK_NO_SENSE) {
4210 if ( (sk==SK_UNIT_ATTENTION && asc==0x29 && (ascq==0x00 || ascq==0x01))
4211 || (sk==SK_NOT_READY && asc==0x04 && (ascq==0x01 || ascq==0x02))
4212 || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
4219 /* Prevent the system from continually writing to the log
4220 * if a medium is not found: 02 3A 00
4221 * Changer issues: TUR, Read Capacity, Table of Contents continually
4223 if (sk==SK_NOT_READY && asc==0x3A) {
4224 if (ioop->cdbPtr == NULL) {
4226 } else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
4227 (ioop->cdbPtr[0] == CMD_ReadCapacity) ||
4228 (ioop->cdbPtr[0] == 0x43)) {
4232 if (sk==SK_UNIT_ATTENTION) {
4233 if (ioop->cdbPtr == NULL)
4235 else if (ioop->cdbPtr[0] == CMD_TestUnitReady)
4240 * Protect ourselves...
4242 if (ioop->cdbPtr == NULL)
4243 ioop->cdbPtr = dummyCDB;
4244 if (ioop->sensePtr == NULL)
4245 ioop->sensePtr = dummySenseData;
4246 if (ioop->inqPtr == NULL)
4247 ioop->inqPtr = dummyInqData;
4248 if (ioop->dataPtr == NULL)
4249 ioop->dataPtr = dummyScsiData;
4252 if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
4253 ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
4254 (void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
4259 if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
4260 opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
4261 else if (mpt_ScsiOpcodesPtr)
4262 opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
4264 l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n",
4268 l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh",
4269 sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
4271 const char *x1, *x2, *x3, *x4;
4272 x1 = x2 = x3 = x4 = "";
4273 x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
4276 l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
4278 l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
4281 l += sprintf(foo+l, "\n CDB:");
4282 l += dump_cdb(foo+l, ioop->cdbPtr);
4284 l += sprintf(foo+l, " - \"%s\"", opstr);
4285 l += sprintf(foo+l, "\n");
4287 PrintF(("%s\n", foo));
4292 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4294 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4296 * mptscsih_initTarget - Target, LUN alloc/free functionality.
4297 * @hd: Pointer to MPT_SCSI_HOST structure
4298 * @bus_id: Bus number (?)
4299 * @target_id: SCSI target id
4301 * @data: Pointer to data
4302 * @dlen: Number of INQUIRY bytes
4304 * NOTE: It's only SAFE to call this routine if data points to
4305 * sane & valid STANDARD INQUIRY data!
4307 * Allocate and initialize memory for this target.
4308 * Save inquiry data.
4312 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
4314 int indexed_lun, lun_index;
4318 dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
4319 hd->ioc->name, bus_id, target_id, lun, hd));
4321 /* Is LUN supported? If so, upper 3 bits will be 0
4322 * in first byte of inquiry data.
4327 vdev = hd->Targets[target_id];
4329 lun_index = (lun >> 5); /* 32 luns per lun_index */
4330 indexed_lun = (lun % 32);
4331 vdev->luns[lun_index] |= (1 << indexed_lun);
4333 vdev->raidVolume = 0;
4335 if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
4336 vdev->raidVolume = 1;
4337 ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
4341 if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
4343 memcpy (vdev->inq_data, data, 8);
4345 memcpy (vdev->inq_data, data, dlen);
4347 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4349 /* If LUN 0, tape and have not done DV, set the DV flag.
4351 if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) {
4352 ScsiCfgData *pSpi = &hd->ioc->spi_data;
4353 if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
4354 pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
4357 if ( (data[0] == SCSI_TYPE_PROC) &&
4358 !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
4360 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4361 if ( data[44] == 'S' &&
4367 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4368 mptscsih_writeIOCPage4(hd, target_id, bus_id);
4371 /* Treat all Processors as SAF-TE if
4372 * command line option is set */
4373 if ( hd->ioc->spi_data.Saf_Te ) {
4374 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4375 mptscsih_writeIOCPage4(hd, target_id, bus_id);
4382 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
4383 /* Update the target capabilities
4386 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
4389 mptscsih_setTargetNegoParms(hd, vdev, data_56);
4392 dprintk((KERN_INFO " target = %p\n", vdev));
4396 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4398 * Update the target negotiation parameters based on the
4399 * the Inquiry data, adapter capabilities, and NVRAM settings.
4402 void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
4404 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
4405 int id = (int) target->target_id;
4410 u8 width = MPT_NARROW;
4411 u8 factor = MPT_ASYNC;
4413 u8 version, nfactor;
4417 if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
4418 if (target->inq_data[7] & 0x02)
4419 target->tflags |= MPT_TARGET_FLAGS_Q_YES;
4424 target->negoFlags = pspi_data->noQas;
4426 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
4427 * support. If available, default QAS to off and allow enabling.
4428 * If not available, default QAS to on, turn off for non-disks.
4431 /* Set flags based on Inquiry data
4433 if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
4434 version = target->inq_data[2] & 0x07;
4437 factor = MPT_ULTRA2;
4438 offset = pspi_data->maxSyncOffset;
4440 if (target->inq_data[7] & 0x20) {
4444 if (target->inq_data[7] & 0x10) {
4445 /* bits 2 & 3 show DT support
4447 if ((byte56 & 0x04) == 0)
4448 factor = MPT_ULTRA2;
4449 else if ((byte56 & 0x03) == 0)
4450 factor = MPT_ULTRA160;
4452 factor = MPT_ULTRA320;
4453 offset = pspi_data->maxSyncOffset;
4455 /* If RAID, never disable QAS
4456 * else if non RAID, do not disable
4457 * QAS if bit 1 is set
4458 * bit 1 QAS support, non-raid only
4461 if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
4469 if (target->inq_data[7] & 0x02) {
4473 /* Update tflags based on NVRAM settings. (SCSI only)
4475 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4476 nvram = pspi_data->nvram[id];
4477 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
4480 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
4483 /* Ensure factor is set to the
4484 * maximum of: adapter, nvram, inquiry
4487 if (nfactor < pspi_data->minSyncFactor )
4488 nfactor = pspi_data->minSyncFactor;
4490 factor = max(factor, nfactor);
4491 if (factor == MPT_ASYNC)
4502 /* Make sure data is consistent
4504 if ((!width) && (factor < MPT_ULTRA2)) {
4505 factor = MPT_ULTRA2;
4508 /* Save the data to the target structure.
4510 target->minSyncFactor = factor;
4511 target->maxOffset = offset;
4512 target->maxWidth = width;
4514 target->tflags |= MPT_TARGET_FLAGS_Q_YES;
4517 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
4519 /* Disable unused features.
4522 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
4525 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
4527 /* GEM, processor WORKAROUND
4529 if (((target->inq_data[0] & 0x1F) == 0x03)
4530 || ((target->inq_data[0] & 0x1F) > 0x08)) {
4531 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
4532 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
4534 if (noQas && (pspi_data->noQas == 0)) {
4535 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
4536 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4538 /* Disable QAS in a mixed configuration case
4541 // ddvtprintk((KERN_INFO "Disabling QAS!\n"));
4542 for (ii = 0; ii < id; ii++) {
4543 if ( (vdev = hd->Targets[ii]) ) {
4544 vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4554 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4555 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
4556 * Else set the NEED_DV flag after Read Capacity Issued (disks)
4557 * or Mode Sense (cdroms).
4559 * Tapes, initTarget will set this flag on completion of Inquiry command.
4560 * Called only if DV_NOT_DONE flag is set
4562 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
4566 if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
4571 if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
4572 ScsiCfgData *pSpi = &hd->ioc->spi_data;
4573 if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
4574 /* Set NEED_DV for all hidden disks
4576 Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk;
4577 int numPDisk = pSpi->pIocPg3->NumPhysDisks;
4580 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4581 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
4586 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
4587 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
4591 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4593 * If no Target, bus reset on 1st I/O. Set the flag to
4594 * prevent any future negotiations to this device.
4596 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
4599 if ((hd->Targets) && (hd->Targets[target_id] == NULL))
4600 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
4605 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4607 * SCSI Config Page functionality ...
4609 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4610 /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
4611 * based on width, factor and offset parameters.
4613 * @factor: sync factor
4614 * @offset: sync offset
4615 * @requestedPtr: pointer to requested values (updated)
4616 * @configurationPtr: pointer to configuration values (updated)
4617 * @flags: flags to block WDTR or SDTR negotiation
4621 * Remark: Called by writeSDP1 and _dv_params
4624 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
4626 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
4627 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
4629 *configurationPtr = 0;
4630 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
4631 *requestedPtr |= (offset << 16) | (factor << 8);
4633 if (width && offset && !nowide && !nosync) {
4634 if (factor < MPT_ULTRA160) {
4635 *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
4636 if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
4637 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
4638 } else if (factor < MPT_ULTRA2) {
4639 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
4644 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
4647 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
4652 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4653 /* mptscsih_writeSDP1 - write SCSI Device Page 1
4654 * @hd: Pointer to a SCSI Host Strucutre
4655 * @portnum: IOC port number
4656 * @target_id: writeSDP1 for single ID
4657 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
4659 * Return: -EFAULT if read of config page header fails
4662 * Remark: If a target has been found, the settings from the
4663 * target structure are used, else the device is set
4666 * Remark: Called during init and after a FW reload.
4667 * Remark: We do not wait for a return, write pages sequentially.
4670 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
4672 MPT_ADAPTER *ioc = hd->ioc;
4674 SCSIDevicePage1_t *pData;
4675 VirtDevice *pTarget;
4680 u32 requested, configuration, flagsLength;
4682 int id = 0, maxid = 0;
4688 u8 maxwidth, maxoffset, maxfactor;
4690 if (ioc->spi_data.sdp1length == 0)
4693 if (flags & MPT_SCSICFG_ALL_IDS) {
4695 maxid = ioc->sh->max_id - 1;
4696 } else if (ioc->sh) {
4698 maxid = min_t(int, id, ioc->sh->max_id - 1);
4701 for (; id <= maxid; id++) {
4703 if (id == ioc->pfacts[portnum].PortSCSIID)
4706 /* Use NVRAM to get adapter and target maximums
4707 * Data over-riden by target structure information, if present
4709 maxwidth = ioc->spi_data.maxBusWidth;
4710 maxoffset = ioc->spi_data.maxSyncOffset;
4711 maxfactor = ioc->spi_data.minSyncFactor;
4712 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4713 nvram = ioc->spi_data.nvram[id];
4716 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
4718 if (maxoffset > 0) {
4719 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
4720 if (maxfactor == 0) {
4722 maxfactor = MPT_ASYNC;
4724 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
4725 maxfactor = ioc->spi_data.minSyncFactor;
4728 maxfactor = MPT_ASYNC;
4731 /* Set the negotiation flags.
4733 negoFlags = ioc->spi_data.noQas;
4735 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
4738 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
4740 if (flags & MPT_SCSICFG_USE_NVRAM) {
4749 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
4752 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4753 /* Force to async and narrow if DV has not been executed
4756 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
4763 /* If id is not a raid volume, get the updated
4764 * transmission settings from the target structure.
4766 if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
4767 width = pTarget->maxWidth;
4768 factor = pTarget->minSyncFactor;
4769 offset = pTarget->maxOffset;
4770 negoFlags = pTarget->negoFlags;
4773 if (flags & MPT_SCSICFG_BLK_NEGO)
4774 negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
4776 mptscsih_setDevicePage1Flags(width, factor, offset,
4777 &requested, &configuration, negoFlags);
4779 /* Get a MF for this command.
4781 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
4782 dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
4787 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
4788 hd->ioc->name, mf, id, requested, configuration));
4791 /* Set the request and the data pointers.
4792 * Request takes: 36 bytes (32 bit SGE)
4793 * SCSI Device Page 1 requires 16 bytes
4794 * 40 + 16 <= size of SCSI IO Request = 56 bytes
4795 * and MF size >= 64 bytes.
4796 * Place data at end of MF.
4798 pReq = (Config_t *)mf;
4800 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
4801 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
4803 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
4804 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
4806 /* Complete the request frame (same for all requests).
4808 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4810 pReq->ChainOffset = 0;
4811 pReq->Function = MPI_FUNCTION_CONFIG;
4812 pReq->ExtPageLength = 0;
4813 pReq->ExtPageType = 0;
4815 for (ii=0; ii < 8; ii++) {
4816 pReq->Reserved2[ii] = 0;
4818 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
4819 pReq->Header.PageLength = ioc->spi_data.sdp1length;
4820 pReq->Header.PageNumber = 1;
4821 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4822 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
4824 /* Add a SGE to the config request.
4826 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
4828 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
4830 /* Set up the common data portion
4832 pData->Header.PageVersion = pReq->Header.PageVersion;
4833 pData->Header.PageLength = pReq->Header.PageLength;
4834 pData->Header.PageNumber = pReq->Header.PageNumber;
4835 pData->Header.PageType = pReq->Header.PageType;
4836 pData->RequestedParameters = cpu_to_le32(requested);
4837 pData->Reserved = 0;
4838 pData->Configuration = cpu_to_le32(configuration);
4840 dprintk((MYIOC_s_INFO_FMT
4841 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
4842 ioc->name, id, (id | (bus<<8)),
4843 requested, configuration));
4845 mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
4851 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4852 /* mptscsih_writeIOCPage4 - write IOC Page 4
4853 * @hd: Pointer to a SCSI Host Structure
4854 * @target_id: write IOC Page4 for this ID & Bus
4856 * Return: -EAGAIN if unable to obtain a Message Frame
4859 * Remark: We do not wait for a return, write pages sequentially.
4862 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
4864 MPT_ADAPTER *ioc = hd->ioc;
4866 IOCPage4_t *IOCPage4Ptr;
4874 /* Get a MF for this command.
4876 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
4877 dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
4882 ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n",
4883 ioc->name, mf, target_id));
4885 /* Set the request and the data pointers.
4886 * Place data at end of MF.
4888 pReq = (Config_t *)mf;
4890 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
4891 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
4893 /* Complete the request frame (same for all requests).
4895 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4897 pReq->ChainOffset = 0;
4898 pReq->Function = MPI_FUNCTION_CONFIG;
4899 pReq->ExtPageLength = 0;
4900 pReq->ExtPageType = 0;
4902 for (ii=0; ii < 8; ii++) {
4903 pReq->Reserved2[ii] = 0;
4906 IOCPage4Ptr = ioc->spi_data.pIocPg4;
4907 dataDma = ioc->spi_data.IocPg4_dma;
4908 ii = IOCPage4Ptr->ActiveSEP++;
4909 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
4910 IOCPage4Ptr->SEP[ii].SEPBus = bus;
4911 pReq->Header = IOCPage4Ptr->Header;
4912 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
4914 /* Add a SGE to the config request.
4916 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
4917 (IOCPage4Ptr->Header.PageLength + ii) * 4;
4919 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
4921 dsprintk((MYIOC_s_INFO_FMT
4922 "writeIOCPage4: pgaddr 0x%x\n",
4923 ioc->name, (target_id | (bus<<8))));
4925 mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
4930 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4931 /* mptscsih_taskmgmt_timeout - Call back for timeout on a
4932 * task management request.
4933 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
4936 static void mptscsih_taskmgmt_timeout(unsigned long data)
4938 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
4940 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
4941 "TM request timed out!\n", hd->ioc->name));
4943 /* Delete the timer that triggered this callback.
4944 * Remark: del_timer checks to make sure timer is active
4947 del_timer(&hd->TMtimer);
4949 /* Call the reset handler. Already had a TM request
4950 * timeout - so issue a diagnostic reset
4952 INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
4953 schedule_work(&mptscsih_rstTask);
4957 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4958 /* mptscsih_schedule_reset - Call back for timeout on a
4959 * task management request.
4960 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
4964 mptscsih_schedule_reset(void *arg)
4967 hd = (MPT_SCSI_HOST *) arg;
4969 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
4970 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
4972 /* Because we have reset the IOC, no TM requests can be
4973 * pending. So let's make sure the tmPending flag is reset.
4975 dtmprintk((KERN_WARNING MYNAM
4976 ": %s: mptscsih_taskmgmt_timeout\n",
4984 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4986 * Bus Scan and Domain Validation functionality ...
4989 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4991 * mptscsih_scandv_complete - Scan and DV callback routine registered
4992 * to Fustion MPT (base) driver.
4994 * @ioc: Pointer to MPT_ADAPTER structure
4995 * @mf: Pointer to original MPT request frame
4996 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
4998 * This routine is called from mpt.c::mpt_interrupt() at the completion
4999 * of any SCSI IO request.
5000 * This routine is registered with the Fusion MPT (base) driver at driver
5001 * load/init time via the mpt_register() API call.
5003 * Returns 1 indicating alloc'd request frame ptr should be freed.
5005 * Remark: Sets a completion code and (possibly) saves sense data
5006 * in the IOC member localReply structure.
5007 * Used ONLY for DV and other internal commands.
5010 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
5013 SCSIIORequest_t *pReq;
5018 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
5019 printk(MYIOC_s_ERR_FMT
5020 "ScanDvComplete, %s req frame ptr! (=%p)\n",
5021 ioc->name, mf?"BAD":"NULL", (void *) mf);
5025 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
5026 del_timer(&hd->timer);
5027 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5028 hd->ScsiLookup[req_idx] = NULL;
5029 pReq = (SCSIIORequest_t *) mf;
5031 if (mf != hd->cmdPtr) {
5032 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
5033 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
5037 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
5038 hd->ioc->name, mf, mr, req_idx));
5040 hd->pLocal = &hd->localReply;
5041 hd->pLocal->scsiStatus = 0;
5043 /* If target struct exists, clear sense valid flag.
5046 completionCode = MPT_SCANDV_GOOD;
5048 SCSIIOReply_t *pReply;
5051 pReply = (SCSIIOReply_t *) mr;
5053 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
5055 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
5056 status, pReply->SCSIState, pReply->SCSIStatus,
5057 le32_to_cpu(pReply->IOCLogInfo)));
5061 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
5062 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
5065 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
5066 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
5067 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
5068 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
5069 completionCode = MPT_SCANDV_DID_RESET;
5072 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
5073 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
5074 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
5075 if (pReply->Function == MPI_FUNCTION_CONFIG) {
5076 ConfigReply_t *pr = (ConfigReply_t *)mr;
5077 completionCode = MPT_SCANDV_GOOD;
5078 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
5079 hd->pLocal->header.PageLength = pr->Header.PageLength;
5080 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
5081 hd->pLocal->header.PageType = pr->Header.PageType;
5083 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
5084 /* If the RAID Volume request is successful,
5085 * return GOOD, else indicate that
5086 * some type of error occurred.
5088 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
5089 if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
5090 completionCode = MPT_SCANDV_GOOD;
5092 completionCode = MPT_SCANDV_SOME_ERROR;
5094 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
5098 /* save sense data in global structure
5100 completionCode = MPT_SCANDV_SENSE;
5101 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5102 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
5103 (req_idx * MPT_SENSE_BUFFER_ALLOC));
5105 sz = min_t(int, pReq->SenseBufferLength,
5106 SCSI_STD_SENSE_BYTES);
5107 memcpy(hd->pLocal->sense, sense_data, sz);
5109 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
5111 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
5112 if (pReq->CDB[0] == CMD_Inquiry)
5113 completionCode = MPT_SCANDV_ISSUE_SENSE;
5115 completionCode = MPT_SCANDV_DID_RESET;
5117 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
5118 completionCode = MPT_SCANDV_DID_RESET;
5119 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5120 completionCode = MPT_SCANDV_DID_RESET;
5122 /* If no error, this will be equivalent
5123 * to MPT_SCANDV_GOOD
5125 completionCode = MPT_SCANDV_GOOD;
5126 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5130 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
5131 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5132 completionCode = MPT_SCANDV_DID_RESET;
5134 completionCode = MPT_SCANDV_SOME_ERROR;
5138 completionCode = MPT_SCANDV_SOME_ERROR;
5141 } /* switch(status) */
5143 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
5145 } /* end of address reply case */
5147 hd->pLocal->completion = completionCode;
5149 /* MF and RF are freed in mpt_interrupt
5152 /* Free Chain buffers (will never chain) in scan or dv */
5153 //mptscsih_freeChainBuffers(hd, req_idx);
5156 * Wake up the original calling thread
5158 scandv_wait_done = 1;
5159 wake_up(&scandv_waitq);
5164 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5165 /* mptscsih_timer_expired - Call back for timer process.
5166 * Used only for dv functionality.
5167 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5170 static void mptscsih_timer_expired(unsigned long data)
5172 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
5174 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
5177 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
5179 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
5180 /* Desire to issue a task management request here.
5181 * TM requests MUST be single threaded.
5182 * If old eh code and no TM current, issue request.
5183 * If new eh code, do nothing. Wait for OS cmd timeout
5186 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
5188 /* Perform a FW reload */
5189 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
5190 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
5194 /* This should NEVER happen */
5195 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
5198 /* No more processing.
5199 * TM call will generate an interrupt for SCSI TM Management.
5200 * The FW will reply to all outstanding commands, callback will finish cleanup.
5201 * Hard reset clean-up will free all resources.
5203 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
5208 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
5209 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5210 /* mptscsih_do_raid - Format and Issue a RAID volume request message.
5211 * @hd: Pointer to scsi host structure
5212 * @action: What do be done.
5213 * @id: Logical target id.
5214 * @bus: Target locations bus.
5216 * Returns: < 0 on a fatal error
5219 * Remark: Wait to return until reply processed by the ISR.
5222 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
5224 MpiRaidActionRequest_t *pReq;
5228 in_isr = in_interrupt();
5230 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
5235 /* Get and Populate a free Frame
5237 if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
5238 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
5242 pReq = (MpiRaidActionRequest_t *)mf;
5243 pReq->Action = action;
5244 pReq->Reserved1 = 0;
5245 pReq->ChainOffset = 0;
5246 pReq->Function = MPI_FUNCTION_RAID_ACTION;
5247 pReq->VolumeID = io->id;
5248 pReq->VolumeBus = io->bus;
5249 pReq->PhysDiskNum = io->physDiskNum;
5251 pReq->Reserved2 = 0;
5252 pReq->ActionDataWord = 0; /* Reserved for this action */
5253 //pReq->ActionDataSGE = 0;
5255 mpt_add_sge((char *)&pReq->ActionDataSGE,
5256 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
5258 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
5259 hd->ioc->name, action, io->id));
5262 hd->timer.expires = jiffies + HZ*2; /* 2 second timeout */
5263 scandv_wait_done = 0;
5265 /* Save cmd pointer, for resource free if timeout or
5270 add_timer(&hd->timer);
5271 mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
5272 wait_event(scandv_waitq, scandv_wait_done);
5274 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
5279 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5281 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5283 * mptscsih_do_cmd - Do internal command.
5284 * @hd: MPT_SCSI_HOST pointer
5285 * @io: INTERNAL_CMD pointer.
5287 * Issue the specified internally generated command and do command
5288 * specific cleanup. For bus scan / DV only.
5289 * NOTES: If command is Inquiry and status is good,
5290 * initialize a target structure, save the data
5292 * Remark: Single threaded access only.
5295 * < 0 if an illegal command or no resources
5299 * > 0 if command complete but some type of completion error.
5302 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
5305 SCSIIORequest_t *pScsiReq;
5306 SCSIIORequest_t ReqCopy;
5307 int my_idx, ii, dir;
5311 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
5314 in_isr = in_interrupt();
5316 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
5322 /* Set command specific information
5327 dir = MPI_SCSIIO_CONTROL_READ;
5333 case CMD_TestUnitReady:
5335 dir = MPI_SCSIIO_CONTROL_READ;
5339 case CMD_StartStopUnit:
5341 dir = MPI_SCSIIO_CONTROL_READ;
5343 CDB[4] = 1; /*Spin up the disk */
5347 case CMD_RequestSense:
5351 dir = MPI_SCSIIO_CONTROL_READ;
5355 case CMD_ReadBuffer:
5357 dir = MPI_SCSIIO_CONTROL_READ;
5359 if (io->flags & MPT_ICFLAG_ECHO) {
5365 if (io->flags & MPT_ICFLAG_BUF_CAP) {
5368 CDB[6] = (io->size >> 16) & 0xFF;
5369 CDB[7] = (io->size >> 8) & 0xFF;
5370 CDB[8] = io->size & 0xFF;
5374 case CMD_WriteBuffer:
5376 dir = MPI_SCSIIO_CONTROL_WRITE;
5378 if (io->flags & MPT_ICFLAG_ECHO) {
5383 CDB[6] = (io->size >> 16) & 0xFF;
5384 CDB[7] = (io->size >> 8) & 0xFF;
5385 CDB[8] = io->size & 0xFF;
5391 dir = MPI_SCSIIO_CONTROL_READ;
5398 dir = MPI_SCSIIO_CONTROL_READ;
5403 case CMD_SynchronizeCache:
5405 dir = MPI_SCSIIO_CONTROL_READ;
5407 // CDB[1] = 0x02; /* set immediate bit */
5416 /* Get and Populate a free Frame
5418 if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
5419 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
5424 pScsiReq = (SCSIIORequest_t *) mf;
5426 /* Get the request index */
5427 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5428 ADD_INDEX_LOG(my_idx); /* for debug */
5430 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
5431 pScsiReq->TargetID = io->physDiskNum;
5433 pScsiReq->ChainOffset = 0;
5434 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
5436 pScsiReq->TargetID = io->id;
5437 pScsiReq->Bus = io->bus;
5438 pScsiReq->ChainOffset = 0;
5439 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
5442 pScsiReq->CDBLength = cmdLen;
5443 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
5445 pScsiReq->Reserved = 0;
5447 pScsiReq->MsgFlags = mpt_msg_flags();
5448 /* MsgContext set in mpt_get_msg_fram call */
5450 for (ii=0; ii < 8; ii++)
5451 pScsiReq->LUN[ii] = 0;
5452 pScsiReq->LUN[1] = io->lun;
5454 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
5455 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
5457 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
5459 if (cmd == CMD_RequestSense) {
5460 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
5461 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
5462 hd->ioc->name, cmd));
5465 for (ii=0; ii < 16; ii++)
5466 pScsiReq->CDB[ii] = CDB[ii];
5468 pScsiReq->DataLength = cpu_to_le32(io->size);
5469 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
5470 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
5472 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
5473 hd->ioc->name, cmd, io->bus, io->id, io->lun));
5475 if (dir == MPI_SCSIIO_CONTROL_READ) {
5476 mpt_add_sge((char *) &pScsiReq->SGL,
5477 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
5480 mpt_add_sge((char *) &pScsiReq->SGL,
5481 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
5485 /* The ISR will free the request frame, but we need
5486 * the information to initialize the target. Duplicate.
5488 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
5490 /* Issue this command after:
5493 * Wait until the reply has been received
5494 * ScsiScanDvCtx callback function will
5496 * set scandv_wait_done and call wake_up
5499 hd->timer.expires = jiffies + HZ*cmdTimeout;
5500 scandv_wait_done = 0;
5502 /* Save cmd pointer, for resource free if timeout or
5507 add_timer(&hd->timer);
5508 mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
5509 wait_event(scandv_waitq, scandv_wait_done);
5512 rc = hd->pLocal->completion;
5513 hd->pLocal->skip = 0;
5515 /* Always set fatal error codes in some cases.
5517 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
5519 else if (rc == MPT_SCANDV_SOME_ERROR)
5523 /* This should never happen. */
5524 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
5531 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5533 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
5534 * @hd: Pointer to MPT_SCSI_HOST structure
5535 * @portnum: IOC port number
5537 * Uses the ISR, but with special processing.
5538 * MUST be single-threaded.
5540 * Return: 0 on completion
5543 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
5545 MPT_ADAPTER *ioc= hd->ioc;
5546 VirtDevice *pTarget;
5547 SCSIDevicePage1_t *pcfg1Data = NULL;
5550 dma_addr_t cfg1_dma_addr = -1;
5551 ConfigPageHeader_t header1;
5555 int indexed_lun, lun_index;
5556 int hostId = ioc->pfacts[portnum].PortSCSIID;
5558 int requested, configuration, data;
5562 max_id = ioc->sh->max_id - 1;
5564 /* Following parameters will not change
5567 iocmd.cmd = CMD_SynchronizeCache;
5569 iocmd.physDiskNum = -1;
5571 iocmd.data_dma = -1;
5573 iocmd.rsvd = iocmd.rsvd2 = 0;
5577 if (hd->Targets == NULL)
5585 /* Write SDP1 for all SCSI devices
5586 * Alloc memory and set up config buffer
5589 if (ioc->spi_data.sdp1length > 0) {
5590 pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
5591 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
5593 if (pcfg1Data != NULL) {
5595 header1.PageVersion = ioc->spi_data.sdp1version;
5596 header1.PageLength = ioc->spi_data.sdp1length;
5597 header1.PageNumber = 1;
5598 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5600 cfg.physAddr = cfg1_dma_addr;
5601 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5608 /* loop through all devices on this port
5610 while (bus < MPT_MAX_BUS) {
5613 pTarget = hd->Targets[(int)id];
5617 /* Set the negotiation flags */
5618 if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
5619 flags = pTarget->negoFlags;
5621 flags = hd->ioc->spi_data.noQas;
5622 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5623 data = hd->ioc->spi_data.nvram[id];
5625 if (data & MPT_NVRAM_WIDE_DISABLE)
5626 flags |= MPT_TARGET_NO_NEGO_WIDE;
5628 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5629 if ((factor == 0) || (factor == MPT_ASYNC))
5630 flags |= MPT_TARGET_NO_NEGO_SYNC;
5634 /* Force to async, narrow */
5635 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
5636 &configuration, flags);
5637 pcfg1Data->RequestedParameters = le32_to_cpu(requested);
5638 pcfg1Data->Reserved = 0;
5639 pcfg1Data->Configuration = le32_to_cpu(configuration);
5640 cfg.pageAddr = (bus<<8) | id;
5641 mpt_config(hd->ioc, &cfg);
5644 /* If target Ptr NULL or if this target is NOT a disk, skip.
5646 if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
5647 for (lun=0; lun <= MPT_LAST_LUN; lun++) {
5648 /* If LUN present, issue the command
5650 lun_index = (lun >> 5); /* 32 luns per lun_index */
5651 indexed_lun = (lun % 32);
5652 if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
5654 (void) mptscsih_do_cmd(hd, &iocmd);
5659 /* get next relevant device */
5672 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
5678 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
5679 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5681 * mptscsih_domainValidation - Top level handler for domain validation.
5682 * @hd: Pointer to MPT_SCSI_HOST structure.
5684 * Uses the ISR, but with special processing.
5685 * Called from schedule, should not be in interrupt mode.
5686 * While thread alive, do dv for all devices needing dv
5691 mptscsih_domainValidation(void *arg)
5695 unsigned long flags;
5696 int id, maxid, dvStatus, did;
5699 spin_lock_irqsave(&dvtaskQ_lock, flags);
5701 if (dvtaskQ_release) {
5703 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5706 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5708 /* For this ioc, loop through all devices and do dv to each device.
5709 * When complete with this ioc, search through the ioc list, and
5710 * for each scsi ioc found, do dv for all devices. Exit when no
5716 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
5717 spin_lock_irqsave(&dvtaskQ_lock, flags);
5718 if (dvtaskQ_release) {
5720 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5723 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5725 set_current_state(TASK_INTERRUPTIBLE);
5726 schedule_timeout(HZ/4);
5728 /* DV only to SCSI adapters */
5729 if ((int)ioc->chip_type <= (int)FC929)
5732 /* Make sure everything looks ok */
5733 if (ioc->sh == NULL)
5736 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
5740 if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
5741 mpt_read_ioc_pg_3(ioc);
5742 if (ioc->spi_data.pIocPg3) {
5743 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
5744 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
5747 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
5748 ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
5754 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
5757 maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
5759 for (id = 0; id < maxid; id++) {
5760 spin_lock_irqsave(&dvtaskQ_lock, flags);
5761 if (dvtaskQ_release) {
5763 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5766 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5767 dvStatus = hd->ioc->spi_data.dvStatus[id];
5769 if (dvStatus & MPT_SCSICFG_NEED_DV) {
5771 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
5772 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
5774 set_current_state(TASK_INTERRUPTIBLE);
5775 schedule_timeout(HZ/4);
5777 /* If hidden phys disk, block IO's to all
5779 * else, process normally
5781 isPhysDisk = mptscsih_is_phys_disk(ioc, id);
5783 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5784 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
5785 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
5790 if (mptscsih_doDv(hd, 0, id) == 1) {
5791 /* Untagged device was busy, try again
5793 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
5794 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
5796 /* DV is complete. Clear flags.
5798 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
5802 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5803 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
5804 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
5809 /* Post OS IOs that were pended while
5812 post_pendingQ_commands(hd);
5814 if (hd->ioc->spi_data.noQas)
5815 mptscsih_qas_check(hd, id);
5821 spin_lock_irqsave(&dvtaskQ_lock, flags);
5823 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5828 /* Search IOC page 3 to determine if this is hidden physical disk
5830 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
5832 if (ioc->spi_data.pIocPg3) {
5833 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
5834 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
5837 if (pPDisk->PhysDiskID == id) {
5847 /* Write SDP1 if no QAS has been enabled
5849 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
5851 VirtDevice *pTarget;
5854 if (hd->Targets == NULL)
5857 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5861 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
5864 pTarget = hd->Targets[ii];
5866 if ((pTarget != NULL) && (!pTarget->raidVolume)) {
5867 if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
5868 pTarget->negoFlags |= hd->ioc->spi_data.noQas;
5869 mptscsih_writeSDP1(hd, 0, ii, 0);
5872 if (mptscsih_is_phys_disk(hd->ioc, ii) == 1)
5873 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
5881 #define MPT_GET_NVRAM_VALS 0x01
5882 #define MPT_UPDATE_MAX 0x02
5883 #define MPT_SET_MAX 0x04
5884 #define MPT_SET_MIN 0x08
5885 #define MPT_FALLBACK 0x10
5886 #define MPT_SAVE 0x20
5888 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5890 * mptscsih_doDv - Perform domain validation to a target.
5891 * @hd: Pointer to MPT_SCSI_HOST structure.
5892 * @portnum: IOC port number.
5893 * @target: Physical ID of this target
5895 * Uses the ISR, but with special processing.
5896 * MUST be single-threaded.
5897 * Test will exit if target is at async & narrow.
5902 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
5904 MPT_ADAPTER *ioc = hd->ioc;
5905 VirtDevice *pTarget;
5906 SCSIDevicePage1_t *pcfg1Data;
5907 SCSIDevicePage0_t *pcfg0Data;
5911 dma_addr_t dvbuf_dma = -1;
5912 dma_addr_t buf1_dma = -1;
5913 dma_addr_t buf2_dma = -1;
5914 dma_addr_t cfg1_dma_addr = -1;
5915 dma_addr_t cfg0_dma_addr = -1;
5916 ConfigPageHeader_t header1;
5917 ConfigPageHeader_t header0;
5924 int dataBufSize = 0;
5925 int echoBufSize = 0;
5930 int nfactor = MPT_ULTRA320;
5932 char doFallback = 0;
5937 if (ioc->spi_data.sdp1length == 0)
5940 if (ioc->spi_data.sdp0length == 0)
5943 /* If multiple buses are used, require that the initiator
5944 * id be the same on all buses.
5946 if (id == ioc->pfacts[0].PortSCSIID)
5950 bus = (u8) bus_number;
5951 ddvtprintk((MYIOC_s_NOTE_FMT
5952 "DV started: bus=%d, id %d dv @ %p\n",
5953 ioc->name, bus, id, &dv));
5955 /* Prep DV structure
5957 memset (&dv, 0, sizeof(DVPARAMETERS));
5960 /* Populate tmax with the current maximum
5961 * transfer parameters for this target.
5962 * Exit if narrow and async.
5964 dv.cmd = MPT_GET_NVRAM_VALS;
5965 mptscsih_dv_parms(hd, &dv, NULL);
5966 if ((!dv.max.width) && (!dv.max.offset))
5969 /* Prep SCSI IO structure
5975 iocmd.physDiskNum = -1;
5976 iocmd.rsvd = iocmd.rsvd2 = 0;
5978 pTarget = hd->Targets[id];
5979 if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
5980 /* Another GEM workaround. Check peripheral device type,
5981 * if PROCESSOR, quit DV.
5983 if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
5984 pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
5989 /* Use tagged commands if possible.
5992 if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
5993 iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
5995 if (hd->ioc->facts.FWVersion.Word < 0x01000600)
5998 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
5999 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
6004 /* Prep cfg structure
6006 cfg.pageAddr = (bus<<8) | id;
6011 header0.PageVersion = ioc->spi_data.sdp0version;
6012 header0.PageLength = ioc->spi_data.sdp0length;
6013 header0.PageNumber = 0;
6014 header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6018 header1.PageVersion = ioc->spi_data.sdp1version;
6019 header1.PageLength = ioc->spi_data.sdp1length;
6020 header1.PageNumber = 1;
6021 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6023 if (header0.PageLength & 1)
6024 dv_alloc = (header0.PageLength * 4) + 4;
6026 dv_alloc += (2048 + (header1.PageLength * 4));
6028 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
6033 pbuf1 = (u8 *)pDvBuf;
6034 buf1_dma = dvbuf_dma;
6037 pbuf2 = (u8 *) (pDvBuf + sz);
6038 buf2_dma = dvbuf_dma + sz;
6041 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
6042 cfg0_dma_addr = dvbuf_dma + sz;
6043 sz += header0.PageLength * 4;
6047 if (header0.PageLength & 1)
6050 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
6051 cfg1_dma_addr = dvbuf_dma + sz;
6053 /* Skip this ID? Set cfg.hdr to force config page write
6056 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
6057 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6058 /* Set the factor from nvram */
6059 nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
6060 if (nfactor < pspi_data->minSyncFactor )
6061 nfactor = pspi_data->minSyncFactor;
6063 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
6064 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
6066 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
6067 ioc->name, bus, id, lun));
6069 dv.cmd = MPT_SET_MAX;
6070 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6073 /* Save the final negotiated settings to
6074 * SCSI device page 1.
6076 cfg.physAddr = cfg1_dma_addr;
6077 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6079 mpt_config(hd->ioc, &cfg);
6085 /* Finish iocmd inititialization - hidden or visible disk? */
6086 if (ioc->spi_data.pIocPg3) {
6087 /* Searc IOC page 3 for matching id
6089 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
6090 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
6093 if (pPDisk->PhysDiskID == id) {
6095 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
6096 iocmd.physDiskNum = pPDisk->PhysDiskNum;
6100 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
6101 ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
6111 /* RAID Volume ID's may double for a physical device. If RAID but
6112 * not a physical ID as well, skip DV.
6114 if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
6119 * Async & Narrow - Inquiry
6120 * Async & Narrow - Inquiry
6121 * Maximum transfer rate - Inquiry
6123 * If compare, test complete.
6124 * If miscompare and first pass, repeat
6125 * If miscompare and not first pass, fall back and repeat
6129 sz = SCSI_STD_INQUIRY_BYTES;
6130 rc = MPT_SCANDV_GOOD;
6132 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
6134 dv.cmd = MPT_SET_MIN;
6135 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6138 cfg.physAddr = cfg1_dma_addr;
6139 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6141 if (mpt_config(hd->ioc, &cfg) != 0)
6144 /* Wide - narrow - wide workaround case
6146 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
6147 /* Send an untagged command to reset disk Qs corrupted
6148 * when a parity error occurs on a Request Sense.
6150 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
6151 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
6152 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
6154 iocmd.cmd = CMD_RequestSense;
6155 iocmd.data_dma = buf1_dma;
6158 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6161 if (hd->pLocal == NULL)
6163 rc = hd->pLocal->completion;
6164 if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
6174 iocmd.cmd = CMD_Inquiry;
6175 iocmd.data_dma = buf1_dma;
6178 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6181 if (hd->pLocal == NULL)
6183 rc = hd->pLocal->completion;
6184 if (rc == MPT_SCANDV_GOOD) {
6185 if (hd->pLocal->scsiStatus == STS_BUSY) {
6186 if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
6193 } else if (rc == MPT_SCANDV_SENSE) {
6196 /* If first command doesn't complete
6197 * with a good status or with a check condition,
6204 /* Reset the size for disks
6206 inq0 = (*pbuf1) & 0x1F;
6207 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
6212 /* Another GEM workaround. Check peripheral device type,
6213 * if PROCESSOR, quit DV.
6215 if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08))
6218 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6222 if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
6223 && (pTarget->minSyncFactor > 0x09)) {
6224 if ((pbuf1[56] & 0x04) == 0)
6226 else if ((pbuf1[56] & 0x01) == 1) {
6227 pTarget->minSyncFactor =
6228 nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
6230 pTarget->minSyncFactor =
6231 nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
6234 dv.max.factor = pTarget->minSyncFactor;
6236 if ((pbuf1[56] & 0x02) == 0) {
6237 pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
6238 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
6244 dv.cmd = MPT_FALLBACK;
6246 dv.cmd = MPT_SET_MAX;
6248 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6249 if (mpt_config(hd->ioc, &cfg) != 0)
6252 if ((!dv.now.width) && (!dv.now.offset))
6255 iocmd.cmd = CMD_Inquiry;
6256 iocmd.data_dma = buf2_dma;
6259 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6261 else if (hd->pLocal == NULL)
6264 /* Save the return code.
6265 * If this is the first pass,
6266 * read SCSI Device Page 0
6267 * and update the target max parameters.
6269 rc = hd->pLocal->completion;
6271 if (rc == MPT_SCANDV_GOOD) {
6277 cfg.physAddr = cfg0_dma_addr;
6278 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6281 if (mpt_config(hd->ioc, &cfg) != 0)
6284 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
6285 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
6287 /* Quantum and Fujitsu workarounds.
6288 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
6289 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
6290 * Resetart with a request for U160.
6292 if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
6295 dv.cmd = MPT_UPDATE_MAX;
6296 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
6297 /* Update the SCSI device page 1 area
6299 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
6304 /* Quantum workaround. Restart this test will the fallback
6307 if (doFallback == 0) {
6308 if (memcmp(pbuf1, pbuf2, sz) != 0) {
6312 break; /* test complete */
6316 } else if (rc == MPT_SCANDV_ISSUE_SENSE)
6317 doFallback = 1; /* set fallback flag */
6318 else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE))
6319 doFallback = 1; /* set fallback flag */
6326 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
6327 inq0 = (*pbuf1) & 0x1F;
6329 /* Continue only for disks
6334 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
6337 /* Start the Enhanced Test.
6338 * 0) issue TUR to clear out check conditions
6339 * 1) read capacity of echo (regular) buffer
6341 * 3) do write-read-compare data pattern test
6343 * 5) update nego parms to target struct
6346 cfg.physAddr = cfg1_dma_addr;
6347 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6350 iocmd.cmd = CMD_TestUnitReady;
6351 iocmd.data_dma = -1;
6356 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6359 if (hd->pLocal == NULL)
6362 rc = hd->pLocal->completion;
6363 if (rc == MPT_SCANDV_GOOD)
6365 else if (rc == MPT_SCANDV_SENSE) {
6366 u8 skey = hd->pLocal->sense[2] & 0x0F;
6367 u8 asc = hd->pLocal->sense[12];
6368 u8 ascq = hd->pLocal->sense[13];
6369 ddvprintk((MYIOC_s_INFO_FMT
6370 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6371 ioc->name, skey, asc, ascq));
6373 if (skey == SK_UNIT_ATTENTION)
6374 notDone++; /* repeat */
6375 else if ((skey == SK_NOT_READY) &&
6376 (asc == 0x04)&&(ascq == 0x01)) {
6377 /* wait then repeat */
6380 } else if ((skey == SK_NOT_READY) && (asc == 0x3A)) {
6381 /* no medium, try read test anyway */
6384 /* All other errors are fatal.
6386 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
6394 iocmd.cmd = CMD_ReadBuffer;
6395 iocmd.data_dma = buf1_dma;
6398 iocmd.flags |= MPT_ICFLAG_BUF_CAP;
6402 for (patt = 0; patt < 2; patt++) {
6404 iocmd.flags |= MPT_ICFLAG_ECHO;
6406 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6412 /* If not ready after 8 trials,
6413 * give up on this device.
6418 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6420 else if (hd->pLocal == NULL)
6423 rc = hd->pLocal->completion;
6424 ddvprintk(("ReadBuffer Comp Code %d", rc));
6425 ddvprintk((" buff: %0x %0x %0x %0x\n",
6426 pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
6428 if (rc == MPT_SCANDV_GOOD) {
6430 if (iocmd.flags & MPT_ICFLAG_ECHO) {
6431 bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
6433 bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
6435 } else if (rc == MPT_SCANDV_SENSE) {
6436 u8 skey = hd->pLocal->sense[2] & 0x0F;
6437 u8 asc = hd->pLocal->sense[12];
6438 u8 ascq = hd->pLocal->sense[13];
6439 ddvprintk((MYIOC_s_INFO_FMT
6440 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6441 ioc->name, skey, asc, ascq));
6442 if (skey == SK_ILLEGAL_REQUEST) {
6444 } else if (skey == SK_UNIT_ATTENTION) {
6445 notDone++; /* repeat */
6446 } else if ((skey == SK_NOT_READY) &&
6447 (asc == 0x04)&&(ascq == 0x01)) {
6448 /* wait then repeat */
6452 /* All other errors are fatal.
6454 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
6459 /* All other errors are fatal
6466 if (iocmd.flags & MPT_ICFLAG_ECHO)
6467 echoBufSize = bufsize;
6469 dataBufSize = bufsize;
6472 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
6474 /* Use echo buffers if possible,
6475 * Exit if both buffers are 0.
6477 if (echoBufSize > 0) {
6478 iocmd.flags |= MPT_ICFLAG_ECHO;
6479 if (dataBufSize > 0)
6480 bufsize = min(echoBufSize, dataBufSize);
6482 bufsize = echoBufSize;
6483 } else if (dataBufSize == 0)
6486 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
6487 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
6489 /* Data buffers for write-read-compare test max 1K.
6491 sz = min(bufsize, 1024);
6494 * On first pass, always issue a reserve.
6495 * On additional loops, only if a reset has occurred.
6496 * iocmd.flags indicates if echo or regular buffer
6498 for (patt = 0; patt < 4; patt++) {
6499 ddvprintk(("Pattern %d\n", patt));
6500 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
6501 iocmd.cmd = CMD_TestUnitReady;
6502 iocmd.data_dma = -1;
6505 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6508 iocmd.cmd = CMD_Release6;
6509 iocmd.data_dma = -1;
6512 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6514 else if (hd->pLocal == NULL)
6517 rc = hd->pLocal->completion;
6518 ddvprintk(("Release rc %d\n", rc));
6519 if (rc == MPT_SCANDV_GOOD)
6520 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6524 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6526 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
6529 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
6530 iocmd.cmd = CMD_Reserve6;
6531 iocmd.data_dma = -1;
6534 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6536 else if (hd->pLocal == NULL)
6539 rc = hd->pLocal->completion;
6540 if (rc == MPT_SCANDV_GOOD) {
6541 iocmd.flags |= MPT_ICFLAG_RESERVED;
6542 } else if (rc == MPT_SCANDV_SENSE) {
6543 /* Wait if coming ready
6545 u8 skey = hd->pLocal->sense[2] & 0x0F;
6546 u8 asc = hd->pLocal->sense[12];
6547 u8 ascq = hd->pLocal->sense[13];
6548 ddvprintk((MYIOC_s_INFO_FMT
6549 "DV: Reserve Failed: ", ioc->name));
6550 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6553 if ((skey == SK_NOT_READY) && (asc == 0x04)&&
6555 /* wait then repeat */
6559 ddvprintk((MYIOC_s_INFO_FMT
6560 "DV: Reserved Failed.", ioc->name));
6564 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
6571 mptscsih_fillbuf(pbuf1, sz, patt, 1);
6572 iocmd.cmd = CMD_WriteBuffer;
6573 iocmd.data_dma = buf1_dma;
6576 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6578 else if (hd->pLocal == NULL)
6581 rc = hd->pLocal->completion;
6582 if (rc == MPT_SCANDV_GOOD)
6583 ; /* Issue read buffer */
6584 else if (rc == MPT_SCANDV_DID_RESET) {
6585 /* If using echo buffers, reset to data buffers.
6586 * Else do Fallback and restart
6587 * this test (re-issue reserve
6588 * because of bus reset).
6590 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
6591 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6593 dv.cmd = MPT_FALLBACK;
6594 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6596 if (mpt_config(hd->ioc, &cfg) != 0)
6599 if ((!dv.now.width) && (!dv.now.offset))
6603 iocmd.flags |= MPT_ICFLAG_DID_RESET;
6606 } else if (rc == MPT_SCANDV_SENSE) {
6607 /* Restart data test if UA, else quit.
6609 u8 skey = hd->pLocal->sense[2] & 0x0F;
6610 ddvprintk((MYIOC_s_INFO_FMT
6611 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
6612 hd->pLocal->sense[12], hd->pLocal->sense[13]));
6613 if (skey == SK_UNIT_ATTENTION) {
6616 } else if (skey == SK_ILLEGAL_REQUEST) {
6617 if (iocmd.flags & MPT_ICFLAG_ECHO) {
6618 if (dataBufSize >= bufsize) {
6619 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6634 iocmd.cmd = CMD_ReadBuffer;
6635 iocmd.data_dma = buf2_dma;
6638 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6640 else if (hd->pLocal == NULL)
6643 rc = hd->pLocal->completion;
6644 if (rc == MPT_SCANDV_GOOD) {
6645 /* If buffers compare,
6646 * go to next pattern,
6647 * else, do a fallback and restart
6648 * data transfer test.
6650 if (memcmp (pbuf1, pbuf2, sz) == 0) {
6651 ; /* goto next pattern */
6653 /* Miscompare with Echo buffer, go to data buffer,
6654 * if that buffer exists.
6655 * Miscompare with Data buffer, check first 4 bytes,
6656 * some devices return capacity. Exit in this case.
6658 if (iocmd.flags & MPT_ICFLAG_ECHO) {
6659 if (dataBufSize >= bufsize)
6660 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6664 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
6665 /* Argh. Device returning wrong data.
6666 * Quit DV for this device.
6671 /* Had an actual miscompare. Slow down.*/
6672 dv.cmd = MPT_FALLBACK;
6673 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6675 if (mpt_config(hd->ioc, &cfg) != 0)
6678 if ((!dv.now.width) && (!dv.now.offset))
6685 } else if (rc == MPT_SCANDV_DID_RESET) {
6686 /* Do Fallback and restart
6687 * this test (re-issue reserve
6688 * because of bus reset).
6690 dv.cmd = MPT_FALLBACK;
6691 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6693 if (mpt_config(hd->ioc, &cfg) != 0)
6696 if ((!dv.now.width) && (!dv.now.offset))
6699 iocmd.flags |= MPT_ICFLAG_DID_RESET;
6702 } else if (rc == MPT_SCANDV_SENSE) {
6703 /* Restart data test if UA, else quit.
6705 u8 skey = hd->pLocal->sense[2] & 0x0F;
6706 ddvprintk((MYIOC_s_INFO_FMT
6707 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
6708 hd->pLocal->sense[12], hd->pLocal->sense[13]));
6709 if (skey == SK_UNIT_ATTENTION) {
6721 } /* --- end of patt loop ---- */
6724 if (iocmd.flags & MPT_ICFLAG_RESERVED) {
6725 iocmd.cmd = CMD_Release6;
6726 iocmd.data_dma = -1;
6729 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6730 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
6732 else if (hd->pLocal) {
6733 if (hd->pLocal->completion == MPT_SCANDV_GOOD)
6734 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6736 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
6742 /* Set if cfg1_dma_addr contents is valid
6744 if ((cfg.hdr != NULL) && (retcode == 0)){
6745 /* If disk, not U320, disable QAS
6747 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320))
6748 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
6751 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6753 /* Double writes to SDP1 can cause problems,
6754 * skip save of the final negotiated settings to
6755 * SCSI device page 1.
6758 cfg.physAddr = cfg1_dma_addr;
6759 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6761 mpt_config(hd->ioc, &cfg);
6765 /* If this is a RAID Passthrough, enable internal IOs
6767 if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
6768 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
6769 ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
6772 /* Done with the DV scan of the current target
6775 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
6777 ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n",
6783 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6784 /* mptscsih_dv_parms - perform a variety of operations on the
6785 * parameters used for negotiation.
6786 * @hd: Pointer to a SCSI host.
6787 * @dv: Pointer to a structure that contains the maximum and current
6788 * negotiated parameters.
6791 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
6793 VirtDevice *pTarget;
6794 SCSIDevicePage0_t *pPage0;
6795 SCSIDevicePage1_t *pPage1;
6796 int val = 0, data, configuration;
6805 case MPT_GET_NVRAM_VALS:
6806 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
6808 /* Get the NVRAM values and save in tmax
6809 * If not an LVD bus, the adapter minSyncFactor has been
6810 * already throttled back.
6812 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
6813 width = pTarget->maxWidth;
6814 offset = pTarget->maxOffset;
6815 factor = pTarget->minSyncFactor;
6816 negoFlags = pTarget->negoFlags;
6818 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6819 data = hd->ioc->spi_data.nvram[id];
6820 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
6821 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
6824 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
6825 if ((factor == 0) || (factor == MPT_ASYNC)){
6836 /* Set the negotiation flags */
6837 negoFlags = hd->ioc->spi_data.noQas;
6839 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
6842 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
6845 /* limit by adapter capabilities */
6846 width = min(width, hd->ioc->spi_data.maxBusWidth);
6847 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
6848 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
6850 /* Check Consistency */
6851 if (offset && (factor < MPT_ULTRA2) && !width)
6852 factor = MPT_ULTRA2;
6854 dv->max.width = width;
6855 dv->max.offset = offset;
6856 dv->max.factor = factor;
6857 dv->max.flags = negoFlags;
6858 ddvprintk((" width %d, factor %x, offset %x flags %x\n",
6859 width, factor, offset, negoFlags));
6862 case MPT_UPDATE_MAX:
6863 ddvprintk((MYIOC_s_NOTE_FMT
6864 "Updating with SDP0 Data: ", hd->ioc->name));
6865 /* Update tmax values with those from Device Page 0.*/
6866 pPage0 = (SCSIDevicePage0_t *) pPage;
6868 val = cpu_to_le32(pPage0->NegotiatedParameters);
6869 dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
6870 dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
6871 dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
6874 dv->now.width = dv->max.width;
6875 dv->now.offset = dv->max.offset;
6876 dv->now.factor = dv->max.factor;
6877 ddvprintk(("width %d, factor %x, offset %x, flags %x\n",
6878 dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
6882 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
6884 /* Set current to the max values. Update the config page.*/
6885 dv->now.width = dv->max.width;
6886 dv->now.offset = dv->max.offset;
6887 dv->now.factor = dv->max.factor;
6888 dv->now.flags = dv->max.flags;
6890 pPage1 = (SCSIDevicePage1_t *)pPage;
6892 mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
6893 dv->now.offset, &val, &configuration, dv->now.flags);
6894 pPage1->RequestedParameters = le32_to_cpu(val);
6895 pPage1->Reserved = 0;
6896 pPage1->Configuration = le32_to_cpu(configuration);
6900 ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n",
6901 dv->now.width, dv->now.factor, dv->now.offset, val, configuration));
6905 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
6907 /* Set page to asynchronous and narrow
6908 * Do not update now, breaks fallback routine. */
6912 negoFlags = dv->max.flags;
6914 pPage1 = (SCSIDevicePage1_t *)pPage;
6916 mptscsih_setDevicePage1Flags (width, factor,
6917 offset, &val, &configuration, negoFlags);
6918 pPage1->RequestedParameters = le32_to_cpu(val);
6919 pPage1->Reserved = 0;
6920 pPage1->Configuration = le32_to_cpu(configuration);
6922 ddvprintk(("width %d, factor %x, offset %x request %x config %x\n",
6923 width, factor, offset, val, configuration));
6927 ddvprintk((MYIOC_s_NOTE_FMT
6928 "Fallback: Start: offset %d, factor %x, width %d \n",
6929 hd->ioc->name, dv->now.offset,
6930 dv->now.factor, dv->now.width));
6931 width = dv->now.width;
6932 offset = dv->now.offset;
6933 factor = dv->now.factor;
6934 if ((offset) && (dv->max.width)) {
6935 if (factor < MPT_ULTRA160)
6936 factor = MPT_ULTRA160;
6937 else if (factor < MPT_ULTRA2) {
6938 factor = MPT_ULTRA2;
6940 } else if ((factor == MPT_ULTRA2) && width) {
6941 factor = MPT_ULTRA2;
6943 } else if (factor < MPT_ULTRA) {
6946 } else if ((factor == MPT_ULTRA) && width) {
6948 } else if (factor < MPT_FAST) {
6951 } else if ((factor == MPT_FAST) && width) {
6954 } else if (factor < MPT_SCSI) {
6957 } else if ((factor == MPT_SCSI) && width) {
6965 } else if (offset) {
6967 if (factor < MPT_ULTRA)
6969 else if (factor < MPT_FAST)
6971 else if (factor < MPT_SCSI)
6982 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
6984 dv->now.width = width;
6985 dv->now.offset = offset;
6986 dv->now.factor = factor;
6987 dv->now.flags = dv->max.flags;
6989 pPage1 = (SCSIDevicePage1_t *)pPage;
6991 mptscsih_setDevicePage1Flags (width, factor, offset, &val,
6992 &configuration, dv->now.flags);
6994 pPage1->RequestedParameters = le32_to_cpu(val);
6995 pPage1->Reserved = 0;
6996 pPage1->Configuration = le32_to_cpu(configuration);
6999 ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n",
7000 dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
7004 ddvprintk((MYIOC_s_NOTE_FMT
7005 "Saving to Target structure: ", hd->ioc->name));
7006 ddvprintk(("offset %d, factor %x, width %d \n",
7007 dv->now.offset, dv->now.factor, dv->now.width));
7009 /* Save these values to target structures
7010 * or overwrite nvram (phys disks only).
7013 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
7014 pTarget->maxWidth = dv->now.width;
7015 pTarget->maxOffset = dv->now.offset;
7016 pTarget->minSyncFactor = dv->now.factor;
7017 pTarget->negoFlags = dv->now.flags;
7019 /* Preserv all flags, use
7020 * read-modify-write algorithm
7022 if (hd->ioc->spi_data.nvram) {
7023 data = hd->ioc->spi_data.nvram[id];
7026 data &= ~MPT_NVRAM_WIDE_DISABLE;
7028 data |= MPT_NVRAM_WIDE_DISABLE;
7030 if (!dv->now.offset)
7033 data &= ~MPT_NVRAM_SYNC_MASK;
7034 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
7036 hd->ioc->spi_data.nvram[id] = data;
7043 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7044 /* mptscsih_fillbuf - fill a buffer with a special data pattern
7045 * cleanup. For bus scan only.
7047 * @buffer: Pointer to data buffer to be filled.
7048 * @size: Number of bytes to fill
7049 * @index: Pattern index
7050 * @width: bus width, 0 (8 bits) or 1 (16 bits)
7053 mptscsih_fillbuf(char *buffer, int size, int index, int width)
7064 /* Pattern: 0000 FFFF 0000 FFFF
7066 for (ii=0; ii < size; ii++, ptr++) {
7073 /* Pattern: 00 FF 00 FF
7075 for (ii=0; ii < size; ii++, ptr++) {
7086 /* Pattern: 5555 AAAA 5555 AAAA 5555
7088 for (ii=0; ii < size; ii++, ptr++) {
7095 /* Pattern: 55 AA 55 AA 55
7097 for (ii=0; ii < size; ii++, ptr++) {
7107 /* Pattern: 00 01 02 03 04 05
7110 for (ii=0; ii < size; ii++, ptr++)
7116 /* Wide Pattern: FFFE 0001 FFFD 0002
7117 * ... 4000 DFFF 8000 EFFF
7120 for (ii=0; ii < size/2; ii++) {
7121 /* Create the base pattern
7124 /* every 64 (0x40) bytes flip the pattern
7125 * since we fill 2 bytes / iteration,
7126 * test for ii = 0x20
7132 *ptr = (char)( (val & 0xFF00) >> 8);
7134 *ptr = (char)(val & 0xFF);
7139 *ptr = (char)( (val & 0xFF00) >> 8);
7141 *ptr = (char)(val & 0xFF);
7147 /* Narrow Pattern: FE 01 FD 02 FB 04
7148 * .. 7F 80 01 FE 02 FD ... 80 7F
7151 for (ii=0; ii < size; ii++, ptr++) {
7152 /* Base pattern - first 32 bytes
7159 *ptr = (char) (~(1 << byte));
7162 /* Flip the pattern every 32 bytes
7171 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
7173 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7174 /* Commandline Parsing routines and defines.
7177 * insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1"
7179 * mptscsih=width:1,dv:n,factor:0x8,saf-te:1
7189 static char setup_token[] __initdata =
7194 ; /* DO NOT REMOVE THIS ';' */
7198 #define OPT_MAX_WIDTH 2
7199 #define OPT_MIN_SYNC_FACTOR 3
7200 #define OPT_SAF_TE 4
7202 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7205 get_setup_token(char *p)
7207 char *cur = setup_token;
7211 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7214 if (!strncmp(p, cur, pc - cur))
7221 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7223 mptscsih_setup(char *str)
7230 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7242 val = (int) simple_strtoul(pv, &pe, 0);
7244 printk("Found Token: %s, value %x\n", cur, (int)val);
7245 switch (get_setup_token(cur)) {
7247 driver_setup.dv = val;
7251 driver_setup.max_width = val;
7254 case OPT_MIN_SYNC_FACTOR:
7255 driver_setup.min_sync_fac = val;
7259 driver_setup.saf_te = val;
7263 printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
7267 if ((cur = strchr(cur, ARG_SEP)) != NULL)
7273 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7276 module_init(mptscsih_init);
7277 module_exit(mptscsih_exit);