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 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
812 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
813 * But not: DID_BUS_BUSY lest one risk
814 * killing interrupt handler:-(
816 sc->result = STS_BUSY;
819 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
820 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
821 sc->result = DID_BAD_TARGET << 16;
824 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
825 /* Spoof to SCSI Selection Timeout! */
826 sc->result = DID_NO_CONNECT << 16;
828 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
829 hd->sel_timeout[pScsiReq->TargetID]++;
832 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
833 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
834 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
835 /* Linux handles an unsolicited DID_RESET better
836 * than an unsolicited DID_ABORT.
838 sc->result = DID_RESET << 16;
840 /* GEM Workaround. */
842 mptscsih_no_negotiate(hd, sc->device->id);
845 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
846 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
848 * Do upfront check for valid SenseData and give it
851 scsi_status = pScsiReply->SCSIStatus;
852 sc->result = (DID_OK << 16) | scsi_status;
853 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
854 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
855 /* Have already saved the status and sense data
859 if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) {
860 sc->result = DID_SOFT_ERROR << 16;
862 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
865 sc->result = DID_SOFT_ERROR << 16;
867 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
868 /* Not real sure here either... */
869 sc->result = DID_RESET << 16;
873 /* Give report and update residual count.
875 dprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
877 dprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
879 sc->resid = sc->request_bufflen - xfer_cnt;
880 dprintk((KERN_NOTICE " SET sc->resid=%02xh\n", sc->resid));
884 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
885 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
889 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
890 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
891 sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
892 if (scsi_state == 0) {
894 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
896 * If running against circa 200003dd 909 MPT f/w,
897 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
898 * (QUEUE_FULL) returned from device! --> get 0x0000?128
899 * and with SenseBytes set to 0.
901 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
902 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
905 else if (scsi_state &
906 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
911 sc->result = DID_SOFT_ERROR << 16;
913 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
914 /* Not real sure here either... */
915 sc->result = DID_RESET << 16;
917 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
918 /* Device Inq. data indicates that it supports
919 * QTags, but rejects QTag messages.
920 * This command completed OK.
922 * Not real sure here either so do nothing... */
925 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
926 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
929 * Reservation Conflict, Busy,
930 * Command Terminated, CHECK
934 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
935 if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) {
936 /* Not real sure here either... */
937 sc->result = DID_RESET << 16;
939 sc->result = DID_SOFT_ERROR << 16;
942 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
943 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
944 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
945 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
946 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
947 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
948 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
949 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
950 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
951 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
956 sc->result = DID_SOFT_ERROR << 16;
959 } /* switch(status) */
961 dprintk((KERN_NOTICE " sc->result set to %08xh\n", sc->result));
962 } /* end of address reply case */
964 /* Unmap the DMA buffers, if any. */
966 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
967 sc->use_sg, scsi_to_pci_dma_dir(sc->sc_data_direction));
968 } else if (sc->request_bufflen) {
971 my_priv = (scPrivate *) &sc->SCp;
972 pci_unmap_single(ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
974 scsi_to_pci_dma_dir(sc->sc_data_direction));
977 hd->ScsiLookup[req_idx] = NULL;
979 sc->scsi_done(sc); /* Issue the command callback */
981 /* Free Chain buffers */
982 mptscsih_freeChainBuffers(hd, req_idx);
987 * Flush all commands on the doneQ.
988 * Lock Q when deleting/adding members
989 * Lock io_request_lock for OS callback.
992 flush_doneQ(MPT_SCSI_HOST *hd)
1000 dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n"));
1002 spin_lock_irqsave(&hd->freedoneQlock, flags);
1003 if (Q_IS_EMPTY(&hd->doneQ)) {
1004 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1008 buffer = hd->doneQ.head;
1013 /* Set the Scsi_Cmnd pointer
1015 SCpnt = (Scsi_Cmnd *) buffer->argp;
1016 buffer->argp = NULL;
1020 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1021 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1023 /* Do the OS callback.
1025 SCpnt->scsi_done(SCpnt);
1032 * Search the doneQ for a specific command. If found, delete from Q.
1033 * Calling function will finish processing.
1036 search_doneQ_for_cmd(MPT_SCSI_HOST *hd, Scsi_Cmnd *SCpnt)
1038 unsigned long flags;
1041 spin_lock_irqsave(&hd->freedoneQlock, flags);
1042 if (!Q_IS_EMPTY(&hd->doneQ)) {
1043 buffer = hd->doneQ.head;
1045 Scsi_Cmnd *sc = (Scsi_Cmnd *) buffer->argp;
1048 SCpnt->result = sc->result;
1050 /* Set the Scsi_Cmnd pointer
1052 buffer->argp = NULL;
1056 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
1059 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ);
1061 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1066 * mptscsih_flush_running_cmds - For each command found, search
1067 * Scsi_Host instance taskQ and reply to OS.
1068 * Called only if recovering from a FW reload.
1069 * @hd: Pointer to a SCSI HOST structure
1073 * Must be called while new I/Os are being queued.
1076 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
1082 int max = hd->ioc->req_depth;
1083 unsigned long flags;
1085 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
1086 for (ii= 0; ii < max; ii++) {
1087 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
1092 /* Search pendingQ, if found,
1095 mptscsih_search_pendingQ(hd, ii);
1097 /* Null ScsiLookup index
1099 hd->ScsiLookup[ii] = NULL;
1101 mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);
1102 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
1105 /* Set status, free OS resources (SG DMA buffers)
1107 * Free driver resources (chain, msg buffers)
1109 if (SCpnt->use_sg) {
1110 pci_unmap_sg(hd->ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
1111 SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1112 } else if (SCpnt->request_bufflen) {
1115 my_priv = (scPrivate *) &SCpnt->SCp;
1116 pci_unmap_single(hd->ioc->pcidev, (dma_addr_t)(ulong)my_priv->p1,
1117 SCpnt->request_bufflen,
1118 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
1120 SCpnt->result = DID_RESET << 16;
1121 SCpnt->host_scribble = NULL;
1123 /* Free Chain buffers */
1124 mptscsih_freeChainBuffers(hd, ii);
1126 /* Free Message frames */
1127 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
1130 /* Post to doneQ, do not reply until POST phase
1131 * of reset handler....prevents new commands from
1134 spin_lock_irqsave(&hd->freedoneQlock, flags);
1135 if (!Q_IS_EMPTY(&hd->freeQ)) {
1136 buffer = hd->freeQ.head;
1139 /* Set the Scsi_Cmnd pointer
1141 buffer->argp = (void *)SCpnt;
1145 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
1146 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1148 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
1149 SCpnt->scsi_done(SCpnt);
1152 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
1162 * mptscsih_search_running_cmds - Delete any commands associated
1163 * with the specified target and lun. Function called only
1164 * when a lun is disable by mid-layer.
1165 * Do NOT access the referenced Scsi_Cmnd structure or
1166 * members. Will cause either a paging or NULL ptr error.
1167 * @hd: Pointer to a SCSI HOST structure
1168 * @target: target id
1173 * Called from slave_destroy.
1176 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
1178 SCSIIORequest_t *mf = NULL;
1180 int max = hd->ioc->req_depth;
1182 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
1185 for (ii=0; ii < max; ii++) {
1186 if (hd->ScsiLookup[ii] != NULL) {
1188 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
1190 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
1191 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
1193 if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
1198 hd->ScsiLookup[ii] = NULL;
1199 mptscsih_freeChainBuffers(hd, ii);
1200 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, (MPT_FRAME_HDR *)mf);
1207 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1209 * mptscsih_initChainBuffers - Allocate memory for and initialize
1210 * chain buffers, chain buffer control arrays and spinlock.
1211 * @hd: Pointer to MPT_SCSI_HOST structure
1212 * @init: If set, initialize the spin lock.
1215 mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
1217 MPT_FRAME_HDR *chain;
1219 unsigned long flags;
1220 int sz, ii, num_chain;
1223 /* chain buffer allocation done from PrimeIocFifos */
1224 if (hd->ioc->fifo_pool == NULL)
1227 hd->ChainBuffer = hd->ioc->chain_alloc;
1228 hd->ChainBufferDMA = hd->ioc->chain_alloc_dma;
1230 dprintk((KERN_INFO " ChainBuffer @ %p(%p), sz=%d\n",
1231 hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, hd->ioc->chain_alloc_sz));
1233 /* ReqToChain size must equal the req_depth
1236 if (hd->ReqToChain == NULL) {
1237 sz = hd->ioc->req_depth * sizeof(int);
1238 mem = kmalloc(sz, GFP_ATOMIC);
1242 hd->ReqToChain = (int *) mem;
1244 for (ii = 0; ii < hd->ioc->req_depth; ii++)
1245 hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
1247 /* ChainToChain size must equal the total number
1248 * of chain buffers to be allocated.
1251 * Calculate the number of chain buffers needed(plus 1) per I/O
1252 * then multiply the the maximum number of simultaneous cmds
1254 * num_sge = num sge in request frame + last chain buffer
1255 * scale = num sge per chain buffer if no chain element
1257 scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1258 if (sizeof(dma_addr_t) == sizeof(u64))
1259 num_sge = scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
1261 num_sge = 1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
1264 while (hd->max_sge - num_sge > 0) {
1266 num_sge += (scale - 1);
1270 if ((int) hd->ioc->chip_type > (int) FC929)
1271 num_chain *= MPT_SCSI_CAN_QUEUE;
1273 num_chain *= MPT_FC_CAN_QUEUE;
1275 hd->num_chain = num_chain;
1277 sz = num_chain * sizeof(int);
1278 if (hd->ChainToChain == NULL) {
1279 mem = kmalloc(sz, GFP_ATOMIC);
1283 hd->ChainToChain = (int *) mem;
1285 mem = (u8 *) hd->ChainToChain;
1287 memset(mem, 0xFF, sz);
1290 /* Initialize the free chain Q.
1293 spin_lock_init(&hd->FreeChainQlock);
1296 spin_lock_irqsave (&hd->FreeChainQlock, flags);
1297 Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);
1299 /* Post the chain buffers to the FreeChainQ.
1301 mem = (u8 *)hd->ChainBuffer;
1302 for (ii=0; ii < num_chain; ii++) {
1303 chain = (MPT_FRAME_HDR *) mem;
1304 Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);
1305 mem += hd->ioc->req_sz;
1307 spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
1312 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1314 * Hack! It might be nice to report if a device is returning QUEUE_FULL
1315 * but maybe not each and every time...
1317 static long last_queue_full = 0;
1319 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1321 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
1322 * from a SCSI target device.
1323 * @sc: Pointer to Scsi_Cmnd structure
1324 * @pScsiReply: Pointer to SCSIIOReply_t
1325 * @pScsiReq: Pointer to original SCSI request
1327 * This routine periodically reports QUEUE_FULL status returned from a
1328 * SCSI target device. It reports this to the console via kernel
1329 * printk() API call, not more than once every 10 seconds.
1332 mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
1334 long time = jiffies;
1336 if (time - last_queue_full > 10 * HZ) {
1337 char *ioc_str = "ioc?";
1339 if (sc->device && sc->device->host != NULL && sc->device->host->hostdata != NULL)
1340 ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name;
1341 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
1342 ioc_str, 0, sc->device->id, sc->device->lun));
1343 last_queue_full = time;
1347 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1348 static char *info_kbuf = NULL;
1350 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1351 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1353 * mptscsih_probe - Installs scsi devices per bus.
1354 * @pdev: Pointer to pci_dev structure
1356 * Returns 0 for success, non-zero for failure.
1361 mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1363 struct Scsi_Host *sh;
1365 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1366 MPT_DONE_Q *freedoneQ;
1367 unsigned long flags;
1376 /* 20010202 -sralston
1377 * Added sanity check on readiness of the MPT adapter.
1379 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1380 printk(MYIOC_s_WARN_FMT
1381 "Skipping because it's not operational!\n",
1387 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1392 /* Sanity check - ensure at least 1 port is INITIATOR capable
1395 for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
1396 if (ioc->pfacts[ii].ProtocolFlags &
1397 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1402 printk(MYIOC_s_WARN_FMT
1403 "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
1408 sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));
1411 printk(MYIOC_s_WARN_FMT
1412 "Unable to register controller with SCSI subsystem\n",
1417 spin_lock_irqsave(&ioc->FreeQlock, flags);
1419 /* Attach the SCSI Host to the IOC structure
1427 /* set 16 byte cdb's */
1428 sh->max_cmd_len = 16;
1430 /* Yikes! This is important!
1431 * Otherwise, by default, linux
1432 * only scans target IDs 0-7!
1433 * pfactsN->MaxDevices unreliable
1434 * (not supported in early
1435 * versions of the FW).
1436 * max_id = 1 + actual max id,
1437 * max_lun = 1 + actual last lun,
1440 if ((int)ioc->chip_type > (int)FC929) {
1441 sh->max_id = MPT_MAX_SCSI_DEVICES;
1443 /* For FC, increase the queue depth
1444 * from MPT_SCSI_CAN_QUEUE (31)
1445 * to MPT_FC_CAN_QUEUE (63).
1447 sh->can_queue = MPT_FC_CAN_QUEUE;
1449 MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1452 sh->max_lun = MPT_LAST_LUN + 1;
1453 sh->max_sectors = MPT_SCSI_MAX_SECTORS;
1454 sh->max_channel = 0;
1455 sh->this_id = ioc->pfacts[0].PortSCSIID;
1459 sh->unique_id = ioc->id;
1461 /* Verify that we won't exceed the maximum
1462 * number of chain buffers
1463 * We can optimize: ZZ = req_sz/sizeof(SGE)
1465 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1466 * + (req_sz - 64)/sizeof(SGE)
1467 * A slightly different algorithm is required for
1470 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1471 if (sizeof(dma_addr_t) == sizeof(u64)) {
1472 numSGE = (scale - 1) *
1473 (ioc->facts.MaxChainDepth-1) + scale +
1474 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1477 numSGE = 1 + (scale - 1) *
1478 (ioc->facts.MaxChainDepth-1) + scale +
1479 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1483 if (numSGE < sh->sg_tablesize) {
1484 /* Reset this value */
1485 dprintk((MYIOC_s_INFO_FMT
1486 "Resetting sg_tablesize to %d from %d\n",
1487 ioc->name, numSGE, sh->sg_tablesize));
1488 sh->sg_tablesize = numSGE;
1491 /* Set the pci device pointer in Scsi_Host structure.
1493 scsi_set_device(sh, &ioc->pcidev->dev);
1495 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1497 hd = (MPT_SCSI_HOST *) sh->hostdata;
1499 hd->max_sge = sh->sg_tablesize;
1501 if ((int)ioc->chip_type > (int)FC929)
1504 if (DmpService && (ioc->chip_type == FC919 ||
1505 ioc->chip_type == FC929)) {
1506 hd->is_multipath = 1;
1509 /* SCSI needs Scsi_Cmnd lookup table!
1510 * (with size equal to req_depth*PtrSz!)
1512 sz = hd->ioc->req_depth * sizeof(void *);
1513 mem = kmalloc(sz, GFP_ATOMIC);
1516 goto mptscsih_probe_failed;
1520 hd->ScsiLookup = (struct scsi_cmnd **) mem;
1522 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
1523 ioc->name, hd->ScsiLookup, sz));
1525 if (mptscsih_initChainBuffers(hd, 1) < 0) {
1527 goto mptscsih_probe_failed;
1530 /* Allocate memory for free and doneQ's
1532 sz = sh->can_queue * sizeof(MPT_DONE_Q);
1533 mem = kmalloc(sz, GFP_ATOMIC);
1536 goto mptscsih_probe_failed;
1539 memset(mem, 0xFF, sz);
1542 /* Initialize the free, done and pending Qs.
1544 Q_INIT(&hd->freeQ, MPT_DONE_Q);
1545 Q_INIT(&hd->doneQ, MPT_DONE_Q);
1546 Q_INIT(&hd->pendingQ, MPT_DONE_Q);
1547 spin_lock_init(&hd->freedoneQlock);
1550 for (ii=0; ii < sh->can_queue; ii++) {
1551 freedoneQ = (MPT_DONE_Q *) mem;
1552 Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
1553 mem += sizeof(MPT_DONE_Q);
1556 /* Initialize this Scsi_Host
1559 Q_INIT(&hd->taskQ, MPT_FRAME_HDR);
1562 /* Allocate memory for the device structures.
1563 * A non-Null pointer at an offset
1564 * indicates a device exists.
1565 * max_id = 1 + maximum id (hosts.h)
1567 sz = sh->max_id * sizeof(void *);
1568 mem = kmalloc(sz, GFP_ATOMIC);
1571 goto mptscsih_probe_failed;
1575 hd->Targets = (VirtDevice **) mem;
1578 " Targets @ %p, sz=%d\n", hd->Targets, sz));
1580 /* Clear the TM flags
1583 hd->tmState = TM_STATE_NONE;
1584 hd->resetPending = 0;
1585 hd->abortSCpnt = NULL;
1587 hd->numTMrequests = 0;
1589 /* Clear the pointer used to store
1590 * single-threaded commands, i.e., those
1591 * issued during a bus scan, dv and
1592 * configuration pages.
1596 /* Initialize this SCSI Hosts' timers
1597 * To use, set the timer expires field
1600 init_timer(&hd->timer);
1601 hd->timer.data = (unsigned long) hd;
1602 hd->timer.function = mptscsih_timer_expired;
1604 init_timer(&hd->TMtimer);
1605 hd->TMtimer.data = (unsigned long) hd;
1606 hd->TMtimer.function = mptscsih_taskmgmt_timeout;
1607 hd->qtag_tick = jiffies;
1609 /* Moved Earlier Pam D */
1612 #ifdef MPTSCSIH_DBG_TIMEOUT
1613 hd->ioc->timeout_hard = 0;
1614 hd->ioc->timeout_delta = 30 * HZ;
1615 hd->ioc->timeout_maxcnt = 0;
1616 hd->ioc->timeout_cnt = 0;
1617 for (ii=0; ii < 8; ii++)
1621 /* Update with the driver setup
1624 if (hd->ioc->spi_data.maxBusWidth >
1625 driver_setup.max_width) {
1626 hd->ioc->spi_data.maxBusWidth =
1627 driver_setup.max_width;
1630 if (hd->ioc->spi_data.minSyncFactor <
1631 driver_setup.min_sync_fac) {
1632 hd->ioc->spi_data.minSyncFactor =
1633 driver_setup.min_sync_fac;
1636 if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) {
1637 hd->ioc->spi_data.maxSyncOffset = 0;
1640 hd->ioc->spi_data.Saf_Te = driver_setup.saf_te;
1643 #ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1644 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1646 if (driver_setup.dv == 0) {
1647 hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
1650 hd->ioc->spi_data.forceDv = 0;
1651 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
1652 hd->ioc->spi_data.dvStatus[ii] =
1653 MPT_SCSICFG_NEGOTIATE;
1656 if (hd->negoNvram == 0) {
1657 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
1658 hd->ioc->spi_data.dvStatus[ii] |=
1659 MPT_SCSICFG_DV_NOT_DONE;
1662 ddvprintk((MYIOC_s_INFO_FMT
1663 "dv %x width %x factor %x saf_te %x\n",
1664 hd->ioc->name, driver_setup.dv,
1665 driver_setup.max_width,
1666 driver_setup.min_sync_fac,
1667 driver_setup.saf_te));
1672 error = scsi_add_host (sh, &ioc->pcidev->dev);
1674 dprintk((KERN_ERR MYNAM
1675 "scsi_add_host failed\n"));
1676 goto mptscsih_probe_failed;
1682 mptscsih_probe_failed:
1684 mptscsih_remove(pdev);
1689 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1691 * mptscsih_remove - Removed scsi devices
1692 * @pdev: Pointer to pci_dev structure
1697 mptscsih_remove(struct pci_dev *pdev)
1699 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1700 struct Scsi_Host *host = ioc->sh;
1703 unsigned long flags;
1708 scsi_remove_host(host);
1710 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1711 /* Check DV thread active */
1713 spin_lock_irqsave(&dvtaskQ_lock, flags);
1714 if (dvtaskQ_active) {
1715 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1716 while(dvtaskQ_active && --count) {
1717 set_current_state(TASK_INTERRUPTIBLE);
1718 schedule_timeout(1);
1721 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
1724 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
1725 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
1727 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
1731 hd = (MPT_SCSI_HOST *)host->hostdata;
1733 int sz1, sz2, sz3, sztarget=0;
1738 mptscsih_shutdown(&pdev->dev);
1740 sz1 = sz2 = sz3 = 0;
1742 if (hd->ScsiLookup != NULL) {
1743 sz1 = hd->ioc->req_depth * sizeof(void *);
1744 kfree(hd->ScsiLookup);
1745 hd->ScsiLookup = NULL;
1748 if (hd->ReqToChain != NULL) {
1749 szr2chain = hd->ioc->req_depth * sizeof(int);
1750 kfree(hd->ReqToChain);
1751 hd->ReqToChain = NULL;
1754 if (hd->ChainToChain != NULL) {
1755 szc2chain = hd->num_chain * sizeof(int);
1756 kfree(hd->ChainToChain);
1757 hd->ChainToChain = NULL;
1760 if (hd->memQ != NULL) {
1761 szQ = host->can_queue * sizeof(MPT_DONE_Q);
1766 if (hd->Targets != NULL) {
1770 * Free any target structures that were allocated.
1773 max = MPT_MAX_SCSI_DEVICES;
1775 max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
1777 for (ii=0; ii < max; ii++) {
1778 if (hd->Targets[ii]) {
1779 kfree(hd->Targets[ii]);
1780 hd->Targets[ii] = NULL;
1781 sztarget += sizeof(VirtDevice);
1786 * Free pointer array.
1788 sz3 = max * sizeof(void *);
1793 dprintk((MYIOC_s_INFO_FMT
1794 "Free'd ScsiLookup (%d), chain (%d) and Target (%d+%d) memory\n",
1795 hd->ioc->name, sz1, szchain, sz3, sztarget));
1796 dprintk(("Free'd done and free Q (%d) memory\n", szQ));
1798 /* NULL the Scsi_Host pointer
1803 scsi_host_put(host);
1808 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1810 * mptscsih_shutdown - reboot notifier
1814 mptscsih_shutdown(struct device * dev)
1816 MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev));
1817 struct Scsi_Host *host = ioc->sh;
1823 hd = (MPT_SCSI_HOST *)host->hostdata;
1825 /* Flush the cache of this adapter
1828 mptscsih_synchronize_cache(hd, 0);
1833 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1835 * mptscsih_suspend - Fusion MPT scsie driver suspend routine.
1840 mptscsih_suspend(struct pci_dev *pdev, u32 state)
1842 mptscsih_shutdown(&pdev->dev);
1846 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1848 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1853 mptscsih_resume(struct pci_dev *pdev)
1855 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1856 struct Scsi_Host *host = ioc->sh;
1862 hd = (MPT_SCSI_HOST *)host->hostdata;
1866 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1868 unsigned long lflags;
1869 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1870 if (!dvtaskQ_active) {
1872 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1873 MPT_INIT_WORK(&mptscsih_dvTask,
1874 mptscsih_domainValidation, (void *) hd);
1875 SCHEDULE_TASK(&mptscsih_dvTask);
1877 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1886 static struct mpt_pci_driver mptscsih_driver = {
1887 .probe = mptscsih_probe,
1888 .remove = mptscsih_remove,
1889 .shutdown = mptscsih_shutdown,
1891 .suspend = mptscsih_suspend,
1892 .resume = mptscsih_resume,
1897 /* SCSI host fops start here... */
1898 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1900 * mptscsih_init - Register MPT adapter(s) as SCSI host(s) with
1901 * linux scsi mid-layer.
1903 * Returns 0 for success, non-zero for failure.
1909 show_mptmod_ver(my_NAME, my_VERSION);
1911 ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
1912 ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
1913 ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
1915 if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
1916 dprintk((KERN_INFO MYNAM
1917 ": Registered for IOC event notifications\n"));
1920 if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
1921 dprintk((KERN_INFO MYNAM
1922 ": Registered for IOC reset notifications\n"));
1926 /* Evaluate the command line arguments, if any */
1928 mptscsih_setup(mptscsih);
1931 if(mpt_device_driver_register(&mptscsih_driver,
1932 MPTSCSIH_DRIVER) != 0 ) {
1933 dprintk((KERN_INFO MYNAM
1934 ": failed to register dd callbacks\n"));
1941 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1942 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1944 * mptscsih_exit - Unregisters MPT adapter(s)
1952 /* removing devices */
1953 for(ioc = mpt_adapter_find_first(); ioc != NULL;
1954 ioc = mpt_adapter_find_next(ioc)) {
1955 if ((ioc->last_state != MPI_IOC_STATE_OPERATIONAL) ||
1958 mptscsih_remove(ioc->pcidev);
1961 mpt_reset_deregister(ScsiDoneCtx);
1962 dprintk((KERN_INFO MYNAM
1963 ": Deregistered for IOC reset notifications\n"));
1965 mpt_event_deregister(ScsiDoneCtx);
1966 dprintk((KERN_INFO MYNAM
1967 ": Deregistered for IOC event notifications\n"));
1969 mpt_device_driver_deregister(MPTSCSIH_DRIVER);
1970 mpt_deregister(ScsiScanDvCtx);
1971 mpt_deregister(ScsiTaskCtx);
1972 mpt_deregister(ScsiDoneCtx);
1974 if (info_kbuf != NULL)
1979 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1981 * mptscsih_info - Return information about MPT adapter
1982 * @SChost: Pointer to Scsi_Host structure
1984 * (linux Scsi_Host_Template.info routine)
1986 * Returns pointer to buffer where information was written.
1989 mptscsih_info(struct Scsi_Host *SChost)
1994 if (info_kbuf == NULL)
1995 if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1998 h = (MPT_SCSI_HOST *)SChost->hostdata;
1999 info_kbuf[0] = '\0';
2001 mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
2002 info_kbuf[size-1] = '\0';
2015 static void copy_mem_info(struct info_str *info, char *data, int len)
2017 if (info->pos + len > info->length)
2018 len = info->length - info->pos;
2020 if (info->pos + len < info->offset) {
2025 if (info->pos < info->offset) {
2026 data += (info->offset - info->pos);
2027 len -= (info->offset - info->pos);
2031 memcpy(info->buffer + info->pos, data, len);
2036 static int copy_info(struct info_str *info, char *fmt, ...)
2042 va_start(args, fmt);
2043 len = vsprintf(buf, fmt, args);
2046 copy_mem_info(info, buf, len);
2050 static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
2052 struct info_str info;
2056 info.offset = offset;
2059 copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
2060 copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
2061 copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
2062 copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
2064 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
2067 #ifndef MPTSCSIH_DBG_TIMEOUT
2068 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *pbuf, int len)
2070 /* Not yet implemented */
2074 #define is_digit(c) ((c) >= '0' && (c) <= '9')
2075 #define digit_to_bin(c) ((c) - '0')
2076 #define is_space(c) ((c) == ' ' || (c) == '\t')
2078 #define UC_DBG_TIMEOUT 0x01
2079 #define UC_DBG_HARDRESET 0x02
2081 static int skip_spaces(char *ptr, int len)
2085 for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt --);
2090 static int get_int_arg(char *ptr, int len, ulong *pv)
2094 for (v = 0, cnt = len; cnt > 0 && (c=*ptr++) && is_digit(c); cnt --) {
2095 v = (v * 10) + digit_to_bin(c);
2105 static int is_keyword(char *ptr, int len, char *verb)
2107 int verb_len = strlen(verb);
2109 if (len >= strlen(verb) && !memcmp(verb, ptr, verb_len))
2115 #define SKIP_SPACES(min_spaces) \
2116 if ((arg_len = skip_spaces(ptr,len)) < (min_spaces)) \
2121 #define GET_INT_ARG(v) \
2122 if (!(arg_len = get_int_arg(ptr,len, &(v)))) \
2127 static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length)
2130 char btmp[24]; /* REMOVE */
2137 if ((len > 0) && (ptr[len -1] == '\n'))
2141 strncpy(btmp, buffer, len);
2144 strncpy(btmp, buffer, 22);
2147 printk("user_command: ioc %d, buffer %s, length %d\n",
2148 ioc->id, btmp, length);
2150 if ((arg_len = is_keyword(ptr, len, "timeout")) != 0)
2151 cmd = UC_DBG_TIMEOUT;
2152 else if ((arg_len = is_keyword(ptr, len, "hardreset")) != 0)
2153 cmd = UC_DBG_HARDRESET;
2161 case UC_DBG_TIMEOUT:
2163 GET_INT_ARG(number);
2169 printk("user_command: cnt=%ld delta=%ld\n", number, delta);
2174 if (cmd == UC_DBG_HARDRESET) {
2175 ioc->timeout_hard = 1;
2176 } else if (cmd == UC_DBG_TIMEOUT) {
2177 /* process this command ...
2179 ioc->timeout_maxcnt = 0;
2180 ioc->timeout_delta = delta < 2 ? 2 : delta;
2181 ioc->timeout_cnt = 0;
2182 ioc->timeout_maxcnt = number < 8 ? number: 8;
2185 /* Not yet implemented */
2190 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2192 * mptscsih_proc_info - Return information about MPT adapter
2194 * (linux Scsi_Host_Template.info routine)
2196 * buffer: if write, user data; if read, buffer for user
2197 * length: if write, return length;
2198 * offset: if write, 0; if read, the current offset into the buffer from
2199 * the previous read.
2200 * hostno: scsi host number
2201 * func: if write = 1; if read = 0
2203 int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
2204 int length, int func)
2207 MPT_SCSI_HOST *hd = NULL;
2210 dprintk(("Called mptscsih_proc_info: hostno=%d, func=%d\n", host->host_no, func));
2211 dprintk(("buffer %p, start=%p (%p) offset=%ld length = %d\n",
2212 buffer, start, *start, offset, length));
2214 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
2215 if ((ioc->sh) && (ioc->sh == host)) {
2216 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2220 if ((ioc == NULL) || (ioc->sh == NULL) || (hd == NULL))
2224 size = mptscsih_user_command(ioc, buffer, length);
2229 size = mptscsih_host_info(ioc, buffer, offset, length);
2236 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2237 #define ADD_INDEX_LOG(req_ent) do { } while(0)
2239 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2241 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
2242 * @SCpnt: Pointer to Scsi_Cmnd structure
2243 * @done: Pointer SCSI mid-layer IO completion function
2245 * (linux Scsi_Host_Template.queuecommand routine)
2246 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
2247 * from a linux Scsi_Cmnd request and send it to the IOC.
2249 * Returns 0. (rtn value discarded by linux scsi mid-layer)
2252 mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2256 SCSIIORequest_t *pScsiReq;
2257 VirtDevice *pTarget;
2259 unsigned long flags;
2274 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
2275 target = SCpnt->device->id;
2276 lun = SCpnt->device->lun;
2277 SCpnt->scsi_done = done;
2279 pTarget = hd->Targets[target];
2281 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
2282 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
2284 if (hd->resetPending) {
2285 /* Prevent new commands from being issued
2286 * while reloading the FW. Reset timer to 60 seconds,
2287 * as the FW can take some time to come ready.
2288 * For New EH, cmds on doneQ posted to FW.
2291 mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));
2292 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
2293 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2298 * Put together a MPT SCSI request...
2300 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
2301 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
2307 pScsiReq = (SCSIIORequest_t *) mf;
2309 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2311 ADD_INDEX_LOG(my_idx);
2314 * The scsi layer should be handling this stuff
2315 * (In 2.3.x it does -DaveM)
2318 /* BUG FIX! 19991030 -sralston
2319 * TUR's being issued with scsictl=0x02000000 (DATA_IN)!
2320 * Seems we may receive a buffer (datalen>0) even when there
2321 * will be no data transfer! GRRRRR...
2323 datadir = mptscsih_io_direction(SCpnt);
2324 if (datadir == SCSI_DATA_READ) {
2325 datalen = SCpnt->request_bufflen;
2326 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
2327 } else if (datadir == SCSI_DATA_WRITE) {
2328 datalen = SCpnt->request_bufflen;
2329 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
2332 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
2335 /* Default to untagged. Once a target structure has been allocated,
2336 * use the Inquiry data to determine if device supports tagged.
2339 && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
2340 && (SCpnt->device->tagged_supported)) {
2341 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
2343 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
2346 /* Use the above information to set up the message frame
2348 pScsiReq->TargetID = (u8) target;
2349 pScsiReq->Bus = (u8) SCpnt->device->channel;
2350 pScsiReq->ChainOffset = 0;
2351 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
2352 pScsiReq->CDBLength = SCpnt->cmd_len;
2353 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
2354 pScsiReq->Reserved = 0;
2355 pScsiReq->MsgFlags = mpt_msg_flags();
2356 pScsiReq->LUN[0] = 0;
2357 pScsiReq->LUN[1] = lun;
2358 pScsiReq->LUN[2] = 0;
2359 pScsiReq->LUN[3] = 0;
2360 pScsiReq->LUN[4] = 0;
2361 pScsiReq->LUN[5] = 0;
2362 pScsiReq->LUN[6] = 0;
2363 pScsiReq->LUN[7] = 0;
2364 pScsiReq->Control = cpu_to_le32(scsictl);
2367 * Write SCSI CDB into the message
2369 cmd_len = SCpnt->cmd_len;
2370 for (ii=0; ii < cmd_len; ii++)
2371 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
2373 for (ii=cmd_len; ii < 16; ii++)
2374 pScsiReq->CDB[ii] = 0;
2377 pScsiReq->DataLength = cpu_to_le32(datalen);
2379 /* SenseBuffer low address */
2380 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
2381 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
2383 /* Now add the SG list
2384 * Always have a SGE even if null length.
2388 /* Add a NULL SGE */
2389 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
2392 /* Add a 32 or 64 bit SGE */
2393 rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
2397 if (rc == SUCCESS) {
2398 hd->ScsiLookup[my_idx] = SCpnt;
2399 SCpnt->host_scribble = NULL;
2401 /* SCSI specific processing */
2404 int dvStatus = hd->ioc->spi_data.dvStatus[target];
2406 if (dvStatus || hd->ioc->spi_data.forceDv) {
2408 /* Write SDP1 on this I/O to this target */
2409 if (dvStatus & MPT_SCSICFG_NEGOTIATE) {
2410 mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);
2411 dvStatus &= ~MPT_SCSICFG_NEGOTIATE;
2412 hd->ioc->spi_data.dvStatus[target] = dvStatus;
2413 } else if (dvStatus & MPT_SCSICFG_BLK_NEGO) {
2414 mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO);
2415 dvStatus &= ~MPT_SCSICFG_BLK_NEGO;
2416 hd->ioc->spi_data.dvStatus[target] = dvStatus;
2419 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2420 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
2421 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
2422 unsigned long lflags;
2423 /* Schedule DV if necessary */
2424 spin_lock_irqsave(&dvtaskQ_lock, lflags);
2425 if (!dvtaskQ_active) {
2427 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2428 MPT_INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
2430 SCHEDULE_TASK(&mptscsih_dvTask);
2432 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
2434 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
2437 /* Trying to do DV to this target, extend timeout.
2438 * Wait to issue intil flag is clear
2440 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
2441 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
2445 /* Set the DV flags.
2447 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
2448 mptscsih_set_dvflags(hd, pScsiReq);
2453 #ifdef MPTSCSIH_DBG_TIMEOUT
2454 if (hd->ioc->timeout_cnt < hd->ioc->timeout_maxcnt) {
2455 foo_to[hd->ioc->timeout_cnt] = SCpnt;
2456 hd->ioc->timeout_cnt++;
2457 //mod_timer(&SCpnt->eh_timeout, jiffies + hd->ioc->timeout_delta);
2459 printk(MYIOC_s_WARN_FMT
2460 "to pendingQ: (sc=%p, mf=%p, time=%ld)\n",
2461 hd->ioc->name, SCpnt, mf, jiffies);
2466 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2467 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
2468 hd->ioc->name, SCpnt, mf, my_idx));
2470 ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",
2471 hd->ioc->name, SCpnt, my_idx));
2472 /* Place this command on the pendingQ if possible */
2473 spin_lock_irqsave(&hd->freedoneQlock, flags);
2474 if (!Q_IS_EMPTY(&hd->freeQ)) {
2475 buffer = hd->freeQ.head;
2478 /* Save the mf pointer
2480 buffer->argp = (void *)mf;
2482 /* Add to the pendingQ
2484 Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);
2485 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2487 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2488 SCpnt->result = (DID_BUS_BUSY << 16);
2489 SCpnt->scsi_done(SCpnt);
2493 mptscsih_freeChainBuffers(hd, my_idx);
2494 mpt_free_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2502 dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n",
2503 hd->ioc->name, did_errcode, SCpnt));
2504 /* Just wish OS to issue a retry */
2505 SCpnt->result = (DID_BUS_BUSY << 16);
2506 spin_lock_irqsave(&hd->freedoneQlock, flags);
2507 if (!Q_IS_EMPTY(&hd->freeQ)) {
2508 dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n",
2509 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
2510 buffer = hd->freeQ.head;
2513 /* Set the Scsi_Cmnd pointer
2515 buffer->argp = (void *)SCpnt;
2519 Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
2520 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2522 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
2523 SCpnt->scsi_done(SCpnt);
2529 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2531 * mptscsih_freeChainBuffers - Function to free chain buffers associated
2532 * with a SCSI IO request
2533 * @hd: Pointer to the MPT_SCSI_HOST instance
2534 * @req_idx: Index of the SCSI IO request frame.
2536 * Called if SG chain buffer allocation fails and mptscsih callbacks.
2540 mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
2542 MPT_FRAME_HDR *chain;
2543 unsigned long flags;
2547 /* Get the first chain index and reset
2550 chain_idx = hd->ReqToChain[req_idx];
2551 hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
2553 while (chain_idx != MPT_HOST_NO_CHAIN) {
2555 /* Save the next chain buffer index */
2556 next = hd->ChainToChain[chain_idx];
2558 /* Free this chain buffer and reset
2561 hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
2563 chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
2564 + (chain_idx * hd->ioc->req_sz));
2565 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2566 Q_ADD_TAIL(&hd->FreeChainQ.head,
2567 &chain->u.frame.linkage, MPT_FRAME_HDR);
2568 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2570 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
2571 hd->ioc->name, chain_idx));
2579 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2584 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2586 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
2587 * Fall through to mpt_HardResetHandler if: not operational, too many
2588 * failed TM requests or handshake failure.
2590 * @ioc: Pointer to MPT_ADAPTER structure
2591 * @type: Task Management type
2592 * @target: Logical Target ID for reset (if appropriate)
2593 * @lun: Logical Unit for reset (if appropriate)
2594 * @ctx2abort: Context for the task to be aborted (if appropriate)
2595 * @sleepFlag: If set, use udelay instead of schedule in handshake code.
2597 * Remark: Currently invoked from a non-interrupt thread (_bh).
2599 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
2602 * Returns 0 for SUCCESS or -1 if FAILED.
2605 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
2611 unsigned long flags;
2613 /* If FW is being reloaded currently, return success to
2614 * the calling function.
2621 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
2624 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
2626 // SJR - CHECKME - Can we avoid this here?
2627 // (mpt_HardResetHandler has this check...)
2628 spin_lock_irqsave(&ioc->diagLock, flags);
2629 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
2630 spin_unlock_irqrestore(&ioc->diagLock, flags);
2633 spin_unlock_irqrestore(&ioc->diagLock, flags);
2635 /* Do not do a Task Management if there are
2636 * too many failed TMs on this adapter.
2638 if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM)
2641 /* Wait a fixed amount of time for the TM pending flag to be cleared.
2642 * If we time out and not bus reset, then we return a FAILED status to the caller.
2643 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
2644 * successful. Otherwise, reload the FW.
2646 if (mptscsih_tm_pending_wait(hd) == FAILED) {
2647 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
2648 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler abort: "
2649 "Timed out waiting for last TM (%d) to complete! \n",
2650 hd->ioc->name, hd->tmPending));
2652 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
2653 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler target reset: "
2654 "Timed out waiting for last TM (%d) to complete! \n",
2655 hd->ioc->name, hd->tmPending));
2657 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2658 dtmprintk((KERN_WARNING MYNAM ": %s: TMHandler bus reset: "
2659 "Timed out waiting for last TM (%d) to complete! \n",
2660 hd->ioc->name, hd->tmPending));
2661 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
2667 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
2668 hd->tmPending |= (1 << type);
2669 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
2674 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
2676 #ifdef MPT_DEBUG_RESET
2677 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
2678 printk(MYIOC_s_WARN_FMT
2679 "TM Handler: IOC Not operational(0x%x)!\n",
2680 hd->ioc->name, ioc_raw_state);
2684 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
2685 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
2687 /* Isse the Task Mgmt request.
2689 if (hd->hard_resets < -1)
2691 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag);
2693 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
2695 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
2699 #ifdef MPTSCSIH_DBG_TIMEOUT
2700 if (hd->ioc->timeout_hard)
2704 /* Only fall through to the HRH if this is a bus reset
2706 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
2707 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
2708 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
2710 rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
2713 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
2719 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2721 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
2722 * @hd: Pointer to MPT_SCSI_HOST structure
2723 * @type: Task Management type
2724 * @target: Logical Target ID for reset (if appropriate)
2725 * @lun: Logical Unit for reset (if appropriate)
2726 * @ctx2abort: Context for the task to be aborted (if appropriate)
2727 * @sleepFlag: If set, use udelay instead of schedule in handshake code.
2729 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
2730 * or a non-interrupt thread. In the former, must not call schedule().
2732 * Not all fields are meaningfull for all task types.
2734 * Returns 0 for SUCCESS, -999 for "no msg frames",
2735 * else other non-zero value returned.
2738 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
2741 SCSITaskMgmt_t *pScsiTm;
2745 /* Return Fail to calling function if no message frames available.
2747 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
2748 dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
2753 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
2754 hd->ioc->name, mf));
2756 /* Format the Request
2758 pScsiTm = (SCSITaskMgmt_t *) mf;
2759 pScsiTm->TargetID = target;
2760 pScsiTm->Bus = channel;
2761 pScsiTm->ChainOffset = 0;
2762 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
2764 pScsiTm->Reserved = 0;
2765 pScsiTm->TaskType = type;
2766 pScsiTm->Reserved1 = 0;
2767 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
2768 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
2770 for (ii= 0; ii < 8; ii++) {
2771 pScsiTm->LUN[ii] = 0;
2773 pScsiTm->LUN[1] = lun;
2775 for (ii=0; ii < 7; ii++)
2776 pScsiTm->Reserved2[ii] = 0;
2778 pScsiTm->TaskMsgContext = ctx2abort;
2779 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n",
2780 hd->ioc->name, ctx2abort, type));
2782 /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
2783 mpt_put_msg_frame(hd->ioc->id, mf);
2784 * Save the MF pointer in case the request times out.
2787 hd->numTMrequests++;
2788 hd->TMtimer.expires = jiffies + timeout;
2789 add_timer(&hd->TMtimer);
2791 if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
2792 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
2794 dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
2795 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
2796 hd->numTMrequests--;
2798 del_timer(&hd->TMtimer);
2799 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
2805 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2807 * mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
2808 * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
2810 * (linux Scsi_Host_Template.eh_abort_handler routine)
2812 * Returns SUCCESS or FAILED.
2815 mptscsih_abort(Scsi_Cmnd * SCpnt)
2821 spinlock_t *host_lock = SCpnt->device->host->host_lock;
2823 /* If we can't locate our host adapter structure, return FAILED status.
2825 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
2826 SCpnt->result = DID_RESET << 16;
2827 SCpnt->scsi_done(SCpnt);
2828 dtmprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
2829 "Can't locate host! (sc=%p)\n",
2834 if (hd->resetPending)
2837 printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
2838 hd->ioc->name, SCpnt);
2840 if (hd->timeouts < -1)
2843 /* Find this command
2845 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
2846 /* Cmd not found in ScsiLookup. If found in
2847 * doneQ, delete from Q. Do OS callback.
2849 search_doneQ_for_cmd(hd, SCpnt);
2851 SCpnt->result = DID_RESET << 16;
2852 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
2853 "Command not in the active list! (sc=%p)\n",
2854 hd->ioc->name, SCpnt));
2858 /* If this command is pended, then timeout/hang occurred
2859 * during DV. Post command and flush pending Q
2860 * and then following up with the reset request.
2862 if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
2863 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
2864 post_pendingQ_commands(hd);
2865 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
2866 "Posting pended cmd! (sc=%p)\n",
2867 hd->ioc->name, SCpnt));
2870 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
2871 * (the IO to be ABORT'd)
2873 * NOTE: Since we do not byteswap MsgContext, we do not
2874 * swap it here either. It is an opaque cookie to
2875 * the controller, so it does not matter. -DaveM
2877 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
2878 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
2880 hd->abortSCpnt = SCpnt;
2882 spin_unlock_irq(host_lock);
2883 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
2884 SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
2885 ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP)
2888 /* The TM request failed and the subsequent FW-reload failed!
2891 printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
2892 hd->ioc->name, SCpnt);
2894 /* We must clear our pending flag before clearing our state.
2897 hd->tmState = TM_STATE_NONE;
2899 spin_lock_irq(host_lock);
2902 spin_lock_irq(host_lock);
2907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2909 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
2910 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
2912 * (linux Scsi_Host_Template.eh_dev_reset_handler routine)
2914 * Returns SUCCESS or FAILED.
2917 mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
2920 spinlock_t *host_lock = SCpnt->device->host->host_lock;
2922 /* If we can't locate our host adapter structure, return FAILED status.
2924 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2925 dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
2926 "Can't locate host! (sc=%p)\n",
2931 if (hd->resetPending)
2934 printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
2935 hd->ioc->name, SCpnt);
2937 /* Unsupported for SCSI. Supported for FCP
2942 spin_unlock_irq(host_lock);
2943 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
2944 SCpnt->device->channel, SCpnt->device->id,
2945 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
2947 /* The TM request failed and the subsequent FW-reload failed!
2950 printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
2951 hd->ioc->name, SCpnt);
2953 hd->tmState = TM_STATE_NONE;
2954 spin_lock_irq(host_lock);
2957 spin_lock_irq(host_lock);
2962 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2964 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
2965 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
2967 * (linux Scsi_Host_Template.eh_bus_reset_handler routine)
2969 * Returns SUCCESS or FAILED.
2972 mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
2975 spinlock_t *host_lock = SCpnt->device->host->host_lock;
2977 /* If we can't locate our host adapter structure, return FAILED status.
2979 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
2980 dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
2981 "Can't locate host! (sc=%p)\n",
2986 printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
2987 hd->ioc->name, SCpnt);
2989 if (hd->timeouts < -1)
2992 /* We are now ready to execute the task management request. */
2993 spin_unlock_irq(host_lock);
2994 // printk("testing start : mptscsih_schedule_reset\n");
2995 // mptscsih_schedule_reset(hd);
2996 // printk("testing end: mptscsih_schedule_reset\n");
2997 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
2998 SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
3001 /* The TM request failed and the subsequent FW-reload failed!
3004 printk(MYIOC_s_WARN_FMT
3005 "Error processing TaskMgmt request (sc=%p)\n",
3006 hd->ioc->name, SCpnt);
3008 hd->tmState = TM_STATE_NONE;
3009 spin_lock_irq(host_lock);
3012 spin_lock_irq(host_lock);
3016 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3018 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
3020 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
3022 * (linux Scsi_Host_Template.eh_host_reset_handler routine)
3024 * Returns SUCCESS or FAILED.
3027 mptscsih_host_reset(Scsi_Cmnd *SCpnt)
3030 int status = SUCCESS;
3031 spinlock_t *host_lock = SCpnt->device->host->host_lock;
3033 /* If we can't locate the host to reset, then we failed. */
3034 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
3035 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3036 "Can't locate host! (sc=%p)\n",
3041 printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
3042 hd->ioc->name, SCpnt);
3044 /* If our attempts to reset the host failed, then return a failed
3045 * status. The host will be taken off line by the SCSI mid-layer.
3047 spin_unlock_irq(host_lock);
3048 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
3051 /* Make sure TM pending is cleared and TM state is set to
3055 hd->tmState = TM_STATE_NONE;
3057 spin_lock_irq(host_lock);
3060 dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
3062 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
3067 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3069 * mptscsih_tm_pending_wait - wait for pending task management request to
3071 * @hd: Pointer to MPT host structure.
3073 * Returns {SUCCESS,FAILED}.
3076 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
3078 unsigned long flags;
3079 int loop_count = 10 * 4; /* Wait 10 seconds */
3080 int status = FAILED;
3083 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
3084 if (hd->tmState == TM_STATE_NONE) {
3085 hd->tmState = TM_STATE_IN_PROGRESS;
3087 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3091 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
3092 set_current_state(TASK_INTERRUPTIBLE);
3093 schedule_timeout(HZ/4);
3094 } while (--loop_count);
3099 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3101 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
3102 * @ioc: Pointer to MPT_ADAPTER structure
3103 * @mf: Pointer to SCSI task mgmt request frame
3104 * @mr: Pointer to SCSI task mgmt reply frame
3106 * This routine is called from mptbase.c::mpt_interrupt() at the completion
3107 * of any SCSI task management request.
3108 * This routine is registered with the MPT (base) driver at driver
3109 * load/init time via the mpt_register() API call.
3111 * Returns 1 indicating alloc'd request frame ptr should be freed.
3114 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3116 SCSITaskMgmtReply_t *pScsiTmReply;
3117 SCSITaskMgmt_t *pScsiTmReq;
3119 unsigned long flags;
3122 dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
3123 ioc->name, mf, mr));
3125 /* Depending on the thread, a timer is activated for
3126 * the TM request. Delete this timer on completion of TM.
3127 * Decrement count of outstanding TM requests.
3129 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
3131 del_timer(&hd->TMtimer);
3133 dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
3134 ioc->name, hd->taskQcnt));
3136 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
3142 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
3146 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
3147 pScsiTmReq = (SCSITaskMgmt_t*)mf;
3149 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
3150 tmType = pScsiTmReq->TaskType;
3152 dtmprintk((KERN_INFO " TaskType = %d, TerminationCount=%d\n",
3153 tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
3155 /* Error? (anything non-zero?) */
3156 if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
3159 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3160 dtmprintk((KERN_INFO " SCSI TaskMgmt (%d) - Oops!\n", tmType));
3161 dtmprintk((KERN_INFO " IOCStatus = %04xh\n", iocstatus));
3162 dtmprintk((KERN_INFO " IOCLogInfo = %08xh\n",
3163 le32_to_cpu(pScsiTmReply->IOCLogInfo)));
3165 /* clear flags and continue.
3167 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
3168 hd->abortSCpnt = NULL;
3170 /* If an internal command is present
3171 * or the TM failed - reload the FW.
3172 * FC FW may respond FAILED to an ABORT
3174 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
3176 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
3177 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
3178 printk((KERN_WARNING
3179 " Firmware Reload FAILED!!\n"));
3184 dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n"));
3186 hd->numTMrequests--;
3187 hd->abortSCpnt = NULL;
3194 spin_lock_irqsave(&ioc->FreeQlock, flags);
3196 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3197 hd->tmState = TM_STATE_NONE;
3202 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3204 * This is anyones guess quite frankly.
3207 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
3208 sector_t capacity, int geom[])
3220 dummy = heads * sectors;
3221 cylinders = capacity;
3222 sector_div(cylinders,dummy);
3224 cylinders = (ulong)capacity / (heads * sectors);
3228 * Handle extended translation size for logical drives
3231 if ((ulong)capacity >= 0x200000) {
3235 dummy = heads * sectors;
3236 cylinders = capacity;
3237 sector_div(cylinders,dummy);
3239 cylinders = (ulong)capacity / (heads * sectors);
3246 geom[2] = cylinders;
3248 dprintk((KERN_NOTICE
3249 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
3250 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
3255 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3257 * OS entry point to allow host driver to alloc memory
3258 * for each scsi device. Called once per device the bus scan.
3259 * Return non-zero if allocation fails.
3260 * Init memory once per id (not LUN).
3263 mptscsih_slave_alloc(Scsi_Device *device)
3265 struct Scsi_Host *host = device->host;
3269 hd = (MPT_SCSI_HOST *)host->hostdata;
3274 if ((vdev = hd->Targets[device->id]) == NULL) {
3275 if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
3276 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%d) FAILED!\n",
3277 hd->ioc->name, (int)sizeof(VirtDevice));
3280 memset(vdev, 0, sizeof(VirtDevice));
3281 rwlock_init(&vdev->VdevLock);
3282 Q_INIT(&vdev->WaitQ, void);
3283 Q_INIT(&vdev->SentQ, void);
3284 Q_INIT(&vdev->DoneQ, void);
3286 vdev->ioc_id = hd->ioc->id;
3287 vdev->target_id = device->id;
3288 vdev->bus_id = hd->port;
3290 hd->Targets[device->id] = vdev;
3299 * OS entry point to allow for host driver to free allocated memory
3300 * Called if no device present or device being unloaded
3303 mptscsih_slave_destroy(Scsi_Device *device)
3305 struct Scsi_Host *host = device->host;
3310 hd = (MPT_SCSI_HOST *)host->hostdata;
3315 mptscsih_search_running_cmds(hd, device->id, device->lun);
3317 /* Free memory and reset all flags for this target
3319 if ((vdev = hd->Targets[device->id]) != NULL) {
3322 if (vdev->luns[0] & (1 << device->lun))
3323 vdev->luns[0] &= ~(1 << device->lun);
3325 /* Free device structure only if number of luns is 0.
3327 if (vdev->num_luns == 0) {
3328 kfree(hd->Targets[device->id]);
3329 hd->Targets[device->id] = NULL;
3334 if((hd->ioc->spi_data.isRaid) && (hd->ioc->spi_data.pIocPg3)) {
3336 for(i=0;i<hd->ioc->spi_data.pIocPg3->NumPhysDisks &&
3340 hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) {
3342 hd->ioc->spi_data.forceDv |=
3343 MPT_SCSICFG_RELOAD_IOC_PG3;
3348 hd->ioc->spi_data.dvStatus[device->id] =
3349 MPT_SCSICFG_NEGOTIATE;
3351 if (hd->negoNvram == 0)
3352 hd->ioc->spi_data.dvStatus[device->id]
3353 |= MPT_SCSICFG_DV_NOT_DONE;
3362 * OS entry point to adjust the queue_depths on a per-device basis.
3363 * Called once per device the bus scan. Use it to force the queue_depth
3364 * member to 1 if a device does not support Q tags.
3365 * Return non-zero if fails.
3368 mptscsih_slave_configure(Scsi_Device *device)
3370 struct Scsi_Host *sh = device->host;
3371 VirtDevice *pTarget;
3372 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
3374 if ((hd == NULL) || (hd->Targets == NULL)) {
3378 dsprintk((MYIOC_s_INFO_FMT
3379 "device @ %p, id=%d, LUN=%d, channel=%d\n",
3380 hd->ioc->name, device, device->id, device->lun, device->channel));
3381 dsprintk((MYIOC_s_INFO_FMT
3382 "sdtr %d wdtr %d ppr %d inq length=%d\n",
3383 hd->ioc->name, device->sdtr, device->wdtr,
3384 device->ppr, device->inquiry_len));
3386 if (device->id > sh->max_id) {
3387 /* error case, should never happen */
3388 scsi_adjust_queue_depth(device, 0, 1);
3389 goto slave_configure_exit;
3392 pTarget = hd->Targets[device->id];
3394 if (pTarget == NULL) {
3395 /* error case - don't know about this device */
3396 scsi_adjust_queue_depth(device, 0, 1);
3397 goto slave_configure_exit;
3400 mptscsih_initTarget(hd, device->channel, device->id, device->lun,
3401 device->inquiry, device->inquiry_len );
3402 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3403 MPT_SCSI_CMD_PER_DEV_HIGH);
3405 if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
3406 if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
3407 scsi_adjust_queue_depth(device, 0, 1);
3408 else if (((pTarget->inq_data[0] & 0x1f) == 0x00)
3409 && (pTarget->minSyncFactor <= MPT_ULTRA160 ))
3410 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3411 MPT_SCSI_CMD_PER_DEV_HIGH);
3413 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
3414 MPT_SCSI_CMD_PER_DEV_LOW);
3416 /* error case - No Inq. Data */
3417 scsi_adjust_queue_depth(device, 0, 1);
3421 dsprintk((MYIOC_s_INFO_FMT
3422 "Queue depth=%d, tflags=%x\n",
3423 hd->ioc->name, device->queue_depth, pTarget->tflags));
3425 dsprintk((MYIOC_s_INFO_FMT
3426 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
3427 hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
3429 slave_configure_exit:
3431 dsprintk((MYIOC_s_INFO_FMT
3432 "tagged %d, simple %d, ordered %d\n",
3433 hd->ioc->name,device->tagged_supported, device->simple_tags,
3434 device->ordered_tags));
3440 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3442 * Private routines...
3445 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3446 /* Utility function to copy sense data from the scsi_cmnd buffer
3447 * to the FC and SCSI target structures.
3451 copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
3454 SCSIIORequest_t *pReq;
3455 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
3460 /* Get target structure
3462 pReq = (SCSIIORequest_t *) mf;
3463 index = (int) pReq->TargetID;
3464 target = hd->Targets[index];
3465 if (hd->is_multipath && sc->device->hostdata)
3466 target = (VirtDevice *) sc->device->hostdata;
3472 /* Copy the sense received into the scsi command block. */
3473 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3474 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
3475 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
3477 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
3479 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
3480 if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
3482 MPT_ADAPTER *ioc = hd->ioc;
3484 idx = ioc->eventContext % ioc->eventLogSize;
3485 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
3486 ioc->events[idx].eventContext = ioc->eventContext;
3488 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
3489 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
3490 (pReq->Bus << 8) || pReq->TargetID;
3492 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
3494 ioc->eventContext++;
3498 /* Print an error report for the user.
3500 thisIo.cdbPtr = sc->cmnd;
3501 thisIo.sensePtr = sc->sense_buffer;
3502 thisIo.SCSIStatus = pScsiReply->SCSIStatus;
3503 thisIo.DoDisplay = 1;
3504 if (hd->is_multipath)
3505 sprintf(devFoo, "%d:%d:%d",
3510 sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->device->id, sc->device->lun);
3511 thisIo.DevIDStr = devFoo;
3513 thisIo.dataPtr = NULL;
3514 thisIo.inqPtr = NULL;
3516 thisIo.inqPtr = sc->device->vendor-8; /* FIXME!!! */
3518 (void) mpt_ScsiHost_ErrorReport(&thisIo);
3521 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
3529 SCPNT_TO_LOOKUP_IDX(Scsi_Cmnd *sc)
3534 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
3536 for (i = 0; i < hd->ioc->req_depth; i++) {
3537 if (hd->ScsiLookup[i] == sc) {
3546 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3547 /* Search the pendingQ for a command with specific index.
3548 * If found, delete and return mf pointer
3549 * If not found, return NULL
3551 static MPT_FRAME_HDR *
3552 mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx)
3554 unsigned long flags;
3556 MPT_FRAME_HDR *mf = NULL;
3557 MPT_FRAME_HDR *cmdMfPtr;
3559 ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
3560 cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
3561 spin_lock_irqsave(&hd->freedoneQlock, flags);
3562 if (!Q_IS_EMPTY(&hd->pendingQ)) {
3563 buffer = hd->pendingQ.head;
3565 mf = (MPT_FRAME_HDR *) buffer->argp;
3566 if (mf == cmdMfPtr) {
3569 /* clear the arg pointer
3571 buffer->argp = NULL;
3575 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
3579 } while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ);
3581 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3582 ddvtprintk((" ...return %p\n", mf));
3586 /* Post all commands on the pendingQ to the FW.
3587 * Lock Q when deleting/adding members
3588 * Lock io_request_lock for OS callback.
3591 post_pendingQ_commands(MPT_SCSI_HOST *hd)
3595 unsigned long flags;
3597 /* Flush the pendingQ.
3599 ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name));
3601 spin_lock_irqsave(&hd->freedoneQlock, flags);
3602 if (Q_IS_EMPTY(&hd->pendingQ)) {
3603 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3607 buffer = hd->pendingQ.head;
3612 mf = (MPT_FRAME_HDR *) buffer->argp;
3613 buffer->argp = NULL;
3617 Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
3618 spin_unlock_irqrestore(&hd->freedoneQlock, flags);
3621 /* This should never happen */
3622 printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf);
3626 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
3628 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
3630 u16 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3631 Scsi_Cmnd *sc = hd->ScsiLookup[req_idx];
3632 printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
3633 hd->ioc->name, sc, req_idx, mf);
3641 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3643 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
3646 unsigned long flags;
3648 dtmprintk((KERN_WARNING MYNAM
3649 ": IOC %s_reset routed to SCSI host driver!\n",
3650 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
3651 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
3653 /* If a FW reload request arrives after base installed but
3654 * before all scsi hosts have been attached, then an alt_ioc
3655 * may have a NULL sh pointer.
3657 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
3660 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3662 if (reset_phase == MPT_IOC_SETUP_RESET) {
3663 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
3666 * 1. Set Hard Reset Pending Flag
3667 * All new commands go to doneQ
3669 hd->resetPending = 1;
3671 } else if (reset_phase == MPT_IOC_PRE_RESET) {
3672 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
3674 /* 2. Flush running commands
3675 * Clean drop test code - if compiled
3676 * Clean ScsiLookup (and associated memory)
3680 /* 2a. Drop Test Command.
3683 /* 2b. Reply to OS all known outstanding I/O commands.
3685 mptscsih_flush_running_cmds(hd);
3687 /* 2c. If there was an internal command that
3688 * has not completed, configuration or io request,
3689 * free these resources.
3692 del_timer(&hd->timer);
3693 mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr);
3696 /* 2d. If a task management has not completed,
3697 * free resources associated with this request.
3700 del_timer(&hd->TMtimer);
3701 mpt_free_msg_frame(ScsiTaskCtx, ioc->id, hd->tmPtr);
3704 #ifdef MPTSCSIH_DBG_TIMEOUT
3705 ioc->timeout_hard = 0;
3708 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
3711 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
3713 /* Once a FW reload begins, all new OS commands are
3714 * redirected to the doneQ w/ a reset status.
3715 * Init all control structures.
3718 /* ScsiLookup initialization
3722 for (ii=0; ii < hd->ioc->req_depth; ii++)
3723 hd->ScsiLookup[ii] = NULL;
3726 /* 2. Chain Buffer initialization
3728 mptscsih_initChainBuffers(hd, 0);
3736 /* 4. Renegotiate to all devices, if SCSI
3739 mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
3741 /* 5. Enable new commands to be posted
3743 spin_lock_irqsave(&ioc->FreeQlock, flags);
3745 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3746 hd->resetPending = 0;
3747 hd->numTMrequests = 0;
3748 hd->tmState = TM_STATE_NONE;
3750 /* 6. If there was an internal command,
3751 * wake this process up.
3755 * Wake up the original calling thread
3757 hd->pLocal = &hd->localReply;
3758 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
3759 scandv_wait_done = 1;
3760 wake_up(&scandv_waitq);
3768 /* 8. Set flag to force DV and re-read IOC Page 3
3771 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
3772 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
3775 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
3779 return 1; /* currently means nothing really */
3782 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3784 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
3787 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
3789 dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
3793 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
3796 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
3797 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
3800 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3801 if (hd && (hd->is_spi) && (hd->soft_resets < -1))
3805 case MPI_EVENT_LOGOUT: /* 09 */
3810 * CHECKME! Don't think we need to do
3811 * anything for these, but...
3813 case MPI_EVENT_RESCAN: /* 06 */
3814 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
3815 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
3817 * CHECKME! Falling thru...
3821 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
3822 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3823 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
3824 * if DV disabled. Need to check for target mode.
3828 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3830 if (hd && (hd->is_spi) && (hd->negoNvram == 0)) {
3832 Ioc3PhysDisk_t *pPDisk;
3837 reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
3838 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
3839 /* New or replaced disk.
3840 * Set DV flag and schedule DV.
3842 pSpi = &ioc->spi_data;
3843 physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
3844 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
3845 if (pSpi->pIocPg3) {
3846 pPDisk = pSpi->pIocPg3->PhysDisk;
3847 numPDisk =pSpi->pIocPg3->NumPhysDisks;
3850 if (physDiskNum == pPDisk->PhysDiskNum) {
3851 pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
3852 pSpi->forceDv = MPT_SCSICFG_NEED_DV;
3853 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
3860 if (numPDisk == 0) {
3861 /* The physical disk that needs DV was not found
3862 * in the stored IOC Page 3. The driver must reload
3863 * this page. DV routine will set the NEED_DV flag for
3864 * all phys disks that have DV_NOT_DONE set.
3866 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
3867 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
3874 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
3875 printk("Raid Event RF: ");
3877 u32 *m = (u32 *)pEvReply;
3879 int n = (int)pEvReply->MsgLength;
3880 for (ii=6; ii < n; ii++)
3881 printk(" %08x", le32_to_cpu(m[ii]));
3887 case MPI_EVENT_NONE: /* 00 */
3888 case MPI_EVENT_LOG_DATA: /* 01 */
3889 case MPI_EVENT_STATE_CHANGE: /* 02 */
3890 case MPI_EVENT_EVENT_CHANGE: /* 0A */
3892 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
3896 return 1; /* currently means nothing really */
3899 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3903 static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
3905 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3906 /* old symsense.c stuff... */
3907 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3910 * To protect ourselves against those that would pass us bogus pointers
3912 static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
3913 = { 0x1F, 0x00, 0x00, 0x00,
3914 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3915 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3916 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3917 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3918 static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
3919 = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
3920 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3922 static u8 dummyCDB[16]
3923 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3924 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3925 static u8 dummyScsiData[16]
3926 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3927 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3929 static char *ScsiStatusString[] = {
3932 "CHECK CONDITION", /* 02h */
3934 "CONDITION MET", /* 04h */
3946 "INTERMEDIATE", /* 10h */
3950 "INTERMEDIATE-CONDITION MET", /* 14h */
3954 "RESERVATION CONFLICT", /* 18h */
3964 "COMMAND TERMINATED", /* 22h */
3970 "TASK SET FULL", /* 28h */
3978 "ACA ACTIVE", /* 30h */
3982 static const char *ScsiCommonOpString[] = {
3983 "TEST UNIT READY", /* 00h */
3984 "REZERO UNIT (REWIND)", /* 01h */
3986 "REQUEST_SENSE", /* 03h */
3987 "FORMAT UNIT (MEDIUM)", /* 04h */
3988 "READ BLOCK LIMITS", /* 05h */
3990 "REASSIGN BLOCKS", /* 07h */
3991 "READ(6)", /* 08h */
3993 "WRITE(6)", /* 0Ah */
3994 "SEEK(6)", /* 0Bh */
3998 "READ REVERSE", /* 0Fh */
3999 "WRITE_FILEMARKS", /* 10h */
4000 "SPACE(6)", /* 11h */
4001 "INQUIRY", /* 12h */
4005 static const char *SenseKeyString[] = {
4006 "NO SENSE", /* 0h */
4007 "RECOVERED ERROR", /* 1h */
4008 "NOT READY", /* 2h */
4009 "MEDIUM ERROR", /* 3h */
4010 "HARDWARE ERROR", /* 4h */
4011 "ILLEGAL REQUEST", /* 5h */
4012 "UNIT ATTENTION", /* 6h */
4013 "DATA PROTECT", /* 7h */
4014 "BLANK CHECK", /* 8h */
4015 "VENDOR-SPECIFIC", /* 9h */
4016 "ABORTED COPY", /* Ah */
4017 "ABORTED COMMAND", /* Bh */
4018 "EQUAL (obsolete)", /* Ch */
4019 "VOLUME OVERFLOW", /* Dh */
4020 "MISCOMPARE", /* Eh */
4021 "RESERVED", /* Fh */
4025 #define SPECIAL_ASCQ(c,q) \
4026 (((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
4028 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4029 static int dump_cdb(char *foo, unsigned char *cdb)
4031 int i, grpCode, cdbLen;
4034 grpCode = cdb[0] >> 5;
4037 else if (grpCode < 3)
4039 else if (grpCode == 5)
4044 for (i=0; i < cdbLen; i++)
4045 l += sprintf(foo+l, " %02X", cdb[i]);
4050 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4051 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4052 /* Do ASC/ASCQ lookup/grindage to English readable string(s) */
4053 static const char * ascq_set_strings_4max(
4055 const char **s1, const char **s2, const char **s3, const char **s4)
4057 static const char *asc_04_part1_string = "LOGICAL UNIT ";
4058 static const char *asc_04_part2a_string = "NOT READY, ";
4059 static const char *asc_04_part2b_string = "IS ";
4060 static const char *asc_04_ascq_NN_part3_strings[] = { /* ASC ASCQ (hex) */
4061 "CAUSE NOT REPORTABLE", /* 04 00 */
4062 "IN PROCESS OF BECOMING READY", /* 04 01 */
4063 "INITIALIZING CMD. REQUIRED", /* 04 02 */
4064 "MANUAL INTERVENTION REQUIRED", /* 04 03 */
4065 /* Add " IN PROGRESS" to all the following... */
4066 "FORMAT", /* 04 04 */
4067 "REBUILD", /* 04 05 */
4068 "RECALCULATION", /* 04 06 */
4069 "OPERATION", /* 04 07 */
4070 "LONG WRITE", /* 04 08 */
4071 "SELF-TEST", /* 04 09 */
4074 static char *asc_04_part4_string = " IN PROGRESS";
4076 static char *asc_29_ascq_NN_strings[] = { /* ASC ASCQ (hex) */
4077 "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED", /* 29 00 */
4078 "POWER ON OCCURRED", /* 29 01 */
4079 "SCSI BUS RESET OCCURRED", /* 29 02 */
4080 "BUS DEVICE RESET FUNCTION OCCURRED", /* 29 03 */
4081 "DEVICE INTERNAL RESET", /* 29 04 */
4082 "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED", /* 29 05 */
4083 "TRANSCEIVER MODE CHANGED TO LVD", /* 29 06 */
4086 static char *ascq_vendor_uniq = "(Vendor Unique)";
4087 static char *ascq_noone = "(no matching ASC/ASCQ description found)";
4090 *s1 = *s2 = *s3 = *s4 = ""; /* set'em all to the empty "" string */
4092 /* CHECKME! Need lock/sem?
4093 * Update and examine for isense module presense.
4095 mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
4097 if (mptscsih_ASCQ_TablePtr == NULL) {
4098 /* 2nd chances... */
4099 if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
4100 *s1 = asc_04_part1_string;
4101 *s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
4102 *s3 = asc_04_ascq_NN_part3_strings[ASCQ];
4103 /* check for " IN PROGRESS" ones */
4105 *s4 = asc_04_part4_string;
4106 } else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
4107 *s1 = asc_29_ascq_NN_strings[ASCQ];
4109 * Else { leave all *s[1-4] values pointing to the empty "" string }
4115 * Need to check ASC here; if it is "special," then
4116 * the ASCQ is variable, and indicates failed component number.
4117 * We must treat the ASCQ as a "don't care" while searching the
4118 * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
4119 * on when we actually need to identify the failed component.
4121 if (SPECIAL_ASCQ(ASC,ASCQ))
4124 /* OK, now search mptscsih_ASCQ_Table[] for a matching entry */
4125 for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
4126 if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) {
4127 *s1 = mptscsih_ASCQ_TablePtr[idx].Description;
4131 if ((ASC >= 0x80) || (ASCQ >= 0x80))
4132 *s1 = ascq_vendor_uniq;
4139 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4141 * SCSI Information Report; desired output format...
4143 SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION)
4144 Key=6h (UNIT ATTENTION); FRU=03h
4145 ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4146 CDB: 00 00 00 00 00 00 - TestUnitReady
4150 * SCSI Error Report; desired output format...
4152 SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
4153 SCSI_Status=02h (CHECK CONDITION)
4154 Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
4155 SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
4156 SenseKey=6h (UNIT ATTENTION); FRU=03h
4157 ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
4161 int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
4167 int sk = SD_Sense_Key(ioop->sensePtr);
4168 const char *skstr = SenseKeyString[sk];
4169 unsigned char asc = SD_ASC(ioop->sensePtr);
4170 unsigned char ascq = SD_ASCQ(ioop->sensePtr);
4173 /* Change the error logging to only report errors on
4174 * read and write commands. Ignore errors on other commands.
4175 * Should this be configurable via proc?
4177 switch (ioop->cdbPtr[0]) {
4193 * Filter out common, repetitive, warning-type errors... like:
4194 * POWER ON (06,29/00 or 06,29/01),
4195 * SPINNING UP (02,04/01),
4196 * LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
4198 if (sk == SK_NO_SENSE) {
4202 if ( (sk==SK_UNIT_ATTENTION && asc==0x29 && (ascq==0x00 || ascq==0x01))
4203 || (sk==SK_NOT_READY && asc==0x04 && (ascq==0x01 || ascq==0x02))
4204 || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
4211 /* Prevent the system from continually writing to the log
4212 * if a medium is not found: 02 3A 00
4213 * Changer issues: TUR, Read Capacity, Table of Contents continually
4215 if (sk==SK_NOT_READY && asc==0x3A) {
4216 if (ioop->cdbPtr == NULL) {
4218 } else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
4219 (ioop->cdbPtr[0] == CMD_ReadCapacity) ||
4220 (ioop->cdbPtr[0] == 0x43)) {
4224 if (sk==SK_UNIT_ATTENTION) {
4225 if (ioop->cdbPtr == NULL)
4227 else if (ioop->cdbPtr[0] == CMD_TestUnitReady)
4232 * Protect ourselves...
4234 if (ioop->cdbPtr == NULL)
4235 ioop->cdbPtr = dummyCDB;
4236 if (ioop->sensePtr == NULL)
4237 ioop->sensePtr = dummySenseData;
4238 if (ioop->inqPtr == NULL)
4239 ioop->inqPtr = dummyInqData;
4240 if (ioop->dataPtr == NULL)
4241 ioop->dataPtr = dummyScsiData;
4244 if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
4245 ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
4246 (void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
4251 if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
4252 opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
4253 else if (mpt_ScsiOpcodesPtr)
4254 opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
4256 l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n",
4260 l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh",
4261 sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
4263 const char *x1, *x2, *x3, *x4;
4264 x1 = x2 = x3 = x4 = "";
4265 x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
4268 l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
4270 l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
4273 l += sprintf(foo+l, "\n CDB:");
4274 l += dump_cdb(foo+l, ioop->cdbPtr);
4276 l += sprintf(foo+l, " - \"%s\"", opstr);
4277 l += sprintf(foo+l, "\n");
4279 PrintF(("%s\n", foo));
4284 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4286 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4288 * mptscsih_initTarget - Target, LUN alloc/free functionality.
4289 * @hd: Pointer to MPT_SCSI_HOST structure
4290 * @bus_id: Bus number (?)
4291 * @target_id: SCSI target id
4293 * @data: Pointer to data
4294 * @dlen: Number of INQUIRY bytes
4296 * NOTE: It's only SAFE to call this routine if data points to
4297 * sane & valid STANDARD INQUIRY data!
4299 * Allocate and initialize memory for this target.
4300 * Save inquiry data.
4304 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
4306 int indexed_lun, lun_index;
4310 dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
4311 hd->ioc->name, bus_id, target_id, lun, hd));
4313 /* Is LUN supported? If so, upper 3 bits will be 0
4314 * in first byte of inquiry data.
4319 vdev = hd->Targets[target_id];
4321 lun_index = (lun >> 5); /* 32 luns per lun_index */
4322 indexed_lun = (lun % 32);
4323 vdev->luns[lun_index] |= (1 << indexed_lun);
4325 vdev->raidVolume = 0;
4327 if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
4328 vdev->raidVolume = 1;
4329 ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
4333 if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
4335 memcpy (vdev->inq_data, data, 8);
4337 memcpy (vdev->inq_data, data, dlen);
4339 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4341 /* If LUN 0, tape and have not done DV, set the DV flag.
4343 if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) {
4344 ScsiCfgData *pSpi = &hd->ioc->spi_data;
4345 if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
4346 pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
4349 if ( (data[0] == SCSI_TYPE_PROC) &&
4350 !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
4352 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
4353 if ( data[44] == 'S' &&
4359 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4360 mptscsih_writeIOCPage4(hd, target_id, bus_id);
4363 /* Treat all Processors as SAF-TE if
4364 * command line option is set */
4365 if ( hd->ioc->spi_data.Saf_Te ) {
4366 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
4367 mptscsih_writeIOCPage4(hd, target_id, bus_id);
4374 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
4375 /* Update the target capabilities
4378 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
4381 mptscsih_setTargetNegoParms(hd, vdev, data_56);
4384 dprintk((KERN_INFO " target = %p\n", vdev));
4388 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4390 * Update the target negotiation parameters based on the
4391 * the Inquiry data, adapter capabilities, and NVRAM settings.
4394 void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
4396 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
4397 int id = (int) target->target_id;
4402 u8 width = MPT_NARROW;
4403 u8 factor = MPT_ASYNC;
4405 u8 version, nfactor;
4409 if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
4410 if (target->inq_data[7] & 0x02)
4411 target->tflags |= MPT_TARGET_FLAGS_Q_YES;
4416 target->negoFlags = pspi_data->noQas;
4418 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
4419 * support. If available, default QAS to off and allow enabling.
4420 * If not available, default QAS to on, turn off for non-disks.
4423 /* Set flags based on Inquiry data
4425 if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
4426 version = target->inq_data[2] & 0x07;
4429 factor = MPT_ULTRA2;
4430 offset = pspi_data->maxSyncOffset;
4432 if (target->inq_data[7] & 0x20) {
4436 if (target->inq_data[7] & 0x10) {
4437 /* bits 2 & 3 show DT support
4439 if ((byte56 & 0x04) == 0)
4440 factor = MPT_ULTRA2;
4441 else if ((byte56 & 0x03) == 0)
4442 factor = MPT_ULTRA160;
4444 factor = MPT_ULTRA320;
4445 offset = pspi_data->maxSyncOffset;
4447 /* If RAID, never disable QAS
4448 * else if non RAID, do not disable
4449 * QAS if bit 1 is set
4450 * bit 1 QAS support, non-raid only
4453 if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
4461 if (target->inq_data[7] & 0x02) {
4465 /* Update tflags based on NVRAM settings. (SCSI only)
4467 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4468 nvram = pspi_data->nvram[id];
4469 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
4472 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
4475 /* Ensure factor is set to the
4476 * maximum of: adapter, nvram, inquiry
4479 if (nfactor < pspi_data->minSyncFactor )
4480 nfactor = pspi_data->minSyncFactor;
4482 factor = max(factor, nfactor);
4483 if (factor == MPT_ASYNC)
4494 /* Make sure data is consistent
4496 if ((!width) && (factor < MPT_ULTRA2)) {
4497 factor = MPT_ULTRA2;
4500 /* Save the data to the target structure.
4502 target->minSyncFactor = factor;
4503 target->maxOffset = offset;
4504 target->maxWidth = width;
4506 target->tflags |= MPT_TARGET_FLAGS_Q_YES;
4509 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
4511 /* Disable unused features.
4514 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
4517 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
4519 /* GEM, processor WORKAROUND
4521 if (((target->inq_data[0] & 0x1F) == 0x03)
4522 || ((target->inq_data[0] & 0x1F) > 0x08)) {
4523 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
4524 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
4526 if (noQas && (pspi_data->noQas == 0)) {
4527 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
4528 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4530 /* Disable QAS in a mixed configuration case
4533 // ddvtprintk((KERN_INFO "Disabling QAS!\n"));
4534 for (ii = 0; ii < id; ii++) {
4535 if ( (vdev = hd->Targets[ii]) ) {
4536 vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4546 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4547 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
4548 * Else set the NEED_DV flag after Read Capacity Issued (disks)
4549 * or Mode Sense (cdroms).
4551 * Tapes, initTarget will set this flag on completion of Inquiry command.
4552 * Called only if DV_NOT_DONE flag is set
4554 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
4558 if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
4563 if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
4564 ScsiCfgData *pSpi = &hd->ioc->spi_data;
4565 if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
4566 /* Set NEED_DV for all hidden disks
4568 Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk;
4569 int numPDisk = pSpi->pIocPg3->NumPhysDisks;
4572 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4573 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
4578 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
4579 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
4583 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4585 * If no Target, bus reset on 1st I/O. Set the flag to
4586 * prevent any future negotiations to this device.
4588 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
4591 if ((hd->Targets) && (hd->Targets[target_id] == NULL))
4592 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
4597 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4599 * SCSI Config Page functionality ...
4601 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4602 /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
4603 * based on width, factor and offset parameters.
4605 * @factor: sync factor
4606 * @offset: sync offset
4607 * @requestedPtr: pointer to requested values (updated)
4608 * @configurationPtr: pointer to configuration values (updated)
4609 * @flags: flags to block WDTR or SDTR negotiation
4613 * Remark: Called by writeSDP1 and _dv_params
4616 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
4618 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
4619 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
4621 *configurationPtr = 0;
4622 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
4623 *requestedPtr |= (offset << 16) | (factor << 8);
4625 if (width && offset && !nowide && !nosync) {
4626 if (factor < MPT_ULTRA160) {
4627 *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
4628 if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
4629 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
4630 } else if (factor < MPT_ULTRA2) {
4631 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
4636 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
4639 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
4644 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4645 /* mptscsih_writeSDP1 - write SCSI Device Page 1
4646 * @hd: Pointer to a SCSI Host Strucutre
4647 * @portnum: IOC port number
4648 * @target_id: writeSDP1 for single ID
4649 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
4651 * Return: -EFAULT if read of config page header fails
4654 * Remark: If a target has been found, the settings from the
4655 * target structure are used, else the device is set
4658 * Remark: Called during init and after a FW reload.
4659 * Remark: We do not wait for a return, write pages sequentially.
4662 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
4664 MPT_ADAPTER *ioc = hd->ioc;
4666 SCSIDevicePage1_t *pData;
4667 VirtDevice *pTarget;
4672 u32 requested, configuration, flagsLength;
4674 int id = 0, maxid = 0;
4680 u8 maxwidth, maxoffset, maxfactor;
4682 if (ioc->spi_data.sdp1length == 0)
4685 if (flags & MPT_SCSICFG_ALL_IDS) {
4687 maxid = ioc->sh->max_id - 1;
4688 } else if (ioc->sh) {
4690 maxid = min_t(int, id, ioc->sh->max_id - 1);
4693 for (; id <= maxid; id++) {
4695 if (id == ioc->pfacts[portnum].PortSCSIID)
4698 /* Use NVRAM to get adapter and target maximums
4699 * Data over-riden by target structure information, if present
4701 maxwidth = ioc->spi_data.maxBusWidth;
4702 maxoffset = ioc->spi_data.maxSyncOffset;
4703 maxfactor = ioc->spi_data.minSyncFactor;
4704 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4705 nvram = ioc->spi_data.nvram[id];
4708 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
4710 if (maxoffset > 0) {
4711 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
4712 if (maxfactor == 0) {
4714 maxfactor = MPT_ASYNC;
4716 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
4717 maxfactor = ioc->spi_data.minSyncFactor;
4720 maxfactor = MPT_ASYNC;
4723 /* Set the negotiation flags.
4725 negoFlags = ioc->spi_data.noQas;
4727 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
4730 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
4732 if (flags & MPT_SCSICFG_USE_NVRAM) {
4741 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
4744 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4745 /* Force to async and narrow if DV has not been executed
4748 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
4755 /* If id is not a raid volume, get the updated
4756 * transmission settings from the target structure.
4758 if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
4759 width = pTarget->maxWidth;
4760 factor = pTarget->minSyncFactor;
4761 offset = pTarget->maxOffset;
4762 negoFlags = pTarget->negoFlags;
4765 if (flags & MPT_SCSICFG_BLK_NEGO)
4766 negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
4768 mptscsih_setDevicePage1Flags(width, factor, offset,
4769 &requested, &configuration, negoFlags);
4771 /* Get a MF for this command.
4773 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
4774 dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
4779 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
4780 hd->ioc->name, mf, id, requested, configuration));
4783 /* Set the request and the data pointers.
4784 * Request takes: 36 bytes (32 bit SGE)
4785 * SCSI Device Page 1 requires 16 bytes
4786 * 40 + 16 <= size of SCSI IO Request = 56 bytes
4787 * and MF size >= 64 bytes.
4788 * Place data at end of MF.
4790 pReq = (Config_t *)mf;
4792 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
4793 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
4795 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
4796 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
4798 /* Complete the request frame (same for all requests).
4800 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4802 pReq->ChainOffset = 0;
4803 pReq->Function = MPI_FUNCTION_CONFIG;
4804 pReq->ExtPageLength = 0;
4805 pReq->ExtPageType = 0;
4807 for (ii=0; ii < 8; ii++) {
4808 pReq->Reserved2[ii] = 0;
4810 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
4811 pReq->Header.PageLength = ioc->spi_data.sdp1length;
4812 pReq->Header.PageNumber = 1;
4813 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4814 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
4816 /* Add a SGE to the config request.
4818 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
4820 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
4822 /* Set up the common data portion
4824 pData->Header.PageVersion = pReq->Header.PageVersion;
4825 pData->Header.PageLength = pReq->Header.PageLength;
4826 pData->Header.PageNumber = pReq->Header.PageNumber;
4827 pData->Header.PageType = pReq->Header.PageType;
4828 pData->RequestedParameters = cpu_to_le32(requested);
4829 pData->Reserved = 0;
4830 pData->Configuration = cpu_to_le32(configuration);
4832 dprintk((MYIOC_s_INFO_FMT
4833 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
4834 ioc->name, id, (id | (bus<<8)),
4835 requested, configuration));
4837 mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
4843 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4844 /* mptscsih_writeIOCPage4 - write IOC Page 4
4845 * @hd: Pointer to a SCSI Host Structure
4846 * @target_id: write IOC Page4 for this ID & Bus
4848 * Return: -EAGAIN if unable to obtain a Message Frame
4851 * Remark: We do not wait for a return, write pages sequentially.
4854 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
4856 MPT_ADAPTER *ioc = hd->ioc;
4858 IOCPage4_t *IOCPage4Ptr;
4866 /* Get a MF for this command.
4868 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc->id)) == NULL) {
4869 dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
4874 ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n",
4875 ioc->name, mf, target_id));
4877 /* Set the request and the data pointers.
4878 * Place data at end of MF.
4880 pReq = (Config_t *)mf;
4882 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
4883 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
4885 /* Complete the request frame (same for all requests).
4887 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4889 pReq->ChainOffset = 0;
4890 pReq->Function = MPI_FUNCTION_CONFIG;
4891 pReq->ExtPageLength = 0;
4892 pReq->ExtPageType = 0;
4894 for (ii=0; ii < 8; ii++) {
4895 pReq->Reserved2[ii] = 0;
4898 IOCPage4Ptr = ioc->spi_data.pIocPg4;
4899 dataDma = ioc->spi_data.IocPg4_dma;
4900 ii = IOCPage4Ptr->ActiveSEP++;
4901 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
4902 IOCPage4Ptr->SEP[ii].SEPBus = bus;
4903 pReq->Header = IOCPage4Ptr->Header;
4904 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
4906 /* Add a SGE to the config request.
4908 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
4909 (IOCPage4Ptr->Header.PageLength + ii) * 4;
4911 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
4913 dsprintk((MYIOC_s_INFO_FMT
4914 "writeIOCPage4: pgaddr 0x%x\n",
4915 ioc->name, (target_id | (bus<<8))));
4917 mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
4922 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4923 /* mptscsih_taskmgmt_timeout - Call back for timeout on a
4924 * task management request.
4925 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
4928 static void mptscsih_taskmgmt_timeout(unsigned long data)
4930 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
4932 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
4933 "TM request timed out!\n", hd->ioc->name));
4935 /* Delete the timer that triggered this callback.
4936 * Remark: del_timer checks to make sure timer is active
4939 del_timer(&hd->TMtimer);
4941 /* Call the reset handler. Already had a TM request
4942 * timeout - so issue a diagnostic reset
4944 MPT_INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
4945 SCHEDULE_TASK(&mptscsih_rstTask);
4949 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4950 /* mptscsih_schedule_reset - Call back for timeout on a
4951 * task management request.
4952 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
4956 mptscsih_schedule_reset(void *arg)
4959 hd = (MPT_SCSI_HOST *) arg;
4961 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
4962 printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
4964 /* Because we have reset the IOC, no TM requests can be
4965 * pending. So let's make sure the tmPending flag is reset.
4967 dtmprintk((KERN_WARNING MYNAM
4968 ": %s: mptscsih_taskmgmt_timeout\n",
4976 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4978 * Bus Scan and Domain Validation functionality ...
4981 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4983 * mptscsih_scandv_complete - Scan and DV callback routine registered
4984 * to Fustion MPT (base) driver.
4986 * @ioc: Pointer to MPT_ADAPTER structure
4987 * @mf: Pointer to original MPT request frame
4988 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
4990 * This routine is called from mpt.c::mpt_interrupt() at the completion
4991 * of any SCSI IO request.
4992 * This routine is registered with the Fusion MPT (base) driver at driver
4993 * load/init time via the mpt_register() API call.
4995 * Returns 1 indicating alloc'd request frame ptr should be freed.
4997 * Remark: Sets a completion code and (possibly) saves sense data
4998 * in the IOC member localReply structure.
4999 * Used ONLY for DV and other internal commands.
5002 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
5005 SCSIIORequest_t *pReq;
5010 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
5011 printk(MYIOC_s_ERR_FMT
5012 "ScanDvComplete, %s req frame ptr! (=%p)\n",
5013 ioc->name, mf?"BAD":"NULL", (void *) mf);
5017 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
5018 del_timer(&hd->timer);
5019 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5020 hd->ScsiLookup[req_idx] = NULL;
5021 pReq = (SCSIIORequest_t *) mf;
5023 if (mf != hd->cmdPtr) {
5024 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
5025 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
5029 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
5030 hd->ioc->name, mf, mr, req_idx));
5032 hd->pLocal = &hd->localReply;
5033 hd->pLocal->scsiStatus = 0;
5035 /* If target struct exists, clear sense valid flag.
5038 completionCode = MPT_SCANDV_GOOD;
5040 SCSIIOReply_t *pReply;
5043 pReply = (SCSIIOReply_t *) mr;
5045 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
5047 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
5048 status, pReply->SCSIState, pReply->SCSIStatus,
5049 le32_to_cpu(pReply->IOCLogInfo)));
5053 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
5054 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
5057 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
5058 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
5059 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
5060 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
5061 completionCode = MPT_SCANDV_DID_RESET;
5064 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
5065 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
5066 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
5067 if (pReply->Function == MPI_FUNCTION_CONFIG) {
5068 ConfigReply_t *pr = (ConfigReply_t *)mr;
5069 completionCode = MPT_SCANDV_GOOD;
5070 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
5071 hd->pLocal->header.PageLength = pr->Header.PageLength;
5072 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
5073 hd->pLocal->header.PageType = pr->Header.PageType;
5075 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
5076 /* If the RAID Volume request is successful,
5077 * return GOOD, else indicate that
5078 * some type of error occurred.
5080 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
5081 if (pr->ActionStatus == MPI_RAID_ACTION_ASTATUS_SUCCESS)
5082 completionCode = MPT_SCANDV_GOOD;
5084 completionCode = MPT_SCANDV_SOME_ERROR;
5086 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
5090 /* save sense data in global structure
5092 completionCode = MPT_SCANDV_SENSE;
5093 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5094 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
5095 (req_idx * MPT_SENSE_BUFFER_ALLOC));
5097 sz = min_t(int, pReq->SenseBufferLength,
5098 SCSI_STD_SENSE_BYTES);
5099 memcpy(hd->pLocal->sense, sense_data, sz);
5101 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
5103 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
5104 if (pReq->CDB[0] == CMD_Inquiry)
5105 completionCode = MPT_SCANDV_ISSUE_SENSE;
5107 completionCode = MPT_SCANDV_DID_RESET;
5109 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
5110 completionCode = MPT_SCANDV_DID_RESET;
5111 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5112 completionCode = MPT_SCANDV_DID_RESET;
5114 /* If no error, this will be equivalent
5115 * to MPT_SCANDV_GOOD
5117 completionCode = MPT_SCANDV_GOOD;
5118 hd->pLocal->scsiStatus = pReply->SCSIStatus;
5122 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
5123 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
5124 completionCode = MPT_SCANDV_DID_RESET;
5126 completionCode = MPT_SCANDV_SOME_ERROR;
5130 completionCode = MPT_SCANDV_SOME_ERROR;
5133 } /* switch(status) */
5135 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
5137 } /* end of address reply case */
5139 hd->pLocal->completion = completionCode;
5141 /* MF and RF are freed in mpt_interrupt
5144 /* Free Chain buffers (will never chain) in scan or dv */
5145 //mptscsih_freeChainBuffers(hd, req_idx);
5148 * Wake up the original calling thread
5150 scandv_wait_done = 1;
5151 wake_up(&scandv_waitq);
5156 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5157 /* mptscsih_timer_expired - Call back for timer process.
5158 * Used only for dv functionality.
5159 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
5162 static void mptscsih_timer_expired(unsigned long data)
5164 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
5166 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
5169 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
5171 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
5172 /* Desire to issue a task management request here.
5173 * TM requests MUST be single threaded.
5174 * If old eh code and no TM current, issue request.
5175 * If new eh code, do nothing. Wait for OS cmd timeout
5178 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
5180 /* Perform a FW reload */
5181 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
5182 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
5186 /* This should NEVER happen */
5187 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
5190 /* No more processing.
5191 * TM call will generate an interrupt for SCSI TM Management.
5192 * The FW will reply to all outstanding commands, callback will finish cleanup.
5193 * Hard reset clean-up will free all resources.
5195 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
5200 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
5201 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5202 /* mptscsih_do_raid - Format and Issue a RAID volume request message.
5203 * @hd: Pointer to scsi host structure
5204 * @action: What do be done.
5205 * @id: Logical target id.
5206 * @bus: Target locations bus.
5208 * Returns: < 0 on a fatal error
5211 * Remark: Wait to return until reply processed by the ISR.
5214 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
5216 MpiRaidActionRequest_t *pReq;
5220 in_isr = in_interrupt();
5222 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
5227 /* Get and Populate a free Frame
5229 if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
5230 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
5234 pReq = (MpiRaidActionRequest_t *)mf;
5235 pReq->Action = action;
5236 pReq->Reserved1 = 0;
5237 pReq->ChainOffset = 0;
5238 pReq->Function = MPI_FUNCTION_RAID_ACTION;
5239 pReq->VolumeID = io->id;
5240 pReq->VolumeBus = io->bus;
5241 pReq->PhysDiskNum = io->physDiskNum;
5243 pReq->Reserved2 = 0;
5244 pReq->ActionDataWord = 0; /* Reserved for this action */
5245 //pReq->ActionDataSGE = 0;
5247 mpt_add_sge((char *)&pReq->ActionDataSGE,
5248 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
5250 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
5251 hd->ioc->name, action, io->id));
5254 hd->timer.expires = jiffies + HZ*2; /* 2 second timeout */
5255 scandv_wait_done = 0;
5257 /* Save cmd pointer, for resource free if timeout or
5262 add_timer(&hd->timer);
5263 mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
5264 wait_event(scandv_waitq, scandv_wait_done);
5266 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
5271 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5273 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5275 * mptscsih_do_cmd - Do internal command.
5276 * @hd: MPT_SCSI_HOST pointer
5277 * @io: INTERNAL_CMD pointer.
5279 * Issue the specified internally generated command and do command
5280 * specific cleanup. For bus scan / DV only.
5281 * NOTES: If command is Inquiry and status is good,
5282 * initialize a target structure, save the data
5284 * Remark: Single threaded access only.
5287 * < 0 if an illegal command or no resources
5291 * > 0 if command complete but some type of completion error.
5294 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
5297 SCSIIORequest_t *pScsiReq;
5298 SCSIIORequest_t ReqCopy;
5299 int my_idx, ii, dir;
5303 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
5306 in_isr = in_interrupt();
5308 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
5314 /* Set command specific information
5319 dir = MPI_SCSIIO_CONTROL_READ;
5325 case CMD_TestUnitReady:
5327 dir = MPI_SCSIIO_CONTROL_READ;
5331 case CMD_StartStopUnit:
5333 dir = MPI_SCSIIO_CONTROL_READ;
5335 CDB[4] = 1; /*Spin up the disk */
5339 case CMD_RequestSense:
5343 dir = MPI_SCSIIO_CONTROL_READ;
5347 case CMD_ReadBuffer:
5349 dir = MPI_SCSIIO_CONTROL_READ;
5351 if (io->flags & MPT_ICFLAG_ECHO) {
5357 if (io->flags & MPT_ICFLAG_BUF_CAP) {
5360 CDB[6] = (io->size >> 16) & 0xFF;
5361 CDB[7] = (io->size >> 8) & 0xFF;
5362 CDB[8] = io->size & 0xFF;
5366 case CMD_WriteBuffer:
5368 dir = MPI_SCSIIO_CONTROL_WRITE;
5370 if (io->flags & MPT_ICFLAG_ECHO) {
5375 CDB[6] = (io->size >> 16) & 0xFF;
5376 CDB[7] = (io->size >> 8) & 0xFF;
5377 CDB[8] = io->size & 0xFF;
5383 dir = MPI_SCSIIO_CONTROL_READ;
5390 dir = MPI_SCSIIO_CONTROL_READ;
5395 case CMD_SynchronizeCache:
5397 dir = MPI_SCSIIO_CONTROL_READ;
5399 // CDB[1] = 0x02; /* set immediate bit */
5408 /* Get and Populate a free Frame
5410 if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc->id)) == NULL) {
5411 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
5416 pScsiReq = (SCSIIORequest_t *) mf;
5418 /* Get the request index */
5419 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
5420 ADD_INDEX_LOG(my_idx); /* for debug */
5422 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
5423 pScsiReq->TargetID = io->physDiskNum;
5425 pScsiReq->ChainOffset = 0;
5426 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
5428 pScsiReq->TargetID = io->id;
5429 pScsiReq->Bus = io->bus;
5430 pScsiReq->ChainOffset = 0;
5431 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
5434 pScsiReq->CDBLength = cmdLen;
5435 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
5437 pScsiReq->Reserved = 0;
5439 pScsiReq->MsgFlags = mpt_msg_flags();
5440 /* MsgContext set in mpt_get_msg_fram call */
5442 for (ii=0; ii < 8; ii++)
5443 pScsiReq->LUN[ii] = 0;
5444 pScsiReq->LUN[1] = io->lun;
5446 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
5447 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
5449 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
5451 if (cmd == CMD_RequestSense) {
5452 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
5453 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
5454 hd->ioc->name, cmd));
5457 for (ii=0; ii < 16; ii++)
5458 pScsiReq->CDB[ii] = CDB[ii];
5460 pScsiReq->DataLength = cpu_to_le32(io->size);
5461 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
5462 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
5464 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
5465 hd->ioc->name, cmd, io->bus, io->id, io->lun));
5467 if (dir == MPI_SCSIIO_CONTROL_READ) {
5468 mpt_add_sge((char *) &pScsiReq->SGL,
5469 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
5472 mpt_add_sge((char *) &pScsiReq->SGL,
5473 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
5477 /* The ISR will free the request frame, but we need
5478 * the information to initialize the target. Duplicate.
5480 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
5482 /* Issue this command after:
5485 * Wait until the reply has been received
5486 * ScsiScanDvCtx callback function will
5488 * set scandv_wait_done and call wake_up
5491 hd->timer.expires = jiffies + HZ*cmdTimeout;
5492 scandv_wait_done = 0;
5494 /* Save cmd pointer, for resource free if timeout or
5499 add_timer(&hd->timer);
5500 mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
5501 wait_event(scandv_waitq, scandv_wait_done);
5504 rc = hd->pLocal->completion;
5505 hd->pLocal->skip = 0;
5507 /* Always set fatal error codes in some cases.
5509 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
5511 else if (rc == MPT_SCANDV_SOME_ERROR)
5515 /* This should never happen. */
5516 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
5523 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5525 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
5526 * @hd: Pointer to MPT_SCSI_HOST structure
5527 * @portnum: IOC port number
5529 * Uses the ISR, but with special processing.
5530 * MUST be single-threaded.
5532 * Return: 0 on completion
5535 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
5537 MPT_ADAPTER *ioc= hd->ioc;
5538 VirtDevice *pTarget;
5539 SCSIDevicePage1_t *pcfg1Data = NULL;
5542 dma_addr_t cfg1_dma_addr = -1;
5543 ConfigPageHeader_t header1;
5547 int indexed_lun, lun_index;
5548 int hostId = ioc->pfacts[portnum].PortSCSIID;
5550 int requested, configuration, data;
5554 max_id = ioc->sh->max_id - 1;
5556 /* Following parameters will not change
5559 iocmd.cmd = CMD_SynchronizeCache;
5561 iocmd.physDiskNum = -1;
5563 iocmd.data_dma = -1;
5565 iocmd.rsvd = iocmd.rsvd2 = 0;
5569 if (hd->Targets == NULL)
5577 /* Write SDP1 for all SCSI devices
5578 * Alloc memory and set up config buffer
5581 if (ioc->spi_data.sdp1length > 0) {
5582 pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
5583 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
5585 if (pcfg1Data != NULL) {
5587 header1.PageVersion = ioc->spi_data.sdp1version;
5588 header1.PageLength = ioc->spi_data.sdp1length;
5589 header1.PageNumber = 1;
5590 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
5592 cfg.physAddr = cfg1_dma_addr;
5593 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5600 /* loop through all devices on this port
5602 while (bus < MPT_MAX_BUS) {
5605 pTarget = hd->Targets[(int)id];
5609 /* Set the negotiation flags */
5610 if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
5611 flags = pTarget->negoFlags;
5613 flags = hd->ioc->spi_data.noQas;
5614 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5615 data = hd->ioc->spi_data.nvram[id];
5617 if (data & MPT_NVRAM_WIDE_DISABLE)
5618 flags |= MPT_TARGET_NO_NEGO_WIDE;
5620 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5621 if ((factor == 0) || (factor == MPT_ASYNC))
5622 flags |= MPT_TARGET_NO_NEGO_SYNC;
5626 /* Force to async, narrow */
5627 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
5628 &configuration, flags);
5629 pcfg1Data->RequestedParameters = le32_to_cpu(requested);
5630 pcfg1Data->Reserved = 0;
5631 pcfg1Data->Configuration = le32_to_cpu(configuration);
5632 cfg.pageAddr = (bus<<8) | id;
5633 mpt_config(hd->ioc, &cfg);
5636 /* If target Ptr NULL or if this target is NOT a disk, skip.
5638 if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
5639 for (lun=0; lun <= MPT_LAST_LUN; lun++) {
5640 /* If LUN present, issue the command
5642 lun_index = (lun >> 5); /* 32 luns per lun_index */
5643 indexed_lun = (lun % 32);
5644 if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
5646 (void) mptscsih_do_cmd(hd, &iocmd);
5651 /* get next relevant device */
5664 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
5670 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
5671 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5673 * mptscsih_domainValidation - Top level handler for domain validation.
5674 * @hd: Pointer to MPT_SCSI_HOST structure.
5676 * Uses the ISR, but with special processing.
5677 * Called from schedule, should not be in interrupt mode.
5678 * While thread alive, do dv for all devices needing dv
5683 mptscsih_domainValidation(void *arg)
5687 unsigned long flags;
5688 int id, maxid, dvStatus, did;
5691 spin_lock_irqsave(&dvtaskQ_lock, flags);
5693 if (dvtaskQ_release) {
5695 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5698 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5700 /* For this ioc, loop through all devices and do dv to each device.
5701 * When complete with this ioc, search through the ioc list, and
5702 * for each scsi ioc found, do dv for all devices. Exit when no
5708 for (ioc = mpt_adapter_find_first(); ioc != NULL; ioc = mpt_adapter_find_next(ioc)) {
5709 spin_lock_irqsave(&dvtaskQ_lock, flags);
5710 if (dvtaskQ_release) {
5712 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5715 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5717 set_current_state(TASK_INTERRUPTIBLE);
5718 schedule_timeout(HZ/4);
5720 /* DV only to SCSI adapters */
5721 if ((int)ioc->chip_type <= (int)FC929)
5724 /* Make sure everything looks ok */
5725 if (ioc->sh == NULL)
5728 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
5732 if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
5733 mpt_read_ioc_pg_3(ioc);
5734 if (ioc->spi_data.pIocPg3) {
5735 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
5736 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
5739 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
5740 ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
5746 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
5749 maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
5751 for (id = 0; id < maxid; id++) {
5752 spin_lock_irqsave(&dvtaskQ_lock, flags);
5753 if (dvtaskQ_release) {
5755 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5758 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5759 dvStatus = hd->ioc->spi_data.dvStatus[id];
5761 if (dvStatus & MPT_SCSICFG_NEED_DV) {
5763 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
5764 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
5766 set_current_state(TASK_INTERRUPTIBLE);
5767 schedule_timeout(HZ/4);
5769 /* If hidden phys disk, block IO's to all
5771 * else, process normally
5773 isPhysDisk = mptscsih_is_phys_disk(ioc, id);
5775 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5776 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
5777 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
5782 if (mptscsih_doDv(hd, 0, id) == 1) {
5783 /* Untagged device was busy, try again
5785 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
5786 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
5788 /* DV is complete. Clear flags.
5790 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
5794 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5795 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
5796 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
5801 /* Post OS IOs that were pended while
5804 post_pendingQ_commands(hd);
5806 if (hd->ioc->spi_data.noQas)
5807 mptscsih_qas_check(hd, id);
5813 spin_lock_irqsave(&dvtaskQ_lock, flags);
5815 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
5820 /* Search IOC page 3 to determine if this is hidden physical disk
5822 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
5824 if (ioc->spi_data.pIocPg3) {
5825 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
5826 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
5829 if (pPDisk->PhysDiskID == id) {
5839 /* Write SDP1 if no QAS has been enabled
5841 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
5843 VirtDevice *pTarget;
5846 if (hd->Targets == NULL)
5849 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
5853 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
5856 pTarget = hd->Targets[ii];
5858 if ((pTarget != NULL) && (!pTarget->raidVolume)) {
5859 if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
5860 pTarget->negoFlags |= hd->ioc->spi_data.noQas;
5861 mptscsih_writeSDP1(hd, 0, ii, 0);
5864 if (mptscsih_is_phys_disk(hd->ioc, ii) == 1)
5865 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
5873 #define MPT_GET_NVRAM_VALS 0x01
5874 #define MPT_UPDATE_MAX 0x02
5875 #define MPT_SET_MAX 0x04
5876 #define MPT_SET_MIN 0x08
5877 #define MPT_FALLBACK 0x10
5878 #define MPT_SAVE 0x20
5880 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5882 * mptscsih_doDv - Perform domain validation to a target.
5883 * @hd: Pointer to MPT_SCSI_HOST structure.
5884 * @portnum: IOC port number.
5885 * @target: Physical ID of this target
5887 * Uses the ISR, but with special processing.
5888 * MUST be single-threaded.
5889 * Test will exit if target is at async & narrow.
5894 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
5896 MPT_ADAPTER *ioc = hd->ioc;
5897 VirtDevice *pTarget;
5898 SCSIDevicePage1_t *pcfg1Data;
5899 SCSIDevicePage0_t *pcfg0Data;
5903 dma_addr_t dvbuf_dma = -1;
5904 dma_addr_t buf1_dma = -1;
5905 dma_addr_t buf2_dma = -1;
5906 dma_addr_t cfg1_dma_addr = -1;
5907 dma_addr_t cfg0_dma_addr = -1;
5908 ConfigPageHeader_t header1;
5909 ConfigPageHeader_t header0;
5916 int dataBufSize = 0;
5917 int echoBufSize = 0;
5922 int nfactor = MPT_ULTRA320;
5924 char doFallback = 0;
5929 if (ioc->spi_data.sdp1length == 0)
5932 if (ioc->spi_data.sdp0length == 0)
5935 /* If multiple buses are used, require that the initiator
5936 * id be the same on all buses.
5938 if (id == ioc->pfacts[0].PortSCSIID)
5942 bus = (u8) bus_number;
5943 ddvtprintk((MYIOC_s_NOTE_FMT
5944 "DV started: bus=%d, id %d dv @ %p\n",
5945 ioc->name, bus, id, &dv));
5947 /* Prep DV structure
5949 memset (&dv, 0, sizeof(DVPARAMETERS));
5952 /* Populate tmax with the current maximum
5953 * transfer parameters for this target.
5954 * Exit if narrow and async.
5956 dv.cmd = MPT_GET_NVRAM_VALS;
5957 mptscsih_dv_parms(hd, &dv, NULL);
5958 if ((!dv.max.width) && (!dv.max.offset))
5961 /* Prep SCSI IO structure
5967 iocmd.physDiskNum = -1;
5968 iocmd.rsvd = iocmd.rsvd2 = 0;
5970 pTarget = hd->Targets[id];
5971 if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
5972 /* Another GEM workaround. Check peripheral device type,
5973 * if PROCESSOR, quit DV.
5975 if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
5976 pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
5981 /* Use tagged commands if possible.
5984 if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
5985 iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
5987 if (hd->ioc->facts.FWVersion.Word < 0x01000600)
5990 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
5991 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
5996 /* Prep cfg structure
5998 cfg.pageAddr = (bus<<8) | id;
6003 header0.PageVersion = ioc->spi_data.sdp0version;
6004 header0.PageLength = ioc->spi_data.sdp0length;
6005 header0.PageNumber = 0;
6006 header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6010 header1.PageVersion = ioc->spi_data.sdp1version;
6011 header1.PageLength = ioc->spi_data.sdp1length;
6012 header1.PageNumber = 1;
6013 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
6015 if (header0.PageLength & 1)
6016 dv_alloc = (header0.PageLength * 4) + 4;
6018 dv_alloc += (2048 + (header1.PageLength * 4));
6020 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
6025 pbuf1 = (u8 *)pDvBuf;
6026 buf1_dma = dvbuf_dma;
6029 pbuf2 = (u8 *) (pDvBuf + sz);
6030 buf2_dma = dvbuf_dma + sz;
6033 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
6034 cfg0_dma_addr = dvbuf_dma + sz;
6035 sz += header0.PageLength * 4;
6039 if (header0.PageLength & 1)
6042 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
6043 cfg1_dma_addr = dvbuf_dma + sz;
6045 /* Skip this ID? Set cfg.hdr to force config page write
6048 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
6049 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6050 /* Set the factor from nvram */
6051 nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
6052 if (nfactor < pspi_data->minSyncFactor )
6053 nfactor = pspi_data->minSyncFactor;
6055 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
6056 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
6058 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
6059 ioc->name, bus, id, lun));
6061 dv.cmd = MPT_SET_MAX;
6062 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6065 /* Save the final negotiated settings to
6066 * SCSI device page 1.
6068 cfg.physAddr = cfg1_dma_addr;
6069 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6071 mpt_config(hd->ioc, &cfg);
6077 /* Finish iocmd inititialization - hidden or visible disk? */
6078 if (ioc->spi_data.pIocPg3) {
6079 /* Searc IOC page 3 for matching id
6081 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
6082 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
6085 if (pPDisk->PhysDiskID == id) {
6087 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
6088 iocmd.physDiskNum = pPDisk->PhysDiskNum;
6092 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
6093 ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
6103 /* RAID Volume ID's may double for a physical device. If RAID but
6104 * not a physical ID as well, skip DV.
6106 if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
6111 * Async & Narrow - Inquiry
6112 * Async & Narrow - Inquiry
6113 * Maximum transfer rate - Inquiry
6115 * If compare, test complete.
6116 * If miscompare and first pass, repeat
6117 * If miscompare and not first pass, fall back and repeat
6121 sz = SCSI_STD_INQUIRY_BYTES;
6122 rc = MPT_SCANDV_GOOD;
6124 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
6126 dv.cmd = MPT_SET_MIN;
6127 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6130 cfg.physAddr = cfg1_dma_addr;
6131 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6133 if (mpt_config(hd->ioc, &cfg) != 0)
6136 /* Wide - narrow - wide workaround case
6138 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
6139 /* Send an untagged command to reset disk Qs corrupted
6140 * when a parity error occurs on a Request Sense.
6142 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
6143 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
6144 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
6146 iocmd.cmd = CMD_RequestSense;
6147 iocmd.data_dma = buf1_dma;
6150 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6153 if (hd->pLocal == NULL)
6155 rc = hd->pLocal->completion;
6156 if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
6166 iocmd.cmd = CMD_Inquiry;
6167 iocmd.data_dma = buf1_dma;
6170 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6173 if (hd->pLocal == NULL)
6175 rc = hd->pLocal->completion;
6176 if (rc == MPT_SCANDV_GOOD) {
6177 if (hd->pLocal->scsiStatus == STS_BUSY) {
6178 if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
6185 } else if (rc == MPT_SCANDV_SENSE) {
6188 /* If first command doesn't complete
6189 * with a good status or with a check condition,
6196 /* Reset the size for disks
6198 inq0 = (*pbuf1) & 0x1F;
6199 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
6204 /* Another GEM workaround. Check peripheral device type,
6205 * if PROCESSOR, quit DV.
6207 if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08))
6210 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6214 if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
6215 && (pTarget->minSyncFactor > 0x09)) {
6216 if ((pbuf1[56] & 0x04) == 0)
6218 else if ((pbuf1[56] & 0x01) == 1) {
6219 pTarget->minSyncFactor =
6220 nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
6222 pTarget->minSyncFactor =
6223 nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
6226 dv.max.factor = pTarget->minSyncFactor;
6228 if ((pbuf1[56] & 0x02) == 0) {
6229 pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
6230 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
6236 dv.cmd = MPT_FALLBACK;
6238 dv.cmd = MPT_SET_MAX;
6240 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6241 if (mpt_config(hd->ioc, &cfg) != 0)
6244 if ((!dv.now.width) && (!dv.now.offset))
6247 iocmd.cmd = CMD_Inquiry;
6248 iocmd.data_dma = buf2_dma;
6251 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6253 else if (hd->pLocal == NULL)
6256 /* Save the return code.
6257 * If this is the first pass,
6258 * read SCSI Device Page 0
6259 * and update the target max parameters.
6261 rc = hd->pLocal->completion;
6263 if (rc == MPT_SCANDV_GOOD) {
6269 cfg.physAddr = cfg0_dma_addr;
6270 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
6273 if (mpt_config(hd->ioc, &cfg) != 0)
6276 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
6277 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
6279 /* Quantum and Fujitsu workarounds.
6280 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
6281 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
6282 * Resetart with a request for U160.
6284 if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
6287 dv.cmd = MPT_UPDATE_MAX;
6288 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
6289 /* Update the SCSI device page 1 area
6291 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
6296 /* Quantum workaround. Restart this test will the fallback
6299 if (doFallback == 0) {
6300 if (memcmp(pbuf1, pbuf2, sz) != 0) {
6304 break; /* test complete */
6308 } else if (rc == MPT_SCANDV_ISSUE_SENSE)
6309 doFallback = 1; /* set fallback flag */
6310 else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE))
6311 doFallback = 1; /* set fallback flag */
6318 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
6319 inq0 = (*pbuf1) & 0x1F;
6321 /* Continue only for disks
6326 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
6329 /* Start the Enhanced Test.
6330 * 0) issue TUR to clear out check conditions
6331 * 1) read capacity of echo (regular) buffer
6333 * 3) do write-read-compare data pattern test
6335 * 5) update nego parms to target struct
6338 cfg.physAddr = cfg1_dma_addr;
6339 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6342 iocmd.cmd = CMD_TestUnitReady;
6343 iocmd.data_dma = -1;
6348 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6351 if (hd->pLocal == NULL)
6354 rc = hd->pLocal->completion;
6355 if (rc == MPT_SCANDV_GOOD)
6357 else if (rc == MPT_SCANDV_SENSE) {
6358 u8 skey = hd->pLocal->sense[2] & 0x0F;
6359 u8 asc = hd->pLocal->sense[12];
6360 u8 ascq = hd->pLocal->sense[13];
6361 ddvprintk((MYIOC_s_INFO_FMT
6362 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6363 ioc->name, skey, asc, ascq));
6365 if (skey == SK_UNIT_ATTENTION)
6366 notDone++; /* repeat */
6367 else if ((skey == SK_NOT_READY) &&
6368 (asc == 0x04)&&(ascq == 0x01)) {
6369 /* wait then repeat */
6372 } else if ((skey == SK_NOT_READY) && (asc == 0x3A)) {
6373 /* no medium, try read test anyway */
6376 /* All other errors are fatal.
6378 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
6386 iocmd.cmd = CMD_ReadBuffer;
6387 iocmd.data_dma = buf1_dma;
6390 iocmd.flags |= MPT_ICFLAG_BUF_CAP;
6394 for (patt = 0; patt < 2; patt++) {
6396 iocmd.flags |= MPT_ICFLAG_ECHO;
6398 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6404 /* If not ready after 8 trials,
6405 * give up on this device.
6410 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6412 else if (hd->pLocal == NULL)
6415 rc = hd->pLocal->completion;
6416 ddvprintk(("ReadBuffer Comp Code %d", rc));
6417 ddvprintk((" buff: %0x %0x %0x %0x\n",
6418 pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
6420 if (rc == MPT_SCANDV_GOOD) {
6422 if (iocmd.flags & MPT_ICFLAG_ECHO) {
6423 bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
6425 bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
6427 } else if (rc == MPT_SCANDV_SENSE) {
6428 u8 skey = hd->pLocal->sense[2] & 0x0F;
6429 u8 asc = hd->pLocal->sense[12];
6430 u8 ascq = hd->pLocal->sense[13];
6431 ddvprintk((MYIOC_s_INFO_FMT
6432 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6433 ioc->name, skey, asc, ascq));
6434 if (skey == SK_ILLEGAL_REQUEST) {
6436 } else if (skey == SK_UNIT_ATTENTION) {
6437 notDone++; /* repeat */
6438 } else if ((skey == SK_NOT_READY) &&
6439 (asc == 0x04)&&(ascq == 0x01)) {
6440 /* wait then repeat */
6444 /* All other errors are fatal.
6446 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
6451 /* All other errors are fatal
6458 if (iocmd.flags & MPT_ICFLAG_ECHO)
6459 echoBufSize = bufsize;
6461 dataBufSize = bufsize;
6464 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
6466 /* Use echo buffers if possible,
6467 * Exit if both buffers are 0.
6469 if (echoBufSize > 0) {
6470 iocmd.flags |= MPT_ICFLAG_ECHO;
6471 if (dataBufSize > 0)
6472 bufsize = min(echoBufSize, dataBufSize);
6474 bufsize = echoBufSize;
6475 } else if (dataBufSize == 0)
6478 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
6479 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
6481 /* Data buffers for write-read-compare test max 1K.
6483 sz = min(bufsize, 1024);
6486 * On first pass, always issue a reserve.
6487 * On additional loops, only if a reset has occurred.
6488 * iocmd.flags indicates if echo or regular buffer
6490 for (patt = 0; patt < 4; patt++) {
6491 ddvprintk(("Pattern %d\n", patt));
6492 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
6493 iocmd.cmd = CMD_TestUnitReady;
6494 iocmd.data_dma = -1;
6497 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6500 iocmd.cmd = CMD_Release6;
6501 iocmd.data_dma = -1;
6504 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6506 else if (hd->pLocal == NULL)
6509 rc = hd->pLocal->completion;
6510 ddvprintk(("Release rc %d\n", rc));
6511 if (rc == MPT_SCANDV_GOOD)
6512 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6516 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6518 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
6521 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
6522 iocmd.cmd = CMD_Reserve6;
6523 iocmd.data_dma = -1;
6526 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6528 else if (hd->pLocal == NULL)
6531 rc = hd->pLocal->completion;
6532 if (rc == MPT_SCANDV_GOOD) {
6533 iocmd.flags |= MPT_ICFLAG_RESERVED;
6534 } else if (rc == MPT_SCANDV_SENSE) {
6535 /* Wait if coming ready
6537 u8 skey = hd->pLocal->sense[2] & 0x0F;
6538 u8 asc = hd->pLocal->sense[12];
6539 u8 ascq = hd->pLocal->sense[13];
6540 ddvprintk((MYIOC_s_INFO_FMT
6541 "DV: Reserve Failed: ", ioc->name));
6542 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
6545 if ((skey == SK_NOT_READY) && (asc == 0x04)&&
6547 /* wait then repeat */
6551 ddvprintk((MYIOC_s_INFO_FMT
6552 "DV: Reserved Failed.", ioc->name));
6556 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
6563 mptscsih_fillbuf(pbuf1, sz, patt, 1);
6564 iocmd.cmd = CMD_WriteBuffer;
6565 iocmd.data_dma = buf1_dma;
6568 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6570 else if (hd->pLocal == NULL)
6573 rc = hd->pLocal->completion;
6574 if (rc == MPT_SCANDV_GOOD)
6575 ; /* Issue read buffer */
6576 else if (rc == MPT_SCANDV_DID_RESET) {
6577 /* If using echo buffers, reset to data buffers.
6578 * Else do Fallback and restart
6579 * this test (re-issue reserve
6580 * because of bus reset).
6582 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
6583 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6585 dv.cmd = MPT_FALLBACK;
6586 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6588 if (mpt_config(hd->ioc, &cfg) != 0)
6591 if ((!dv.now.width) && (!dv.now.offset))
6595 iocmd.flags |= MPT_ICFLAG_DID_RESET;
6598 } else if (rc == MPT_SCANDV_SENSE) {
6599 /* Restart data test if UA, else quit.
6601 u8 skey = hd->pLocal->sense[2] & 0x0F;
6602 ddvprintk((MYIOC_s_INFO_FMT
6603 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
6604 hd->pLocal->sense[12], hd->pLocal->sense[13]));
6605 if (skey == SK_UNIT_ATTENTION) {
6608 } else if (skey == SK_ILLEGAL_REQUEST) {
6609 if (iocmd.flags & MPT_ICFLAG_ECHO) {
6610 if (dataBufSize >= bufsize) {
6611 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6626 iocmd.cmd = CMD_ReadBuffer;
6627 iocmd.data_dma = buf2_dma;
6630 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6632 else if (hd->pLocal == NULL)
6635 rc = hd->pLocal->completion;
6636 if (rc == MPT_SCANDV_GOOD) {
6637 /* If buffers compare,
6638 * go to next pattern,
6639 * else, do a fallback and restart
6640 * data transfer test.
6642 if (memcmp (pbuf1, pbuf2, sz) == 0) {
6643 ; /* goto next pattern */
6645 /* Miscompare with Echo buffer, go to data buffer,
6646 * if that buffer exists.
6647 * Miscompare with Data buffer, check first 4 bytes,
6648 * some devices return capacity. Exit in this case.
6650 if (iocmd.flags & MPT_ICFLAG_ECHO) {
6651 if (dataBufSize >= bufsize)
6652 iocmd.flags &= ~MPT_ICFLAG_ECHO;
6656 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
6657 /* Argh. Device returning wrong data.
6658 * Quit DV for this device.
6663 /* Had an actual miscompare. Slow down.*/
6664 dv.cmd = MPT_FALLBACK;
6665 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6667 if (mpt_config(hd->ioc, &cfg) != 0)
6670 if ((!dv.now.width) && (!dv.now.offset))
6677 } else if (rc == MPT_SCANDV_DID_RESET) {
6678 /* Do Fallback and restart
6679 * this test (re-issue reserve
6680 * because of bus reset).
6682 dv.cmd = MPT_FALLBACK;
6683 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6685 if (mpt_config(hd->ioc, &cfg) != 0)
6688 if ((!dv.now.width) && (!dv.now.offset))
6691 iocmd.flags |= MPT_ICFLAG_DID_RESET;
6694 } else if (rc == MPT_SCANDV_SENSE) {
6695 /* Restart data test if UA, else quit.
6697 u8 skey = hd->pLocal->sense[2] & 0x0F;
6698 ddvprintk((MYIOC_s_INFO_FMT
6699 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
6700 hd->pLocal->sense[12], hd->pLocal->sense[13]));
6701 if (skey == SK_UNIT_ATTENTION) {
6713 } /* --- end of patt loop ---- */
6716 if (iocmd.flags & MPT_ICFLAG_RESERVED) {
6717 iocmd.cmd = CMD_Release6;
6718 iocmd.data_dma = -1;
6721 if (mptscsih_do_cmd(hd, &iocmd) < 0)
6722 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
6724 else if (hd->pLocal) {
6725 if (hd->pLocal->completion == MPT_SCANDV_GOOD)
6726 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
6728 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
6734 /* Set if cfg1_dma_addr contents is valid
6736 if ((cfg.hdr != NULL) && (retcode == 0)){
6737 /* If disk, not U320, disable QAS
6739 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320))
6740 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
6743 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
6745 /* Double writes to SDP1 can cause problems,
6746 * skip save of the final negotiated settings to
6747 * SCSI device page 1.
6750 cfg.physAddr = cfg1_dma_addr;
6751 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
6753 mpt_config(hd->ioc, &cfg);
6757 /* If this is a RAID Passthrough, enable internal IOs
6759 if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
6760 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
6761 ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
6764 /* Done with the DV scan of the current target
6767 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
6769 ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n",
6775 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
6776 /* mptscsih_dv_parms - perform a variety of operations on the
6777 * parameters used for negotiation.
6778 * @hd: Pointer to a SCSI host.
6779 * @dv: Pointer to a structure that contains the maximum and current
6780 * negotiated parameters.
6783 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
6785 VirtDevice *pTarget;
6786 SCSIDevicePage0_t *pPage0;
6787 SCSIDevicePage1_t *pPage1;
6788 int val = 0, data, configuration;
6797 case MPT_GET_NVRAM_VALS:
6798 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
6800 /* Get the NVRAM values and save in tmax
6801 * If not an LVD bus, the adapter minSyncFactor has been
6802 * already throttled back.
6804 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
6805 width = pTarget->maxWidth;
6806 offset = pTarget->maxOffset;
6807 factor = pTarget->minSyncFactor;
6808 negoFlags = pTarget->negoFlags;
6810 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
6811 data = hd->ioc->spi_data.nvram[id];
6812 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
6813 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
6816 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
6817 if ((factor == 0) || (factor == MPT_ASYNC)){
6828 /* Set the negotiation flags */
6829 negoFlags = hd->ioc->spi_data.noQas;
6831 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
6834 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
6837 /* limit by adapter capabilities */
6838 width = min(width, hd->ioc->spi_data.maxBusWidth);
6839 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
6840 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
6842 /* Check Consistency */
6843 if (offset && (factor < MPT_ULTRA2) && !width)
6844 factor = MPT_ULTRA2;
6846 dv->max.width = width;
6847 dv->max.offset = offset;
6848 dv->max.factor = factor;
6849 dv->max.flags = negoFlags;
6850 ddvprintk((" width %d, factor %x, offset %x flags %x\n",
6851 width, factor, offset, negoFlags));
6854 case MPT_UPDATE_MAX:
6855 ddvprintk((MYIOC_s_NOTE_FMT
6856 "Updating with SDP0 Data: ", hd->ioc->name));
6857 /* Update tmax values with those from Device Page 0.*/
6858 pPage0 = (SCSIDevicePage0_t *) pPage;
6860 val = cpu_to_le32(pPage0->NegotiatedParameters);
6861 dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
6862 dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
6863 dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
6866 dv->now.width = dv->max.width;
6867 dv->now.offset = dv->max.offset;
6868 dv->now.factor = dv->max.factor;
6869 ddvprintk(("width %d, factor %x, offset %x, flags %x\n",
6870 dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
6874 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
6876 /* Set current to the max values. Update the config page.*/
6877 dv->now.width = dv->max.width;
6878 dv->now.offset = dv->max.offset;
6879 dv->now.factor = dv->max.factor;
6880 dv->now.flags = dv->max.flags;
6882 pPage1 = (SCSIDevicePage1_t *)pPage;
6884 mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
6885 dv->now.offset, &val, &configuration, dv->now.flags);
6886 pPage1->RequestedParameters = le32_to_cpu(val);
6887 pPage1->Reserved = 0;
6888 pPage1->Configuration = le32_to_cpu(configuration);
6892 ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n",
6893 dv->now.width, dv->now.factor, dv->now.offset, val, configuration));
6897 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
6899 /* Set page to asynchronous and narrow
6900 * Do not update now, breaks fallback routine. */
6904 negoFlags = dv->max.flags;
6906 pPage1 = (SCSIDevicePage1_t *)pPage;
6908 mptscsih_setDevicePage1Flags (width, factor,
6909 offset, &val, &configuration, negoFlags);
6910 pPage1->RequestedParameters = le32_to_cpu(val);
6911 pPage1->Reserved = 0;
6912 pPage1->Configuration = le32_to_cpu(configuration);
6914 ddvprintk(("width %d, factor %x, offset %x request %x config %x\n",
6915 width, factor, offset, val, configuration));
6919 ddvprintk((MYIOC_s_NOTE_FMT
6920 "Fallback: Start: offset %d, factor %x, width %d \n",
6921 hd->ioc->name, dv->now.offset,
6922 dv->now.factor, dv->now.width));
6923 width = dv->now.width;
6924 offset = dv->now.offset;
6925 factor = dv->now.factor;
6926 if ((offset) && (dv->max.width)) {
6927 if (factor < MPT_ULTRA160)
6928 factor = MPT_ULTRA160;
6929 else if (factor < MPT_ULTRA2) {
6930 factor = MPT_ULTRA2;
6932 } else if ((factor == MPT_ULTRA2) && width) {
6933 factor = MPT_ULTRA2;
6935 } else if (factor < MPT_ULTRA) {
6938 } else if ((factor == MPT_ULTRA) && width) {
6940 } else if (factor < MPT_FAST) {
6943 } else if ((factor == MPT_FAST) && width) {
6946 } else if (factor < MPT_SCSI) {
6949 } else if ((factor == MPT_SCSI) && width) {
6957 } else if (offset) {
6959 if (factor < MPT_ULTRA)
6961 else if (factor < MPT_FAST)
6963 else if (factor < MPT_SCSI)
6974 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
6976 dv->now.width = width;
6977 dv->now.offset = offset;
6978 dv->now.factor = factor;
6979 dv->now.flags = dv->max.flags;
6981 pPage1 = (SCSIDevicePage1_t *)pPage;
6983 mptscsih_setDevicePage1Flags (width, factor, offset, &val,
6984 &configuration, dv->now.flags);
6986 pPage1->RequestedParameters = le32_to_cpu(val);
6987 pPage1->Reserved = 0;
6988 pPage1->Configuration = le32_to_cpu(configuration);
6991 ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n",
6992 dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
6996 ddvprintk((MYIOC_s_NOTE_FMT
6997 "Saving to Target structure: ", hd->ioc->name));
6998 ddvprintk(("offset %d, factor %x, width %d \n",
6999 dv->now.offset, dv->now.factor, dv->now.width));
7001 /* Save these values to target structures
7002 * or overwrite nvram (phys disks only).
7005 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
7006 pTarget->maxWidth = dv->now.width;
7007 pTarget->maxOffset = dv->now.offset;
7008 pTarget->minSyncFactor = dv->now.factor;
7009 pTarget->negoFlags = dv->now.flags;
7011 /* Preserv all flags, use
7012 * read-modify-write algorithm
7014 if (hd->ioc->spi_data.nvram) {
7015 data = hd->ioc->spi_data.nvram[id];
7018 data &= ~MPT_NVRAM_WIDE_DISABLE;
7020 data |= MPT_NVRAM_WIDE_DISABLE;
7022 if (!dv->now.offset)
7025 data &= ~MPT_NVRAM_SYNC_MASK;
7026 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
7028 hd->ioc->spi_data.nvram[id] = data;
7035 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7036 /* mptscsih_fillbuf - fill a buffer with a special data pattern
7037 * cleanup. For bus scan only.
7039 * @buffer: Pointer to data buffer to be filled.
7040 * @size: Number of bytes to fill
7041 * @index: Pattern index
7042 * @width: bus width, 0 (8 bits) or 1 (16 bits)
7045 mptscsih_fillbuf(char *buffer, int size, int index, int width)
7056 /* Pattern: 0000 FFFF 0000 FFFF
7058 for (ii=0; ii < size; ii++, ptr++) {
7065 /* Pattern: 00 FF 00 FF
7067 for (ii=0; ii < size; ii++, ptr++) {
7078 /* Pattern: 5555 AAAA 5555 AAAA 5555
7080 for (ii=0; ii < size; ii++, ptr++) {
7087 /* Pattern: 55 AA 55 AA 55
7089 for (ii=0; ii < size; ii++, ptr++) {
7099 /* Pattern: 00 01 02 03 04 05
7102 for (ii=0; ii < size; ii++, ptr++)
7108 /* Wide Pattern: FFFE 0001 FFFD 0002
7109 * ... 4000 DFFF 8000 EFFF
7112 for (ii=0; ii < size/2; ii++) {
7113 /* Create the base pattern
7116 /* every 64 (0x40) bytes flip the pattern
7117 * since we fill 2 bytes / iteration,
7118 * test for ii = 0x20
7124 *ptr = (char)( (val & 0xFF00) >> 8);
7126 *ptr = (char)(val & 0xFF);
7131 *ptr = (char)( (val & 0xFF00) >> 8);
7133 *ptr = (char)(val & 0xFF);
7139 /* Narrow Pattern: FE 01 FD 02 FB 04
7140 * .. 7F 80 01 FE 02 FD ... 80 7F
7143 for (ii=0; ii < size; ii++, ptr++) {
7144 /* Base pattern - first 32 bytes
7151 *ptr = (char) (~(1 << byte));
7154 /* Flip the pattern every 32 bytes
7163 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
7165 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7166 /* Commandline Parsing routines and defines.
7169 * insmod mptscsih mptscsih="width:1 dv:n factor:0x09 saf-te:1"
7171 * mptscsih=width:1,dv:n,factor:0x8,saf-te:1
7181 static char setup_token[] __initdata =
7186 ; /* DO NOT REMOVE THIS ';' */
7190 #define OPT_MAX_WIDTH 2
7191 #define OPT_MIN_SYNC_FACTOR 3
7192 #define OPT_SAF_TE 4
7194 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7197 get_setup_token(char *p)
7199 char *cur = setup_token;
7203 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7206 if (!strncmp(p, cur, pc - cur))
7213 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7215 mptscsih_setup(char *str)
7222 while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
7234 val = (int) simple_strtoul(pv, &pe, 0);
7236 printk("Found Token: %s, value %x\n", cur, (int)val);
7237 switch (get_setup_token(cur)) {
7239 driver_setup.dv = val;
7243 driver_setup.max_width = val;
7246 case OPT_MIN_SYNC_FACTOR:
7247 driver_setup.min_sync_fac = val;
7251 driver_setup.saf_te = val;
7255 printk("mptscsih_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
7259 if ((cur = strchr(cur, ARG_SEP)) != NULL)
7265 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
7268 module_init(mptscsih_init);
7269 module_exit(mptscsih_exit);