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 "../../scsi/scsi.h"
78 #include <scsi/scsi_host.h>
85 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
86 #define my_NAME "Fusion MPT SCSI Host driver"
87 #define my_VERSION MPT_LINUX_VERSION_COMMON
88 #define MYNAM "mptscsih"
90 MODULE_AUTHOR(MODULEAUTHOR);
91 MODULE_DESCRIPTION(my_NAME);
92 MODULE_LICENSE("GPL");
94 /* Set string for command line args from insmod */
99 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
101 typedef struct _BIG_SENSE_BUF {
102 u8 data[MPT_SENSE_BUFFER_ALLOC];
105 #define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
106 #define MPT_SCANDV_DID_RESET (0x00000001)
107 #define MPT_SCANDV_SENSE (0x00000002)
108 #define MPT_SCANDV_SOME_ERROR (0x00000004)
109 #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
110 #define MPT_SCANDV_ISSUE_SENSE (0x00000010)
112 #define MPT_SCANDV_MAX_RETRIES (10)
114 #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
115 #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
116 #define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */
117 #define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */
118 #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
119 #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
121 typedef struct _internal_cmd {
122 char *data; /* data pointer */
123 dma_addr_t data_dma; /* data dma address */
124 int size; /* transfer size */
125 u8 cmd; /* SCSI Op Code */
126 u8 bus; /* bus number */
127 u8 id; /* SCSI ID (virtual) */
129 u8 flags; /* Bit Field - See above */
130 u8 physDiskNum; /* Phys disk number, -1 else */
135 typedef struct _negoparms {
142 typedef struct _dv_parameters {
152 * Other private/forward protos...
154 static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
155 static void mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
156 static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
158 static int mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
159 SCSIIORequest_t *pReq, int req_idx);
160 static void mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
161 static int mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
162 static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
163 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
164 static u32 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc);
165 static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
166 static void post_pendingQ_commands(MPT_SCSI_HOST *hd);
168 static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
169 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
171 static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
172 static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
174 static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
175 void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
176 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
177 static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
178 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
179 static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
180 static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
181 static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
182 static void mptscsih_timer_expired(unsigned long data);
183 static void mptscsih_taskmgmt_timeout(unsigned long data);
184 static void mptscsih_schedule_reset(void *hd);
185 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
186 static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
188 static struct mpt_work_struct mptscsih_rstTask;
190 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
191 static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
192 static void mptscsih_domainValidation(void *hd);
193 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
194 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
195 static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
196 static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
197 static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
200 static int mptscsih_setup(char *str);
202 /* module entry point */
203 static int __init mptscsih_init (void);
204 static void __exit mptscsih_exit (void);
206 static int mptscsih_probe (struct pci_dev *, const struct pci_device_id *);
207 static void mptscsih_remove(struct pci_dev *);
208 static void mptscsih_shutdown(struct device *);
210 static int mptscsih_suspend(struct pci_dev *pdev, u32 state);
211 static int mptscsih_resume(struct pci_dev *pdev);
219 static int mpt_scsi_hosts = 0;
221 static int ScsiDoneCtx = -1;
222 static int ScsiTaskCtx = -1;
223 static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
225 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
227 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
229 * Domain Validation task structure
231 static spinlock_t dvtaskQ_lock = SPIN_LOCK_UNLOCKED;
232 static int dvtaskQ_active = 0;
233 static int dvtaskQ_release = 0;
234 static struct mpt_work_struct mptscsih_dvTask;
240 static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
241 static int scandv_wait_done = 1;
243 /* Driver default setup
245 static struct mptscsih_driver_setup
246 driver_setup = MPTSCSIH_DRIVER_SETUP;
248 #ifdef MPTSCSIH_DBG_TIMEOUT
249 static Scsi_Cmnd *foo_to[8];
252 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
256 static struct scsi_host_template driver_template = {
257 .proc_name = "mptscsih",
258 .proc_info = x_scsi_proc_info,
259 .name = "MPT SCSI Host",
261 .queuecommand = x_scsi_queuecommand,
262 .slave_alloc = x_scsi_slave_alloc,
263 .slave_configure = x_scsi_slave_configure,
264 .slave_destroy = x_scsi_slave_destroy,
265 .eh_abort_handler = x_scsi_abort,
266 .eh_device_reset_handler = x_scsi_dev_reset,
267 .eh_bus_reset_handler = x_scsi_bus_reset,
268 .eh_host_reset_handler = x_scsi_host_reset,
269 .bios_param = x_scsi_bios_param,
270 .can_queue = MPT_SCSI_CAN_QUEUE,
272 .sg_tablesize = MPT_SCSI_SG_DEPTH,
273 .max_sectors = MPT_SCSI_MAX_SECTORS,
274 .cmd_per_lun = MPT_SCSI_CMD_PER_LUN,
275 .use_clustering = ENABLE_CLUSTERING,
278 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
280 * Private inline routines...
282 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
283 /* 19991030 -sralston
284 * Return absolute SCSI data direction:
289 * Changed: 3-20-2002 pdelaney to use the default data
290 * direction and the defines set up in the
292 * 1 = _DATA_OUT changed to SCSI_DATA_WRITE (1)
293 * 0 = _DIR_NONE changed to SCSI_DATA_NONE (3)
294 * -1 = _DATA_IN changed to SCSI_DATA_READ (2)
295 * If the direction is unknown, fall through to original code.
297 * Mid-layer bug fix(): sg interface generates the wrong data
298 * direction in some cases. Set the direction the hard way for
299 * the most common commands.
302 mptscsih_io_direction(Scsi_Cmnd *cmd)
304 switch (cmd->cmnd[0]) {
308 return SCSI_DATA_WRITE;
313 return SCSI_DATA_READ;
317 if (cmd->sc_data_direction != SCSI_DATA_UNKNOWN)
318 return cmd->sc_data_direction;
320 switch (cmd->cmnd[0]) {
321 /* _DATA_OUT commands */
322 case WRITE_6: case WRITE_10: case WRITE_12:
324 case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
325 case WRITE_VERIFY: case WRITE_VERIFY_12:
326 case COMPARE: case COPY: case COPY_VERIFY:
327 case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
328 case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12:
329 case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT:
330 case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK:
331 case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG:
332 case REASSIGN_BLOCKS:
333 case PERSISTENT_RESERVE_OUT:
336 return SCSI_DATA_WRITE;
338 /* No data transfer commands */
339 case SEEK_6: case SEEK_10:
340 case RESERVE: case RELEASE:
341 case TEST_UNIT_READY:
343 case ALLOW_MEDIUM_REMOVAL:
344 return SCSI_DATA_NONE;
346 /* Conditional data transfer commands */
348 if (cmd->cmnd[1] & 0x10) /* FmtData (data out phase)? */
349 return SCSI_DATA_WRITE;
351 return SCSI_DATA_NONE;
354 if (cmd->cmnd[1] & 0x02) /* VERIFY:BYTCHK (data out phase)? */
355 return SCSI_DATA_WRITE;
357 return SCSI_DATA_NONE;
360 if (cmd->cmnd[1] & 0x03) /* RESERVE:{LongID|Extent} (data out phase)? */
361 return SCSI_DATA_WRITE;
363 return SCSI_DATA_NONE;
365 /* Must be data _IN! */
367 return SCSI_DATA_READ;
369 } /* mptscsih_io_direction() */
371 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
373 * mptscsih_add_sge - Place a simple SGE at address pAddr.
374 * @pAddr: virtual address for SGE
375 * @flagslength: SGE flags and data transfer length
376 * @dma_addr: Physical address
378 * This routine places a MPT request frame back on the MPT adapter's
382 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
384 if (sizeof(dma_addr_t) == sizeof(u64)) {
385 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
386 u32 tmp = dma_addr & 0xFFFFFFFF;
388 pSge->FlagsLength = cpu_to_le32(flagslength);
389 pSge->Address.Low = cpu_to_le32(tmp);
390 tmp = (u32) ((u64)dma_addr >> 32);
391 pSge->Address.High = cpu_to_le32(tmp);
394 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
395 pSge->FlagsLength = cpu_to_le32(flagslength);
396 pSge->Address = cpu_to_le32(dma_addr);
398 } /* mptscsih_add_sge() */
400 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
402 * mptscsih_add_chain - Place a chain SGE at address pAddr.
403 * @pAddr: virtual address for SGE
404 * @next: nextChainOffset value (u32's)
405 * @length: length of next SGL segment
406 * @dma_addr: Physical address
408 * This routine places a MPT request frame back on the MPT adapter's
412 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
414 if (sizeof(dma_addr_t) == sizeof(u64)) {
415 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
416 u32 tmp = dma_addr & 0xFFFFFFFF;
418 pChain->Length = cpu_to_le16(length);
419 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
421 pChain->NextChainOffset = next;
423 pChain->Address.Low = cpu_to_le32(tmp);
424 tmp = (u32) ((u64)dma_addr >> 32);
425 pChain->Address.High = cpu_to_le32(tmp);
427 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
428 pChain->Length = cpu_to_le16(length);
429 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
430 pChain->NextChainOffset = next;
431 pChain->Address = cpu_to_le32(dma_addr);
433 } /* mptscsih_add_chain() */
435 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
437 * mptscsih_getFreeChainBuffes - Function to get a free chain
438 * from the MPT_SCSI_HOST FreeChainQ.
439 * @hd: Pointer to the MPT_SCSI_HOST instance
440 * @req_idx: Index of the SCSI IO request frame. (output)
442 * return SUCCESS or FAILED
445 mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
447 MPT_FRAME_HDR *chainBuf;
452 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
453 if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
457 chainBuf = hd->FreeChainQ.head;
458 Q_DEL_ITEM(&chainBuf->u.frame.linkage);
459 offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
460 chain_idx = offset / hd->ioc->req_sz;
465 chain_idx = MPT_HOST_NO_CHAIN;
467 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
470 *retIndex = chain_idx;
472 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
473 hd->ioc->name, *retIndex, chainBuf));
476 } /* mptscsih_getFreeChainBuffer() */
478 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
480 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
481 * SCSIIORequest_t Message Frame.
482 * @hd: Pointer to MPT_SCSI_HOST structure
483 * @SCpnt: Pointer to Scsi_Cmnd structure
484 * @pReq: Pointer to SCSIIORequest_t structure
489 mptscsih_AddSGE(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt,
490 SCSIIORequest_t *pReq, int req_idx)
494 struct scatterlist *sg;
496 int sges_left, sg_done;
497 int chain_idx = MPT_HOST_NO_CHAIN;
499 int numSgeSlots, numSgeThisFrame;
500 u32 sgflags, sgdir, thisxfer = 0;
501 int chain_dma_off = 0;
506 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
507 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
508 sgdir = MPT_TRANSFER_HOST_TO_IOC;
510 sgdir = MPT_TRANSFER_IOC_TO_HOST;
513 psge = (char *) &pReq->SGL;
514 frm_sz = hd->ioc->req_sz;
516 /* Map the data portion, if any.
517 * sges_left = 0 if no data transfer.
519 if ( (sges_left = SCpnt->use_sg) ) {
520 sges_left = pci_map_sg(hd->ioc->pcidev,
521 (struct scatterlist *) SCpnt->request_buffer,
523 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
526 } else if (SCpnt->request_bufflen) {
527 dma_addr_t buf_dma_addr;
530 buf_dma_addr = pci_map_single(hd->ioc->pcidev,
531 SCpnt->request_buffer,
532 SCpnt->request_bufflen,
533 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
535 /* We hide it here for later unmap. */
536 my_priv = (scPrivate *) &SCpnt->SCp;
537 my_priv->p1 = (void *)(ulong) buf_dma_addr;
539 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
540 hd->ioc->name, SCpnt, SCpnt->request_bufflen));
542 mptscsih_add_sge((char *) &pReq->SGL,
543 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
549 /* Handle the SG case.
551 sg = (struct scatterlist *) SCpnt->request_buffer;
553 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
556 /* Prior to entering this loop - the following must be set
557 * current MF: sgeOffset (bytes)
558 * chainSge (Null if original MF is not a chain buffer)
559 * sg_done (num SGE done for this MF)
563 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
564 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
566 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
568 /* Get first (num - 1) SG elements
569 * Skip any SG entries with a length of 0
570 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
572 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
573 thisxfer = sg_dma_len(sg);
575 sg ++; /* Get next SG element from the OS */
580 v2 = sg_dma_address(sg);
581 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
583 sg++; /* Get next SG element from the OS */
584 psge += (sizeof(u32) + sizeof(dma_addr_t));
585 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
589 if (numSgeThisFrame == sges_left) {
590 /* Add last element, end of buffer and end of list flags.
592 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
593 MPT_SGE_FLAGS_END_OF_BUFFER |
594 MPT_SGE_FLAGS_END_OF_LIST;
596 /* Add last SGE and set termination flags.
597 * Note: Last SGE may have a length of 0 - which should be ok.
599 thisxfer = sg_dma_len(sg);
601 v2 = sg_dma_address(sg);
602 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
605 psge += (sizeof(u32) + sizeof(dma_addr_t));
607 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
611 /* The current buffer is a chain buffer,
612 * but there is not another one.
613 * Update the chain element
614 * Offset and Length fields.
616 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
618 /* The current buffer is the original MF
619 * and there is no Chain buffer.
621 pReq->ChainOffset = 0;
624 /* At least one chain buffer is needed.
625 * Complete the first MF
626 * - last SGE element, set the LastElement bit
627 * - set ChainOffset (words) for orig MF
628 * (OR finish previous MF chain buffer)
629 * - update MFStructPtr ChainIndex
630 * - Populate chain element
635 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
636 hd->ioc->name, sg_done));
638 /* Set LAST_ELEMENT flag for last non-chain element
639 * in the buffer. Since psge points at the NEXT
640 * SGE element, go back one SGE element, update the flags
641 * and reset the pointer. (Note: sgflags & thisxfer are already
645 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
646 sgflags = le32_to_cpu(*ptmp);
647 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
648 *ptmp = cpu_to_le32(sgflags);
652 /* The current buffer is a chain buffer.
653 * chainSge points to the previous Chain Element.
654 * Update its chain element Offset and Length (must
655 * include chain element size) fields.
656 * Old chain element is now complete.
658 u8 nextChain = (u8) (sgeOffset >> 2);
659 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
660 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
662 /* The original MF buffer requires a chain buffer -
664 * Last element in this MF is a chain element.
666 pReq->ChainOffset = (u8) (sgeOffset >> 2);
669 sges_left -= sg_done;
672 /* NOTE: psge points to the beginning of the chain element
673 * in current buffer. Get a chain buffer.
675 if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
678 /* Update the tracking arrays.
679 * If chainSge == NULL, update ReqToChain, else ChainToChain
682 hd->ChainToChain[chain_idx] = newIndex;
684 hd->ReqToChain[req_idx] = newIndex;
686 chain_idx = newIndex;
687 chain_dma_off = hd->ioc->req_sz * chain_idx;
689 /* Populate the chainSGE for the current buffer.
690 * - Set chain buffer pointer to psge and fill
691 * out the Address and Flags fields.
693 chainSge = (char *) psge;
694 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
697 /* Start the SGE for the next buffer
699 psge = (char *) (hd->ChainBuffer + chain_dma_off);
703 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
706 /* Start the SGE for the next buffer
713 } /* mptscsih_AddSGE() */
715 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
717 * mptscsih_io_done - Main SCSI IO callback routine registered to
718 * Fusion MPT (base) driver
719 * @ioc: Pointer to MPT_ADAPTER structure
720 * @mf: Pointer to original MPT request frame
721 * @r: Pointer to MPT reply frame (NULL if TurboReply)
723 * This routine is called from mpt.c::mpt_interrupt() at the completion
724 * of any SCSI IO request.
725 * This routine is registered with the Fusion MPT (base) driver at driver
726 * load/init time via the mpt_register() API call.
728 * Returns 1 indicating alloc'd request frame ptr should be freed.
731 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
735 SCSIIORequest_t *pScsiReq;
736 SCSIIOReply_t *pScsiReply;
739 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
741 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
742 sc = hd->ScsiLookup[req_idx];
744 MPIHeader_t *hdr = (MPIHeader_t *)mf;
746 /* Remark: writeSDP1 will use the ScsiDoneCtx
747 * If a SCSI I/O cmd, device disabled by OS and
748 * completion done. Cannot touch sc struct. Just free mem.
750 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
751 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
754 mptscsih_freeChainBuffers(hd, req_idx);
758 dmfprintk((MYIOC_s_INFO_FMT
759 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
760 ioc->name, mf, mr, sc, req_idx));
762 sc->result = DID_OK << 16; /* Set default reply as OK */
763 pScsiReq = (SCSIIORequest_t *) mf;
764 pScsiReply = (SCSIIOReply_t *) mr;
766 #ifdef MPTSCSIH_DBG_TIMEOUT
767 if (ioc->timeout_cnt > 0) {
770 for (ii=0; ii < 8; ii++) {
771 if (sc == foo_to[ii]) {
772 printk(MYIOC_s_INFO_FMT "complete (%p, %ld)\n",
773 ioc->name, sc, jiffies);
776 if (foo_to[ii] != NULL)
781 ioc->timeout_maxcnt = 0;
782 ioc->timeout_cnt = 0;
787 if (pScsiReply == NULL) {
788 /* special context reply handling */
793 u8 scsi_state, scsi_status;
795 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
796 scsi_state = pScsiReply->SCSIState;
798 dprintk((KERN_NOTICE " Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
799 ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
801 dprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh"
802 ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
803 status, scsi_state, pScsiReply->SCSIStatus,
804 le32_to_cpu(pScsiReply->IOCLogInfo)));
806 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
807 copy_sense_data(sc, hd, mf, pScsiReply);
810 * Look for + dump FCP ResponseInfo[]!
812 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
813 printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n",
814 le32_to_cpu(pScsiReply->ResponseInfo));
818 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
820 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
821 * But not: DID_BUS_BUSY lest one risk
822 * killing interrupt handler:-(
824 sc->result = STS_BUSY;
827 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
828 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
829 sc->result = DID_BAD_TARGET << 16;
832 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
833 /* Spoof to SCSI Selection Timeout! */
834 sc->result = DID_NO_CONNECT << 16;
836 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
837 hd->sel_timeout[pScsiReq->TargetID]++;
840 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
841 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
842 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
843 /* Linux handles an unsolicited DID_RESET better
844 * than an unsolicited DID_ABORT.
846 sc->result = DID_RESET << 16;
848 /* GEM Workaround. */
850 mptscsih_no_negotiate(hd, sc->device->id);
853 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
854 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
856 * Do upfront check for valid SenseData and give it
859 scsi_status = pScsiReply->SCSIStatus;
860 sc->result = (DID_OK << 16) | scsi_status;
861 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
862 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
863 /* Have already saved the status and sense data
867 if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) {
868 sc->result = DID_SOFT_ERROR << 16;
870 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
873 sc->result = DID_SOFT_ERROR << 16;
875 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
876 /* Not real sure here either... */
877 sc->result = DID_RESET << 16;
881 /* Give report and update residual count.
883 dprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
885 dprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
887 sc->resid = sc->request_bufflen - xfer_cnt;
888 dprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid));
892 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
893 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
897 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
898 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
899 sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
900 if (scsi_state == 0) {
902 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
904 * If running against circa 200003dd 909 MPT f/w,
905 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
906 * (QUEUE_FULL) returned from device! --> get 0x0000?128
907 * and with SenseBytes set to 0.
909 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
910 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
913 else if (scsi_state &
914 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
919 sc->result = DID_SOFT_ERROR << 16;
921 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
922 /* Not real sure here either... */
923 sc->result = DID_RESET << 16;
925 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
926 /* Device Inq. data indicates that it supports
927 * QTags, but rejects QTag messages.
928 * This command completed OK.
930 * Not real sure here either so do nothing... */
933 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
934 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
937 * Reservation Conflict, Busy,
938 * Command Terminated, CHECK
942 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
943 sc->result = DID_SOFT_ERROR << 16;
946 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
947 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
948 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
949 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
950 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
951 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
952 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
953 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
954 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
955 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
960 sc->result = DID_SOFT_ERROR << 16;
963 } /* switch(status) */
965 dprintk((KERN_NOTICE " sc->result set to %08xh\n", sc->result));
966 } /* end of address reply case */
968 /* Unmap the DMA buffers, if any. */
970 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
971 sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
972 } else if (sc->request_bufflen) {
975 my_priv = (scPrivate *) &sc->SCp;
976 pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
978 scsi_to_pci_dma_dir(sc->sc_data_direction));
981 hd->ScsiLookup[req_idx] = NULL;
983 sc->scsi_done(sc); /* Issue the command callback */
985 /* Free Chain buffers */
986 mptscsih_freeChainBuffers(hd, req_idx);
991 * Flush all commands on the doneQ.
992 * Lock Q when deleting/adding members
993 * Lock io_request_lock for OS callback.
996 flush_doneQ(MPT_SCSI_HOST *hd)
1000 unsigned long flags;
1004 dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n"));
1006 spin_lock_irqsave(&hd->freedoneQlock, flags);
1007 if (Q_IS_EMPTY(&hd->doneQ)) {
1008 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1012 buffer = hd->doneQ.head;
1017 /* Set the Scsi_Cmnd pointer
1019 SCpnt = (Scsi_Cmnd *) buffer->argp;
1020 buffer->argp = NULL;
1024 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1025 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1027 /* Do the OS callback.
1029 SCpnt->scsi_done(SCpnt);
1036 * Search the doneQ for a specific command. If found, delete from Q.
1037 * Calling function will finish processing.
1040 search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt)
1042 unsigned long flags;
1045 spin_lock_irqsave(&hd->freedoneQlock, flags);
1046 if (!Q_IS_EMPTY(&hd->doneQ)) {
1047 buffer = hd->doneQ.head;
1049 Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp;
1052 SCpnt->result = sc->result;
1054 /* Set the Scsi_Cmnd pointer
1056 buffer->argp = NULL;
1060 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1063 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ);
1065 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1070 * mptscsih_flush_running_cmds - For each command found, search
1071 * Scsi_Host instance taskQ and reply to OS.
1072 * Called only if recovering from a FW reload.
1073 * @hd: Pointer to a SCSI HOST structure
1077 * Must be called while new I/Os are being queued.
1080 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
1086 int max = hd->ioc->req_depth;
1087 unsigned long flags;
1089 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
1090 for (ii= 0; ii < max; ii++) {
1091 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
1096 /* Search pendingQ, if found,
1099 mptscsih_search_pendingQ(hd, ii);
1101 /* Null ScsiLookup index
1103 hd->ScsiLookup[ii] = NULL;
1105 mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);
1106 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
1109 /* Set status, free OS resources (SG DMA buffers)
1111 * Free driver resources (chain, msg buffers)
1113 if (scsi_device_online(SCpnt->device)) {
1114 if (SCpnt->use_sg) {
1115 pci_unmap_sg(hd->ioc->pcidev,
1116 (struct scatterlist *) SCpnt->request_buffer,
1118 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1119 } else if (SCpnt->request_bufflen) {
1122 my_priv = (scPrivate *) &SCpnt->SCp;
1123 pci_unmap_single(hd->ioc->pcidev,
1124 (dma_addr_t)(ulong)my_priv->p1,
1125 SCpnt->request_bufflen,
1126 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1129 SCpnt->result = DID_RESET << 16;
1130 SCpnt->host_scribble = NULL;
1132 /* Free Chain buffers */
1133 mptscsih_freeChainBuffers(hd, ii);
1135 /* Free Message frames */
1136 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
1139 /* Post to doneQ, do not reply until POST phase
1140 * of reset handler....prevents new commands from
1143 spin_lock_irqsave(&hd->freedoneQlock, flags);
1144 if (!Q_IS_EMPTY(&hd->freeQ)) {
1145 buffer = hd->freeQ.head;
1148 /* Set the Scsi_Cmnd pointer
1150 buffer->argp = (void *)SCpnt;
1154 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
1155 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1157 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1158 SCpnt->scsi_done(SCpnt);
1161 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
1171 * mptscsih_search_running_cmds - Delete any commands associated
1172 * with the specified target and lun. Function called only
1173 * when a lun is disable by mid-layer.
1174 * Do NOT access the referenced Scsi_Cmnd structure or
1175 * members. Will cause either a paging or NULL ptr error.
1176 * @hd: Pointer to a SCSI HOST structure
1177 * @target: target id
1182 * Called from slave_destroy.
1185 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
1187 SCSIIORequest_t *mf = NULL;
1189 int max = hd->ioc->req_depth;
1191 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
1194 for (ii=0; ii < max; ii++) {
1195 if (hd->ScsiLookup[ii] != NULL) {
1197 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
1199 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
1200 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
1202 if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
1207 hd->ScsiLookup[ii] = NULL;
1208 mptscsih_freeChainBuffers(hd, ii);
1209 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, (MPT_FRAME_HDR *)mf);
1216 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1218 * mptscsih_initChainBuffers - Allocate memory for and initialize
1219 * chain buffers, chain buffer control arrays and spinlock.
1220 * @hd: Pointer to MPT_SCSI_HOST structure
1221 * @init: If set, initialize the spin lock.
1224 mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
1226 MPT_FRAME_HDR *chain;
1228 unsigned long flags;
1229 int sz, ii, num_chain;
1232 /* chain buffer allocation done from PrimeIocFifos */
1233 if (hd->ioc->fifo_pool == NULL)
1236 hd->ChainBuffer = hd->ioc->chain_alloc;
1237 hd->ChainBufferDMA = hd->ioc->chain_alloc_dma;
1239 dprintk((KERN_INFO " ChainBuffer @ %p(%p), sz=%d\n",
1240 hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, hd->ioc->chain_alloc_sz));
1242 /* ReqToChain size must equal the req_depth
1245 if (hd->ReqToChain == NULL) {
1246 sz = hd->ioc->req_depth * sizeof(int);
1247 mem = kmalloc(sz, GFP_ATOMIC);
1251 hd->ReqToChain = (int *) mem;
1253 for (ii = 0; ii < hd->ioc->req_depth; ii++)
1254 hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
1256 /* ChainToChain size must equal the total number
1257 * of chain buffers to be allocated.
1260 * Calculate the number of chain buffers needed(plus 1) per I/O
1261 * then multiply the the maximum number of simultaneous cmds
1263 * num_sge = num sge in request frame + last chain buffer
1264 * scale = num sge per chain buffer if no chain element
1266 scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1267 if (sizeof(dma_addr_t) == sizeof(u64))
1268 num_sge = scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
1270 num_sge = 1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
1273 while (hd->max_sge - num_sge > 0) {
1275 num_sge += (scale - 1);
1279 if ((int) hd->ioc->chip_type > (int) FC929)
1280 num_chain *= MPT_SCSI_CAN_QUEUE;
1282 num_chain *= MPT_FC_CAN_QUEUE;
1284 hd->num_chain = num_chain;
1286 sz = num_chain * sizeof(int);
1287 if (hd->ChainToChain == NULL) {
1288 mem = kmalloc(sz, GFP_ATOMIC);
1292 hd->ChainToChain = (int *) mem;
1294 mem = (u8 *) hd->ChainToChain;
1296 memset(mem, 0xFF, sz);
1299 /* Initialize the free chain Q.
1302 spin_lock_init(&hd->FreeChainQlock);
1305 spin_lock_irqsave (&hd->FreeChainQlock, flags);
1306 Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);
1308 /* Post the chain buffers to the FreeChainQ.
1310 mem = (u8 *)hd->ChainBuffer;
1311 for (ii=0; ii < num_chain; ii++) {
1312 chain = (MPT_FRAME_HDR *) mem;
1313 Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);
1314 mem += hd->ioc->req_sz;
1316 spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
1321 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1323 * Hack! It might be nice to report if a device is returning QUEUE_FULL
1324 * but maybe not each and every time...
1326 static long last_queue_full = 0;
1328 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1330 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1331 * from a SCSI target device.
1332 * @sc: Pointer to Scsi_Cmnd structure
1333 * @pScsiReply: Pointer to SCSIIOReply_t
1334 * @pScsiReq: Pointer to original SCSI request
1336 * This routine periodically reports QUEUE_FULL status returned from a
1337 * SCSI target device. It reports this to the console via kernel
1338 * printk() API call, not more than once every 10 seconds.
1341 mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1343 long time = jiffies;
1345 if (time - last_queue_full > 10 * HZ) {
1346 char *ioc_str = "ioc?";
1348 if (sc->device && sc->device->host != NULL && sc->device->host->hostdata != NULL)
1349 ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name;
1350 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1351 ioc_str, 0, sc->device->id, sc->device->lun));
1352 last_queue_full = time;
1356 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1357 static char *info_kbuf = NULL;
1359 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1360 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1362 * mptscsih_probe - Installs scsi devices per bus.
1363 * @pdev: Pointer to pci_dev structure
1365 * Returns 0 for success, non-zero for failure.
1370 mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1372 struct Scsi_Host *sh;
1374 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1375 MPT_DONE_Q *freedoneQ;
1376 unsigned long flags;
1385 /* 20010202 -sralston
1386 * Added sanity check on readiness of the MPT adapter.
1388 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1389 printk(MYIOC_s_WARN_FMT
1390 "Skipping because it's not operational!\n",
1396 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1401 /* Sanity check - ensure at least 1 port is INITIATOR capable
1404 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1405 if (ioc->pfacts[ii].ProtocolFlags &
1406 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1411 printk(MYIOC_s_WARN_FMT
1412 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1417 sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));
1420 printk(MYIOC_s_WARN_FMT
1421 "Unable to register controller with SCSI subsystem\n",
1426 spin_lock_irqsave(&ioc->FreeQlock, flags);
1428 /* Attach the SCSI Host to the IOC structure
1436 /* set 16 byte cdb's */
1437 sh->max_cmd_len = 16;
1439 /* Yikes! This is important!
1440 * Otherwise, by default, linux
1441 * only scans target IDs 0-7!
1442 * pfactsN->MaxDevices unreliable
1443 * (not supported in early
1444 * versions of the FW).
1445 * max_id = 1 + actual max id,
1446 * max_lun = 1 + actual last lun,
1449 if ((int)ioc->chip_type > (int)FC929) {
1450 sh->max_id = MPT_MAX_SCSI_DEVICES;
1452 /* For FC, increase the queue depth
1453 * from MPT_SCSI_CAN_QUEUE (31)
1454 * to MPT_FC_CAN_QUEUE (63).
1456 sh->can_queue = MPT_FC_CAN_QUEUE;
1458 MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1461 sh->max_lun = MPT_LAST_LUN + 1;
1462 sh->max_sectors = MPT_SCSI_MAX_SECTORS;
1463 sh->max_channel = 0;
1464 sh->this_id = ioc->pfacts[0].PortSCSIID;
1468 sh->unique_id = ioc->id;
1470 /* Verify that we won't exceed the maximum
1471 * number of chain buffers
1472 * We can optimize: ZZ = req_sz/sizeof(SGE)
1474 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1475 * + (req_sz - 64)/sizeof(SGE)
1476 * A slightly different algorithm is required for
1479 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1480 if (sizeof(dma_addr_t) == sizeof(u64)) {
1481 numSGE = (scale - 1) *
1482 (ioc->facts.MaxChainDepth-1) + scale +
1483 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1486 numSGE = 1 + (scale - 1) *
1487 (ioc->facts.MaxChainDepth-1) + scale +
1488 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1492 if (numSGE < sh->sg_tablesize) {
1493 /* Reset this value */
1494 dprintk((MYIOC_s_INFO_FMT
1495 "Resetting sg_tablesize to %d from %d\n",
1496 ioc->name, numSGE, sh->sg_tablesize));
1497 sh->sg_tablesize = numSGE;
1500 /* Set the pci device pointer in Scsi_Host structure.
1502 scsi_set_device(sh, &ioc->pcidev->dev);
1504 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1506 hd = (MPT_SCSI_HOST *) sh->hostdata;
1508 hd->max_sge = sh->sg_tablesize;
1510 if ((int)ioc->chip_type > (int)FC929)
1513 if (DmpService && (ioc->chip_type == FC919 ||
1514 ioc->chip_type == FC929)) {
1515 hd->is_multipath = 1;
1518 /* SCSI needs Scsi_Cmnd lookup table!
1519 * (with size equal to req_depth*PtrSz!)
1521 sz = hd->ioc->req_depth * sizeof(void *);
1522 mem = kmalloc(sz, GFP_ATOMIC);
1525 goto mptscsih_probe_failed;
1529 hd->ScsiLookup = (struct scsi_cmnd **) mem;
1531 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
1532 ioc->name, hd->ScsiLookup, sz));
1534 if (mptscsih_initChainBuffers(hd, 1) < 0) {
1536 goto mptscsih_probe_failed;
1539 /* Allocate memory for free and doneQ's
1541 sz = sh->can_queue * sizeof(MPT_DONE_Q);
1542 mem = kmalloc(sz, GFP_ATOMIC);
1545 goto mptscsih_probe_failed;
1548 memset(mem, 0xFF, sz);
1551 /* Initialize the free, done and pending Qs.
1553 Q_INIT(&hd->freeQ, MPT_DONE_Q);
1554 Q_INIT(&hd->doneQ, MPT_DONE_Q);
1555 Q_INIT(&hd->pendingQ, MPT_DONE_Q);
1556 spin_lock_init(&hd->freedoneQlock);
1559 for (ii=0; ii < sh->can_queue; ii++) {
1560 freedoneQ = (MPT_DONE_Q *) mem;
1561 Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
1562 mem += sizeof(MPT_DONE_Q);
1565 /* Initialize this Scsi_Host
1568 Q_INIT(&hd->taskQ, MPT_FRAME_HDR);
1571 /* Allocate memory for the device structures.
1572 * A non-Null pointer at an offset
1573 * indicates a device exists.
1574 * max_id = 1 + maximum id (hosts.h)
1576 sz = sh->max_id * sizeof(void *);
1577 mem = kmalloc(sz, GFP_ATOMIC);
1580 goto mptscsih_probe_failed;
1584 hd->Targets = (VirtDevice **) mem;
1587 " Targets @ %p, sz=%d\n", hd->Targets, sz));
1589 /* Clear the TM flags
1592 hd->tmState = TM_STATE_NONE;
1593 hd->resetPending = 0;
1594 hd->abortSCpnt = NULL;
1596 hd->numTMrequests = 0;
1598 /* Clear the pointer used to store
1599 * single-threaded commands, i.e., those
1600 * issued during a bus scan, dv and
1601 * configuration pages.
1605 /* Initialize this SCSI Hosts' timers
1606 * To use, set the timer expires field
1609 init_timer(&hd->timer);
1610 hd->timer.data = (unsigned long) hd;
1611 hd->timer.function = mptscsih_timer_expired;
1613 init_timer(&hd->TMtimer);
1614 hd->TMtimer.data = (unsigned long) hd;
1615 hd->TMtimer.function = mptscsih_taskmgmt_timeout;
1616 hd->qtag_tick = jiffies;
1618 /* Moved Earlier Pam D */
1621 #ifdef MPTSCSIH_DBG_TIMEOUT
1622 hd->ioc->timeout_hard = 0;
1623 hd->ioc->timeout_delta = 30 * HZ;
1624 hd->ioc->timeout_maxcnt = 0;
1625 hd->ioc->timeout_cnt = 0;
1626 for (ii=0; ii < 8; ii++)
1630 /* Update with the driver setup
1633 if (hd->ioc->spi_data.maxBusWidth >
1634 driver_setup.max_width) {
1635 hd->ioc->spi_data.maxBusWidth =
1636 driver_setup.max_width;
1639 if (hd->ioc->spi_data.minSyncFactor <
1640 driver_setup.min_sync_fac) {
1641 hd->ioc->spi_data.minSyncFactor =
1642 driver_setup.min_sync_fac;
1645 if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) {
1646 hd->ioc->spi_data.maxSyncOffset = 0;
1649 hd->ioc->spi_data.Saf_Te = driver_setup.saf_te;
1652 #ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1653 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1655 if (driver_setup.dv == 0) {
1656 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1659 hd->ioc->spi_data.forceDv = 0;
1660 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1661 hd->ioc->spi_data.dvStatus[ii] =
1662 MPT_SCSICFG_NEGOTIATE;
1665 if (hd->negoNvram == 0) {
1666 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
1667 hd->ioc->spi_data.dvStatus[ii] |=
1668 MPT_SCSICFG_DV_NOT_DONE;
1671 ddvprintk((MYIOC_s_INFO_FMT
1672 "dv %x width %x factor %x saf_te %x\n",
1673 hd->ioc->name, driver_setup.dv,
1674 driver_setup.max_width,
1675 driver_setup.min_sync_fac,
1676 driver_setup.saf_te));
1681 error = scsi_add_host (sh, &ioc->pcidev->dev);
1683 dprintk((KERN_ERR MYNAM
1684 "scsi_add_host failed\n"));
1685 goto mptscsih_probe_failed;
1691 mptscsih_probe_failed:
1693 mptscsih_remove(pdev);
1698 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1700 * mptscsih_remove - Removed scsi devices
1701 * @pdev: Pointer to pci_dev structure
1706 mptscsih_remove(struct pci_dev *pdev)
1708 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1709 struct Scsi_Host *host = ioc->sh;
1712 unsigned long flags;
1717 scsi_remove_host(host);
1719 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1720 /* Check DV thread active */
1722 spin_lock_irqsave(&dvtaskQ_lock, flags);
1723 if (dvtaskQ_active) {
1724 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1725 while(dvtaskQ_active && --count) {
1726 set_current_state(TASK_INTERRUPTIBLE);
1727 schedule_timeout(1);
1730 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1733 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
1734 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
1736 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
1740 hd = (MPT_SCSI_HOST *)host->hostdata;
1742 int sz1, sz2, sz3, sztarget=0;
1747 mptscsih_shutdown(&pdev->dev);
1749 sz1 = sz2 = sz3 = 0;
1751 if (hd->ScsiLookup != NULL) {
1752 sz1 = hd->ioc->req_depth * sizeof(void *);
1753 kfree(hd->ScsiLookup);
1754 hd->ScsiLookup = NULL;
1757 if (hd->ReqToChain != NULL) {
1758 szr2chain = hd->ioc->req_depth * sizeof(int);
1759 kfree(hd->ReqToChain);
1760 hd->ReqToChain = NULL;
1763 if (hd->ChainToChain != NULL) {
1764 szc2chain = hd->num_chain * sizeof(int);
1765 kfree(hd->ChainToChain);
1766 hd->ChainToChain = NULL;
1769 if (hd->memQ != NULL) {
1770 szQ = host->can_queue * sizeof(MPT_DONE_Q);
1775 if (hd->Targets != NULL) {
1779 * Free any target structures that were allocated.
1782 max = MPT_MAX_SCSI_DEVICES;
1784 max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1786 for (ii=0; ii < max; ii++) {
1787 if (hd->Targets[ii]) {
1788 kfree(hd->Targets[ii]);
1789 hd->Targets[ii] = NULL;
1790 sztarget += sizeof(VirtDevice);
1795 * Free pointer array.
1797 sz3 = max * sizeof(void *);
1802 dprintk((MYIOC_s_INFO_FMT
1803 "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",
1804 hd->ioc->name, sz1, szchain, sz3, sztarget));
1805 dprintk(("Free'd done and free Q (%d) memory\n", szQ));
1807 /* NULL the Scsi_Host pointer
1812 scsi_host_put(host);
1817 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1819 * mptscsih_shutdown - reboot notifier
1823 mptscsih_shutdown(struct device * dev)
1825 MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev));
1826 struct Scsi_Host *host = ioc->sh;
1832 hd = (MPT_SCSI_HOST *)host->hostdata;
1834 /* Flush the cache of this adapter
1837 mptscsih_synchronize_cache(hd, 0);
1842 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1844 * mptscsih_suspend - Fusion MPT scsie driver suspend routine.
1849 mptscsih_suspend(struct pci_dev *pdev, u32 state)
1851 mptscsih_shutdown(&pdev->dev);
1855 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1857 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1862 mptscsih_resume(struct pci_dev *pdev)
1864 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1865 struct Scsi_Host *host = ioc->sh;
1871 hd = (MPT_SCSI_HOST *)host->hostdata;
1875 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1877 unsigned long lflags;
1878 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1879 if (!dvtaskQ_active) {
1881 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1882 MPT_INIT_WORK(&mptscsih_dvTask,
1883 mptscsih_domainValidation, (void *) hd);
1884 SCHEDULE_TASK(&mptscsih_dvTask);
1886 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1895 static struct mpt_pci_driver mptscsih_driver = {
1896 .probe = mptscsih_probe,
1897 .remove = mptscsih_remove,
1898 .shutdown = mptscsih_shutdown,
1900 .suspend = mptscsih_suspend,
1901 .resume = mptscsih_resume,
1906 /* SCSI host fops start here... */
1907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1909 * mptscsih_init - Register MPT adapter(s) as SCSI host(s) with
1910 * linux scsi mid-layer.
1912 * Returns 0 for success, non-zero for failure.
1918 show_mptmod_ver(my_NAME, my_VERSION);
1920 ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
1921 ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
1922 ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
1924 if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
1925 dprintk((KERN_INFO MYNAM
1926 ": Registered for IOC event notifications\n"));
1929 if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
1930 dprintk((KERN_INFO MYNAM
1931 ": Registered for IOC reset notifications\n"));
1935 /* Evaluate the command line arguments, if any */
1937 mptscsih_setup(mptscsih);
1940 if(mpt_device_driver_register(&mptscsih_driver,
1941 MPTSCSIH_DRIVER) != 0 ) {
1942 dprintk((KERN_INFO MYNAM
1943 ": failed to register dd callbacks\n"));
1950 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1951 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1953 * mptscsih_exit - Unregisters MPT adapter(s)
1961 /* removing devices */
1962 for(ioc = mpt_adapter_find_first(); ioc != NULL;
1963 ioc = mpt_adapter_find_next(ioc)) {
1964 if ((ioc->last_state != MPI_IOC_STATE_OPERATIONAL) ||
1967 mptscsih_remove(ioc->pcidev);
1970 mpt_reset_deregister(ScsiDoneCtx);
1971 dprintk((KERN_INFO MYNAM
1972 ": Deregistered for IOC reset notifications\n"));
1974 mpt_event_deregister(ScsiDoneCtx);
1975 dprintk((KERN_INFO MYNAM
1976 ": Deregistered for IOC event notifications\n"));
1978 mpt_device_driver_deregister(MPTSCSIH_DRIVER);
1979 mpt_deregister(ScsiScanDvCtx);
1980 mpt_deregister(ScsiTaskCtx);
1981 mpt_deregister(ScsiDoneCtx);
1983 if (info_kbuf != NULL)
1988 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1990 * mptscsih_info - Return information about MPT adapter
1991 * @SChost: Pointer to Scsi_Host structure
1993 * (linux Scsi_Host_Template.info routine)
1995 * Returns pointer to buffer where information was written.
1998 mptscsih_info(struct Scsi_Host *SChost)
2003 if (info_kbuf == NULL)
2004 if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
2007 h = (MPT_SCSI_HOST *)SChost->hostdata;
2008 info_kbuf[0] = '\0';
2010 mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
2011 info_kbuf[size-1] = '\0';
2024 static void copy_mem_info(struct info_str *info, char *data, int len)
2026 if (info->pos + len > info->length)
2027 len = info->length - info->pos;
2029 if (info->pos + len < info->offset) {
2034 if (info->pos < info->offset) {
2035 data += (info->offset - info->pos);
2036 len -= (info->offset - info->pos);
2040 memcpy(info->buffer + info->pos, data, len);
2045 static int copy_info(struct info_str *info, char *fmt, ...)
2051 va_start(args, fmt);
2052 len = vsprintf(buf, fmt, args);
2055 copy_mem_info(info, buf, len);
2059 static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
2061 struct info_str info;
2065 info.offset = offset;
2068 copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
2069 copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
2070 copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
2071 copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
2073 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
2076 #ifndef MPTSCSIH_DBG_TIMEOUT
2077 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len)
2079 /* Not yet implemented */
2083 #define is_digit(c) ((c) >= '0' && (c) <= '9')
2084 #define digit_to_bin(c) ((c) - '0')
2085 #define is_space(c) ((c) == ' ' || (c) == '\t')
2087 #define UC_DBG_TIMEOUT 0x01
2088 #define UC_DBG_HARDRESET 0x02
2090 static int skip_spaces(char *ptr, int len)
2094 for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --);
2099 static int get_int_arg(char *ptr, int len, ulong *pv)
2103 for (v = 0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) {
2104 v = (v * 10) + digit_to_bin(c);
2114 static int is_keyword(char *ptr, int len, char *verb)
2116 int verb_len = strlen(verb);
2118 if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))
2124 #define SKIP_SPACES(min_spaces) \
2125 if ((arg_len = skip_spaces(ptr,len)) < (min_spaces)) \
2130 #define GET_INT_ARG(v) \
2131 if (!(arg_len = get_int_arg(ptr,len, &(v)))) \
2136 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length)
2139 char btmp[24]; /* REMOVE */
2146 if ((len > 0) && (ptr[len -1] == '\n'))
2150 strncpy(btmp, buffer, len);
2153 strncpy(btmp, buffer, 22);
2156 printk("user_command: ioc %d, buffer %s, length %d\n",
2157 ioc->id, btmp, length);
2159 if ((arg_len = is_keyword(ptr, len, "timeout")) != 0)
2160 cmd = UC_DBG_TIMEOUT;
2161 else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0)
2162 cmd = UC_DBG_HARDRESET;
2170 case UC_DBG_TIMEOUT:
2172 GET_INT_ARG(number);
2178 printk("user_command: cnt=%ld delta=%ld\n", number, delta);
2183 if (cmd == UC_DBG_HARDRESET) {
2184 ioc->timeout_hard = 1;
2185 } else if (cmd == UC_DBG_TIMEOUT) {
2186 /* process this command ...
2188 ioc->timeout_maxcnt = 0;
2189 ioc->timeout_delta = delta < 2 ? 2 : delta;
2190 ioc->timeout_cnt = 0;
2191 ioc->timeout_maxcnt = number < 8 ? number: 8;
2194 /* Not yet implemented */
2199 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2201 * mptscsih_proc_info - Return information about MPT adapter
2203 * (linux Scsi_Host_Template.info routine)
2205 * buffer: if write, user data; if read, buffer for user
2206 * length: if write, return length;
2207 * offset: if write, 0; if read, the current offset into the buffer from
2208 * the previous read.
2209 * hostno: scsi host number
2210 * func: if write = 1; if read = 0
2212 int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
2213 int length, int func)
2216 MPT_SCSI_HOST *hd = NULL;
2219 dprintk(("Called mptscsih_proc_info: hostno=%d, func=%d\n", host->host_no, func));
2220 dprintk(("buffer %p, start=%p (%p) offset=%ld length = %d\n",
2221 buffer, start, *start, offset, length));
2223 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
2224 if ((ioc->sh) && (ioc->sh == host)) {
2225 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2229 if ((ioc == NULL) || (ioc->sh == NULL) || (hd == NULL))
2233 size = mptscsih_user_command(ioc, buffer, length);
2238 size = mptscsih_host_info(ioc, buffer, offset, length);
2245 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2246 #define ADD_INDEX_LOG(req_ent) do { } while(0)
2248 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2250 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
2251 * @SCpnt: Pointer to Scsi_Cmnd structure
2252 * @done: Pointer SCSI mid-layer IO completion function
2254 * (linux Scsi_Host_Template.queuecommand routine)
2255 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
2256 * from a linux Scsi_Cmnd request and send it to the IOC.
2258 * Returns 0. (rtn value discarded by linux scsi mid-layer)
2261 mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2265 SCSIIORequest_t *pScsiReq;
2266 VirtDevice *pTarget;
2268 unsigned long flags;
2283 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
2284 target = SCpnt->device->id;
2285 lun = SCpnt->device->lun;
2286 SCpnt->scsi_done = done;
2288 pTarget = hd->Targets[target];
2290 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
2291 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
2293 if (hd->resetPending) {
2294 /* Prevent new commands from being issued
2295 * while reloading the FW. Reset timer to 60 seconds,
2296 * as the FW can take some time to come ready.
2297 * For New EH, cmds on doneQ posted to FW.
2300 mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));
2301 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
2302 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2307 * Put together a MPT SCSI request...
2309 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
2310 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
2316 pScsiReq = (SCSIIORequest_t *) mf;
2318 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2320 ADD_INDEX_LOG(my_idx);
2323 * The scsi layer should be handling this stuff
2324 * (In 2.3.x it does -DaveM)
2327 /* BUG FIX! 19991030 -sralston
2328 * TUR's being issued with scsictl=0x02000000 (DATA_IN)!
2329 * Seems we may receive a buffer (datalen>0) even when there
2330 * will be no data transfer! GRRRRR...
2332 datadir = mptscsih_io_direction(SCpnt);
2333 if (datadir == SCSI_DATA_READ) {
2334 datalen = SCpnt->request_bufflen;
2335 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
2336 } else if (datadir == SCSI_DATA_WRITE) {
2337 datalen = SCpnt->request_bufflen;
2338 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
2341 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
2344 /* Default to untagged. Once a target structure has been allocated,
2345 * use the Inquiry data to determine if device supports tagged.
2348 && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
2349 && (SCpnt->device->tagged_supported)) {
2350 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
2352 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
2355 /* Use the above information to set up the message frame
2357 pScsiReq->TargetID = (u8) target;
2358 pScsiReq->Bus = (u8) SCpnt->device->channel;
2359 pScsiReq->ChainOffset = 0;
2360 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
2361 pScsiReq->CDBLength = SCpnt->cmd_len;
2362 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2363 pScsiReq->Reserved = 0;
2364 pScsiReq->MsgFlags = mpt_msg_flags();
2365 pScsiReq->LUN[0] = 0;
2366 pScsiReq->LUN[1] = lun;
2367 pScsiReq->LUN[2] = 0;
2368 pScsiReq->LUN[3] = 0;
2369 pScsiReq->LUN[4] = 0;
2370 pScsiReq->LUN[5] = 0;
2371 pScsiReq->LUN[6] = 0;
2372 pScsiReq->LUN[7] = 0;
2373 pScsiReq->Control = cpu_to_le32(scsictl);
2376 * Write SCSI CDB into the message
2378 cmd_len = SCpnt->cmd_len;
2379 for (ii=0; ii < cmd_len; ii++)
2380 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
2382 for (ii=cmd_len; ii < 16; ii++)
2383 pScsiReq->CDB[ii] = 0;
2386 pScsiReq->DataLength = cpu_to_le32(datalen);
2388 /* SenseBuffer low address */
2389 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
2390 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
2392 /* Now add the SG list
2393 * Always have a SGE even if null length.
2397 /* Add a NULL SGE */
2398 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
2401 /* Add a 32 or 64 bit SGE */
2402 rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
2406 if (rc == SUCCESS) {
2407 hd->ScsiLookup[my_idx] = SCpnt;
2408 SCpnt->host_scribble = NULL;
2410 /* SCSI specific processing */
2413 int dvStatus = hd->ioc->spi_data.dvStatus[target];
2415 if (dvStatus || hd->ioc->spi_data.forceDv) {
2417 /* Write SDP1 on this I/O to this target */
2418 if (dvStatus & MPT_SCSICFG_NEGOTIATE) {
2419 mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);
2420 dvStatus &= ~MPT_SCSICFG_NEGOTIATE;
2421 hd->ioc->spi_data.dvStatus[target] = dvStatus;
2422 } else if (dvStatus & MPT_SCSICFG_BLK_NEGO) {
2423 mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO);
2424 dvStatus &= ~MPT_SCSICFG_BLK_NEGO;
2425 hd->ioc->spi_data.dvStatus[target] = dvStatus;
2428 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2429 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
2430 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
2431 unsigned long lflags;
2432 /* Schedule DV if necessary */
2433 spin_lock_irqsave(&dvtaskQ_lock, lflags);
2434 if (!dvtaskQ_active) {
2436 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2437 MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
2439 SCHEDULE_TASK(&mptscsih_dvTask);
2441 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2443 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
2446 /* Trying to do DV to this target, extend timeout.
2447 * Wait to issue intil flag is clear
2449 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
2450 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
2454 /* Set the DV flags.
2456 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
2457 mptscsih_set_dvflags(hd, pScsiReq);
2462 #ifdef MPTSCSIH_DBG_TIMEOUT
2463 if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) {
2464 foo_to[hd->ioc->timeout_cnt] = SCpnt;
2465 hd->ioc->timeout_cnt++;
2466 //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta);
2468 printk(MYIOC_s_WARN_FMT
2469 "to pendingQ: (sc=%p, mf=%p, time=%ld)\n",
2470 hd->ioc->name, SCpnt, mf, jiffies);
2475 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2476 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
2477 hd->ioc->name, SCpnt, mf, my_idx));
2479 ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",
2480 hd->ioc->name, SCpnt, my_idx));
2481 /* Place this command on the pendingQ if possible */
2482 spin_lock_irqsave(&hd->freedoneQlock, flags);
2483 if (!Q_IS_EMPTY(&hd->freeQ)) {
2484 buffer = hd->freeQ.head;
2487 /* Save the mf pointer
2489 buffer->argp = (void *)mf;
2491 /* Add to the pendingQ
2493 Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);
2494 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2496 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2497 SCpnt->result = (DID_BUS_BUSY << 16);
2498 SCpnt->scsi_done(SCpnt);
2502 mptscsih_freeChainBuffers(hd, my_idx);
2503 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2511 dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n",
2512 hd->ioc->name, did_errcode, SCpnt));
2513 /* Just wish OS to issue a retry */
2514 SCpnt->result = (DID_BUS_BUSY << 16);
2515 spin_lock_irqsave(&hd->freedoneQlock, flags);
2516 if (!Q_IS_EMPTY(&hd->freeQ)) {
2517 dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n",
2518 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2519 buffer = hd->freeQ.head;
2522 /* Set the Scsi_Cmnd pointer
2524 buffer->argp = (void *)SCpnt;
2528 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
2529 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2531 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2532 SCpnt->scsi_done(SCpnt);
2538 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2540 * mptscsih_freeChainBuffers - Function to free chain buffers associated
2541 * with a SCSI IO request
2542 * @hd: Pointer to the MPT_SCSI_HOST instance
2543 * @req_idx: Index of the SCSI IO request frame.
2545 * Called if SG chain buffer allocation fails and mptscsih callbacks.
2549 mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
2551 MPT_FRAME_HDR *chain;
2552 unsigned long flags;
2556 /* Get the first chain index and reset
2559 chain_idx = hd->ReqToChain[req_idx];
2560 hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
2562 while (chain_idx != MPT_HOST_NO_CHAIN) {
2564 /* Save the next chain buffer index */
2565 next = hd->ChainToChain[chain_idx];
2567 /* Free this chain buffer and reset
2570 hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
2572 chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
2573 + (chain_idx * hd->ioc->req_sz));
2574 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2575 Q_ADD_TAIL(&hd->FreeChainQ.head,
2576 &chain->u.frame.linkage, MPT_FRAME_HDR);
2577 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2579 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
2580 hd->ioc->name, chain_idx));
2588 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2593 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2595 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
2596 * Fall through to mpt_HardResetHandler if: not operational, too many
2597 * failed TM requests or handshake failure.
2599 * @ioc: Pointer to MPT_ADAPTER structure
2600 * @type: Task Management type
2601 * @target: Logical Target ID for reset (if appropriate)
2602 * @lun: Logical Unit for reset (if appropriate)
2603 * @ctx2abort: Context for the task to be aborted (if appropriate)
2604 * @sleepFlag: If set, use udelay instead of schedule in handshake code.
2606 * Remark: Currently invoked from a non-interrupt thread (_bh).
2608 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
2611 * Returns 0 for SUCCESS or -1 if FAILED.
2614 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
2620 unsigned long flags;
2622 /* If FW is being reloaded currently, return success to
2623 * the calling function.
2630 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
2633 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
2635 // SJR - CHECKME - Can we avoid this here?
2636 // (mpt_HardResetHandler has this check...)
2637 spin_lock_irqsave(&ioc->diagLock, flags);
2638 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
2639 spin_unlock_irqrestore(&ioc->diagLock, flags);
2642 spin_unlock_irqrestore(&ioc->diagLock, flags);
2644 /* Do not do a Task Management if there are
2645 * too many failed TMs on this adapter.
2647 if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM)
2650 /* Wait a fixed amount of time for the TM pending flag to be cleared.
2651 * If we time out and not bus reset, then we return a FAILED status to the caller.
2652 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
2653 * successful. Otherwise, reload the FW.
2655 if (mptscsih_tm_pending_wait(hd) == FAILED) {
2656 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
2657 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
2658 "Timed out waiting for last TM (%d) to complete! \n",
2659 hd->ioc->name, hd->tmPending));
2661 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
2662 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
2663 "Timed out waiting for last TM (%d) to complete! \n",
2664 hd->ioc->name, hd->tmPending));
2666 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2667 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
2668 "Timed out waiting for last TM (%d) to complete! \n",
2669 hd->ioc->name, hd->tmPending));
2670 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
2676 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2677 hd->tmPending |= (1 << type);
2678 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2683 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
2685 #ifdef MPT_DEBUG_RESET
2686 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
2687 printk(MYIOC_s_WARN_FMT
2688 "TM Handler: IOC Not operational(0x%x)!\n",
2689 hd->ioc->name, ioc_raw_state);
2693 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
2694 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
2696 /* Isse the Task Mgmt request.
2698 if (hd->hard_resets < -1)
2700 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag);
2702 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
2704 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
2708 #ifdef MPTSCSIH_DBG_TIMEOUT
2709 if (hd->ioc->timeout_hard)
2713 /* Only fall through to the HRH if this is a bus reset
2715 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
2716 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
2717 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
2719 rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
2722 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
2728 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2730 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
2731 * @hd: Pointer to MPT_SCSI_HOST structure
2732 * @type: Task Management type
2733 * @target: Logical Target ID for reset (if appropriate)
2734 * @lun: Logical Unit for reset (if appropriate)
2735 * @ctx2abort: Context for the task to be aborted (if appropriate)
2736 * @sleepFlag: If set, use udelay instead of schedule in handshake code.
2738 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
2739 * or a non-interrupt thread. In the former, must not call schedule().
2741 * Not all fields are meaningfull for all task types.
2743 * Returns 0 for SUCCESS, -999 for "no msg frames",
2744 * else other non-zero value returned.
2747 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
2750 SCSITaskMgmt_t *pScsiTm;
2754 /* Return Fail to calling function if no message frames available.
2756 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
2757 dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
2762 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
2763 hd->ioc->name, mf));
2765 /* Format the Request
2767 pScsiTm = (SCSITaskMgmt_t *) mf;
2768 pScsiTm->TargetID = target;
2769 pScsiTm->Bus = channel;
2770 pScsiTm->ChainOffset = 0;
2771 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
2773 pScsiTm->Reserved = 0;
2774 pScsiTm->TaskType = type;
2775 pScsiTm->Reserved1 = 0;
2776 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
2777 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
2779 for (ii= 0; ii < 8; ii++) {
2780 pScsiTm->LUN[ii] = 0;
2782 pScsiTm->LUN[1] = lun;
2784 for (ii=0; ii < 7; ii++)
2785 pScsiTm->Reserved2[ii] = 0;
2787 pScsiTm->TaskMsgContext = ctx2abort;
2788 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n",
2789 hd->ioc->name, ctx2abort, type));
2791 /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
2792 mpt_put_msg_frame(hd->ioc->id, mf);
2793 * Save the MF pointer in case the request times out.
2796 hd->numTMrequests++;
2797 hd->TMtimer.expires = jiffies + timeout;
2798 add_timer(&hd->TMtimer);
2800 if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
2801 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
2803 dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
2804 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
2805 hd->numTMrequests--;
2807 del_timer(&hd->TMtimer);
2808 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
2814 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2816 * mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
2817 * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
2819 * (linux Scsi_Host_Template.eh_abort_handler routine)
2821 * Returns SUCCESS or FAILED.
2824 mptscsih_abort(Scsi_Cmnd * SCpnt)
2830 spinlock_t *host_lock = SCpnt->device->host->host_lock;
2832 /* If we can't locate our host adapter structure, return FAILED status.
2834 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
2835 SCpnt->result = DID_RESET << 16;
2836 SCpnt->scsi_done(SCpnt);
2837 dtmprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
2838 "Can't locate host! (sc=%p)\n",
2843 if (hd->resetPending)
2846 printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
2847 hd->ioc->name, SCpnt);
2849 if (hd->timeouts < -1)
2852 /* Find this command
2854 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
2855 /* Cmd not found in ScsiLookup. If found in
2856 * doneQ, delete from Q. Do OS callback.
2858 search_doneQ_for_cmd(hd, SCpnt);
2860 SCpnt->result = DID_RESET << 16;
2861 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
2862 "Command not in the active list! (sc=%p)\n",
2863 hd->ioc->name, SCpnt));
2867 /* If this command is pended, then timeout/hang occurred
2868 * during DV. Post command and flush pending Q
2869 * and then following up with the reset request.
2871 if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
2872 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2873 post_pendingQ_commands(hd);
2874 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
2875 "Posting pended cmd! (sc=%p)\n",
2876 hd->ioc->name, SCpnt));
2879 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
2880 * (the IO to be ABORT'd)
2882 * NOTE: Since we do not byteswap MsgContext, we do not
2883 * swap it here either. It is an opaque cookie to
2884 * the controller, so it does not matter. -DaveM
2886 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
2887 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
2889 hd->abortSCpnt = SCpnt;
2891 spin_unlock_irq(host_lock);
2892 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
2893 SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
2894 ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP)
2897 /* The TM request failed and the subsequent FW-reload failed!
2900 printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
2901 hd->ioc->name, SCpnt);
2903 /* We must clear our pending flag before clearing our state.
2906 hd->tmState = TM_STATE_NONE;
2908 spin_lock_irq(host_lock);
2911 spin_lock_irq(host_lock);
2916 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2918 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
2919 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
2921 * (linux Scsi_Host_Template.eh_dev_reset_handler routine)
2923 * Returns SUCCESS or FAILED.
2926 mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
2929 spinlock_t *host_lock = SCpnt->device->host->host_lock;
2931 /* If we can't locate our host adapter structure, return FAILED status.
2933 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2934 dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
2935 "Can't locate host! (sc=%p)\n",
2940 if (hd->resetPending)
2943 printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
2944 hd->ioc->name, SCpnt);
2946 /* Unsupported for SCSI. Supported for FCP
2951 spin_unlock_irq(host_lock);
2952 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
2953 SCpnt->device->channel, SCpnt->device->id,
2954 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
2956 /* The TM request failed and the subsequent FW-reload failed!
2959 printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
2960 hd->ioc->name, SCpnt);
2962 hd->tmState = TM_STATE_NONE;
2963 spin_lock_irq(host_lock);
2966 spin_lock_irq(host_lock);
2971 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2973 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
2974 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
2976 * (linux Scsi_Host_Template.eh_bus_reset_handler routine)
2978 * Returns SUCCESS or FAILED.
2981 mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
2984 spinlock_t *host_lock = SCpnt->device->host->host_lock;
2986 /* If we can't locate our host adapter structure, return FAILED status.
2988 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2989 dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
2990 "Can't locate host! (sc=%p)\n",
2995 printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
2996 hd->ioc->name, SCpnt);
2998 if (hd->timeouts < -1)
3001 /* We are now ready to execute the task management request. */
3002 spin_unlock_irq(host_lock);
3003 // printk("testing start : mptscsih_schedule_reset\n");
3004 // mptscsih_schedule_reset(hd);
3005 // printk("testing end: mptscsih_schedule_reset\n");
3006 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
3007 SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
3010 /* The TM request failed and the subsequent FW-reload failed!
3013 printk(MYIOC_s_WARN_FMT
3014 "Error processing TaskMgmt request (sc=%p)\n",
3015 hd->ioc->name, SCpnt);
3017 hd->tmState = TM_STATE_NONE;
3018 spin_lock_irq(host_lock);
3021 spin_lock_irq(host_lock);
3025 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3027 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
3029 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
3031 * (linux Scsi_Host_Template.eh_host_reset_handler routine)
3033 * Returns SUCCESS or FAILED.
3036 mptscsih_host_reset(Scsi_Cmnd *SCpnt)
3039 int status = SUCCESS;
3040 spinlock_t *host_lock = SCpnt->device->host->host_lock;
3042 /* If we can't locate the host to reset, then we failed. */
3043 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
3044 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3045 "Can't locate host! (sc=%p)\n",
3050 printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
3051 hd->ioc->name, SCpnt);
3053 /* If our attempts to reset the host failed, then return a failed
3054 * status. The host will be taken off line by the SCSI mid-layer.
3056 spin_unlock_irq(host_lock);
3057 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
3060 /* Make sure TM pending is cleared and TM state is set to
3064 hd->tmState = TM_STATE_NONE;
3066 spin_lock_irq(host_lock);
3069 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3071 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
3076 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3078 * mptscsih_tm_pending_wait - wait for pending task management request to
3080 * @hd: Pointer to MPT host structure.
3082 * Returns {SUCCESS,FAILED}.
3085 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
3087 unsigned long flags;
3088 int loop_count = 10 * 4; /* Wait 10 seconds */
3089 int status = FAILED;
3092 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
3093 if (hd->tmState == TM_STATE_NONE) {
3094 hd->tmState = TM_STATE_IN_PROGRESS;
3096 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3100 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3101 set_current_state(TASK_INTERRUPTIBLE);
3102 schedule_timeout(HZ/4);
3103 } while (--loop_count);
3108 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3110 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
3111 * @ioc: Pointer to MPT_ADAPTER structure
3112 * @mf: Pointer to SCSI task mgmt request frame
3113 * @mr: Pointer to SCSI task mgmt reply frame
3115 * This routine is called from mptbase.c::mpt_interrupt() at the completion
3116 * of any SCSI task management request.
3117 * This routine is registered with the MPT (base) driver at driver
3118 * load/init time via the mpt_register() API call.
3120 * Returns 1 indicating alloc'd request frame ptr should be freed.
3123 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3125 SCSITaskMgmtReply_t *pScsiTmReply;
3126 SCSITaskMgmt_t *pScsiTmReq;
3128 unsigned long flags;
3131 dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
3132 ioc->name, mf, mr));
3134 /* Depending on the thread, a timer is activated for
3135 * the TM request. Delete this timer on completion of TM.
3136 * Decrement count of outstanding TM requests.
3138 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
3140 del_timer(&hd->TMtimer);
3142 dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
3143 ioc->name, hd->taskQcnt));
3145 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
3151 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
3155 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
3156 pScsiTmReq = (SCSITaskMgmt_t*)mf;
3158 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
3159 tmType = pScsiTmReq->TaskType;
3161 dtmprintk((KERN_INFO " TaskType = %d, TerminationCount=%d\n",
3162 tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
3164 /* Error? (anything non-zero?) */
3165 if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
3168 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3169 dtmprintk((KERN_INFO " SCSI TaskMgmt (%d) - Oops!\n", tmType));
3170 dtmprintk((KERN_INFO " IOCStatus = %04xh\n", iocstatus));
3171 dtmprintk((KERN_INFO " IOCLogInfo = %08xh\n",
3172 le32_to_cpu(pScsiTmReply->IOCLogInfo)));
3174 /* clear flags and continue.
3176 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
3177 hd->abortSCpnt = NULL;
3179 /* If an internal command is present
3180 * or the TM failed - reload the FW.
3181 * FC FW may respond FAILED to an ABORT
3183 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
3185 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
3186 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
3187 printk((KERN_WARNING
3188 " Firmware Reload FAILED!!\n"));
3193 dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n"));
3195 hd->numTMrequests--;
3196 hd->abortSCpnt = NULL;
3203 spin_lock_irqsave(&ioc->FreeQlock, flags);
3205 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3206 hd->tmState = TM_STATE_NONE;
3211 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3213 * This is anyones guess quite frankly.
3216 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
3217 sector_t capacity, int geom[])
3229 dummy = heads * sectors;
3230 cylinders = capacity;
3231 sector_div(cylinders,dummy);
3233 cylinders = (ulong)capacity / (heads * sectors);
3237 * Handle extended translation size for logical drives
3240 if ((ulong)capacity >= 0x200000) {
3244 dummy = heads * sectors;
3245 cylinders = capacity;
3246 sector_div(cylinders,dummy);
3248 cylinders = (ulong)capacity / (heads * sectors);
3255 geom[2] = cylinders;
3257 dprintk((KERN_NOTICE
3258 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
3259 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
3264 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3266 * OS entry point to allow host driver to alloc memory
3267 * for each scsi device. Called once per device the bus scan.
3268 * Return non-zero if allocation fails.
3269 * Init memory once per id (not LUN).
3272 mptscsih_slave_alloc(Scsi_Device *device)
3274 struct Scsi_Host *host = device->host;
3278 hd = (MPT_SCSI_HOST *)host->hostdata;
3283 if ((vdev = hd->Targets[device->id]) == NULL) {
3284 if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
3285 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%d) FAILED!\n",
3286 hd->ioc->name, (int)sizeof(VirtDevice));
3289 memset(vdev, 0, sizeof(VirtDevice));
3290 rwlock_init(&vdev->VdevLock);
3291 Q_INIT(&vdev->WaitQ, void);
3292 Q_INIT(&vdev->SentQ, void);
3293 Q_INIT(&vdev->DoneQ, void);
3295 vdev->ioc_id = hd->ioc->id;
3296 vdev->target_id = device->id;
3297 vdev->bus_id = hd->port;
3299 hd->Targets[device->id] = vdev;
3308 * OS entry point to allow for host driver to free allocated memory
3309 * Called if no device present or device being unloaded
3312 mptscsih_slave_destroy(Scsi_Device *device)
3314 struct Scsi_Host *host = device->host;
3319 hd = (MPT_SCSI_HOST *)host->hostdata;
3324 mptscsih_search_running_cmds(hd, device->id, device->lun);
3326 /* Free memory and reset all flags for this target
3328 if ((vdev = hd->Targets[device->id]) != NULL) {
3331 if (vdev->luns[0] & (1 << device->lun))
3332 vdev->luns[0] &= ~(1 << device->lun);
3334 /* Free device structure only if number of luns is 0.
3336 if (vdev->num_luns == 0) {
3337 kfree(hd->Targets[device->id]);
3338 hd->Targets[device->id] = NULL;
3343 if((hd->ioc->spi_data.isRaid) && (hd->ioc->spi_data.pIocPg3)) {
3345 for(i=0;i<hd->ioc->spi_data.pIocPg3->NumPhysDisks &&
3349 hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) {
3351 hd->ioc->spi_data.forceDv |=
3352 MPT_SCSICFG_RELOAD_IOC_PG3;
3357 hd->ioc->spi_data.dvStatus[device->id] =
3358 MPT_SCSICFG_NEGOTIATE;
3360 if (hd->negoNvram == 0)
3361 hd->ioc->spi_data.dvStatus[device->id]
3362 |= MPT_SCSICFG_DV_NOT_DONE;
3371 * OS entry point to adjust the queue_depths on a per-device basis.
3372 * Called once per device the bus scan. Use it to force the queue_depth
3373 * member to 1 if a device does not support Q tags.
3374 * Return non-zero if fails.
3377 mptscsih_slave_configure(Scsi_Device *device)
3379 struct Scsi_Host *sh = device->host;
3380 VirtDevice *pTarget;
3381 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
3383 if ((hd == NULL) || (hd->Targets == NULL)) {
3387 dsprintk((MYIOC_s_INFO_FMT
3388 "device @ %p, id=%d, LUN=%d, channel=%d\n",
3389 hd->ioc->name, device, device->id, device->lun, device->channel));
3390 dsprintk((MYIOC_s_INFO_FMT
3391 "sdtr %d wdtr %d ppr %d inq length=%d\n",
3392 hd->ioc->name, device->sdtr, device->wdtr,
3393 device->ppr, device->inquiry_len));
3395 if (device->id > sh->max_id) {
3396 /* error case, should never happen */
3397 scsi_adjust_queue_depth(device, 0, 1);
3398 goto slave_configure_exit;
3401 pTarget = hd->Targets[device->id];
3403 if (pTarget == NULL) {
3404 /* error case - don't know about this device */
3405 scsi_adjust_queue_depth(device, 0, 1);
3406 goto slave_configure_exit;
3409 mptscsih_initTarget(hd, device->channel, device->id, device->lun,
3410 device->inquiry, device->inquiry_len );
3411 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3412 MPT_SCSI_CMD_PER_DEV_HIGH);
3414 if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
3415 if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
3416 scsi_adjust_queue_depth(device, 0, 1);
3417 else if (((pTarget->inq_data[0] & 0x1f) == 0x00)
3418 && (pTarget->minSyncFactor <= MPT_ULTRA160 ))
3419 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3420 MPT_SCSI_CMD_PER_DEV_HIGH);
3422 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3423 MPT_SCSI_CMD_PER_DEV_LOW);
3425 /* error case - No Inq. Data */
3426 scsi_adjust_queue_depth(device, 0, 1);
3430 dsprintk((MYIOC_s_INFO_FMT
3431 "Queue depth=%d, tflags=%x\n",
3432 hd->ioc->name, device->queue_depth, pTarget->tflags));
3434 dsprintk((MYIOC_s_INFO_FMT
3435 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
3436 hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
3438 slave_configure_exit:
3440 dsprintk((MYIOC_s_INFO_FMT
3441 "tagged %d, simple %d, ordered %d\n",
3442 hd->ioc->name,device->tagged_supported, device->simple_tags,
3443 device->ordered_tags));
3449 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3451 * Private routines...
3454 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3455 /* Utility function to copy sense data from the scsi_cmnd buffer
3456 * to the FC and SCSI target structures.
3460 copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
3463 SCSIIORequest_t *pReq;
3464 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
3469 /* Get target structure
3471 pReq = (SCSIIORequest_t *) mf;
3472 index = (int) pReq->TargetID;
3473 target = hd->Targets[index];
3474 if (hd->is_multipath && sc->device->hostdata)
3475 target = (VirtDevice *) sc->device->hostdata;
3481 /* Copy the sense received into the scsi command block. */
3482 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3483 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
3484 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
3486 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
3488 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
3489 if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
3491 MPT_ADAPTER *ioc = hd->ioc;
3493 idx = ioc->eventContext % ioc->eventLogSize;
3494 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
3495 ioc->events[idx].eventContext = ioc->eventContext;
3497 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
3498 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
3499 (pReq->Bus << 8) || pReq->TargetID;
3501 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
3503 ioc->eventContext++;
3507 /* Print an error report for the user.
3509 thisIo.cdbPtr = sc->cmnd;
3510 thisIo.sensePtr = sc->sense_buffer;
3511 thisIo.SCSIStatus = pScsiReply->SCSIStatus;
3512 thisIo.DoDisplay = 1;
3513 if (hd->is_multipath)
3514 sprintf(devFoo, "%d:%d:%d",
3519 sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->device->id, sc->device->lun);
3520 thisIo.DevIDStr = devFoo;
3522 thisIo.dataPtr = NULL;
3523 thisIo.inqPtr = NULL;
3525 thisIo.inqPtr = sc->device->vendor-8; /* FIXME!!! */
3527 (void) mpt_ScsiHost_ErrorReport(&thisIo);
3530 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
3538 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
3543 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
3545 for (i = 0; i < hd->ioc->req_depth; i++) {
3546 if (hd->ScsiLookup[i] == sc) {
3555 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3556 /* Search the pendingQ for a command with specific index.
3557 * If found, delete and return mf pointer
3558 * If not found, return NULL
3560 static MPT_FRAME_HDR *
3561 mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx)
3563 unsigned long flags;
3565 MPT_FRAME_HDR *mf = NULL;
3566 MPT_FRAME_HDR *cmdMfPtr;
3568 ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
3569 cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
3570 spin_lock_irqsave(&hd->freedoneQlock, flags);
3571 if (!Q_IS_EMPTY(&hd->pendingQ)) {
3572 buffer = hd->pendingQ.head;
3574 mf = (MPT_FRAME_HDR *) buffer->argp;
3575 if (mf == cmdMfPtr) {
3578 /* clear the arg pointer
3580 buffer->argp = NULL;
3584 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
3588 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ);
3590 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3591 ddvtprintk((" ...return %p\n", mf));
3595 /* Post all commands on the pendingQ to the FW.
3596 * Lock Q when deleting/adding members
3597 * Lock io_request_lock for OS callback.
3600 post_pendingQ_commands(MPT_SCSI_HOST *hd)
3604 unsigned long flags;
3606 /* Flush the pendingQ.
3608 ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name));
3610 spin_lock_irqsave(&hd->freedoneQlock, flags);
3611 if (Q_IS_EMPTY(&hd->pendingQ)) {
3612 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3616 buffer = hd->pendingQ.head;
3621 mf = (MPT_FRAME_HDR *) buffer->argp;
3622 buffer->argp = NULL;
3626 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
3627 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3630 /* This should never happen */
3631 printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf);
3635 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
3637 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
3639 u16 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3640 Scsi_Cmnd *sc = hd->ScsiLookup[req_idx];
3641 printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
3642 hd->ioc->name, sc, req_idx, mf);
3650 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3652 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
3655 unsigned long flags;
3657 dtmprintk((KERN_WARNING MYNAM
3658 ": IOC %s_reset routed to SCSI host driver!\n",
3659 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
3660 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
3662 /* If a FW reload request arrives after base installed but
3663 * before all scsi hosts have been attached, then an alt_ioc
3664 * may have a NULL sh pointer.
3666 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
3669 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3671 if (reset_phase == MPT_IOC_SETUP_RESET) {
3672 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
3675 * 1. Set Hard Reset Pending Flag
3676 * All new commands go to doneQ
3678 hd->resetPending = 1;
3680 } else if (reset_phase == MPT_IOC_PRE_RESET) {
3681 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
3683 /* 2. Flush running commands
3684 * Clean drop test code - if compiled
3685 * Clean ScsiLookup (and associated memory)
3689 /* 2a. Drop Test Command.
3692 /* 2b. Reply to OS all known outstanding I/O commands.
3694 mptscsih_flush_running_cmds(hd);
3696 /* 2c. If there was an internal command that
3697 * has not completed, configuration or io request,
3698 * free these resources.
3701 del_timer(&hd->timer);
3702 mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr);
3705 /* 2d. If a task management has not completed,
3706 * free resources associated with this request.
3709 del_timer(&hd->TMtimer);
3710 mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr);
3713 #ifdef MPTSCSIH_DBG_TIMEOUT
3714 ioc->timeout_hard = 0;
3717 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
3720 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
3722 /* Once a FW reload begins, all new OS commands are
3723 * redirected to the doneQ w/ a reset status.
3724 * Init all control structures.
3727 /* ScsiLookup initialization
3731 for (ii=0; ii < hd->ioc->req_depth; ii++)
3732 hd->ScsiLookup[ii] = NULL;
3735 /* 2. Chain Buffer initialization
3737 mptscsih_initChainBuffers(hd, 0);
3745 /* 4. Renegotiate to all devices, if SCSI
3748 mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
3750 /* 5. Enable new commands to be posted
3752 spin_lock_irqsave(&ioc->FreeQlock, flags);
3754 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3755 hd->resetPending = 0;
3756 hd->numTMrequests = 0;
3757 hd->tmState = TM_STATE_NONE;
3759 /* 6. If there was an internal command,
3760 * wake this process up.
3764 * Wake up the original calling thread
3766 hd->pLocal = &hd->localReply;
3767 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
3768 scandv_wait_done = 1;
3769 wake_up(&scandv_waitq);
3777 /* 8. Set flag to force DV and re-read IOC Page 3
3780 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
3781 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
3784 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
3788 return 1; /* currently means nothing really */
3791 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3793 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
3796 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
3798 dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
3802 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
3805 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
3806 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
3809 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3810 if (hd && (hd->is_spi) && (hd->soft_resets < -1))
3814 case MPI_EVENT_LOGOUT: /* 09 */
3819 * CHECKME! Don't think we need to do
3820 * anything for these, but...
3822 case MPI_EVENT_RESCAN: /* 06 */
3823 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
3824 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
3826 * CHECKME! Falling thru...
3830 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
3831 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3832 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
3833 * if DV disabled. Need to check for target mode.
3837 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3839 if (hd && (hd->is_spi) && (hd->negoNvram == 0)) {
3841 Ioc3PhysDisk_t *pPDisk;
3846 reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
3847 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
3848 /* New or replaced disk.
3849 * Set DV flag and schedule DV.
3851 pSpi = &ioc->spi_data;
3852 physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
3853 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
3854 if (pSpi->pIocPg3) {
3855 pPDisk = pSpi->pIocPg3->PhysDisk;
3856 numPDisk =pSpi->pIocPg3->NumPhysDisks;
3859 if (physDiskNum == pPDisk->PhysDiskNum) {
3860 pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
3861 pSpi->forceDv = MPT_SCSICFG_NEED_DV;
3862 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
3869 if (numPDisk == 0) {
3870 /* The physical disk that needs DV was not found
3871 * in the stored IOC Page 3. The driver must reload
3872 * this page. DV routine will set the NEED_DV flag for
3873 * all phys disks that have DV_NOT_DONE set.
3875 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
3876 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
3883 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
3884 printk("Raid Event RF: ");
3886 u32 *m = (u32 *)pEvReply;
3888 int n = (int)pEvReply->MsgLength;
3889 for (ii=6; ii < n; ii++)
3890 printk(" %08x", le32_to_cpu(m[ii]));
3896 case MPI_EVENT_NONE: /* 00 */
3897 case MPI_EVENT_LOG_DATA: /* 01 */
3898 case MPI_EVENT_STATE_CHANGE: /* 02 */
3899 case MPI_EVENT_EVENT_CHANGE: /* 0A */
3901 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
3905 return 1; /* currently means nothing really */
3908 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3912 static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
3914 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3915 /* old symsense.c stuff... */
3916 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3919 * To protect ourselves against those that would pass us bogus pointers
3921 static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
3922 = { 0x1F, 0x00, 0x00, 0x00,
3923 0x1F, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3927 static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
3928 = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
3929 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3931 static u8 dummyCDB[16]
3932 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3933 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3934 static u8 dummyScsiData[16]
3935 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3936 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3938 static char *ScsiStatusString[] = {
3941 "CHECK CONDITION", /* 02h */
3943 "CONDITION MET", /* 04h */
3955 "INTERMEDIATE", /* 10h */
3959 "INTERMEDIATE-CONDITION MET", /* 14h */
3963 "RESERVATION CONFLICT", /* 18h */
3973 "COMMAND TERMINATED", /* 22h */
3979 "TASK SET FULL", /* 28h */
3987 "ACA ACTIVE", /* 30h */
3991 static const char *ScsiCommonOpString[] = {
3992 "TEST UNIT READY", /* 00h */
3993 "REZERO UNIT (REWIND)", /* 01h */
3995 "REQUEST_SENSE", /* 03h */
3996 "FORMAT UNIT (MEDIUM)", /* 04h */
3997 "READ BLOCK LIMITS", /* 05h */
3999 "REASSIGN BLOCKS", /* 07h */
4000 "READ(6)", /* 08h */
4002 "WRITE(6)", /* 0Ah */
4003 "SEEK(6)", /* 0Bh */
4007 "READ REVERSE", /* 0Fh */
4008 "WRITE_FILEMARKS", /* 10h */
4009 "SPACE(6)", /* 11h */
4010 "INQUIRY", /* 12h */
4014 static const char *SenseKeyString[] = {
4015 "NO SENSE", /* 0h */
4016 "RECOVERED ERROR", /* 1h */
4017 "NOT READY", /* 2h */
4018 "MEDIUM ERROR", /* 3h */
4019 "HARDWARE ERROR", /* 4h */
4020 "ILLEGAL REQUEST", /* 5h */
4021 "UNIT ATTENTION", /* 6h */
4022 "DATA PROTECT", /* 7h */
4023 "BLANK CHECK", /* 8h */
4024 "VENDOR-SPECIFIC", /* 9h */
4025 "ABORTED COPY", /* Ah */
4026 "ABORTED COMMAND", /* Bh */
4027 "EQUAL (obsolete)", /* Ch */
4028 "VOLUME OVERFLOW", /* Dh */
4029 "MISCOMPARE", /* Eh */
4030 "RESERVED", /* Fh */
4034 #define SPECIAL_ASCQ(c,q) \
4035 (((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
4037 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4038 static int dump_cdb(char *foo, unsigned char *cdb)
4040 int i, grpCode, cdbLen;
4043 grpCode = cdb[0] >> 5;
4046 else if (grpCode < 3)
4048 else if (grpCode == 5)
4053 for (i=0; i < cdbLen; i++)
4054 l += sprintf(foo+l, " %02X", cdb[i]);
4059 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4060 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4061 /* Do ASC/ASCQ lookup/grindage to English readable string(s) */
4062 static const char * ascq_set_strings_4max(
4064 const char **s1, const char **s2, const char **s3, const char **s4)
4066 static const char *asc_04_part1_string = "LOGICAL UNIT ";
4067 static const char *asc_04_part2a_string = "NOT READY, ";
4068 static const char *asc_04_part2b_string = "IS ";
4069 static const char *asc_04_ascq_NN_part3_strings[] = { /* ASC ASCQ (hex) */
4070 "CAUSE NOT REPORTABLE", /* 04 00 */
4071 "IN PROCESS OF BECOMING READY", /* 04 01 */
4072 "INITIALIZING CMD. REQUIRED", /* 04 02 */
4073 "MANUAL INTERVENTION REQUIRED", /* 04 03 */
4074 /* Add " IN PROGRESS" to all the following... */
4075 "FORMAT", /* 04 04 */
4076 "REBUILD", /* 04 05 */
4077 "RECALCULATION", /* 04 06 */
4078 "OPERATION", /* 04 07 */
4079 "LONG WRITE", /* 04 08 */
4080 "SELF-TEST", /* 04 09 */
4083 static char *asc_04_part4_string = " IN PROGRESS";
4085 static char *asc_29_ascq_NN_strings[] = { /* ASC ASCQ (hex) */
4086 "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED", /* 29 00 */
4087 "POWER ON OCCURRED", /* 29 01 */
4088 "SCSI BUS RESET OCCURRED", /* 29 02 */
4089 "BUS DEVICE RESET FUNCTION OCCURRED", /* 29 03 */
4090 "DEVICE INTERNAL RESET", /* 29 04 */
4091 "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED", /* 29 05 */
4092 "TRANSCEIVER MODE CHANGED TO LVD", /* 29 06 */
4095 static char *ascq_vendor_uniq = "(Vendor Unique)";
4096 static char *ascq_noone = "(no matching ASC/ASCQ description found)";
4099 *s1 = *s2 = *s3 = *s4 = ""; /* set'em all to the empty "" string */
4101 /* CHECKME! Need lock/sem?
4102 * Update and examine for isense module presense.
4104 mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
4106 if (mptscsih_ASCQ_TablePtr == NULL) {
4107 /* 2nd chances... */
4108 if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
4109 *s1 = asc_04_part1_string;
4110 *s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
4111 *s3 = asc_04_ascq_NN_part3_strings[ASCQ];
4112 /* check for " IN PROGRESS" ones */
4114 *s4 = asc_04_part4_string;
4115 } else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
4116 *s1 = asc_29_ascq_NN_strings[ASCQ];
4118 * Else { leave all *s[1-4] values pointing to the empty "" string }
4124 * Need to check ASC here; if it is "special," then
4125 * the ASCQ is variable, and indicates failed component number.
4126 * We must treat the ASCQ as a "don't care" while searching the
4127 * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
4128 * on when we actually need to identify the failed component.
4130 if (SPECIAL_ASCQ(ASC,ASCQ))
4133 /* OK, now search mptscsih_ASCQ_Table[] for a matching entry */
4134 for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
4135 if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) {
4136 *s1 = mptscsih_ASCQ_TablePtr[idx].Description;
4140 if ((ASC >= 0x80) || (ASCQ >= 0x80))
4141 *s1 = ascq_vendor_uniq;
4148 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4150 * SCSI Information Report; desired output format...
4152 SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION)
4153 Key=6h (UNIT ATTENTION); FRU=03h
4154 ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4155 CDB: 00 00 00 00 00 00 - TestUnitReady
4159 * SCSI Error Report; desired output format...
4161 SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
4162 SCSI_Status=02h (CHECK CONDITION)
4163 Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
4164 SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
4165 SenseKey=6h (UNIT ATTENTION); FRU=03h
4166 ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4170 int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
4176 int sk = SD_Sense_Key(ioop->sensePtr);
4177 const char *skstr = SenseKeyString[sk];
4178 unsigned char asc = SD_ASC(ioop->sensePtr);
4179 unsigned char ascq = SD_ASCQ(ioop->sensePtr);
4182 /* Change the error logging to only report errors on
4183 * read and write commands. Ignore errors on other commands.
4184 * Should this be configurable via proc?
4186 switch (ioop->cdbPtr[0]) {
4202 * Filter out common, repetitive, warning-type errors... like:
4203 * POWER ON (06,29/00 or 06,29/01),
4204 * SPINNING UP (02,04/01),
4205 * LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
4207 if (sk == SK_NO_SENSE) {
4211 if ( (sk==SK_UNIT_ATTENTION && asc==0x29 && (ascq==0x00 || ascq==0x01))
4212 || (sk==SK_NOT_READY && asc==0x04 && (ascq==0x01 || ascq==0x02))
4213 || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
4220 /* Prevent the system from continually writing to the log
4221 * if a medium is not found: 02 3A 00
4222 * Changer issues: TUR, Read Capacity, Table of Contents continually
4224 if (sk==SK_NOT_READY && asc==0x3A) {
4225 if (ioop->cdbPtr == NULL) {
4227 } else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
4228 (ioop->cdbPtr[0] == CMD_ReadCapacity) ||
4229 (ioop->cdbPtr[0] == 0x43)) {
4233 if (sk==SK_UNIT_ATTENTION) {
4234 if (ioop->cdbPtr == NULL)
4236 else if (ioop->cdbPtr[0] == CMD_TestUnitReady)
4241 * Protect ourselves...
4243 if (ioop->cdbPtr == NULL)
4244 ioop->cdbPtr = dummyCDB;
4245 if (ioop->sensePtr == NULL)
4246 ioop->sensePtr = dummySenseData;
4247 if (ioop->inqPtr == NULL)
4248 ioop->inqPtr = dummyInqData;
4249 if (ioop->dataPtr == NULL)
4250 ioop->dataPtr = dummyScsiData;
4253 if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
4254 ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
4255 (void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
4260 if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
4261 opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
4262 else if (mpt_ScsiOpcodesPtr)
4263 opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
4265 l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n",
4269 l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh",
4270 sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
4272 const char *x1, *x2, *x3, *x4;
4273 x1 = x2 = x3 = x4 = "";
4274 x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
4277 l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
4279 l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
4282 l += sprintf(foo+l, "\n CDB:");
4283 l += dump_cdb(foo+l, ioop->cdbPtr);
4285 l += sprintf(foo+l, " - \"%s\"", opstr);
4286 l += sprintf(foo+l, "\n");
4288 PrintF(("%s\n", foo));
4293 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4295 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4297 * mptscsih_initTarget - Target, LUN alloc/free functionality.
4298 * @hd: Pointer to MPT_SCSI_HOST structure
4299 * @bus_id: Bus number (?)
4300 * @target_id: SCSI target id
4302 * @data: Pointer to data
4303 * @dlen: Number of INQUIRY bytes
4305 * NOTE: It's only SAFE to call this routine if data points to
4306 * sane & valid STANDARD INQUIRY data!
4308 * Allocate and initialize memory for this target.
4309 * Save inquiry data.
4313 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
4315 int indexed_lun, lun_index;
4319 dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
4320 hd->ioc->name, bus_id, target_id, lun, hd));
4322 /* Is LUN supported? If so, upper 3 bits will be 0
4323 * in first byte of inquiry data.
4328 vdev = hd->Targets[target_id];
4330 lun_index = (lun >> 5); /* 32 luns per lun_index */
4331 indexed_lun = (lun % 32);
4332 vdev->luns[lun_index] |= (1 << indexed_lun);
4334 vdev->raidVolume = 0;
4336 if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
4337 vdev->raidVolume = 1;
4338 ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
4342 if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
4344 memcpy (vdev->inq_data, data, 8);
4346 memcpy (vdev->inq_data, data, dlen);
4348 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4350 /* If LUN 0, tape and have not done DV, set the DV flag.
4352 if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) {
4353 ScsiCfgData *pSpi = &hd->ioc->spi_data;
4354 if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
4355 pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
4358 if ( (data[0] == SCSI_TYPE_PROC) &&
4359 !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
4361 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4362 if ( data[44] == 'S' &&
4368 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4369 mptscsih_writeIOCPage4(hd, target_id, bus_id);
4372 /* Treat all Processors as SAF-TE if
4373 * command line option is set */
4374 if ( hd->ioc->spi_data.Saf_Te ) {
4375 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4376 mptscsih_writeIOCPage4(hd, target_id, bus_id);
4383 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
4384 /* Update the target capabilities
4387 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
4390 mptscsih_setTargetNegoParms(hd, vdev, data_56);
4393 dprintk((KERN_INFO " target = %p\n", vdev));
4397 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4399 * Update the target negotiation parameters based on the
4400 * the Inquiry data, adapter capabilities, and NVRAM settings.
4403 void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
4405 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
4406 int id = (int) target->target_id;
4411 u8 width = MPT_NARROW;
4412 u8 factor = MPT_ASYNC;
4414 u8 version, nfactor;
4418 if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
4419 if (target->inq_data[7] & 0x02)
4420 target->tflags |= MPT_TARGET_FLAGS_Q_YES;
4425 target->negoFlags = pspi_data->noQas;
4427 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
4428 * support. If available, default QAS to off and allow enabling.
4429 * If not available, default QAS to on, turn off for non-disks.
4432 /* Set flags based on Inquiry data
4434 if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
4435 version = target->inq_data[2] & 0x07;
4438 factor = MPT_ULTRA2;
4439 offset = pspi_data->maxSyncOffset;
4441 if (target->inq_data[7] & 0x20) {
4445 if (target->inq_data[7] & 0x10) {
4446 /* bits 2 & 3 show DT support
4448 if ((byte56 & 0x04) == 0)
4449 factor = MPT_ULTRA2;
4450 else if ((byte56 & 0x03) == 0)
4451 factor = MPT_ULTRA160;
4453 factor = MPT_ULTRA320;
4454 offset = pspi_data->maxSyncOffset;
4456 /* If RAID, never disable QAS
4457 * else if non RAID, do not disable
4458 * QAS if bit 1 is set
4459 * bit 1 QAS support, non-raid only
4462 if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
4470 if (target->inq_data[7] & 0x02) {
4474 /* Update tflags based on NVRAM settings. (SCSI only)
4476 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4477 nvram = pspi_data->nvram[id];
4478 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
4481 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
4484 /* Ensure factor is set to the
4485 * maximum of: adapter, nvram, inquiry
4488 if (nfactor < pspi_data->minSyncFactor )
4489 nfactor = pspi_data->minSyncFactor;
4491 factor = max(factor, nfactor);
4492 if (factor == MPT_ASYNC)
4503 /* Make sure data is consistent
4505 if ((!width) && (factor < MPT_ULTRA2)) {
4506 factor = MPT_ULTRA2;
4509 /* Save the data to the target structure.
4511 target->minSyncFactor = factor;
4512 target->maxOffset = offset;
4513 target->maxWidth = width;
4515 target->tflags |= MPT_TARGET_FLAGS_Q_YES;
4518 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
4520 /* Disable unused features.
4523 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
4526 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
4528 /* GEM, processor WORKAROUND
4530 if (((target->inq_data[0] & 0x1F) == 0x03)
4531 || ((target->inq_data[0] & 0x1F) > 0x08)) {
4532 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
4533 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
4535 if (noQas && (pspi_data->noQas == 0)) {
4536 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
4537 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4539 /* Disable QAS in a mixed configuration case
4542 // ddvtprintk((KERN_INFO "Disabling QAS!\n"));
4543 for (ii = 0; ii < id; ii++) {
4544 if ( (vdev = hd->Targets[ii]) ) {
4545 vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4555 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4556 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
4557 * Else set the NEED_DV flag after Read Capacity Issued (disks)
4558 * or Mode Sense (cdroms).
4560 * Tapes, initTarget will set this flag on completion of Inquiry command.
4561 * Called only if DV_NOT_DONE flag is set
4563 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
4567 if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
4572 if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
4573 ScsiCfgData *pSpi = &hd->ioc->spi_data;
4574 if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
4575 /* Set NEED_DV for all hidden disks
4577 Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk;
4578 int numPDisk = pSpi->pIocPg3->NumPhysDisks;
4581 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4582 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
4587 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
4588 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
4592 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4594 * If no Target, bus reset on 1st I/O. Set the flag to
4595 * prevent any future negotiations to this device.
4597 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
4600 if ((hd->Targets) && (hd->Targets[target_id] == NULL))
4601 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
4606 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4608 * SCSI Config Page functionality ...
4610 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4611 /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
4612 * based on width, factor and offset parameters.
4614 * @factor: sync factor
4615 * @offset: sync offset
4616 * @requestedPtr: pointer to requested values (updated)
4617 * @configurationPtr: pointer to configuration values (updated)
4618 * @flags: flags to block WDTR or SDTR negotiation
4622 * Remark: Called by writeSDP1 and _dv_params
4625 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
4627 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
4628 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
4630 *configurationPtr = 0;
4631 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
4632 *requestedPtr |= (offset << 16) | (factor << 8);
4634 if (width && offset && !nowide && !nosync) {
4635 if (factor < MPT_ULTRA160) {
4636 *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
4637 if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
4638 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
4639 } else if (factor < MPT_ULTRA2) {
4640 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
4645 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
4648 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
4653 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4654 /* mptscsih_writeSDP1 - write SCSI Device Page 1
4655 * @hd: Pointer to a SCSI Host Strucutre
4656 * @portnum: IOC port number
4657 * @target_id: writeSDP1 for single ID
4658 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
4660 * Return: -EFAULT if read of config page header fails
4663 * Remark: If a target has been found, the settings from the
4664 * target structure are used, else the device is set
4667 * Remark: Called during init and after a FW reload.
4668 * Remark: We do not wait for a return, write pages sequentially.
4671 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
4673 MPT_ADAPTER *ioc = hd->ioc;
4675 SCSIDevicePage1_t *pData;
4676 VirtDevice *pTarget;
4681 u32 requested, configuration, flagsLength;
4683 int id = 0, maxid = 0;
4689 u8 maxwidth, maxoffset, maxfactor;
4691 if (ioc->spi_data.sdp1length == 0)
4694 if (flags & MPT_SCSICFG_ALL_IDS) {
4696 maxid = ioc->sh->max_id - 1;
4697 } else if (ioc->sh) {
4699 maxid = min_t(int, id, ioc->sh->max_id - 1);
4702 for (; id <= maxid; id++) {
4704 if (id == ioc->pfacts[portnum].PortSCSIID)
4707 /* Use NVRAM to get adapter and target maximums
4708 * Data over-riden by target structure information, if present
4710 maxwidth = ioc->spi_data.maxBusWidth;
4711 maxoffset = ioc->spi_data.maxSyncOffset;
4712 maxfactor = ioc->spi_data.minSyncFactor;
4713 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4714 nvram = ioc->spi_data.nvram[id];
4717 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
4719 if (maxoffset > 0) {
4720 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
4721 if (maxfactor == 0) {
4723 maxfactor = MPT_ASYNC;
4725 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
4726 maxfactor = ioc->spi_data.minSyncFactor;
4729 maxfactor = MPT_ASYNC;
4732 /* Set the negotiation flags.
4734 negoFlags = ioc->spi_data.noQas;
4736 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
4739 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
4741 if (flags & MPT_SCSICFG_USE_NVRAM) {
4750 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
4753 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4754 /* Force to async and narrow if DV has not been executed
4757 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
4764 /* If id is not a raid volume, get the updated
4765 * transmission settings from the target structure.
4767 if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
4768 width = pTarget->maxWidth;
4769 factor = pTarget->minSyncFactor;
4770 offset = pTarget->maxOffset;
4771 negoFlags = pTarget->negoFlags;
4774 if (flags & MPT_SCSICFG_BLK_NEGO)
4775 negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
4777 mptscsih_setDevicePage1Flags(width, factor, offset,
4778 &requested, &configuration, negoFlags);
4780 /* Get a MF for this command.
4782 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
4783 dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
4788 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
4789 hd->ioc->name, mf, id, requested, configuration));
4792 /* Set the request and the data pointers.
4793 * Request takes: 36 bytes (32 bit SGE)
4794 * SCSI Device Page 1 requires 16 bytes
4795 * 40 + 16 <= size of SCSI IO Request = 56 bytes
4796 * and MF size >= 64 bytes.
4797 * Place data at end of MF.
4799 pReq = (Config_t *)mf;
4801 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
4802 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
4804 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
4805 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
4807 /* Complete the request frame (same for all requests).
4809 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4811 pReq->ChainOffset = 0;
4812 pReq->Function = MPI_FUNCTION_CONFIG;
4813 pReq->ExtPageLength = 0;
4814 pReq->ExtPageType = 0;
4816 for (ii=0; ii < 8; ii++) {
4817 pReq->Reserved2[ii] = 0;
4819 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
4820 pReq->Header.PageLength = ioc->spi_data.sdp1length;
4821 pReq->Header.PageNumber = 1;
4822 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4823 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
4825 /* Add a SGE to the config request.
4827 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
4829 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
4831 /* Set up the common data portion
4833 pData->Header.PageVersion = pReq->Header.PageVersion;
4834 pData->Header.PageLength = pReq->Header.PageLength;
4835 pData->Header.PageNumber = pReq->Header.PageNumber;
4836 pData->Header.PageType = pReq->Header.PageType;
4837 pData->RequestedParameters = cpu_to_le32(requested);
4838 pData->Reserved = 0;
4839 pData->Configuration = cpu_to_le32(configuration);
4841 dprintk((MYIOC_s_INFO_FMT
4842 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
4843 ioc->name, id, (id | (bus<<8)),
4844 requested, configuration));
4846 mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
4852 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4853 /* mptscsih_writeIOCPage4 - write IOC Page 4
4854 * @hd: Pointer to a SCSI Host Structure
4855 * @target_id: write IOC Page4 for this ID & Bus
4857 * Return: -EAGAIN if unable to obtain a Message Frame
4860 * Remark: We do not wait for a return, write pages sequentially.
4863 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
4865 MPT_ADAPTER *ioc = hd->ioc;
4867 IOCPage4_t *IOCPage4Ptr;
4875 /* Get a MF for this command.
4877 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
4878 dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
4883 ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n",
4884 ioc->name, mf, target_id));
4886 /* Set the request and the data pointers.
4887 * Place data at end of MF.
4889 pReq = (Config_t *)mf;
4891 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
4892 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
4894 /* Complete the request frame (same for all requests).
4896 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4898 pReq->ChainOffset = 0;
4899 pReq->Function = MPI_FUNCTION_CONFIG;
4900 pReq->ExtPageLength = 0;
4901 pReq->ExtPageType = 0;
4903 for (ii=0; ii < 8; ii++) {
4904 pReq->Reserved2[ii] = 0;
4907 IOCPage4Ptr = ioc->spi_data.pIocPg4;
4908 dataDma = ioc->spi_data.IocPg4_dma;
4909 ii = IOCPage4Ptr->ActiveSEP++;
4910 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
4911 IOCPage4Ptr->SEP[ii].SEPBus = bus;
4912 pReq->Header = IOCPage4Ptr->Header;
4913 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
4915 /* Add a SGE to the config request.
4917 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
4918 (IOCPage4Ptr->Header.PageLength + ii) * 4;
4920 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
4922 dsprintk((MYIOC_s_INFO_FMT
4923 "writeIOCPage4: pgaddr 0x%x\n",
4924 ioc->name, (target_id | (bus<<8))));
4926 mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
4931 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4932 /* mptscsih_taskmgmt_timeout - Call back for timeout on a
4933 * task management request.
4934 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
4937 static void mptscsih_taskmgmt_timeout(unsigned long data)
4939 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
4941 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
4942 "TM request timed out!\n", hd->ioc->name));
4944 /* Delete the timer that triggered this callback.
4945 * Remark: del_timer checks to make sure timer is active
4948 del_timer(&hd->TMtimer);
4950 /* Call the reset handler. Already had a TM request
4951 * timeout - so issue a diagnostic reset
4953 MPT_INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
4954 SCHEDULE_TASK(&mptscsih_rstTask);
4958 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4959 /* mptscsih_schedule_reset - Call back for timeout on a
4960 * task management request.
4961 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
4965 mptscsih_schedule_reset(void *arg)
4968 hd = (MPT_SCSI_HOST *) arg;
4970 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
4971 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
4973 /* Because we have reset the IOC, no TM requests can be
4974 * pending. So let's make sure the tmPending flag is reset.
4976 dtmprintk((KERN_WARNING MYNAM
4977 ": %s: mptscsih_taskmgmt_timeout\n",
4985 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4987 * Bus Scan and Domain Validation functionality ...
4990 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4992 * mptscsih_scandv_complete - Scan and DV callback routine registered
4993 * to Fustion MPT (base) driver.
4995 * @ioc: Pointer to MPT_ADAPTER structure
4996 * @mf: Pointer to original MPT request frame
4997 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
4999 * This routine is called from mpt.c::mpt_interrupt() at the completion
5000 * of any SCSI IO request.
5001 * This routine is registered with the Fusion MPT (base) driver at driver
5002 * load/init time via the mpt_register() API call.
5004 * Returns 1 indicating alloc'd request frame ptr should be freed.
5006 * Remark: Sets a completion code and (possibly) saves sense data
5007 * in the IOC member localReply structure.
5008 * Used ONLY for DV and other internal commands.
5011 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
5014 SCSIIORequest_t *pReq;
5019 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
5020 printk(MYIOC_s_ERR_FMT
5021 "ScanDvComplete, %s req frame ptr! (=%p)\n",
5022 ioc->name, mf?"BAD":"NULL", (void *) mf);
5026 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
5027 del_timer(&hd->timer);
5028 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5029 hd->ScsiLookup[req_idx] = NULL;
5030 pReq = (SCSIIORequest_t *) mf;
5032 if (mf != hd->cmdPtr) {
5033 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
5034 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
5038 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
5039 hd->ioc->name, mf, mr, req_idx));
5041 hd->pLocal = &hd->localReply;
5042 hd->pLocal->scsiStatus = 0;
5044 /* If target struct exists, clear sense valid flag.
5047 completionCode = MPT_SCANDV_GOOD;
5049 SCSIIOReply_t *pReply;
5052 pReply = (SCSIIOReply_t *) mr;
5054 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
5056 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
5057 status, pReply->SCSIState, pReply->SCSIStatus,
5058 le32_to_cpu(pReply->IOCLogInfo)));
5062 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
5063 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
5066 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
5067 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
5068 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
5069 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
5070 completionCode = MPT_SCANDV_DID_RESET;
5073 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
5074 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
5075 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
5076 if (pReply->Function == MPI_FUNCTION_CONFIG) {
5077 ConfigReply_t *pr = (ConfigReply_t *)mr;
5078 completionCode = MPT_SCANDV_GOOD;
5079 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
5080 hd->pLocal->header.PageLength = pr->Header.PageLength;
5081 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
5082 hd->pLocal->header.PageType = pr->Header.PageType;
5084 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
5085 /* If the RAID Volume request is successful,
5086 * return GOOD, else indicate that
5087 * some type of error occurred.
5089 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
5090 if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
5091 completionCode = MPT_SCANDV_GOOD;
5093 completionCode = MPT_SCANDV_SOME_ERROR;
5095 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
5099 /* save sense data in global structure
5101 completionCode = MPT_SCANDV_SENSE;
5102 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5103 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
5104 (req_idx * MPT_SENSE_BUFFER_ALLOC));
5106 sz = min_t(int, pReq->SenseBufferLength,
5107 SCSI_STD_SENSE_BYTES);
5108 memcpy(hd->pLocal->sense, sense_data, sz);
5110 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
5112 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
5113 if (pReq->CDB[0] == CMD_Inquiry)
5114 completionCode = MPT_SCANDV_ISSUE_SENSE;
5116 completionCode = MPT_SCANDV_DID_RESET;
5118 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
5119 completionCode = MPT_SCANDV_DID_RESET;
5120 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5121 completionCode = MPT_SCANDV_DID_RESET;
5123 /* If no error, this will be equivalent
5124 * to MPT_SCANDV_GOOD
5126 completionCode = MPT_SCANDV_GOOD;
5127 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5131 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
5132 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5133 completionCode = MPT_SCANDV_DID_RESET;
5135 completionCode = MPT_SCANDV_SOME_ERROR;
5139 completionCode = MPT_SCANDV_SOME_ERROR;
5142 } /* switch(status) */
5144 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
5146 } /* end of address reply case */
5148 hd->pLocal->completion = completionCode;
5150 /* MF and RF are freed in mpt_interrupt
5153 /* Free Chain buffers (will never chain) in scan or dv */
5154 //mptscsih_freeChainBuffers(hd, req_idx);
5157 * Wake up the original calling thread
5159 scandv_wait_done = 1;
5160 wake_up(&scandv_waitq);
5165 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5166 /* mptscsih_timer_expired - Call back for timer process.
5167 * Used only for dv functionality.
5168 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5171 static void mptscsih_timer_expired(unsigned long data)
5173 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
5175 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
5178 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
5180 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
5181 /* Desire to issue a task management request here.
5182 * TM requests MUST be single threaded.
5183 * If old eh code and no TM current, issue request.
5184 * If new eh code, do nothing. Wait for OS cmd timeout
5187 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
5189 /* Perform a FW reload */
5190 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
5191 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
5195 /* This should NEVER happen */
5196 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
5199 /* No more processing.
5200 * TM call will generate an interrupt for SCSI TM Management.
5201 * The FW will reply to all outstanding commands, callback will finish cleanup.
5202 * Hard reset clean-up will free all resources.
5204 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
5209 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
5210 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5211 /* mptscsih_do_raid - Format and Issue a RAID volume request message.
5212 * @hd: Pointer to scsi host structure
5213 * @action: What do be done.
5214 * @id: Logical target id.
5215 * @bus: Target locations bus.
5217 * Returns: < 0 on a fatal error
5220 * Remark: Wait to return until reply processed by the ISR.
5223 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
5225 MpiRaidActionRequest_t *pReq;
5229 in_isr = in_interrupt();
5231 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
5236 /* Get and Populate a free Frame
5238 if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
5239 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
5243 pReq = (MpiRaidActionRequest_t *)mf;
5244 pReq->Action = action;
5245 pReq->Reserved1 = 0;
5246 pReq->ChainOffset = 0;
5247 pReq->Function = MPI_FUNCTION_RAID_ACTION;
5248 pReq->VolumeID = io->id;
5249 pReq->VolumeBus = io->bus;
5250 pReq->PhysDiskNum = io->physDiskNum;
5252 pReq->Reserved2 = 0;
5253 pReq->ActionDataWord = 0; /* Reserved for this action */
5254 //pReq->ActionDataSGE = 0;
5256 mpt_add_sge((char *)&pReq->ActionDataSGE,
5257 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
5259 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
5260 hd->ioc->name, action, io->id));
5263 hd->timer.expires = jiffies + HZ*2; /* 2 second timeout */
5264 scandv_wait_done = 0;
5266 /* Save cmd pointer, for resource free if timeout or
5271 add_timer(&hd->timer);
5272 mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
5273 wait_event(scandv_waitq, scandv_wait_done);
5275 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
5280 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5282 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5284 * mptscsih_do_cmd - Do internal command.
5285 * @hd: MPT_SCSI_HOST pointer
5286 * @io: INTERNAL_CMD pointer.
5288 * Issue the specified internally generated command and do command
5289 * specific cleanup. For bus scan / DV only.
5290 * NOTES: If command is Inquiry and status is good,
5291 * initialize a target structure, save the data
5293 * Remark: Single threaded access only.
5296 * < 0 if an illegal command or no resources
5300 * > 0 if command complete but some type of completion error.
5303 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
5306 SCSIIORequest_t *pScsiReq;
5307 SCSIIORequest_t ReqCopy;
5308 int my_idx, ii, dir;
5312 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
5315 in_isr = in_interrupt();
5317 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
5323 /* Set command specific information
5328 dir = MPI_SCSIIO_CONTROL_READ;
5334 case CMD_TestUnitReady:
5336 dir = MPI_SCSIIO_CONTROL_READ;
5340 case CMD_StartStopUnit:
5342 dir = MPI_SCSIIO_CONTROL_READ;
5344 CDB[4] = 1; /*Spin up the disk */
5348 case CMD_RequestSense:
5352 dir = MPI_SCSIIO_CONTROL_READ;
5356 case CMD_ReadBuffer:
5358 dir = MPI_SCSIIO_CONTROL_READ;
5360 if (io->flags & MPT_ICFLAG_ECHO) {
5366 if (io->flags & MPT_ICFLAG_BUF_CAP) {
5369 CDB[6] = (io->size >> 16) & 0xFF;
5370 CDB[7] = (io->size >> 8) & 0xFF;
5371 CDB[8] = io->size & 0xFF;
5375 case CMD_WriteBuffer:
5377 dir = MPI_SCSIIO_CONTROL_WRITE;
5379 if (io->flags & MPT_ICFLAG_ECHO) {
5384 CDB[6] = (io->size >> 16) & 0xFF;
5385 CDB[7] = (io->size >> 8) & 0xFF;
5386 CDB[8] = io->size & 0xFF;
5392 dir = MPI_SCSIIO_CONTROL_READ;
5399 dir = MPI_SCSIIO_CONTROL_READ;
5404 case CMD_SynchronizeCache:
5406 dir = MPI_SCSIIO_CONTROL_READ;
5408 // CDB[1] = 0x02; /* set immediate bit */
5417 /* Get and Populate a free Frame
5419 if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
5420 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
5425 pScsiReq = (SCSIIORequest_t *) mf;
5427 /* Get the request index */
5428 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5429 ADD_INDEX_LOG(my_idx); /* for debug */
5431 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
5432 pScsiReq->TargetID = io->physDiskNum;
5434 pScsiReq->ChainOffset = 0;
5435 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
5437 pScsiReq->TargetID = io->id;
5438 pScsiReq->Bus = io->bus;
5439 pScsiReq->ChainOffset = 0;
5440 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
5443 pScsiReq->CDBLength = cmdLen;
5444 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
5446 pScsiReq->Reserved = 0;
5448 pScsiReq->MsgFlags = mpt_msg_flags();
5449 /* MsgContext set in mpt_get_msg_fram call */
5451 for (ii=0; ii < 8; ii++)
5452 pScsiReq->LUN[ii] = 0;
5453 pScsiReq->LUN[1] = io->lun;
5455 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
5456 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
5458 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
5460 if (cmd == CMD_RequestSense) {
5461 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
5462 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
5463 hd->ioc->name, cmd));
5466 for (ii=0; ii < 16; ii++)
5467 pScsiReq->CDB[ii] = CDB[ii];
5469 pScsiReq->DataLength = cpu_to_le32(io->size);
5470 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
5471 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
5473 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
5474 hd->ioc->name, cmd, io->bus, io->id, io->lun));
5476 if (dir == MPI_SCSIIO_CONTROL_READ) {
5477 mpt_add_sge((char *) &pScsiReq->SGL,
5478 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
5481 mpt_add_sge((char *) &pScsiReq->SGL,
5482 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
5486 /* The ISR will free the request frame, but we need
5487 * the information to initialize the target. Duplicate.
5489 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
5491 /* Issue this command after:
5494 * Wait until the reply has been received
5495 * ScsiScanDvCtx callback function will
5497 * set scandv_wait_done and call wake_up
5500 hd->timer.expires = jiffies + HZ*cmdTimeout;
5501 scandv_wait_done = 0;
5503 /* Save cmd pointer, for resource free if timeout or
5508 add_timer(&hd->timer);
5509 mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
5510 wait_event(scandv_waitq, scandv_wait_done);
5513 rc = hd->pLocal->completion;
5514 hd->pLocal->skip = 0;
5516 /* Always set fatal error codes in some cases.
5518 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
5520 else if (rc == MPT_SCANDV_SOME_ERROR)
5524 /* This should never happen. */
5525 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
5532 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5534 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
5535 * @hd: Pointer to MPT_SCSI_HOST structure
5536 * @portnum: IOC port number
5538 * Uses the ISR, but with special processing.
5539 * MUST be single-threaded.
5541 * Return: 0 on completion
5544 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
5546 MPT_ADAPTER *ioc= hd->ioc;
5547 VirtDevice *pTarget;
5548 SCSIDevicePage1_t *pcfg1Data = NULL;
5551 dma_addr_t cfg1_dma_addr = -1;
5552 ConfigPageHeader_t header1;
5556 int indexed_lun, lun_index;
5557 int hostId = ioc->pfacts[portnum].PortSCSIID;
5559 int requested, configuration, data;
5563 max_id = ioc->sh->max_id - 1;
5565 /* Following parameters will not change
5568 iocmd.cmd = CMD_SynchronizeCache;
5570 iocmd.physDiskNum = -1;
5572 iocmd.data_dma = -1;
5574 iocmd.rsvd = iocmd.rsvd2 = 0;
5578 if (hd->Targets == NULL)
5586 /* Write SDP1 for all SCSI devices
5587 * Alloc memory and set up config buffer
5590 if (ioc->spi_data.sdp1length > 0) {
5591 pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
5592 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
5594 if (pcfg1Data != NULL) {
5596 header1.PageVersion = ioc->spi_data.sdp1version;
5597 header1.PageLength = ioc->spi_data.sdp1length;
5598 header1.PageNumber = 1;
5599 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5601 cfg.physAddr = cfg1_dma_addr;
5602 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5609 /* loop through all devices on this port
5611 while (bus < MPT_MAX_BUS) {
5614 pTarget = hd->Targets[(int)id];
5618 /* Set the negotiation flags */
5619 if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
5620 flags = pTarget->negoFlags;
5622 flags = hd->ioc->spi_data.noQas;
5623 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5624 data = hd->ioc->spi_data.nvram[id];
5626 if (data & MPT_NVRAM_WIDE_DISABLE)
5627 flags |= MPT_TARGET_NO_NEGO_WIDE;
5629 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5630 if ((factor == 0) || (factor == MPT_ASYNC))
5631 flags |= MPT_TARGET_NO_NEGO_SYNC;
5635 /* Force to async, narrow */
5636 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
5637 &configuration, flags);
5638 pcfg1Data->RequestedParameters = le32_to_cpu(requested);
5639 pcfg1Data->Reserved = 0;
5640 pcfg1Data->Configuration = le32_to_cpu(configuration);
5641 cfg.pageAddr = (bus<<8) | id;
5642 mpt_config(hd->ioc, &cfg);
5645 /* If target Ptr NULL or if this target is NOT a disk, skip.
5647 if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
5648 for (lun=0; lun <= MPT_LAST_LUN; lun++) {
5649 /* If LUN present, issue the command
5651 lun_index = (lun >> 5); /* 32 luns per lun_index */
5652 indexed_lun = (lun % 32);
5653 if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
5655 (void) mptscsih_do_cmd(hd, &iocmd);
5660 /* get next relevant device */
5673 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
5679 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
5680 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5682 * mptscsih_domainValidation - Top level handler for domain validation.
5683 * @hd: Pointer to MPT_SCSI_HOST structure.
5685 * Uses the ISR, but with special processing.
5686 * Called from schedule, should not be in interrupt mode.
5687 * While thread alive, do dv for all devices needing dv
5692 mptscsih_domainValidation(void *arg)
5696 unsigned long flags;
5697 int id, maxid, dvStatus, did;
5700 spin_lock_irqsave(&dvtaskQ_lock, flags);
5702 if (dvtaskQ_release) {
5704 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5707 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5709 /* For this ioc, loop through all devices and do dv to each device.
5710 * When complete with this ioc, search through the ioc list, and
5711 * for each scsi ioc found, do dv for all devices. Exit when no
5717 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
5718 spin_lock_irqsave(&dvtaskQ_lock, flags);
5719 if (dvtaskQ_release) {
5721 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5724 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5726 set_current_state(TASK_INTERRUPTIBLE);
5727 schedule_timeout(HZ/4);
5729 /* DV only to SCSI adapters */
5730 if ((int)ioc->chip_type <= (int)FC929)
5733 /* Make sure everything looks ok */
5734 if (ioc->sh == NULL)
5737 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
5741 if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
5742 mpt_read_ioc_pg_3(ioc);
5743 if (ioc->spi_data.pIocPg3) {
5744 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
5745 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
5748 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
5749 ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
5755 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
5758 maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
5760 for (id = 0; id < maxid; id++) {
5761 spin_lock_irqsave(&dvtaskQ_lock, flags);
5762 if (dvtaskQ_release) {
5764 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5767 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5768 dvStatus = hd->ioc->spi_data.dvStatus[id];
5770 if (dvStatus & MPT_SCSICFG_NEED_DV) {
5772 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
5773 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
5775 set_current_state(TASK_INTERRUPTIBLE);
5776 schedule_timeout(HZ/4);
5778 /* If hidden phys disk, block IO's to all
5780 * else, process normally
5782 isPhysDisk = mptscsih_is_phys_disk(ioc, id);
5784 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5785 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
5786 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
5791 if (mptscsih_doDv(hd, 0, id) == 1) {
5792 /* Untagged device was busy, try again
5794 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
5795 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
5797 /* DV is complete. Clear flags.
5799 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
5803 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5804 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
5805 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
5810 /* Post OS IOs that were pended while
5813 post_pendingQ_commands(hd);
5815 if (hd->ioc->spi_data.noQas)
5816 mptscsih_qas_check(hd, id);
5822 spin_lock_irqsave(&dvtaskQ_lock, flags);
5824 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5829 /* Search IOC page 3 to determine if this is hidden physical disk
5831 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
5833 if (ioc->spi_data.pIocPg3) {
5834 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
5835 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
5838 if (pPDisk->PhysDiskID == id) {
5848 /* Write SDP1 if no QAS has been enabled
5850 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
5852 VirtDevice *pTarget;
5855 if (hd->Targets == NULL)
5858 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5862 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
5865 pTarget = hd->Targets[ii];
5867 if ((pTarget != NULL) && (!pTarget->raidVolume)) {
5868 if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
5869 pTarget->negoFlags |= hd->ioc->spi_data.noQas;
5870 mptscsih_writeSDP1(hd, 0, ii, 0);
5873 if (mptscsih_is_phys_disk(hd->ioc, ii) == 1)
5874 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
5882 #define MPT_GET_NVRAM_VALS 0x01
5883 #define MPT_UPDATE_MAX 0x02
5884 #define MPT_SET_MAX 0x04
5885 #define MPT_SET_MIN 0x08
5886 #define MPT_FALLBACK 0x10
5887 #define MPT_SAVE 0x20
5889 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5891 * mptscsih_doDv - Perform domain validation to a target.
5892 * @hd: Pointer to MPT_SCSI_HOST structure.
5893 * @portnum: IOC port number.
5894 * @target: Physical ID of this target
5896 * Uses the ISR, but with special processing.
5897 * MUST be single-threaded.
5898 * Test will exit if target is at async & narrow.
5903 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
5905 MPT_ADAPTER *ioc = hd->ioc;
5906 VirtDevice *pTarget;
5907 SCSIDevicePage1_t *pcfg1Data;
5908 SCSIDevicePage0_t *pcfg0Data;
5912 dma_addr_t dvbuf_dma = -1;
5913 dma_addr_t buf1_dma = -1;
5914 dma_addr_t buf2_dma = -1;
5915 dma_addr_t cfg1_dma_addr = -1;
5916 dma_addr_t cfg0_dma_addr = -1;
5917 ConfigPageHeader_t header1;
5918 ConfigPageHeader_t header0;
5925 int dataBufSize = 0;
5926 int echoBufSize = 0;
5931 int nfactor = MPT_ULTRA320;
5933 char doFallback = 0;
5938 if (ioc->spi_data.sdp1length == 0)
5941 if (ioc->spi_data.sdp0length == 0)
5944 /* If multiple buses are used, require that the initiator
5945 * id be the same on all buses.
5947 if (id == ioc->pfacts[0].PortSCSIID)
5951 bus = (u8) bus_number;
5952 ddvtprintk((MYIOC_s_NOTE_FMT
5953 "DV started: bus=%d, id %d dv @ %p\n",
5954 ioc->name, bus, id, &dv));
5956 /* Prep DV structure
5958 memset (&dv, 0, sizeof(DVPARAMETERS));
5961 /* Populate tmax with the current maximum
5962 * transfer parameters for this target.
5963 * Exit if narrow and async.
5965 dv.cmd = MPT_GET_NVRAM_VALS;
5966 mptscsih_dv_parms(hd, &dv, NULL);
5967 if ((!dv.max.width) && (!dv.max.offset))
5970 /* Prep SCSI IO structure
5976 iocmd.physDiskNum = -1;
5977 iocmd.rsvd = iocmd.rsvd2 = 0;
5979 pTarget = hd->Targets[id];
5980 if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
5981 /* Another GEM workaround. Check peripheral device type,
5982 * if PROCESSOR, quit DV.
5984 if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
5985 pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
5990 /* Use tagged commands if possible.
5993 if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
5994 iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
5996 if (hd->ioc->facts.FWVersion.Word < 0x01000600)
5999 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
6000 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
6005 /* Prep cfg structure
6007 cfg.pageAddr = (bus<<8) | id;
6012 header0.PageVersion = ioc->spi_data.sdp0version;
6013 header0.PageLength = ioc->spi_data.sdp0length;
6014 header0.PageNumber = 0;
6015 header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6019 header1.PageVersion = ioc->spi_data.sdp1version;
6020 header1.PageLength = ioc->spi_data.sdp1length;
6021 header1.PageNumber = 1;
6022 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6024 if (header0.PageLength & 1)
6025 dv_alloc = (header0.PageLength * 4) + 4;
6027 dv_alloc += (2048 + (header1.PageLength * 4));
6029 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
6034 pbuf1 = (u8 *)pDvBuf;
6035 buf1_dma = dvbuf_dma;
6038 pbuf2 = (u8 *) (pDvBuf + sz);
6039 buf2_dma = dvbuf_dma + sz;
6042 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
6043 cfg0_dma_addr = dvbuf_dma + sz;
6044 sz += header0.PageLength * 4;
6048 if (header0.PageLength & 1)
6051 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
6052 cfg1_dma_addr = dvbuf_dma + sz;
6054 /* Skip this ID? Set cfg.hdr to force config page write
6057 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
6058 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6059 /* Set the factor from nvram */
6060 nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
6061 if (nfactor < pspi_data->minSyncFactor )
6062 nfactor = pspi_data->minSyncFactor;
6064 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
6065 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
6067 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
6068 ioc->name, bus, id, lun));
6070 dv.cmd = MPT_SET_MAX;
6071 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6074 /* Save the final negotiated settings to
6075 * SCSI device page 1.
6077 cfg.physAddr = cfg1_dma_addr;
6078 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6080 mpt_config(hd->ioc, &cfg);
6086 /* Finish iocmd inititialization - hidden or visible disk? */
6087 if (ioc->spi_data.pIocPg3) {
6088 /* Searc IOC page 3 for matching id
6090 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
6091 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
6094 if (pPDisk->PhysDiskID == id) {
6096 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
6097 iocmd.physDiskNum = pPDisk->PhysDiskNum;
6101 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
6102 ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
6112 /* RAID Volume ID's may double for a physical device. If RAID but
6113 * not a physical ID as well, skip DV.
6115 if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
6120 * Async & Narrow - Inquiry
6121 * Async & Narrow - Inquiry
6122 * Maximum transfer rate - Inquiry
6124 * If compare, test complete.
6125 * If miscompare and first pass, repeat
6126 * If miscompare and not first pass, fall back and repeat
6130 sz = SCSI_STD_INQUIRY_BYTES;
6131 rc = MPT_SCANDV_GOOD;
6133 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
6135 dv.cmd = MPT_SET_MIN;
6136 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6139 cfg.physAddr = cfg1_dma_addr;
6140 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6142 if (mpt_config(hd->ioc, &cfg) != 0)
6145 /* Wide - narrow - wide workaround case
6147 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
6148 /* Send an untagged command to reset disk Qs corrupted
6149 * when a parity error occurs on a Request Sense.
6151 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
6152 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
6153 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
6155 iocmd.cmd = CMD_RequestSense;
6156 iocmd.data_dma = buf1_dma;
6159 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6162 if (hd->pLocal == NULL)
6164 rc = hd->pLocal->completion;
6165 if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
6175 iocmd.cmd = CMD_Inquiry;
6176 iocmd.data_dma = buf1_dma;
6179 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6182 if (hd->pLocal == NULL)
6184 rc = hd->pLocal->completion;
6185 if (rc == MPT_SCANDV_GOOD) {
6186 if (hd->pLocal->scsiStatus == STS_BUSY) {
6187 if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
6194 } else if (rc == MPT_SCANDV_SENSE) {
6197 /* If first command doesn't complete
6198 * with a good status or with a check condition,
6205 /* Reset the size for disks
6207 inq0 = (*pbuf1) & 0x1F;
6208 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
6213 /* Another GEM workaround. Check peripheral device type,
6214 * if PROCESSOR, quit DV.
6216 if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08))
6219 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6223 if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
6224 && (pTarget->minSyncFactor > 0x09)) {
6225 if ((pbuf1[56] & 0x04) == 0)
6227 else if ((pbuf1[56] & 0x01) == 1) {
6228 pTarget->minSyncFactor =
6229 nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
6231 pTarget->minSyncFactor =
6232 nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
6235 dv.max.factor = pTarget->minSyncFactor;
6237 if ((pbuf1[56] & 0x02) == 0) {
6238 pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
6239 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
6245 dv.cmd = MPT_FALLBACK;
6247 dv.cmd = MPT_SET_MAX;
6249 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6250 if (mpt_config(hd->ioc, &cfg) != 0)
6253 if ((!dv.now.width) && (!dv.now.offset))
6256 iocmd.cmd = CMD_Inquiry;
6257 iocmd.data_dma = buf2_dma;
6260 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6262 else if (hd->pLocal == NULL)
6265 /* Save the return code.
6266 * If this is the first pass,
6267 * read SCSI Device Page 0
6268 * and update the target max parameters.
6270 rc = hd->pLocal->completion;
6272 if (rc == MPT_SCANDV_GOOD) {
6278 cfg.physAddr = cfg0_dma_addr;
6279 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6282 if (mpt_config(hd->ioc, &cfg) != 0)
6285 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
6286 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
6288 /* Quantum and Fujitsu workarounds.
6289 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
6290 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
6291 * Resetart with a request for U160.
6293 if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
6296 dv.cmd = MPT_UPDATE_MAX;
6297 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
6298 /* Update the SCSI device page 1 area
6300 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
6305 /* Quantum workaround. Restart this test will the fallback
6308 if (doFallback == 0) {
6309 if (memcmp(pbuf1, pbuf2, sz) != 0) {
6313 break; /* test complete */
6317 } else if (rc == MPT_SCANDV_ISSUE_SENSE)
6318 doFallback = 1; /* set fallback flag */
6319 else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE))
6320 doFallback = 1; /* set fallback flag */
6327 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
6328 inq0 = (*pbuf1) & 0x1F;
6330 /* Continue only for disks
6335 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
6338 /* Start the Enhanced Test.
6339 * 0) issue TUR to clear out check conditions
6340 * 1) read capacity of echo (regular) buffer
6342 * 3) do write-read-compare data pattern test
6344 * 5) update nego parms to target struct
6347 cfg.physAddr = cfg1_dma_addr;
6348 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6351 iocmd.cmd = CMD_TestUnitReady;
6352 iocmd.data_dma = -1;
6357 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6360 if (hd->pLocal == NULL)
6363 rc = hd->pLocal->completion;
6364 if (rc == MPT_SCANDV_GOOD)
6366 else if (rc == MPT_SCANDV_SENSE) {
6367 u8 skey = hd->pLocal->sense[2] & 0x0F;
6368 u8 asc = hd->pLocal->sense[12];
6369 u8 ascq = hd->pLocal->sense[13];
6370 ddvprintk((MYIOC_s_INFO_FMT
6371 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6372 ioc->name, skey, asc, ascq));
6374 if (skey == SK_UNIT_ATTENTION)
6375 notDone++; /* repeat */
6376 else if ((skey == SK_NOT_READY) &&
6377 (asc == 0x04)&&(ascq == 0x01)) {
6378 /* wait then repeat */
6381 } else if ((skey == SK_NOT_READY) && (asc == 0x3A)) {
6382 /* no medium, try read test anyway */
6385 /* All other errors are fatal.
6387 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
6395 iocmd.cmd = CMD_ReadBuffer;
6396 iocmd.data_dma = buf1_dma;
6399 iocmd.flags |= MPT_ICFLAG_BUF_CAP;
6403 for (patt = 0; patt < 2; patt++) {
6405 iocmd.flags |= MPT_ICFLAG_ECHO;
6407 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6413 /* If not ready after 8 trials,
6414 * give up on this device.
6419 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6421 else if (hd->pLocal == NULL)
6424 rc = hd->pLocal->completion;
6425 ddvprintk(("ReadBuffer Comp Code %d", rc));
6426 ddvprintk((" buff: %0x %0x %0x %0x\n",
6427 pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
6429 if (rc == MPT_SCANDV_GOOD) {
6431 if (iocmd.flags & MPT_ICFLAG_ECHO) {
6432 bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
6434 bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
6436 } else if (rc == MPT_SCANDV_SENSE) {
6437 u8 skey = hd->pLocal->sense[2] & 0x0F;
6438 u8 asc = hd->pLocal->sense[12];
6439 u8 ascq = hd->pLocal->sense[13];
6440 ddvprintk((MYIOC_s_INFO_FMT
6441 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6442 ioc->name, skey, asc, ascq));
6443 if (skey == SK_ILLEGAL_REQUEST) {
6445 } else if (skey == SK_UNIT_ATTENTION) {
6446 notDone++; /* repeat */
6447 } else if ((skey == SK_NOT_READY) &&
6448 (asc == 0x04)&&(ascq == 0x01)) {
6449 /* wait then repeat */
6453 /* All other errors are fatal.
6455 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
6460 /* All other errors are fatal
6467 if (iocmd.flags & MPT_ICFLAG_ECHO)
6468 echoBufSize = bufsize;
6470 dataBufSize = bufsize;
6473 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
6475 /* Use echo buffers if possible,
6476 * Exit if both buffers are 0.
6478 if (echoBufSize > 0) {
6479 iocmd.flags |= MPT_ICFLAG_ECHO;
6480 if (dataBufSize > 0)
6481 bufsize = min(echoBufSize, dataBufSize);
6483 bufsize = echoBufSize;
6484 } else if (dataBufSize == 0)
6487 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
6488 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
6490 /* Data buffers for write-read-compare test max 1K.
6492 sz = min(bufsize, 1024);
6495 * On first pass, always issue a reserve.
6496 * On additional loops, only if a reset has occurred.
6497 * iocmd.flags indicates if echo or regular buffer
6499 for (patt = 0; patt < 4; patt++) {
6500 ddvprintk(("Pattern %d\n", patt));
6501 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
6502 iocmd.cmd = CMD_TestUnitReady;
6503 iocmd.data_dma = -1;
6506 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6509 iocmd.cmd = CMD_Release6;
6510 iocmd.data_dma = -1;
6513 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6515 else if (hd->pLocal == NULL)
6518 rc = hd->pLocal->completion;
6519 ddvprintk(("Release rc %d\n", rc));
6520 if (rc == MPT_SCANDV_GOOD)
6521 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6525 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6527 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
6530 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
6531 iocmd.cmd = CMD_Reserve6;
6532 iocmd.data_dma = -1;
6535 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6537 else if (hd->pLocal == NULL)
6540 rc = hd->pLocal->completion;
6541 if (rc == MPT_SCANDV_GOOD) {
6542 iocmd.flags |= MPT_ICFLAG_RESERVED;
6543 } else if (rc == MPT_SCANDV_SENSE) {
6544 /* Wait if coming ready
6546 u8 skey = hd->pLocal->sense[2] & 0x0F;
6547 u8 asc = hd->pLocal->sense[12];
6548 u8 ascq = hd->pLocal->sense[13];
6549 ddvprintk((MYIOC_s_INFO_FMT
6550 "DV: Reserve Failed: ", ioc->name));
6551 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6554 if ((skey == SK_NOT_READY) && (asc == 0x04)&&
6556 /* wait then repeat */
6560 ddvprintk((MYIOC_s_INFO_FMT
6561 "DV: Reserved Failed.", ioc->name));
6565 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
6572 mptscsih_fillbuf(pbuf1, sz, patt, 1);
6573 iocmd.cmd = CMD_WriteBuffer;
6574 iocmd.data_dma = buf1_dma;
6577 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6579 else if (hd->pLocal == NULL)
6582 rc = hd->pLocal->completion;
6583 if (rc == MPT_SCANDV_GOOD)
6584 ; /* Issue read buffer */
6585 else if (rc == MPT_SCANDV_DID_RESET) {
6586 /* If using echo buffers, reset to data buffers.
6587 * Else do Fallback and restart
6588 * this test (re-issue reserve
6589 * because of bus reset).
6591 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
6592 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6594 dv.cmd = MPT_FALLBACK;
6595 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6597 if (mpt_config(hd->ioc, &cfg) != 0)
6600 if ((!dv.now.width) && (!dv.now.offset))
6604 iocmd.flags |= MPT_ICFLAG_DID_RESET;
6607 } else if (rc == MPT_SCANDV_SENSE) {
6608 /* Restart data test if UA, else quit.
6610 u8 skey = hd->pLocal->sense[2] & 0x0F;
6611 ddvprintk((MYIOC_s_INFO_FMT
6612 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
6613 hd->pLocal->sense[12], hd->pLocal->sense[13]));
6614 if (skey == SK_UNIT_ATTENTION) {
6617 } else if (skey == SK_ILLEGAL_REQUEST) {
6618 if (iocmd.flags & MPT_ICFLAG_ECHO) {
6619 if (dataBufSize >= bufsize) {
6620 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6635 iocmd.cmd = CMD_ReadBuffer;
6636 iocmd.data_dma = buf2_dma;
6639 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6641 else if (hd->pLocal == NULL)
6644 rc = hd->pLocal->completion;
6645 if (rc == MPT_SCANDV_GOOD) {
6646 /* If buffers compare,
6647 * go to next pattern,
6648 * else, do a fallback and restart
6649 * data transfer test.
6651 if (memcmp (pbuf1, pbuf2, sz) == 0) {
6652 ; /* goto next pattern */
6654 /* Miscompare with Echo buffer, go to data buffer,
6655 * if that buffer exists.
6656 * Miscompare with Data buffer, check first 4 bytes,
6657 * some devices return capacity. Exit in this case.
6659 if (iocmd.flags & MPT_ICFLAG_ECHO) {
6660 if (dataBufSize >= bufsize)
6661 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6665 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
6666 /* Argh. Device returning wrong data.
6667 * Quit DV for this device.
6672 /* Had an actual miscompare. Slow down.*/
6673 dv.cmd = MPT_FALLBACK;
6674 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6676 if (mpt_config(hd->ioc, &cfg) != 0)
6679 if ((!dv.now.width) && (!dv.now.offset))
6686 } else if (rc == MPT_SCANDV_DID_RESET) {
6687 /* Do Fallback and restart
6688 * this test (re-issue reserve
6689 * because of bus reset).
6691 dv.cmd = MPT_FALLBACK;
6692 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6694 if (mpt_config(hd->ioc, &cfg) != 0)
6697 if ((!dv.now.width) && (!dv.now.offset))
6700 iocmd.flags |= MPT_ICFLAG_DID_RESET;
6703 } else if (rc == MPT_SCANDV_SENSE) {
6704 /* Restart data test if UA, else quit.
6706 u8 skey = hd->pLocal->sense[2] & 0x0F;
6707 ddvprintk((MYIOC_s_INFO_FMT
6708 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
6709 hd->pLocal->sense[12], hd->pLocal->sense[13]));
6710 if (skey == SK_UNIT_ATTENTION) {
6722 } /* --- end of patt loop ---- */
6725 if (iocmd.flags & MPT_ICFLAG_RESERVED) {
6726 iocmd.cmd = CMD_Release6;
6727 iocmd.data_dma = -1;
6730 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6731 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
6733 else if (hd->pLocal) {
6734 if (hd->pLocal->completion == MPT_SCANDV_GOOD)
6735 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6737 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
6743 /* Set if cfg1_dma_addr contents is valid
6745 if ((cfg.hdr != NULL) && (retcode == 0)){
6746 /* If disk, not U320, disable QAS
6748 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320))
6749 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
6752 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6754 /* Double writes to SDP1 can cause problems,
6755 * skip save of the final negotiated settings to
6756 * SCSI device page 1.
6759 cfg.physAddr = cfg1_dma_addr;
6760 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6762 mpt_config(hd->ioc, &cfg);
6766 /* If this is a RAID Passthrough, enable internal IOs
6768 if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
6769 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
6770 ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
6773 /* Done with the DV scan of the current target
6776 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
6778 ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n",
6784 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6785 /* mptscsih_dv_parms - perform a variety of operations on the
6786 * parameters used for negotiation.
6787 * @hd: Pointer to a SCSI host.
6788 * @dv: Pointer to a structure that contains the maximum and current
6789 * negotiated parameters.
6792 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
6794 VirtDevice *pTarget;
6795 SCSIDevicePage0_t *pPage0;
6796 SCSIDevicePage1_t *pPage1;
6797 int val = 0, data, configuration;
6806 case MPT_GET_NVRAM_VALS:
6807 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
6809 /* Get the NVRAM values and save in tmax
6810 * If not an LVD bus, the adapter minSyncFactor has been
6811 * already throttled back.
6813 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
6814 width = pTarget->maxWidth;
6815 offset = pTarget->maxOffset;
6816 factor = pTarget->minSyncFactor;
6817 negoFlags = pTarget->negoFlags;
6819 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6820 data = hd->ioc->spi_data.nvram[id];
6821 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
6822 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
6825 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
6826 if ((factor == 0) || (factor == MPT_ASYNC)){
6837 /* Set the negotiation flags */
6838 negoFlags = hd->ioc->spi_data.noQas;
6840 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
6843 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
6846 /* limit by adapter capabilities */
6847 width = min(width, hd->ioc->spi_data.maxBusWidth);
6848 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
6849 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
6851 /* Check Consistency */
6852 if (offset && (factor < MPT_ULTRA2) && !width)
6853 factor = MPT_ULTRA2;
6855 dv->max.width = width;
6856 dv->max.offset = offset;
6857 dv->max.factor = factor;
6858 dv->max.flags = negoFlags;
6859 ddvprintk((" width %d, factor %x, offset %x flags %x\n",
6860 width, factor, offset, negoFlags));
6863 case MPT_UPDATE_MAX:
6864 ddvprintk((MYIOC_s_NOTE_FMT
6865 "Updating with SDP0 Data: ", hd->ioc->name));
6866 /* Update tmax values with those from Device Page 0.*/
6867 pPage0 = (SCSIDevicePage0_t *) pPage;
6869 val = cpu_to_le32(pPage0->NegotiatedParameters);
6870 dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
6871 dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
6872 dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
6875 dv->now.width = dv->max.width;
6876 dv->now.offset = dv->max.offset;
6877 dv->now.factor = dv->max.factor;
6878 ddvprintk(("width %d, factor %x, offset %x, flags %x\n",
6879 dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
6883 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
6885 /* Set current to the max values. Update the config page.*/
6886 dv->now.width = dv->max.width;
6887 dv->now.offset = dv->max.offset;
6888 dv->now.factor = dv->max.factor;
6889 dv->now.flags = dv->max.flags;
6891 pPage1 = (SCSIDevicePage1_t *)pPage;
6893 mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
6894 dv->now.offset, &val, &configuration, dv->now.flags);
6895 pPage1->RequestedParameters = le32_to_cpu(val);
6896 pPage1->Reserved = 0;
6897 pPage1->Configuration = le32_to_cpu(configuration);
6901 ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n",
6902 dv->now.width, dv->now.factor, dv->now.offset, val, configuration));
6906 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
6908 /* Set page to asynchronous and narrow
6909 * Do not update now, breaks fallback routine. */
6913 negoFlags = dv->max.flags;
6915 pPage1 = (SCSIDevicePage1_t *)pPage;
6917 mptscsih_setDevicePage1Flags (width, factor,
6918 offset, &val, &configuration, negoFlags);
6919 pPage1->RequestedParameters = le32_to_cpu(val);
6920 pPage1->Reserved = 0;
6921 pPage1->Configuration = le32_to_cpu(configuration);
6923 ddvprintk(("width %d, factor %x, offset %x request %x config %x\n",
6924 width, factor, offset, val, configuration));
6928 ddvprintk((MYIOC_s_NOTE_FMT
6929 "Fallback: Start: offset %d, factor %x, width %d \n",
6930 hd->ioc->name, dv->now.offset,
6931 dv->now.factor, dv->now.width));
6932 width = dv->now.width;
6933 offset = dv->now.offset;
6934 factor = dv->now.factor;
6935 if ((offset) && (dv->max.width)) {
6936 if (factor < MPT_ULTRA160)
6937 factor = MPT_ULTRA160;
6938 else if (factor < MPT_ULTRA2) {
6939 factor = MPT_ULTRA2;
6941 } else if ((factor == MPT_ULTRA2) && width) {
6942 factor = MPT_ULTRA2;
6944 } else if (factor < MPT_ULTRA) {
6947 } else if ((factor == MPT_ULTRA) && width) {
6949 } else if (factor < MPT_FAST) {
6952 } else if ((factor == MPT_FAST) && width) {
6955 } else if (factor < MPT_SCSI) {
6958 } else if ((factor == MPT_SCSI) && width) {
6966 } else if (offset) {
6968 if (factor < MPT_ULTRA)
6970 else if (factor < MPT_FAST)
6972 else if (factor < MPT_SCSI)
6983 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
6985 dv->now.width = width;
6986 dv->now.offset = offset;
6987 dv->now.factor = factor;
6988 dv->now.flags = dv->max.flags;
6990 pPage1 = (SCSIDevicePage1_t *)pPage;
6992 mptscsih_setDevicePage1Flags (width, factor, offset, &val,
6993 &configuration, dv->now.flags);
6995 pPage1->RequestedParameters = le32_to_cpu(val);
6996 pPage1->Reserved = 0;
6997 pPage1->Configuration = le32_to_cpu(configuration);
7000 ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n",
7001 dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
7005 ddvprintk((MYIOC_s_NOTE_FMT
7006 "Saving to Target structure: ", hd->ioc->name));
7007 ddvprintk(("offset %d, factor %x, width %d \n",
7008 dv->now.offset, dv->now.factor, dv->now.width));
7010 /* Save these values to target structures
7011 * or overwrite nvram (phys disks only).
7014 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
7015 pTarget->maxWidth = dv->now.width;
7016 pTarget->maxOffset = dv->now.offset;
7017 pTarget->minSyncFactor = dv->now.factor;
7018 pTarget->negoFlags = dv->now.flags;
7020 /* Preserv all flags, use
7021 * read-modify-write algorithm
7023 if (hd->ioc->spi_data.nvram) {
7024 data = hd->ioc->spi_data.nvram[id];
7027 data &= ~MPT_NVRAM_WIDE_DISABLE;
7029 data |= MPT_NVRAM_WIDE_DISABLE;
7031 if (!dv->now.offset)
7034 data &= ~MPT_NVRAM_SYNC_MASK;
7035 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
7037 hd->ioc->spi_data.nvram[id] = data;
7044 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7045 /* mptscsih_fillbuf - fill a buffer with a special data pattern
7046 * cleanup. For bus scan only.
7048 * @buffer: Pointer to data buffer to be filled.
7049 * @size: Number of bytes to fill
7050 * @index: Pattern index
7051 * @width: bus width, 0 (8 bits) or 1 (16 bits)
7054 mptscsih_fillbuf(char *buffer, int size, int index, int width)
7065 /* Pattern: 0000 FFFF 0000 FFFF
7067 for (ii=0; ii < size; ii++, ptr++) {
7074 /* Pattern: 00 FF 00 FF
7076 for (ii=0; ii < size; ii++, ptr++) {
7087 /* Pattern: 5555 AAAA 5555 AAAA 5555
7089 for (ii=0; ii < size; ii++, ptr++) {
7096 /* Pattern: 55 AA 55 AA 55
7098 for (ii=0; ii < size; ii++, ptr++) {
7108 /* Pattern: 00 01 02 03 04 05
7111 for (ii=0; ii < size; ii++, ptr++)
7117 /* Wide Pattern: FFFE 0001 FFFD 0002
7118 * ... 4000 DFFF 8000 EFFF
7121 for (ii=0; ii < size/2; ii++) {
7122 /* Create the base pattern
7125 /* every 64 (0x40) bytes flip the pattern
7126 * since we fill 2 bytes / iteration,
7127 * test for ii = 0x20
7133 *ptr = (char)( (val & 0xFF00) >> 8);
7135 *ptr = (char)(val & 0xFF);
7140 *ptr = (char)( (val & 0xFF00) >> 8);
7142 *ptr = (char)(val & 0xFF);
7148 /* Narrow Pattern: FE 01 FD 02 FB 04
7149 * .. 7F 80 01 FE 02 FD ... 80 7F
7152 for (ii=0; ii < size; ii++, ptr++) {
7153 /* Base pattern - first 32 bytes
7160 *ptr = (char) (~(1 << byte));
7163 /* Flip the pattern every 32 bytes
7172 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
7174 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7175 /* Commandline Parsing routines and defines.
7178 * insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1"
7180 * mptscsih=width:1,dv:n,factor:0x8,saf-te:1
7190 static char setup_token[] __initdata =
7195 ; /* DO NOT REMOVE THIS ';' */
7199 #define OPT_MAX_WIDTH 2
7200 #define OPT_MIN_SYNC_FACTOR 3
7201 #define OPT_SAF_TE 4
7203 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7206 get_setup_token(char *p)
7208 char *cur = setup_token;
7212 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7215 if (!strncmp(p, cur, pc - cur))
7222 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7224 mptscsih_setup(char *str)
7231 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7243 val = (int) simple_strtoul(pv, &pe, 0);
7245 printk("Found Token: %s, value %x\n", cur, (int)val);
7246 switch (get_setup_token(cur)) {
7248 driver_setup.dv = val;
7252 driver_setup.max_width = val;
7255 case OPT_MIN_SYNC_FACTOR:
7256 driver_setup.min_sync_fac = val;
7260 driver_setup.saf_te = val;
7264 printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
7268 if ((cur = strchr(cur, ARG_SEP)) != NULL)
7274 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7277 module_init(mptscsih_init);
7278 module_exit(mptscsih_exit);