[PATCH] W1: w1_netlink: New init/fini netlink callbacks.
[linux-2.6/verdex.git] / drivers / message / fusion / mptscsih.c
blob4a003dc5fde86084b66cd8316467c3fe1e5f2d57
1 /*
2 * linux/drivers/message/fusion/mptscsih.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
9 */
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
47 #include "linux_compat.h" /* linux-2.6 tweaks */
48 #include <linux/module.h>
49 #include <linux/kernel.h>
50 #include <linux/init.h>
51 #include <linux/errno.h>
52 #include <linux/kdev_t.h>
53 #include <linux/blkdev.h>
54 #include <linux/delay.h> /* for mdelay */
55 #include <linux/interrupt.h> /* needed for in_interrupt() proto */
56 #include <linux/reboot.h> /* notifier code */
57 #include <linux/sched.h>
58 #include <linux/workqueue.h>
60 #include <scsi/scsi.h>
61 #include <scsi/scsi_cmnd.h>
62 #include <scsi/scsi_device.h>
63 #include <scsi/scsi_host.h>
64 #include <scsi/scsi_tcq.h>
66 #include "mptbase.h"
67 #include "mptscsih.h"
69 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
70 #define my_NAME "Fusion MPT SCSI Host driver"
71 #define my_VERSION MPT_LINUX_VERSION_COMMON
72 #define MYNAM "mptscsih"
74 MODULE_AUTHOR(MODULEAUTHOR);
75 MODULE_DESCRIPTION(my_NAME);
76 MODULE_LICENSE("GPL");
78 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
80 typedef struct _BIG_SENSE_BUF {
81 u8 data[MPT_SENSE_BUFFER_ALLOC];
82 } BIG_SENSE_BUF;
84 #define MPT_SCANDV_GOOD (0x00000000) /* must be 0 */
85 #define MPT_SCANDV_DID_RESET (0x00000001)
86 #define MPT_SCANDV_SENSE (0x00000002)
87 #define MPT_SCANDV_SOME_ERROR (0x00000004)
88 #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008)
89 #define MPT_SCANDV_ISSUE_SENSE (0x00000010)
90 #define MPT_SCANDV_FALLBACK (0x00000020)
92 #define MPT_SCANDV_MAX_RETRIES (10)
94 #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */
95 #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */
96 #define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */
97 #define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */
98 #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */
99 #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */
101 typedef struct _internal_cmd {
102 char *data; /* data pointer */
103 dma_addr_t data_dma; /* data dma address */
104 int size; /* transfer size */
105 u8 cmd; /* SCSI Op Code */
106 u8 bus; /* bus number */
107 u8 id; /* SCSI ID (virtual) */
108 u8 lun;
109 u8 flags; /* Bit Field - See above */
110 u8 physDiskNum; /* Phys disk number, -1 else */
111 u8 rsvd2;
112 u8 rsvd;
113 } INTERNAL_CMD;
115 typedef struct _negoparms {
116 u8 width;
117 u8 offset;
118 u8 factor;
119 u8 flags;
120 } NEGOPARMS;
122 typedef struct _dv_parameters {
123 NEGOPARMS max;
124 NEGOPARMS now;
125 u8 cmd;
126 u8 id;
127 u16 pad1;
128 } DVPARAMETERS;
131 * Other private/forward protos...
133 int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
134 static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
135 int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
137 static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
138 SCSIIORequest_t *pReq, int req_idx);
139 static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
140 static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
141 static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
142 static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
143 static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
145 static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
146 static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
148 int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
149 int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
151 static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
152 static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
153 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
154 static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
155 static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
156 static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
157 static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
158 int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
159 static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
160 static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
162 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
163 static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
164 static void mptscsih_domainValidation(void *hd);
165 static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
166 static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
167 static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
168 static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
169 static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
170 #endif
172 void mptscsih_remove(struct pci_dev *);
173 void mptscsih_shutdown(struct pci_dev *);
174 #ifdef CONFIG_PM
175 int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
176 int mptscsih_resume(struct pci_dev *pdev);
177 #endif
179 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
181 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
183 * Domain Validation task structure
185 static DEFINE_SPINLOCK(dvtaskQ_lock);
186 static int dvtaskQ_active = 0;
187 static int dvtaskQ_release = 0;
188 static struct work_struct dvTaskQ_task;
189 #endif
191 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
193 * mptscsih_add_sge - Place a simple SGE at address pAddr.
194 * @pAddr: virtual address for SGE
195 * @flagslength: SGE flags and data transfer length
196 * @dma_addr: Physical address
198 * This routine places a MPT request frame back on the MPT adapter's
199 * FreeQ.
201 static inline void
202 mptscsih_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr)
204 if (sizeof(dma_addr_t) == sizeof(u64)) {
205 SGESimple64_t *pSge = (SGESimple64_t *) pAddr;
206 u32 tmp = dma_addr & 0xFFFFFFFF;
208 pSge->FlagsLength = cpu_to_le32(flagslength);
209 pSge->Address.Low = cpu_to_le32(tmp);
210 tmp = (u32) ((u64)dma_addr >> 32);
211 pSge->Address.High = cpu_to_le32(tmp);
213 } else {
214 SGESimple32_t *pSge = (SGESimple32_t *) pAddr;
215 pSge->FlagsLength = cpu_to_le32(flagslength);
216 pSge->Address = cpu_to_le32(dma_addr);
218 } /* mptscsih_add_sge() */
220 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
222 * mptscsih_add_chain - Place a chain SGE at address pAddr.
223 * @pAddr: virtual address for SGE
224 * @next: nextChainOffset value (u32's)
225 * @length: length of next SGL segment
226 * @dma_addr: Physical address
228 * This routine places a MPT request frame back on the MPT adapter's
229 * FreeQ.
231 static inline void
232 mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
234 if (sizeof(dma_addr_t) == sizeof(u64)) {
235 SGEChain64_t *pChain = (SGEChain64_t *) pAddr;
236 u32 tmp = dma_addr & 0xFFFFFFFF;
238 pChain->Length = cpu_to_le16(length);
239 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
241 pChain->NextChainOffset = next;
243 pChain->Address.Low = cpu_to_le32(tmp);
244 tmp = (u32) ((u64)dma_addr >> 32);
245 pChain->Address.High = cpu_to_le32(tmp);
246 } else {
247 SGEChain32_t *pChain = (SGEChain32_t *) pAddr;
248 pChain->Length = cpu_to_le16(length);
249 pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT | mpt_addr_size();
250 pChain->NextChainOffset = next;
251 pChain->Address = cpu_to_le32(dma_addr);
253 } /* mptscsih_add_chain() */
255 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
257 * mptscsih_getFreeChainBuffer - Function to get a free chain
258 * from the MPT_SCSI_HOST FreeChainQ.
259 * @ioc: Pointer to MPT_ADAPTER structure
260 * @req_idx: Index of the SCSI IO request frame. (output)
262 * return SUCCESS or FAILED
264 static inline int
265 mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
267 MPT_FRAME_HDR *chainBuf;
268 unsigned long flags;
269 int rc;
270 int chain_idx;
272 dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
273 ioc->name));
274 spin_lock_irqsave(&ioc->FreeQlock, flags);
275 if (!list_empty(&ioc->FreeChainQ)) {
276 int offset;
278 chainBuf = list_entry(ioc->FreeChainQ.next, MPT_FRAME_HDR,
279 u.frame.linkage.list);
280 list_del(&chainBuf->u.frame.linkage.list);
281 offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
282 chain_idx = offset / ioc->req_sz;
283 rc = SUCCESS;
284 dsgprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n",
285 ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx));
286 } else {
287 rc = FAILED;
288 chain_idx = MPT_HOST_NO_CHAIN;
289 dfailprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer failed\n",
290 ioc->name));
292 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
294 *retIndex = chain_idx;
295 return rc;
296 } /* mptscsih_getFreeChainBuffer() */
298 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
300 * mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
301 * SCSIIORequest_t Message Frame.
302 * @ioc: Pointer to MPT_ADAPTER structure
303 * @SCpnt: Pointer to scsi_cmnd structure
304 * @pReq: Pointer to SCSIIORequest_t structure
306 * Returns ...
308 static int
309 mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
310 SCSIIORequest_t *pReq, int req_idx)
312 char *psge;
313 char *chainSge;
314 struct scatterlist *sg;
315 int frm_sz;
316 int sges_left, sg_done;
317 int chain_idx = MPT_HOST_NO_CHAIN;
318 int sgeOffset;
319 int numSgeSlots, numSgeThisFrame;
320 u32 sgflags, sgdir, thisxfer = 0;
321 int chain_dma_off = 0;
322 int newIndex;
323 int ii;
324 dma_addr_t v2;
325 u32 RequestNB;
327 sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
328 if (sgdir == MPI_SCSIIO_CONTROL_WRITE) {
329 sgdir = MPT_TRANSFER_HOST_TO_IOC;
330 } else {
331 sgdir = MPT_TRANSFER_IOC_TO_HOST;
334 psge = (char *) &pReq->SGL;
335 frm_sz = ioc->req_sz;
337 /* Map the data portion, if any.
338 * sges_left = 0 if no data transfer.
340 if ( (sges_left = SCpnt->use_sg) ) {
341 sges_left = pci_map_sg(ioc->pcidev,
342 (struct scatterlist *) SCpnt->request_buffer,
343 SCpnt->use_sg,
344 SCpnt->sc_data_direction);
345 if (sges_left == 0)
346 return FAILED;
347 } else if (SCpnt->request_bufflen) {
348 SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,
349 SCpnt->request_buffer,
350 SCpnt->request_bufflen,
351 SCpnt->sc_data_direction);
352 dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",
353 ioc->name, SCpnt, SCpnt->request_bufflen));
354 mptscsih_add_sge((char *) &pReq->SGL,
355 0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,
356 SCpnt->SCp.dma_handle);
358 return SUCCESS;
361 /* Handle the SG case.
363 sg = (struct scatterlist *) SCpnt->request_buffer;
364 sg_done = 0;
365 sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);
366 chainSge = NULL;
368 /* Prior to entering this loop - the following must be set
369 * current MF: sgeOffset (bytes)
370 * chainSge (Null if original MF is not a chain buffer)
371 * sg_done (num SGE done for this MF)
374 nextSGEset:
375 numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );
376 numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;
378 sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;
380 /* Get first (num - 1) SG elements
381 * Skip any SG entries with a length of 0
382 * NOTE: at finish, sg and psge pointed to NEXT data/location positions
384 for (ii=0; ii < (numSgeThisFrame-1); ii++) {
385 thisxfer = sg_dma_len(sg);
386 if (thisxfer == 0) {
387 sg ++; /* Get next SG element from the OS */
388 sg_done++;
389 continue;
392 v2 = sg_dma_address(sg);
393 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
395 sg++; /* Get next SG element from the OS */
396 psge += (sizeof(u32) + sizeof(dma_addr_t));
397 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
398 sg_done++;
401 if (numSgeThisFrame == sges_left) {
402 /* Add last element, end of buffer and end of list flags.
404 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |
405 MPT_SGE_FLAGS_END_OF_BUFFER |
406 MPT_SGE_FLAGS_END_OF_LIST;
408 /* Add last SGE and set termination flags.
409 * Note: Last SGE may have a length of 0 - which should be ok.
411 thisxfer = sg_dma_len(sg);
413 v2 = sg_dma_address(sg);
414 mptscsih_add_sge(psge, sgflags | thisxfer, v2);
416 sg++;
417 psge += (sizeof(u32) + sizeof(dma_addr_t));
419 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
420 sg_done++;
422 if (chainSge) {
423 /* The current buffer is a chain buffer,
424 * but there is not another one.
425 * Update the chain element
426 * Offset and Length fields.
428 mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
429 } else {
430 /* The current buffer is the original MF
431 * and there is no Chain buffer.
433 pReq->ChainOffset = 0;
434 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
435 dsgprintk((MYIOC_s_INFO_FMT
436 "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
437 ioc->RequestNB[req_idx] = RequestNB;
439 } else {
440 /* At least one chain buffer is needed.
441 * Complete the first MF
442 * - last SGE element, set the LastElement bit
443 * - set ChainOffset (words) for orig MF
444 * (OR finish previous MF chain buffer)
445 * - update MFStructPtr ChainIndex
446 * - Populate chain element
447 * Also
448 * Loop until done.
451 dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
452 ioc->name, sg_done));
454 /* Set LAST_ELEMENT flag for last non-chain element
455 * in the buffer. Since psge points at the NEXT
456 * SGE element, go back one SGE element, update the flags
457 * and reset the pointer. (Note: sgflags & thisxfer are already
458 * set properly).
460 if (sg_done) {
461 u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));
462 sgflags = le32_to_cpu(*ptmp);
463 sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;
464 *ptmp = cpu_to_le32(sgflags);
467 if (chainSge) {
468 /* The current buffer is a chain buffer.
469 * chainSge points to the previous Chain Element.
470 * Update its chain element Offset and Length (must
471 * include chain element size) fields.
472 * Old chain element is now complete.
474 u8 nextChain = (u8) (sgeOffset >> 2);
475 sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
476 mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
477 } else {
478 /* The original MF buffer requires a chain buffer -
479 * set the offset.
480 * Last element in this MF is a chain element.
482 pReq->ChainOffset = (u8) (sgeOffset >> 2);
483 RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor) + 1) & 0x03;
484 dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
485 ioc->RequestNB[req_idx] = RequestNB;
488 sges_left -= sg_done;
491 /* NOTE: psge points to the beginning of the chain element
492 * in current buffer. Get a chain buffer.
494 if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED) {
495 dfailprintk((MYIOC_s_INFO_FMT
496 "getFreeChainBuffer FAILED SCSI cmd=%02x (%p)\n",
497 ioc->name, pReq->CDB[0], SCpnt));
498 return FAILED;
501 /* Update the tracking arrays.
502 * If chainSge == NULL, update ReqToChain, else ChainToChain
504 if (chainSge) {
505 ioc->ChainToChain[chain_idx] = newIndex;
506 } else {
507 ioc->ReqToChain[req_idx] = newIndex;
509 chain_idx = newIndex;
510 chain_dma_off = ioc->req_sz * chain_idx;
512 /* Populate the chainSGE for the current buffer.
513 * - Set chain buffer pointer to psge and fill
514 * out the Address and Flags fields.
516 chainSge = (char *) psge;
517 dsgprintk((KERN_INFO " Current buff @ %p (index 0x%x)",
518 psge, req_idx));
520 /* Start the SGE for the next buffer
522 psge = (char *) (ioc->ChainBuffer + chain_dma_off);
523 sgeOffset = 0;
524 sg_done = 0;
526 dsgprintk((KERN_INFO " Chain buff @ %p (index 0x%x)\n",
527 psge, chain_idx));
529 /* Start the SGE for the next buffer
532 goto nextSGEset;
535 return SUCCESS;
536 } /* mptscsih_AddSGE() */
538 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
540 * mptscsih_io_done - Main SCSI IO callback routine registered to
541 * Fusion MPT (base) driver
542 * @ioc: Pointer to MPT_ADAPTER structure
543 * @mf: Pointer to original MPT request frame
544 * @r: Pointer to MPT reply frame (NULL if TurboReply)
546 * This routine is called from mpt.c::mpt_interrupt() at the completion
547 * of any SCSI IO request.
548 * This routine is registered with the Fusion MPT (base) driver at driver
549 * load/init time via the mpt_register() API call.
551 * Returns 1 indicating alloc'd request frame ptr should be freed.
554 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
556 struct scsi_cmnd *sc;
557 MPT_SCSI_HOST *hd;
558 SCSIIORequest_t *pScsiReq;
559 SCSIIOReply_t *pScsiReply;
560 u16 req_idx;
562 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
564 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
565 sc = hd->ScsiLookup[req_idx];
566 if (sc == NULL) {
567 MPIHeader_t *hdr = (MPIHeader_t *)mf;
569 /* Remark: writeSDP1 will use the ScsiDoneCtx
570 * If a SCSI I/O cmd, device disabled by OS and
571 * completion done. Cannot touch sc struct. Just free mem.
573 if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST)
574 printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
575 ioc->name);
577 mptscsih_freeChainBuffers(ioc, req_idx);
578 return 1;
581 sc->result = DID_OK << 16; /* Set default reply as OK */
582 pScsiReq = (SCSIIORequest_t *) mf;
583 pScsiReply = (SCSIIOReply_t *) mr;
585 if((ioc->facts.MsgVersion >= MPI_VERSION_01_05) && pScsiReply){
586 dmfprintk((MYIOC_s_INFO_FMT
587 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d,task-tag=%d)\n",
588 ioc->name, mf, mr, sc, req_idx, pScsiReply->TaskTag));
589 }else{
590 dmfprintk((MYIOC_s_INFO_FMT
591 "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
592 ioc->name, mf, mr, sc, req_idx));
595 if (pScsiReply == NULL) {
596 /* special context reply handling */
598 } else {
599 u32 xfer_cnt;
600 u16 status;
601 u8 scsi_state, scsi_status;
603 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
604 scsi_state = pScsiReply->SCSIState;
605 scsi_status = pScsiReply->SCSIStatus;
606 xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
607 sc->resid = sc->request_bufflen - xfer_cnt;
609 dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
610 "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
611 "resid=%d bufflen=%d xfer_cnt=%d\n",
612 ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
613 status, scsi_state, scsi_status, sc->resid,
614 sc->request_bufflen, xfer_cnt));
616 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
617 mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
620 * Look for + dump FCP ResponseInfo[]!
622 if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
623 printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n",
624 le32_to_cpu(pScsiReply->ResponseInfo));
627 switch(status) {
628 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
629 /* CHECKME!
630 * Maybe: DRIVER_BUSY | SUGGEST_RETRY | DID_SOFT_ERROR (retry)
631 * But not: DID_BUS_BUSY lest one risk
632 * killing interrupt handler:-(
634 sc->result = SAM_STAT_BUSY;
635 break;
637 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
638 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
639 sc->result = DID_BAD_TARGET << 16;
640 break;
642 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
643 /* Spoof to SCSI Selection Timeout! */
644 sc->result = DID_NO_CONNECT << 16;
646 if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF)
647 hd->sel_timeout[pScsiReq->TargetID]++;
648 break;
650 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
651 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
652 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
653 /* Linux handles an unsolicited DID_RESET better
654 * than an unsolicited DID_ABORT.
656 sc->result = DID_RESET << 16;
658 /* GEM Workaround. */
659 if (ioc->bus_type == SCSI)
660 mptscsih_no_negotiate(hd, sc->device->id);
661 break;
663 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
664 if ( xfer_cnt >= sc->underflow ) {
665 /* Sufficient data transfer occurred */
666 sc->result = (DID_OK << 16) | scsi_status;
667 } else if ( xfer_cnt == 0 ) {
668 /* A CRC Error causes this condition; retry */
669 sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
670 (CHECK_CONDITION << 1);
671 sc->sense_buffer[0] = 0x70;
672 sc->sense_buffer[2] = NO_SENSE;
673 sc->sense_buffer[12] = 0;
674 sc->sense_buffer[13] = 0;
675 } else {
676 sc->result = DID_SOFT_ERROR << 16;
678 dreplyprintk((KERN_NOTICE
679 "RESIDUAL_MISMATCH: result=%x on id=%d\n",
680 sc->result, sc->device->id));
681 break;
683 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
685 * Do upfront check for valid SenseData and give it
686 * precedence!
688 sc->result = (DID_OK << 16) | scsi_status;
689 if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
690 /* Have already saved the status and sense data
693 } else {
694 if (xfer_cnt < sc->underflow) {
695 sc->result = DID_SOFT_ERROR << 16;
697 if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
698 /* What to do?
700 sc->result = DID_SOFT_ERROR << 16;
702 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
703 /* Not real sure here either... */
704 sc->result = DID_RESET << 16;
708 dreplyprintk((KERN_NOTICE " sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
709 sc->underflow));
710 dreplyprintk((KERN_NOTICE " ActBytesXferd=%02xh\n", xfer_cnt));
711 /* Report Queue Full
713 if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
714 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
716 break;
718 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
719 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
720 scsi_status = pScsiReply->SCSIStatus;
721 sc->result = (DID_OK << 16) | scsi_status;
722 if (scsi_state == 0) {
724 } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
726 * If running against circa 200003dd 909 MPT f/w,
727 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
728 * (QUEUE_FULL) returned from device! --> get 0x0000?128
729 * and with SenseBytes set to 0.
731 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
732 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
735 else if (scsi_state &
736 (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)
739 * What to do?
741 sc->result = DID_SOFT_ERROR << 16;
743 else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
744 /* Not real sure here either... */
745 sc->result = DID_RESET << 16;
747 else if (scsi_state & MPI_SCSI_STATE_QUEUE_TAG_REJECTED) {
748 /* Device Inq. data indicates that it supports
749 * QTags, but rejects QTag messages.
750 * This command completed OK.
752 * Not real sure here either so do nothing... */
755 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
756 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
758 /* Add handling of:
759 * Reservation Conflict, Busy,
760 * Command Terminated, CHECK
762 break;
764 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
765 sc->result = DID_SOFT_ERROR << 16;
766 break;
768 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
769 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
770 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
771 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
772 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
773 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
774 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
775 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
776 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
777 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
778 default:
780 * What to do?
782 sc->result = DID_SOFT_ERROR << 16;
783 break;
785 } /* switch(status) */
787 dreplyprintk((KERN_NOTICE " sc->result is %08xh\n", sc->result));
788 } /* end of address reply case */
790 /* Unmap the DMA buffers, if any. */
791 if (sc->use_sg) {
792 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) sc->request_buffer,
793 sc->use_sg, sc->sc_data_direction);
794 } else if (sc->request_bufflen) {
795 pci_unmap_single(ioc->pcidev, sc->SCp.dma_handle,
796 sc->request_bufflen, sc->sc_data_direction);
799 hd->ScsiLookup[req_idx] = NULL;
801 sc->scsi_done(sc); /* Issue the command callback */
803 /* Free Chain buffers */
804 mptscsih_freeChainBuffers(ioc, req_idx);
805 return 1;
809 * mptscsih_flush_running_cmds - For each command found, search
810 * Scsi_Host instance taskQ and reply to OS.
811 * Called only if recovering from a FW reload.
812 * @hd: Pointer to a SCSI HOST structure
814 * Returns: None.
816 * Must be called while new I/Os are being queued.
818 static void
819 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
821 MPT_ADAPTER *ioc = hd->ioc;
822 struct scsi_cmnd *SCpnt;
823 MPT_FRAME_HDR *mf;
824 int ii;
825 int max = ioc->req_depth;
827 dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
828 for (ii= 0; ii < max; ii++) {
829 if ((SCpnt = hd->ScsiLookup[ii]) != NULL) {
831 /* Command found.
834 /* Null ScsiLookup index
836 hd->ScsiLookup[ii] = NULL;
838 mf = MPT_INDEX_2_MFPTR(ioc, ii);
839 dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
840 mf, SCpnt));
842 /* Set status, free OS resources (SG DMA buffers)
843 * Do OS callback
844 * Free driver resources (chain, msg buffers)
846 if (SCpnt->use_sg) {
847 pci_unmap_sg(ioc->pcidev,
848 (struct scatterlist *) SCpnt->request_buffer,
849 SCpnt->use_sg,
850 SCpnt->sc_data_direction);
851 } else if (SCpnt->request_bufflen) {
852 pci_unmap_single(ioc->pcidev,
853 SCpnt->SCp.dma_handle,
854 SCpnt->request_bufflen,
855 SCpnt->sc_data_direction);
857 SCpnt->result = DID_RESET << 16;
858 SCpnt->host_scribble = NULL;
860 /* Free Chain buffers */
861 mptscsih_freeChainBuffers(ioc, ii);
863 /* Free Message frames */
864 mpt_free_msg_frame(ioc, mf);
866 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
870 return;
874 * mptscsih_search_running_cmds - Delete any commands associated
875 * with the specified target and lun. Function called only
876 * when a lun is disable by mid-layer.
877 * Do NOT access the referenced scsi_cmnd structure or
878 * members. Will cause either a paging or NULL ptr error.
879 * @hd: Pointer to a SCSI HOST structure
880 * @target: target id
881 * @lun: lun
883 * Returns: None.
885 * Called from slave_destroy.
887 static void
888 mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
890 SCSIIORequest_t *mf = NULL;
891 int ii;
892 int max = hd->ioc->req_depth;
894 dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
895 target, lun, max));
897 for (ii=0; ii < max; ii++) {
898 if (hd->ScsiLookup[ii] != NULL) {
900 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii);
902 dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
903 hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
905 if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
906 continue;
908 /* Cleanup
910 hd->ScsiLookup[ii] = NULL;
911 mptscsih_freeChainBuffers(hd->ioc, ii);
912 mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
916 return;
919 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
921 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
923 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
924 * from a SCSI target device.
925 * @sc: Pointer to scsi_cmnd structure
926 * @pScsiReply: Pointer to SCSIIOReply_t
927 * @pScsiReq: Pointer to original SCSI request
929 * This routine periodically reports QUEUE_FULL status returned from a
930 * SCSI target device. It reports this to the console via kernel
931 * printk() API call, not more than once every 10 seconds.
933 static void
934 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
936 long time = jiffies;
937 MPT_SCSI_HOST *hd;
939 if (sc->device == NULL)
940 return;
941 if (sc->device->host == NULL)
942 return;
943 if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
944 return;
946 if (time - hd->last_queue_full > 10 * HZ) {
947 dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
948 hd->ioc->name, 0, sc->device->id, sc->device->lun));
949 hd->last_queue_full = time;
953 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
955 * mptscsih_remove - Removed scsi devices
956 * @pdev: Pointer to pci_dev structure
960 void
961 mptscsih_remove(struct pci_dev *pdev)
963 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
964 struct Scsi_Host *host = ioc->sh;
965 MPT_SCSI_HOST *hd;
966 int count;
967 unsigned long flags;
968 int sz1;
970 if(!host)
971 return;
973 scsi_remove_host(host);
975 if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
976 return;
978 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
979 /* Check DV thread active */
980 count = 10 * HZ;
981 spin_lock_irqsave(&dvtaskQ_lock, flags);
982 if (dvtaskQ_active) {
983 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
984 while(dvtaskQ_active && --count) {
985 set_current_state(TASK_INTERRUPTIBLE);
986 schedule_timeout(1);
988 } else {
989 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
991 if (!count)
992 printk(KERN_ERR MYNAM ": ERROR - DV thread still active!\n");
993 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
994 else
995 printk(KERN_ERR MYNAM ": DV thread orig %d, count %d\n", 10 * HZ, count);
996 #endif
997 #endif
999 mptscsih_shutdown(pdev);
1001 sz1=0;
1003 if (hd->ScsiLookup != NULL) {
1004 sz1 = hd->ioc->req_depth * sizeof(void *);
1005 kfree(hd->ScsiLookup);
1006 hd->ScsiLookup = NULL;
1010 * Free pointer array.
1012 kfree(hd->Targets);
1013 hd->Targets = NULL;
1015 dprintk((MYIOC_s_INFO_FMT
1016 "Free'd ScsiLookup (%d) memory\n",
1017 hd->ioc->name, sz1));
1019 kfree(hd->info_kbuf);
1021 /* NULL the Scsi_Host pointer
1023 hd->ioc->sh = NULL;
1025 scsi_host_put(host);
1027 mpt_detach(pdev);
1031 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1033 * mptscsih_shutdown - reboot notifier
1036 void
1037 mptscsih_shutdown(struct pci_dev *pdev)
1039 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1040 struct Scsi_Host *host = ioc->sh;
1041 MPT_SCSI_HOST *hd;
1043 if(!host)
1044 return;
1046 hd = (MPT_SCSI_HOST *)host->hostdata;
1048 /* Flush the cache of this adapter
1050 if(hd != NULL)
1051 mptscsih_synchronize_cache(hd, 0);
1055 #ifdef CONFIG_PM
1056 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1058 * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
1063 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
1065 mptscsih_shutdown(pdev);
1066 return mpt_suspend(pdev,state);
1069 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1071 * mptscsih_resume - Fusion MPT scsi driver resume routine.
1076 mptscsih_resume(struct pci_dev *pdev)
1078 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1079 struct Scsi_Host *host = ioc->sh;
1080 MPT_SCSI_HOST *hd;
1082 mpt_resume(pdev);
1084 if(!host)
1085 return 0;
1087 hd = (MPT_SCSI_HOST *)host->hostdata;
1088 if(!hd)
1089 return 0;
1091 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1093 unsigned long lflags;
1094 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1095 if (!dvtaskQ_active) {
1096 dvtaskQ_active = 1;
1097 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1098 INIT_WORK(&dvTaskQ_task,
1099 mptscsih_domainValidation, (void *) hd);
1100 schedule_work(&dvTaskQ_task);
1101 } else {
1102 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1105 #endif
1106 return 0;
1109 #endif
1111 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1113 * mptscsih_info - Return information about MPT adapter
1114 * @SChost: Pointer to Scsi_Host structure
1116 * (linux scsi_host_template.info routine)
1118 * Returns pointer to buffer where information was written.
1120 const char *
1121 mptscsih_info(struct Scsi_Host *SChost)
1123 MPT_SCSI_HOST *h;
1124 int size = 0;
1126 h = (MPT_SCSI_HOST *)SChost->hostdata;
1128 if (h) {
1129 if (h->info_kbuf == NULL)
1130 if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
1131 return h->info_kbuf;
1132 h->info_kbuf[0] = '\0';
1134 mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
1135 h->info_kbuf[size-1] = '\0';
1138 return h->info_kbuf;
1141 struct info_str {
1142 char *buffer;
1143 int length;
1144 int offset;
1145 int pos;
1148 static void
1149 mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
1151 if (info->pos + len > info->length)
1152 len = info->length - info->pos;
1154 if (info->pos + len < info->offset) {
1155 info->pos += len;
1156 return;
1159 if (info->pos < info->offset) {
1160 data += (info->offset - info->pos);
1161 len -= (info->offset - info->pos);
1164 if (len > 0) {
1165 memcpy(info->buffer + info->pos, data, len);
1166 info->pos += len;
1170 static int
1171 mptscsih_copy_info(struct info_str *info, char *fmt, ...)
1173 va_list args;
1174 char buf[81];
1175 int len;
1177 va_start(args, fmt);
1178 len = vsprintf(buf, fmt, args);
1179 va_end(args);
1181 mptscsih_copy_mem_info(info, buf, len);
1182 return len;
1185 static int
1186 mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
1188 struct info_str info;
1190 info.buffer = pbuf;
1191 info.length = len;
1192 info.offset = offset;
1193 info.pos = 0;
1195 mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
1196 mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
1197 mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
1198 mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
1200 return ((info.pos > info.offset) ? info.pos - info.offset : 0);
1203 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1205 * mptscsih_proc_info - Return information about MPT adapter
1207 * (linux scsi_host_template.info routine)
1209 * buffer: if write, user data; if read, buffer for user
1210 * length: if write, return length;
1211 * offset: if write, 0; if read, the current offset into the buffer from
1212 * the previous read.
1213 * hostno: scsi host number
1214 * func: if write = 1; if read = 0
1217 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
1218 int length, int func)
1220 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1221 MPT_ADAPTER *ioc = hd->ioc;
1222 int size = 0;
1224 if (func) {
1226 * write is not supported
1228 } else {
1229 if (start)
1230 *start = buffer;
1232 size = mptscsih_host_info(ioc, buffer, offset, length);
1235 return size;
1238 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1239 #define ADD_INDEX_LOG(req_ent) do { } while(0)
1241 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1243 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
1244 * @SCpnt: Pointer to scsi_cmnd structure
1245 * @done: Pointer SCSI mid-layer IO completion function
1247 * (linux scsi_host_template.queuecommand routine)
1248 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
1249 * from a linux scsi_cmnd request and send it to the IOC.
1251 * Returns 0. (rtn value discarded by linux scsi mid-layer)
1254 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1256 MPT_SCSI_HOST *hd;
1257 MPT_FRAME_HDR *mf;
1258 SCSIIORequest_t *pScsiReq;
1259 VirtDevice *pTarget;
1260 int target;
1261 int lun;
1262 u32 datalen;
1263 u32 scsictl;
1264 u32 scsidir;
1265 u32 cmd_len;
1266 int my_idx;
1267 int ii;
1269 hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata;
1270 target = SCpnt->device->id;
1271 lun = SCpnt->device->lun;
1272 SCpnt->scsi_done = done;
1274 pTarget = hd->Targets[target];
1276 dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n",
1277 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
1279 if (hd->resetPending) {
1280 dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
1281 (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
1282 return SCSI_MLQUEUE_HOST_BUSY;
1286 * Put together a MPT SCSI request...
1288 if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
1289 dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
1290 hd->ioc->name));
1291 return SCSI_MLQUEUE_HOST_BUSY;
1294 pScsiReq = (SCSIIORequest_t *) mf;
1296 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
1298 ADD_INDEX_LOG(my_idx);
1300 /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
1301 * Seems we may receive a buffer (datalen>0) even when there
1302 * will be no data transfer! GRRRRR...
1304 if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
1305 datalen = SCpnt->request_bufflen;
1306 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
1307 } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
1308 datalen = SCpnt->request_bufflen;
1309 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
1310 } else {
1311 datalen = 0;
1312 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
1315 /* Default to untagged. Once a target structure has been allocated,
1316 * use the Inquiry data to determine if device supports tagged.
1318 if ( pTarget
1319 && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
1320 && (SCpnt->device->tagged_supported)) {
1321 scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
1322 } else {
1323 scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
1326 /* Use the above information to set up the message frame
1328 pScsiReq->TargetID = (u8) target;
1329 pScsiReq->Bus = (u8) SCpnt->device->channel;
1330 pScsiReq->ChainOffset = 0;
1331 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1332 pScsiReq->CDBLength = SCpnt->cmd_len;
1333 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
1334 pScsiReq->Reserved = 0;
1335 pScsiReq->MsgFlags = mpt_msg_flags();
1336 pScsiReq->LUN[0] = 0;
1337 pScsiReq->LUN[1] = lun;
1338 pScsiReq->LUN[2] = 0;
1339 pScsiReq->LUN[3] = 0;
1340 pScsiReq->LUN[4] = 0;
1341 pScsiReq->LUN[5] = 0;
1342 pScsiReq->LUN[6] = 0;
1343 pScsiReq->LUN[7] = 0;
1344 pScsiReq->Control = cpu_to_le32(scsictl);
1347 * Write SCSI CDB into the message
1349 cmd_len = SCpnt->cmd_len;
1350 for (ii=0; ii < cmd_len; ii++)
1351 pScsiReq->CDB[ii] = SCpnt->cmnd[ii];
1353 for (ii=cmd_len; ii < 16; ii++)
1354 pScsiReq->CDB[ii] = 0;
1356 /* DataLength */
1357 pScsiReq->DataLength = cpu_to_le32(datalen);
1359 /* SenseBuffer low address */
1360 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
1361 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
1363 /* Now add the SG list
1364 * Always have a SGE even if null length.
1366 if (datalen == 0) {
1367 /* Add a NULL SGE */
1368 mptscsih_add_sge((char *)&pScsiReq->SGL, MPT_SGE_FLAGS_SSIMPLE_READ | 0,
1369 (dma_addr_t) -1);
1370 } else {
1371 /* Add a 32 or 64 bit SGE */
1372 if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS)
1373 goto fail;
1376 hd->ScsiLookup[my_idx] = SCpnt;
1377 SCpnt->host_scribble = NULL;
1379 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
1380 if (hd->ioc->bus_type == SCSI) {
1381 int dvStatus = hd->ioc->spi_data.dvStatus[target];
1382 int issueCmd = 1;
1384 if (dvStatus || hd->ioc->spi_data.forceDv) {
1386 if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
1387 (hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
1388 unsigned long lflags;
1389 /* Schedule DV if necessary */
1390 spin_lock_irqsave(&dvtaskQ_lock, lflags);
1391 if (!dvtaskQ_active) {
1392 dvtaskQ_active = 1;
1393 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1394 INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
1396 schedule_work(&dvTaskQ_task);
1397 } else {
1398 spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
1400 hd->ioc->spi_data.forceDv &= ~MPT_SCSICFG_NEED_DV;
1403 /* Trying to do DV to this target, extend timeout.
1404 * Wait to issue until flag is clear
1406 if (dvStatus & MPT_SCSICFG_DV_PENDING) {
1407 mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
1408 issueCmd = 0;
1411 /* Set the DV flags.
1413 if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
1414 mptscsih_set_dvflags(hd, pScsiReq);
1416 if (!issueCmd)
1417 goto fail;
1420 #endif
1422 mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
1423 dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
1424 hd->ioc->name, SCpnt, mf, my_idx));
1425 DBG_DUMP_REQUEST_FRAME(mf)
1426 return 0;
1428 fail:
1429 mptscsih_freeChainBuffers(hd->ioc, my_idx);
1430 mpt_free_msg_frame(hd->ioc, mf);
1431 return SCSI_MLQUEUE_HOST_BUSY;
1434 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1436 * mptscsih_freeChainBuffers - Function to free chain buffers associated
1437 * with a SCSI IO request
1438 * @hd: Pointer to the MPT_SCSI_HOST instance
1439 * @req_idx: Index of the SCSI IO request frame.
1441 * Called if SG chain buffer allocation fails and mptscsih callbacks.
1442 * No return.
1444 static void
1445 mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
1447 MPT_FRAME_HDR *chain;
1448 unsigned long flags;
1449 int chain_idx;
1450 int next;
1452 /* Get the first chain index and reset
1453 * tracker state.
1455 chain_idx = ioc->ReqToChain[req_idx];
1456 ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
1458 while (chain_idx != MPT_HOST_NO_CHAIN) {
1460 /* Save the next chain buffer index */
1461 next = ioc->ChainToChain[chain_idx];
1463 /* Free this chain buffer and reset
1464 * tracker
1466 ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
1468 chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
1469 + (chain_idx * ioc->req_sz));
1471 spin_lock_irqsave(&ioc->FreeQlock, flags);
1472 list_add_tail(&chain->u.frame.linkage.list, &ioc->FreeChainQ);
1473 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1475 dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
1476 ioc->name, chain_idx));
1478 /* handle next */
1479 chain_idx = next;
1481 return;
1484 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1486 * Reset Handling
1489 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1491 * mptscsih_TMHandler - Generic handler for SCSI Task Management.
1492 * Fall through to mpt_HardResetHandler if: not operational, too many
1493 * failed TM requests or handshake failure.
1495 * @ioc: Pointer to MPT_ADAPTER structure
1496 * @type: Task Management type
1497 * @target: Logical Target ID for reset (if appropriate)
1498 * @lun: Logical Unit for reset (if appropriate)
1499 * @ctx2abort: Context for the task to be aborted (if appropriate)
1501 * Remark: Currently invoked from a non-interrupt thread (_bh).
1503 * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC
1504 * will be active.
1506 * Returns 0 for SUCCESS or -1 if FAILED.
1508 static int
1509 mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1511 MPT_ADAPTER *ioc;
1512 int rc = -1;
1513 int doTask = 1;
1514 u32 ioc_raw_state;
1515 unsigned long flags;
1517 /* If FW is being reloaded currently, return success to
1518 * the calling function.
1520 if (hd == NULL)
1521 return 0;
1523 ioc = hd->ioc;
1524 if (ioc == NULL) {
1525 printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n");
1526 return FAILED;
1528 dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name));
1530 // SJR - CHECKME - Can we avoid this here?
1531 // (mpt_HardResetHandler has this check...)
1532 spin_lock_irqsave(&ioc->diagLock, flags);
1533 if ((ioc->diagPending) || (ioc->alt_ioc && ioc->alt_ioc->diagPending)) {
1534 spin_unlock_irqrestore(&ioc->diagLock, flags);
1535 return FAILED;
1537 spin_unlock_irqrestore(&ioc->diagLock, flags);
1539 /* Wait a fixed amount of time for the TM pending flag to be cleared.
1540 * If we time out and not bus reset, then we return a FAILED status to the caller.
1541 * The call to mptscsih_tm_pending_wait() will set the pending flag if we are
1542 * successful. Otherwise, reload the FW.
1544 if (mptscsih_tm_pending_wait(hd) == FAILED) {
1545 if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1546 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler abort: "
1547 "Timed out waiting for last TM (%d) to complete! \n",
1548 hd->ioc->name, hd->tmPending));
1549 return FAILED;
1550 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
1551 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: "
1552 "Timed out waiting for last TM (%d) to complete! \n",
1553 hd->ioc->name, hd->tmPending));
1554 return FAILED;
1555 } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
1556 dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: "
1557 "Timed out waiting for last TM (%d) to complete! \n",
1558 hd->ioc->name, hd->tmPending));
1559 if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS))
1560 return FAILED;
1562 doTask = 0;
1564 } else {
1565 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1566 hd->tmPending |= (1 << type);
1567 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1570 /* Is operational?
1572 ioc_raw_state = mpt_GetIocState(hd->ioc, 0);
1574 #ifdef MPT_DEBUG_RESET
1575 if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) {
1576 printk(MYIOC_s_WARN_FMT
1577 "TM Handler: IOC Not operational(0x%x)!\n",
1578 hd->ioc->name, ioc_raw_state);
1580 #endif
1582 if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL)
1583 && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) {
1585 /* Isse the Task Mgmt request.
1587 if (hd->hard_resets < -1)
1588 hd->hard_resets++;
1589 rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
1590 if (rc) {
1591 printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
1592 } else {
1593 dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name));
1597 /* Only fall through to the HRH if this is a bus reset
1599 if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc ||
1600 ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
1601 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1602 hd->ioc->name));
1603 rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1606 dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
1608 return rc;
1612 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1614 * mptscsih_IssueTaskMgmt - Generic send Task Management function.
1615 * @hd: Pointer to MPT_SCSI_HOST structure
1616 * @type: Task Management type
1617 * @target: Logical Target ID for reset (if appropriate)
1618 * @lun: Logical Unit for reset (if appropriate)
1619 * @ctx2abort: Context for the task to be aborted (if appropriate)
1621 * Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
1622 * or a non-interrupt thread. In the former, must not call schedule().
1624 * Not all fields are meaningfull for all task types.
1626 * Returns 0 for SUCCESS, -999 for "no msg frames",
1627 * else other non-zero value returned.
1629 static int
1630 mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
1632 MPT_FRAME_HDR *mf;
1633 SCSITaskMgmt_t *pScsiTm;
1634 int ii;
1635 int retval;
1637 /* Return Fail to calling function if no message frames available.
1639 if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
1640 dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
1641 hd->ioc->name));
1642 return FAILED;
1644 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt request @ %p\n",
1645 hd->ioc->name, mf));
1647 /* Format the Request
1649 pScsiTm = (SCSITaskMgmt_t *) mf;
1650 pScsiTm->TargetID = target;
1651 pScsiTm->Bus = channel;
1652 pScsiTm->ChainOffset = 0;
1653 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1655 pScsiTm->Reserved = 0;
1656 pScsiTm->TaskType = type;
1657 pScsiTm->Reserved1 = 0;
1658 pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1659 ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
1661 for (ii= 0; ii < 8; ii++) {
1662 pScsiTm->LUN[ii] = 0;
1664 pScsiTm->LUN[1] = lun;
1666 for (ii=0; ii < 7; ii++)
1667 pScsiTm->Reserved2[ii] = 0;
1669 pScsiTm->TaskMsgContext = ctx2abort;
1671 dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
1672 hd->ioc->name, ctx2abort, type));
1674 DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
1676 if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
1677 sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
1678 CAN_SLEEP)) != 0) {
1679 dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
1680 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1681 hd->ioc, mf));
1682 mpt_free_msg_frame(hd->ioc, mf);
1683 return retval;
1686 if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
1687 dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
1688 " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
1689 hd->ioc, mf));
1690 mpt_free_msg_frame(hd->ioc, mf);
1691 dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
1692 hd->ioc->name));
1693 retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
1696 return retval;
1699 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1701 * mptscsih_abort - Abort linux scsi_cmnd routine, new_eh variant
1702 * @SCpnt: Pointer to scsi_cmnd structure, IO to be aborted
1704 * (linux scsi_host_template.eh_abort_handler routine)
1706 * Returns SUCCESS or FAILED.
1709 mptscsih_abort(struct scsi_cmnd * SCpnt)
1711 MPT_SCSI_HOST *hd;
1712 MPT_ADAPTER *ioc;
1713 MPT_FRAME_HDR *mf;
1714 u32 ctx2abort;
1715 int scpnt_idx;
1717 /* If we can't locate our host adapter structure, return FAILED status.
1719 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
1720 SCpnt->result = DID_RESET << 16;
1721 SCpnt->scsi_done(SCpnt);
1722 dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
1723 "Can't locate host! (sc=%p)\n",
1724 SCpnt));
1725 return FAILED;
1728 ioc = hd->ioc;
1729 if (hd->resetPending)
1730 return FAILED;
1732 printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
1733 hd->ioc->name, SCpnt);
1735 if (hd->timeouts < -1)
1736 hd->timeouts++;
1738 /* Find this command
1740 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
1741 /* Cmd not found in ScsiLookup.
1742 * Do OS callback.
1744 SCpnt->result = DID_RESET << 16;
1745 dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
1746 "Command not in the active list! (sc=%p)\n",
1747 hd->ioc->name, SCpnt));
1748 return SUCCESS;
1751 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1752 * (the IO to be ABORT'd)
1754 * NOTE: Since we do not byteswap MsgContext, we do not
1755 * swap it here either. It is an opaque cookie to
1756 * the controller, so it does not matter. -DaveM
1758 mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
1759 ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
1761 hd->abortSCpnt = SCpnt;
1763 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
1764 SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
1765 ctx2abort, 2 /* 2 second timeout */)
1766 < 0) {
1768 /* The TM request failed and the subsequent FW-reload failed!
1769 * Fatal error case.
1771 printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n",
1772 hd->ioc->name, SCpnt);
1774 /* We must clear our pending flag before clearing our state.
1776 hd->tmPending = 0;
1777 hd->tmState = TM_STATE_NONE;
1779 /* Unmap the DMA buffers, if any. */
1780 if (SCpnt->use_sg) {
1781 pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
1782 SCpnt->use_sg, SCpnt->sc_data_direction);
1783 } else if (SCpnt->request_bufflen) {
1784 pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle,
1785 SCpnt->request_bufflen, SCpnt->sc_data_direction);
1787 hd->ScsiLookup[scpnt_idx] = NULL;
1788 SCpnt->result = DID_RESET << 16;
1789 SCpnt->scsi_done(SCpnt); /* Issue the command callback */
1790 mptscsih_freeChainBuffers(ioc, scpnt_idx);
1791 mpt_free_msg_frame(ioc, mf);
1792 return FAILED;
1794 return SUCCESS;
1797 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1799 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1800 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1802 * (linux scsi_host_template.eh_dev_reset_handler routine)
1804 * Returns SUCCESS or FAILED.
1807 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
1809 MPT_SCSI_HOST *hd;
1811 /* If we can't locate our host adapter structure, return FAILED status.
1813 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1814 dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: "
1815 "Can't locate host! (sc=%p)\n",
1816 SCpnt));
1817 return FAILED;
1820 if (hd->resetPending)
1821 return FAILED;
1823 printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
1824 hd->ioc->name, SCpnt);
1826 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
1827 SCpnt->device->channel, SCpnt->device->id,
1828 0, 0, 5 /* 5 second timeout */)
1829 < 0){
1830 /* The TM request failed and the subsequent FW-reload failed!
1831 * Fatal error case.
1833 printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n",
1834 hd->ioc->name, SCpnt);
1835 hd->tmPending = 0;
1836 hd->tmState = TM_STATE_NONE;
1837 return FAILED;
1840 return SUCCESS;
1843 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1845 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1846 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1848 * (linux scsi_host_template.eh_bus_reset_handler routine)
1850 * Returns SUCCESS or FAILED.
1853 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
1855 MPT_SCSI_HOST *hd;
1856 spinlock_t *host_lock = SCpnt->device->host->host_lock;
1858 /* If we can't locate our host adapter structure, return FAILED status.
1860 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1861 dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: "
1862 "Can't locate host! (sc=%p)\n",
1863 SCpnt ) );
1864 return FAILED;
1867 printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
1868 hd->ioc->name, SCpnt);
1870 if (hd->timeouts < -1)
1871 hd->timeouts++;
1873 /* We are now ready to execute the task management request. */
1874 if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
1875 SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
1876 < 0){
1878 /* The TM request failed and the subsequent FW-reload failed!
1879 * Fatal error case.
1881 printk(MYIOC_s_WARN_FMT
1882 "Error processing TaskMgmt request (sc=%p)\n",
1883 hd->ioc->name, SCpnt);
1884 hd->tmPending = 0;
1885 hd->tmState = TM_STATE_NONE;
1886 spin_lock_irq(host_lock);
1887 return FAILED;
1890 return SUCCESS;
1893 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1895 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
1896 * new_eh variant
1897 * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to
1899 * (linux scsi_host_template.eh_host_reset_handler routine)
1901 * Returns SUCCESS or FAILED.
1904 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
1906 MPT_SCSI_HOST * hd;
1907 int status = SUCCESS;
1909 /* If we can't locate the host to reset, then we failed. */
1910 if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
1911 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1912 "Can't locate host! (sc=%p)\n",
1913 SCpnt ) );
1914 return FAILED;
1917 printk(KERN_WARNING MYNAM ": %s: Attempting host reset! (sc=%p)\n",
1918 hd->ioc->name, SCpnt);
1920 /* If our attempts to reset the host failed, then return a failed
1921 * status. The host will be taken off line by the SCSI mid-layer.
1923 if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
1924 status = FAILED;
1925 } else {
1926 /* Make sure TM pending is cleared and TM state is set to
1927 * NONE.
1929 hd->tmPending = 0;
1930 hd->tmState = TM_STATE_NONE;
1933 dtmprintk( ( KERN_INFO MYNAM ": mptscsih_host_reset: "
1934 "Status = %s\n",
1935 (status == SUCCESS) ? "SUCCESS" : "FAILED" ) );
1937 return status;
1940 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1942 * mptscsih_tm_pending_wait - wait for pending task management request to
1943 * complete.
1944 * @hd: Pointer to MPT host structure.
1946 * Returns {SUCCESS,FAILED}.
1948 static int
1949 mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
1951 unsigned long flags;
1952 int loop_count = 4 * 10; /* Wait 10 seconds */
1953 int status = FAILED;
1955 do {
1956 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1957 if (hd->tmState == TM_STATE_NONE) {
1958 hd->tmState = TM_STATE_IN_PROGRESS;
1959 hd->tmPending = 1;
1960 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1961 status = SUCCESS;
1962 break;
1964 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1965 msleep(250);
1966 } while (--loop_count);
1968 return status;
1971 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1973 * mptscsih_tm_wait_for_completion - wait for completion of TM task
1974 * @hd: Pointer to MPT host structure.
1976 * Returns {SUCCESS,FAILED}.
1978 static int
1979 mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
1981 unsigned long flags;
1982 int loop_count = 4 * timeout;
1983 int status = FAILED;
1985 do {
1986 spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
1987 if(hd->tmPending == 0) {
1988 status = SUCCESS;
1989 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1990 break;
1992 spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
1993 msleep_interruptible(250);
1994 } while (--loop_count);
1996 return status;
1999 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2001 * mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
2002 * @ioc: Pointer to MPT_ADAPTER structure
2003 * @mf: Pointer to SCSI task mgmt request frame
2004 * @mr: Pointer to SCSI task mgmt reply frame
2006 * This routine is called from mptbase.c::mpt_interrupt() at the completion
2007 * of any SCSI task management request.
2008 * This routine is registered with the MPT (base) driver at driver
2009 * load/init time via the mpt_register() API call.
2011 * Returns 1 indicating alloc'd request frame ptr should be freed.
2014 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
2016 SCSITaskMgmtReply_t *pScsiTmReply;
2017 SCSITaskMgmt_t *pScsiTmReq;
2018 MPT_SCSI_HOST *hd;
2019 unsigned long flags;
2020 u16 iocstatus;
2021 u8 tmType;
2023 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
2024 ioc->name, mf, mr));
2025 if (ioc->sh) {
2026 /* Depending on the thread, a timer is activated for
2027 * the TM request. Delete this timer on completion of TM.
2028 * Decrement count of outstanding TM requests.
2030 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
2031 } else {
2032 dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
2033 ioc->name));
2034 return 1;
2037 if (mr == NULL) {
2038 dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n",
2039 ioc->name, mf));
2040 return 1;
2041 } else {
2042 pScsiTmReply = (SCSITaskMgmtReply_t*)mr;
2043 pScsiTmReq = (SCSITaskMgmt_t*)mf;
2045 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
2046 tmType = pScsiTmReq->TaskType;
2048 dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n",
2049 ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
2050 DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
2052 iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
2053 dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
2054 ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
2055 /* Error? (anything non-zero?) */
2056 if (iocstatus) {
2058 /* clear flags and continue.
2060 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2061 hd->abortSCpnt = NULL;
2063 /* If an internal command is present
2064 * or the TM failed - reload the FW.
2065 * FC FW may respond FAILED to an ABORT
2067 if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) {
2068 if ((hd->cmdPtr) ||
2069 (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) {
2070 if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) {
2071 printk((KERN_WARNING
2072 " Firmware Reload FAILED!!\n"));
2076 } else {
2077 dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
2079 hd->abortSCpnt = NULL;
2084 spin_lock_irqsave(&ioc->FreeQlock, flags);
2085 hd->tmPending = 0;
2086 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2087 hd->tmState = TM_STATE_NONE;
2089 return 1;
2092 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2094 * This is anyones guess quite frankly.
2097 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
2098 sector_t capacity, int geom[])
2100 int heads;
2101 int sectors;
2102 sector_t cylinders;
2103 ulong dummy;
2105 heads = 64;
2106 sectors = 32;
2108 dummy = heads * sectors;
2109 cylinders = capacity;
2110 sector_div(cylinders,dummy);
2113 * Handle extended translation size for logical drives
2114 * > 1Gb
2116 if ((ulong)capacity >= 0x200000) {
2117 heads = 255;
2118 sectors = 63;
2119 dummy = heads * sectors;
2120 cylinders = capacity;
2121 sector_div(cylinders,dummy);
2124 /* return result */
2125 geom[0] = heads;
2126 geom[1] = sectors;
2127 geom[2] = cylinders;
2129 dprintk((KERN_NOTICE
2130 ": bios_param: Id=%i Lun=%i Channel=%i CHS=%i/%i/%i\n",
2131 sdev->id, sdev->lun,sdev->channel,(int)cylinders,heads,sectors));
2133 return 0;
2136 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2138 * OS entry point to allow host driver to alloc memory
2139 * for each scsi device. Called once per device the bus scan.
2140 * Return non-zero if allocation fails.
2141 * Init memory once per id (not LUN).
2144 mptscsih_slave_alloc(struct scsi_device *device)
2146 struct Scsi_Host *host = device->host;
2147 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2148 VirtDevice *vdev;
2149 uint target = device->id;
2151 if (hd == NULL)
2152 return -ENODEV;
2154 if ((vdev = hd->Targets[target]) != NULL)
2155 goto out;
2157 vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
2158 if (!vdev) {
2159 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
2160 hd->ioc->name, sizeof(VirtDevice));
2161 return -ENOMEM;
2164 memset(vdev, 0, sizeof(VirtDevice));
2165 vdev->tflags = MPT_TARGET_FLAGS_Q_YES;
2166 vdev->ioc_id = hd->ioc->id;
2167 vdev->target_id = device->id;
2168 vdev->bus_id = device->channel;
2169 vdev->raidVolume = 0;
2170 hd->Targets[device->id] = vdev;
2171 if (hd->ioc->bus_type == SCSI) {
2172 if (hd->ioc->spi_data.isRaid & (1 << device->id)) {
2173 vdev->raidVolume = 1;
2174 ddvtprintk((KERN_INFO
2175 "RAID Volume @ id %d\n", device->id));
2177 } else {
2178 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2181 out:
2182 vdev->num_luns++;
2183 return 0;
2186 static int
2187 mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
2189 int i;
2191 if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3)
2192 return 0;
2194 for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) {
2195 if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID)
2196 return 1;
2199 return 0;
2203 * OS entry point to allow for host driver to free allocated memory
2204 * Called if no device present or device being unloaded
2206 void
2207 mptscsih_slave_destroy(struct scsi_device *device)
2209 struct Scsi_Host *host = device->host;
2210 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
2211 VirtDevice *vdev;
2212 uint target = device->id;
2213 uint lun = device->lun;
2215 if (hd == NULL)
2216 return;
2218 mptscsih_search_running_cmds(hd, target, lun);
2220 vdev = hd->Targets[target];
2221 vdev->luns[0] &= ~(1 << lun);
2222 if (--vdev->num_luns)
2223 return;
2225 kfree(hd->Targets[target]);
2226 hd->Targets[target] = NULL;
2228 if (hd->ioc->bus_type == SCSI) {
2229 if (mptscsih_is_raid_volume(hd, target)) {
2230 hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
2231 } else {
2232 hd->ioc->spi_data.dvStatus[target] =
2233 MPT_SCSICFG_NEGOTIATE;
2235 if (!hd->negoNvram) {
2236 hd->ioc->spi_data.dvStatus[target] |=
2237 MPT_SCSICFG_DV_NOT_DONE;
2243 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2245 * mptscsih_change_queue_depth - This function will set a devices queue depth
2246 * @sdev: per scsi_device pointer
2247 * @qdepth: requested queue depth
2249 * Adding support for new 'change_queue_depth' api.
2252 mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
2254 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
2255 VirtDevice *pTarget;
2256 int max_depth;
2257 int tagged;
2259 if (hd == NULL)
2260 return 0;
2261 if (!(pTarget = hd->Targets[sdev->id]))
2262 return 0;
2264 if (hd->ioc->bus_type == SCSI) {
2265 if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
2266 if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
2267 max_depth = 1;
2268 else if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
2269 (pTarget->minSyncFactor <= MPT_ULTRA160 ))
2270 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2271 else
2272 max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
2273 } else {
2274 /* error case - No Inq. Data */
2275 max_depth = 1;
2277 } else
2278 max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
2280 if (qdepth > max_depth)
2281 qdepth = max_depth;
2282 if (qdepth == 1)
2283 tagged = 0;
2284 else
2285 tagged = MSG_SIMPLE_TAG;
2287 scsi_adjust_queue_depth(sdev, tagged, qdepth);
2288 return sdev->queue_depth;
2292 * OS entry point to adjust the queue_depths on a per-device basis.
2293 * Called once per device the bus scan. Use it to force the queue_depth
2294 * member to 1 if a device does not support Q tags.
2295 * Return non-zero if fails.
2298 mptscsih_slave_configure(struct scsi_device *device)
2300 struct Scsi_Host *sh = device->host;
2301 VirtDevice *pTarget;
2302 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
2304 if ((hd == NULL) || (hd->Targets == NULL)) {
2305 return 0;
2308 dsprintk((MYIOC_s_INFO_FMT
2309 "device @ %p, id=%d, LUN=%d, channel=%d\n",
2310 hd->ioc->name, device, device->id, device->lun, device->channel));
2311 dsprintk((MYIOC_s_INFO_FMT
2312 "sdtr %d wdtr %d ppr %d inq length=%d\n",
2313 hd->ioc->name, device->sdtr, device->wdtr,
2314 device->ppr, device->inquiry_len));
2316 if (device->id > sh->max_id) {
2317 /* error case, should never happen */
2318 scsi_adjust_queue_depth(device, 0, 1);
2319 goto slave_configure_exit;
2322 pTarget = hd->Targets[device->id];
2324 if (pTarget == NULL) {
2325 /* Driver doesn't know about this device.
2326 * Kernel may generate a "Dummy Lun 0" which
2327 * may become a real Lun if a
2328 * "scsi add-single-device" command is executed
2329 * while the driver is active (hot-plug a
2330 * device). LSI Raid controllers need
2331 * queue_depth set to DEV_HIGH for this reason.
2333 scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
2334 MPT_SCSI_CMD_PER_DEV_HIGH);
2335 goto slave_configure_exit;
2338 mptscsih_initTarget(hd, device->channel, device->id, device->lun,
2339 device->inquiry, device->inquiry_len );
2340 mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH);
2342 dsprintk((MYIOC_s_INFO_FMT
2343 "Queue depth=%d, tflags=%x\n",
2344 hd->ioc->name, device->queue_depth, pTarget->tflags));
2346 dsprintk((MYIOC_s_INFO_FMT
2347 "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
2348 hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
2350 slave_configure_exit:
2352 dsprintk((MYIOC_s_INFO_FMT
2353 "tagged %d, simple %d, ordered %d\n",
2354 hd->ioc->name,device->tagged_supported, device->simple_tags,
2355 device->ordered_tags));
2357 return 0;
2360 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2362 * Private routines...
2365 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2366 /* Utility function to copy sense data from the scsi_cmnd buffer
2367 * to the FC and SCSI target structures.
2370 static void
2371 mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2373 VirtDevice *target;
2374 SCSIIORequest_t *pReq;
2375 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2376 int index;
2378 /* Get target structure
2380 pReq = (SCSIIORequest_t *) mf;
2381 index = (int) pReq->TargetID;
2382 target = hd->Targets[index];
2384 if (sense_count) {
2385 u8 *sense_data;
2386 int req_index;
2388 /* Copy the sense received into the scsi command block. */
2389 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2390 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
2391 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2393 /* Log SMART data (asc = 0x5D, non-IM case only) if required.
2395 if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
2396 if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
2397 int idx;
2398 MPT_ADAPTER *ioc = hd->ioc;
2400 idx = ioc->eventContext % ioc->eventLogSize;
2401 ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE;
2402 ioc->events[idx].eventContext = ioc->eventContext;
2404 ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
2405 (MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
2406 (pReq->Bus << 8) || pReq->TargetID;
2408 ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
2410 ioc->eventContext++;
2413 } else {
2414 dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
2415 hd->ioc->name));
2419 static u32
2420 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
2422 MPT_SCSI_HOST *hd;
2423 int i;
2425 hd = (MPT_SCSI_HOST *) sc->device->host->hostdata;
2427 for (i = 0; i < hd->ioc->req_depth; i++) {
2428 if (hd->ScsiLookup[i] == sc) {
2429 return i;
2433 return -1;
2436 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2438 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2440 MPT_SCSI_HOST *hd;
2441 unsigned long flags;
2443 dtmprintk((KERN_WARNING MYNAM
2444 ": IOC %s_reset routed to SCSI host driver!\n",
2445 reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
2446 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
2448 /* If a FW reload request arrives after base installed but
2449 * before all scsi hosts have been attached, then an alt_ioc
2450 * may have a NULL sh pointer.
2452 if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL))
2453 return 0;
2454 else
2455 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2457 if (reset_phase == MPT_IOC_SETUP_RESET) {
2458 dtmprintk((MYIOC_s_WARN_FMT "Setup-Diag Reset\n", ioc->name));
2460 /* Clean Up:
2461 * 1. Set Hard Reset Pending Flag
2462 * All new commands go to doneQ
2464 hd->resetPending = 1;
2466 } else if (reset_phase == MPT_IOC_PRE_RESET) {
2467 dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
2469 /* 2. Flush running commands
2470 * Clean ScsiLookup (and associated memory)
2471 * AND clean mytaskQ
2474 /* 2b. Reply to OS all known outstanding I/O commands.
2476 mptscsih_flush_running_cmds(hd);
2478 /* 2c. If there was an internal command that
2479 * has not completed, configuration or io request,
2480 * free these resources.
2482 if (hd->cmdPtr) {
2483 del_timer(&hd->timer);
2484 mpt_free_msg_frame(ioc, hd->cmdPtr);
2487 dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
2489 } else {
2490 dtmprintk((MYIOC_s_WARN_FMT "Post-Diag Reset\n", ioc->name));
2492 /* Once a FW reload begins, all new OS commands are
2493 * redirected to the doneQ w/ a reset status.
2494 * Init all control structures.
2497 /* ScsiLookup initialization
2500 int ii;
2501 for (ii=0; ii < hd->ioc->req_depth; ii++)
2502 hd->ScsiLookup[ii] = NULL;
2505 /* 2. Chain Buffer initialization
2508 /* 4. Renegotiate to all devices, if SCSI
2510 if (ioc->bus_type == SCSI) {
2511 dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
2512 mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
2515 /* 5. Enable new commands to be posted
2517 spin_lock_irqsave(&ioc->FreeQlock, flags);
2518 hd->tmPending = 0;
2519 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2520 hd->resetPending = 0;
2521 hd->tmState = TM_STATE_NONE;
2523 /* 6. If there was an internal command,
2524 * wake this process up.
2526 if (hd->cmdPtr) {
2528 * Wake up the original calling thread
2530 hd->pLocal = &hd->localReply;
2531 hd->pLocal->completion = MPT_SCANDV_DID_RESET;
2532 hd->scandv_wait_done = 1;
2533 wake_up(&hd->scandv_waitq);
2534 hd->cmdPtr = NULL;
2537 /* 7. Set flag to force DV and re-read IOC Page 3
2539 if (ioc->bus_type == SCSI) {
2540 ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2541 ddvtprintk(("Set reload IOC Pg3 Flag\n"));
2544 dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
2548 return 1; /* currently means nothing really */
2551 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2553 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2555 MPT_SCSI_HOST *hd;
2556 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2558 devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
2559 ioc->name, event));
2561 switch (event) {
2562 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2563 /* FIXME! */
2564 break;
2565 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2566 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2567 hd = NULL;
2568 if (ioc->sh) {
2569 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2570 if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
2571 hd->soft_resets++;
2573 break;
2574 case MPI_EVENT_LOGOUT: /* 09 */
2575 /* FIXME! */
2576 break;
2579 * CHECKME! Don't think we need to do
2580 * anything for these, but...
2582 case MPI_EVENT_RESCAN: /* 06 */
2583 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2584 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2586 * CHECKME! Falling thru...
2588 break;
2590 case MPI_EVENT_INTEGRATED_RAID: /* 0B */
2591 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
2592 /* negoNvram set to 0 if DV enabled and to USE_NVRAM if
2593 * if DV disabled. Need to check for target mode.
2595 hd = NULL;
2596 if (ioc->sh)
2597 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
2599 if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) {
2600 ScsiCfgData *pSpi;
2601 Ioc3PhysDisk_t *pPDisk;
2602 int numPDisk;
2603 u8 reason;
2604 u8 physDiskNum;
2606 reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16;
2607 if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) {
2608 /* New or replaced disk.
2609 * Set DV flag and schedule DV.
2611 pSpi = &ioc->spi_data;
2612 physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24;
2613 ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum));
2614 if (pSpi->pIocPg3) {
2615 pPDisk = pSpi->pIocPg3->PhysDisk;
2616 numPDisk =pSpi->pIocPg3->NumPhysDisks;
2618 while (numPDisk) {
2619 if (physDiskNum == pPDisk->PhysDiskNum) {
2620 pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
2621 pSpi->forceDv = MPT_SCSICFG_NEED_DV;
2622 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
2623 break;
2625 pPDisk++;
2626 numPDisk--;
2629 if (numPDisk == 0) {
2630 /* The physical disk that needs DV was not found
2631 * in the stored IOC Page 3. The driver must reload
2632 * this page. DV routine will set the NEED_DV flag for
2633 * all phys disks that have DV_NOT_DONE set.
2635 pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
2636 ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum));
2641 #endif
2643 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
2644 printk("Raid Event RF: ");
2646 u32 *m = (u32 *)pEvReply;
2647 int ii;
2648 int n = (int)pEvReply->MsgLength;
2649 for (ii=6; ii < n; ii++)
2650 printk(" %08x", le32_to_cpu(m[ii]));
2651 printk("\n");
2653 #endif
2654 break;
2656 case MPI_EVENT_NONE: /* 00 */
2657 case MPI_EVENT_LOG_DATA: /* 01 */
2658 case MPI_EVENT_STATE_CHANGE: /* 02 */
2659 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2660 default:
2661 dprintk((KERN_INFO " Ignoring event (=%02Xh)\n", event));
2662 break;
2665 return 1; /* currently means nothing really */
2668 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2670 * mptscsih_initTarget - Target, LUN alloc/free functionality.
2671 * @hd: Pointer to MPT_SCSI_HOST structure
2672 * @bus_id: Bus number (?)
2673 * @target_id: SCSI target id
2674 * @lun: SCSI LUN id
2675 * @data: Pointer to data
2676 * @dlen: Number of INQUIRY bytes
2678 * NOTE: It's only SAFE to call this routine if data points to
2679 * sane & valid STANDARD INQUIRY data!
2681 * Allocate and initialize memory for this target.
2682 * Save inquiry data.
2685 static void
2686 mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
2688 int indexed_lun, lun_index;
2689 VirtDevice *vdev;
2690 ScsiCfgData *pSpi;
2691 char data_56;
2693 dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
2694 hd->ioc->name, bus_id, target_id, lun, hd));
2697 * If the peripheral qualifier filter is enabled then if the target reports a 0x1
2698 * (i.e. The targer is capable of supporting the specified peripheral device type
2699 * on this logical unit; however, the physical device is not currently connected
2700 * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
2701 * capable of supporting a physical device on this logical unit). This is to work
2702 * around a bug in th emid-layer in some distributions in which the mid-layer will
2703 * continue to try to communicate to the LUN and evntually create a dummy LUN.
2705 if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
2706 data[0] |= 0x40;
2708 /* Is LUN supported? If so, upper 2 bits will be 0
2709 * in first byte of inquiry data.
2711 if (data[0] & 0xe0)
2712 return;
2714 if ((vdev = hd->Targets[target_id]) == NULL) {
2715 return;
2718 lun_index = (lun >> 5); /* 32 luns per lun_index */
2719 indexed_lun = (lun % 32);
2720 vdev->luns[lun_index] |= (1 << indexed_lun);
2722 if (hd->ioc->bus_type == SCSI) {
2723 if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
2724 /* Treat all Processors as SAF-TE if
2725 * command line option is set */
2726 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2727 mptscsih_writeIOCPage4(hd, target_id, bus_id);
2728 }else if ((data[0] == TYPE_PROCESSOR) &&
2729 !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
2730 if ( dlen > 49 ) {
2731 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2732 if ( data[44] == 'S' &&
2733 data[45] == 'A' &&
2734 data[46] == 'F' &&
2735 data[47] == '-' &&
2736 data[48] == 'T' &&
2737 data[49] == 'E' ) {
2738 vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
2739 mptscsih_writeIOCPage4(hd, target_id, bus_id);
2743 if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
2744 if ( dlen > 8 ) {
2745 memcpy (vdev->inq_data, data, 8);
2746 } else {
2747 memcpy (vdev->inq_data, data, dlen);
2750 /* If have not done DV, set the DV flag.
2752 pSpi = &hd->ioc->spi_data;
2753 if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
2754 if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
2755 pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
2758 vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
2761 data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */
2762 if (dlen > 56) {
2763 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2764 /* Update the target capabilities
2766 data_56 = data[56];
2767 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
2770 mptscsih_setTargetNegoParms(hd, vdev, data_56);
2771 } else {
2772 /* Initial Inquiry may not request enough data bytes to
2773 * obtain byte 57. DV will; if target doesn't return
2774 * at least 57 bytes, data[56] will be zero. */
2775 if (dlen > 56) {
2776 if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
2777 /* Update the target capabilities
2779 data_56 = data[56];
2780 vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
2781 mptscsih_setTargetNegoParms(hd, vdev, data_56);
2788 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2790 * Update the target negotiation parameters based on the
2791 * the Inquiry data, adapter capabilities, and NVRAM settings.
2794 static void
2795 mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
2797 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
2798 int id = (int) target->target_id;
2799 int nvram;
2800 VirtDevice *vdev;
2801 int ii;
2802 u8 width = MPT_NARROW;
2803 u8 factor = MPT_ASYNC;
2804 u8 offset = 0;
2805 u8 version, nfactor;
2806 u8 noQas = 1;
2808 target->negoFlags = pspi_data->noQas;
2810 /* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
2811 * support. If available, default QAS to off and allow enabling.
2812 * If not available, default QAS to on, turn off for non-disks.
2815 /* Set flags based on Inquiry data
2817 version = target->inq_data[2] & 0x07;
2818 if (version < 2) {
2819 width = 0;
2820 factor = MPT_ULTRA2;
2821 offset = pspi_data->maxSyncOffset;
2822 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2823 } else {
2824 if (target->inq_data[7] & 0x20) {
2825 width = 1;
2828 if (target->inq_data[7] & 0x10) {
2829 factor = pspi_data->minSyncFactor;
2830 if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
2831 /* bits 2 & 3 show Clocking support */
2832 if ((byte56 & 0x0C) == 0)
2833 factor = MPT_ULTRA2;
2834 else {
2835 if ((byte56 & 0x03) == 0)
2836 factor = MPT_ULTRA160;
2837 else {
2838 factor = MPT_ULTRA320;
2839 if (byte56 & 0x02)
2841 ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
2842 noQas = 0;
2844 if (target->inq_data[0] == TYPE_TAPE) {
2845 if (byte56 & 0x01)
2846 target->negoFlags |= MPT_TAPE_NEGO_IDP;
2850 } else {
2851 ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
2852 noQas = 0;
2855 offset = pspi_data->maxSyncOffset;
2857 /* If RAID, never disable QAS
2858 * else if non RAID, do not disable
2859 * QAS if bit 1 is set
2860 * bit 1 QAS support, non-raid only
2861 * bit 0 IU support
2863 if (target->raidVolume == 1) {
2864 noQas = 0;
2866 } else {
2867 factor = MPT_ASYNC;
2868 offset = 0;
2872 if ( (target->inq_data[7] & 0x02) == 0) {
2873 target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
2876 /* Update tflags based on NVRAM settings. (SCSI only)
2878 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
2879 nvram = pspi_data->nvram[id];
2880 nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
2882 if (width)
2883 width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
2885 if (offset > 0) {
2886 /* Ensure factor is set to the
2887 * maximum of: adapter, nvram, inquiry
2889 if (nfactor) {
2890 if (nfactor < pspi_data->minSyncFactor )
2891 nfactor = pspi_data->minSyncFactor;
2893 factor = max(factor, nfactor);
2894 if (factor == MPT_ASYNC)
2895 offset = 0;
2896 } else {
2897 offset = 0;
2898 factor = MPT_ASYNC;
2900 } else {
2901 factor = MPT_ASYNC;
2905 /* Make sure data is consistent
2907 if ((!width) && (factor < MPT_ULTRA2)) {
2908 factor = MPT_ULTRA2;
2911 /* Save the data to the target structure.
2913 target->minSyncFactor = factor;
2914 target->maxOffset = offset;
2915 target->maxWidth = width;
2917 target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
2919 /* Disable unused features.
2921 if (!width)
2922 target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
2924 if (!offset)
2925 target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
2927 if ( factor > MPT_ULTRA320 )
2928 noQas = 0;
2930 /* GEM, processor WORKAROUND
2932 if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
2933 target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
2934 pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
2935 } else {
2936 if (noQas && (pspi_data->noQas == 0)) {
2937 pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
2938 target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2940 /* Disable QAS in a mixed configuration case
2943 ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
2944 for (ii = 0; ii < id; ii++) {
2945 if ( (vdev = hd->Targets[ii]) ) {
2946 vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
2947 mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
2953 /* Write SDP1 on this I/O to this target */
2954 if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
2955 ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
2956 mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
2957 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
2958 } else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
2959 ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
2960 mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
2961 pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
2965 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2966 /* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
2967 * Else set the NEED_DV flag after Read Capacity Issued (disks)
2968 * or Mode Sense (cdroms).
2970 * Tapes, initTarget will set this flag on completion of Inquiry command.
2971 * Called only if DV_NOT_DONE flag is set
2973 static void
2974 mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
2976 u8 cmd;
2977 ScsiCfgData *pSpi;
2979 ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
2980 pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
2982 if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
2983 return;
2985 cmd = pReq->CDB[0];
2987 if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
2988 pSpi = &hd->ioc->spi_data;
2989 if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
2990 /* Set NEED_DV for all hidden disks
2992 Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk;
2993 int numPDisk = pSpi->pIocPg3->NumPhysDisks;
2995 while (numPDisk) {
2996 pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
2997 ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
2998 pPDisk++;
2999 numPDisk--;
3002 pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
3003 ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
3007 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3009 * If no Target, bus reset on 1st I/O. Set the flag to
3010 * prevent any future negotiations to this device.
3012 static void
3013 mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
3016 if ((hd->Targets) && (hd->Targets[target_id] == NULL))
3017 hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
3019 return;
3022 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3024 * SCSI Config Page functionality ...
3026 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3027 /* mptscsih_setDevicePage1Flags - add Requested and Configuration fields flags
3028 * based on width, factor and offset parameters.
3029 * @width: bus width
3030 * @factor: sync factor
3031 * @offset: sync offset
3032 * @requestedPtr: pointer to requested values (updated)
3033 * @configurationPtr: pointer to configuration values (updated)
3034 * @flags: flags to block WDTR or SDTR negotiation
3036 * Return: None.
3038 * Remark: Called by writeSDP1 and _dv_params
3040 static void
3041 mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags)
3043 u8 nowide = flags & MPT_TARGET_NO_NEGO_WIDE;
3044 u8 nosync = flags & MPT_TARGET_NO_NEGO_SYNC;
3046 *configurationPtr = 0;
3047 *requestedPtr = width ? MPI_SCSIDEVPAGE1_RP_WIDE : 0;
3048 *requestedPtr |= (offset << 16) | (factor << 8);
3050 if (width && offset && !nowide && !nosync) {
3051 if (factor < MPT_ULTRA160) {
3052 *requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
3053 if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
3054 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
3055 if (flags & MPT_TAPE_NEGO_IDP)
3056 *requestedPtr |= 0x08000000;
3057 } else if (factor < MPT_ULTRA2) {
3058 *requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
3062 if (nowide)
3063 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED;
3065 if (nosync)
3066 *configurationPtr |= MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED;
3068 return;
3071 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3072 /* mptscsih_writeSDP1 - write SCSI Device Page 1
3073 * @hd: Pointer to a SCSI Host Strucutre
3074 * @portnum: IOC port number
3075 * @target_id: writeSDP1 for single ID
3076 * @flags: MPT_SCSICFG_ALL_IDS, MPT_SCSICFG_USE_NVRAM, MPT_SCSICFG_BLK_NEGO
3078 * Return: -EFAULT if read of config page header fails
3079 * or 0 if success.
3081 * Remark: If a target has been found, the settings from the
3082 * target structure are used, else the device is set
3083 * to async/narrow.
3085 * Remark: Called during init and after a FW reload.
3086 * Remark: We do not wait for a return, write pages sequentially.
3088 static int
3089 mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
3091 MPT_ADAPTER *ioc = hd->ioc;
3092 Config_t *pReq;
3093 SCSIDevicePage1_t *pData;
3094 VirtDevice *pTarget;
3095 MPT_FRAME_HDR *mf;
3096 dma_addr_t dataDma;
3097 u16 req_idx;
3098 u32 frameOffset;
3099 u32 requested, configuration, flagsLength;
3100 int ii, nvram;
3101 int id = 0, maxid = 0;
3102 u8 width;
3103 u8 factor;
3104 u8 offset;
3105 u8 bus = 0;
3106 u8 negoFlags;
3107 u8 maxwidth, maxoffset, maxfactor;
3109 if (ioc->spi_data.sdp1length == 0)
3110 return 0;
3112 if (flags & MPT_SCSICFG_ALL_IDS) {
3113 id = 0;
3114 maxid = ioc->sh->max_id - 1;
3115 } else if (ioc->sh) {
3116 id = target_id;
3117 maxid = min_t(int, id, ioc->sh->max_id - 1);
3120 for (; id <= maxid; id++) {
3122 if (id == ioc->pfacts[portnum].PortSCSIID)
3123 continue;
3125 /* Use NVRAM to get adapter and target maximums
3126 * Data over-riden by target structure information, if present
3128 maxwidth = ioc->spi_data.maxBusWidth;
3129 maxoffset = ioc->spi_data.maxSyncOffset;
3130 maxfactor = ioc->spi_data.minSyncFactor;
3131 if (ioc->spi_data.nvram && (ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3132 nvram = ioc->spi_data.nvram[id];
3134 if (maxwidth)
3135 maxwidth = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
3137 if (maxoffset > 0) {
3138 maxfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
3139 if (maxfactor == 0) {
3140 /* Key for async */
3141 maxfactor = MPT_ASYNC;
3142 maxoffset = 0;
3143 } else if (maxfactor < ioc->spi_data.minSyncFactor) {
3144 maxfactor = ioc->spi_data.minSyncFactor;
3146 } else
3147 maxfactor = MPT_ASYNC;
3150 /* Set the negotiation flags.
3152 negoFlags = ioc->spi_data.noQas;
3153 if (!maxwidth)
3154 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
3156 if (!maxoffset)
3157 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
3159 if (flags & MPT_SCSICFG_USE_NVRAM) {
3160 width = maxwidth;
3161 factor = maxfactor;
3162 offset = maxoffset;
3163 } else {
3164 width = 0;
3165 factor = MPT_ASYNC;
3166 offset = 0;
3167 //negoFlags = 0;
3168 //negoFlags = MPT_TARGET_NO_NEGO_SYNC;
3171 /* If id is not a raid volume, get the updated
3172 * transmission settings from the target structure.
3174 if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
3175 width = pTarget->maxWidth;
3176 factor = pTarget->minSyncFactor;
3177 offset = pTarget->maxOffset;
3178 negoFlags = pTarget->negoFlags;
3181 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3182 /* Force to async and narrow if DV has not been executed
3183 * for this ID
3185 if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) {
3186 width = 0;
3187 factor = MPT_ASYNC;
3188 offset = 0;
3190 #endif
3192 if (flags & MPT_SCSICFG_BLK_NEGO)
3193 negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
3195 mptscsih_setDevicePage1Flags(width, factor, offset,
3196 &requested, &configuration, negoFlags);
3197 dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
3198 target_id, width, factor, offset, negoFlags, requested, configuration));
3200 /* Get a MF for this command.
3202 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3203 dfailprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
3204 ioc->name));
3205 return -EAGAIN;
3208 ddvprintk((MYIOC_s_INFO_FMT "WriteSDP1 (mf=%p, id=%d, req=0x%x, cfg=0x%x)\n",
3209 hd->ioc->name, mf, id, requested, configuration));
3212 /* Set the request and the data pointers.
3213 * Request takes: 36 bytes (32 bit SGE)
3214 * SCSI Device Page 1 requires 16 bytes
3215 * 40 + 16 <= size of SCSI IO Request = 56 bytes
3216 * and MF size >= 64 bytes.
3217 * Place data at end of MF.
3219 pReq = (Config_t *)mf;
3221 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3222 frameOffset = ioc->req_sz - sizeof(SCSIDevicePage1_t);
3224 pData = (SCSIDevicePage1_t *)((u8 *) mf + frameOffset);
3225 dataDma = ioc->req_frames_dma + (req_idx * ioc->req_sz) + frameOffset;
3227 /* Complete the request frame (same for all requests).
3229 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3230 pReq->Reserved = 0;
3231 pReq->ChainOffset = 0;
3232 pReq->Function = MPI_FUNCTION_CONFIG;
3233 pReq->ExtPageLength = 0;
3234 pReq->ExtPageType = 0;
3235 pReq->MsgFlags = 0;
3236 for (ii=0; ii < 8; ii++) {
3237 pReq->Reserved2[ii] = 0;
3239 pReq->Header.PageVersion = ioc->spi_data.sdp1version;
3240 pReq->Header.PageLength = ioc->spi_data.sdp1length;
3241 pReq->Header.PageNumber = 1;
3242 pReq->Header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3243 pReq->PageAddress = cpu_to_le32(id | (bus << 8 ));
3245 /* Add a SGE to the config request.
3247 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE | ioc->spi_data.sdp1length * 4;
3249 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3251 /* Set up the common data portion
3253 pData->Header.PageVersion = pReq->Header.PageVersion;
3254 pData->Header.PageLength = pReq->Header.PageLength;
3255 pData->Header.PageNumber = pReq->Header.PageNumber;
3256 pData->Header.PageType = pReq->Header.PageType;
3257 pData->RequestedParameters = cpu_to_le32(requested);
3258 pData->Reserved = 0;
3259 pData->Configuration = cpu_to_le32(configuration);
3261 dprintk((MYIOC_s_INFO_FMT
3262 "write SDP1: id %d pgaddr 0x%x req 0x%x config 0x%x\n",
3263 ioc->name, id, (id | (bus<<8)),
3264 requested, configuration));
3266 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3269 return 0;
3272 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3273 /* mptscsih_writeIOCPage4 - write IOC Page 4
3274 * @hd: Pointer to a SCSI Host Structure
3275 * @target_id: write IOC Page4 for this ID & Bus
3277 * Return: -EAGAIN if unable to obtain a Message Frame
3278 * or 0 if success.
3280 * Remark: We do not wait for a return, write pages sequentially.
3282 static int
3283 mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
3285 MPT_ADAPTER *ioc = hd->ioc;
3286 Config_t *pReq;
3287 IOCPage4_t *IOCPage4Ptr;
3288 MPT_FRAME_HDR *mf;
3289 dma_addr_t dataDma;
3290 u16 req_idx;
3291 u32 frameOffset;
3292 u32 flagsLength;
3293 int ii;
3295 /* Get a MF for this command.
3297 if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
3298 dfailprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
3299 ioc->name));
3300 return -EAGAIN;
3303 /* Set the request and the data pointers.
3304 * Place data at end of MF.
3306 pReq = (Config_t *)mf;
3308 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3309 frameOffset = ioc->req_sz - sizeof(IOCPage4_t);
3311 /* Complete the request frame (same for all requests).
3313 pReq->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3314 pReq->Reserved = 0;
3315 pReq->ChainOffset = 0;
3316 pReq->Function = MPI_FUNCTION_CONFIG;
3317 pReq->ExtPageLength = 0;
3318 pReq->ExtPageType = 0;
3319 pReq->MsgFlags = 0;
3320 for (ii=0; ii < 8; ii++) {
3321 pReq->Reserved2[ii] = 0;
3324 IOCPage4Ptr = ioc->spi_data.pIocPg4;
3325 dataDma = ioc->spi_data.IocPg4_dma;
3326 ii = IOCPage4Ptr->ActiveSEP++;
3327 IOCPage4Ptr->SEP[ii].SEPTargetID = target_id;
3328 IOCPage4Ptr->SEP[ii].SEPBus = bus;
3329 pReq->Header = IOCPage4Ptr->Header;
3330 pReq->PageAddress = cpu_to_le32(target_id | (bus << 8 ));
3332 /* Add a SGE to the config request.
3334 flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE |
3335 (IOCPage4Ptr->Header.PageLength + ii) * 4;
3337 mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
3339 dinitprintk((MYIOC_s_INFO_FMT
3340 "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
3341 ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
3343 mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
3345 return 0;
3348 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3350 * Bus Scan and Domain Validation functionality ...
3353 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3355 * mptscsih_scandv_complete - Scan and DV callback routine registered
3356 * to Fustion MPT (base) driver.
3358 * @ioc: Pointer to MPT_ADAPTER structure
3359 * @mf: Pointer to original MPT request frame
3360 * @mr: Pointer to MPT reply frame (NULL if TurboReply)
3362 * This routine is called from mpt.c::mpt_interrupt() at the completion
3363 * of any SCSI IO request.
3364 * This routine is registered with the Fusion MPT (base) driver at driver
3365 * load/init time via the mpt_register() API call.
3367 * Returns 1 indicating alloc'd request frame ptr should be freed.
3369 * Remark: Sets a completion code and (possibly) saves sense data
3370 * in the IOC member localReply structure.
3371 * Used ONLY for DV and other internal commands.
3374 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
3376 MPT_SCSI_HOST *hd;
3377 SCSIIORequest_t *pReq;
3378 int completionCode;
3379 u16 req_idx;
3381 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
3383 if ((mf == NULL) ||
3384 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
3385 printk(MYIOC_s_ERR_FMT
3386 "ScanDvComplete, %s req frame ptr! (=%p)\n",
3387 ioc->name, mf?"BAD":"NULL", (void *) mf);
3388 goto wakeup;
3391 del_timer(&hd->timer);
3392 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3393 hd->ScsiLookup[req_idx] = NULL;
3394 pReq = (SCSIIORequest_t *) mf;
3396 if (mf != hd->cmdPtr) {
3397 printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n",
3398 hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx);
3400 hd->cmdPtr = NULL;
3402 ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
3403 hd->ioc->name, mf, mr, req_idx));
3405 hd->pLocal = &hd->localReply;
3406 hd->pLocal->scsiStatus = 0;
3408 /* If target struct exists, clear sense valid flag.
3410 if (mr == NULL) {
3411 completionCode = MPT_SCANDV_GOOD;
3412 } else {
3413 SCSIIOReply_t *pReply;
3414 u16 status;
3415 u8 scsi_status;
3417 pReply = (SCSIIOReply_t *) mr;
3419 status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
3420 scsi_status = pReply->SCSIStatus;
3422 ddvtprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
3423 status, pReply->SCSIState, scsi_status,
3424 le32_to_cpu(pReply->IOCLogInfo)));
3426 switch(status) {
3428 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
3429 completionCode = MPT_SCANDV_SELECTION_TIMEOUT;
3430 break;
3432 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
3433 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
3434 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
3435 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
3436 completionCode = MPT_SCANDV_DID_RESET;
3437 break;
3439 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
3440 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
3441 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
3442 if (pReply->Function == MPI_FUNCTION_CONFIG) {
3443 ConfigReply_t *pr = (ConfigReply_t *)mr;
3444 completionCode = MPT_SCANDV_GOOD;
3445 hd->pLocal->header.PageVersion = pr->Header.PageVersion;
3446 hd->pLocal->header.PageLength = pr->Header.PageLength;
3447 hd->pLocal->header.PageNumber = pr->Header.PageNumber;
3448 hd->pLocal->header.PageType = pr->Header.PageType;
3450 } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) {
3451 /* If the RAID Volume request is successful,
3452 * return GOOD, else indicate that
3453 * some type of error occurred.
3455 MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr;
3456 if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS)
3457 completionCode = MPT_SCANDV_GOOD;
3458 else
3459 completionCode = MPT_SCANDV_SOME_ERROR;
3461 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
3462 u8 *sense_data;
3463 int sz;
3465 /* save sense data in global structure
3467 completionCode = MPT_SCANDV_SENSE;
3468 hd->pLocal->scsiStatus = scsi_status;
3469 sense_data = ((u8 *)hd->ioc->sense_buf_pool +
3470 (req_idx * MPT_SENSE_BUFFER_ALLOC));
3472 sz = min_t(int, pReq->SenseBufferLength,
3473 SCSI_STD_SENSE_BYTES);
3474 memcpy(hd->pLocal->sense, sense_data, sz);
3476 ddvprintk((KERN_NOTICE " Check Condition, sense ptr %p\n",
3477 sense_data));
3478 } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
3479 if (pReq->CDB[0] == INQUIRY)
3480 completionCode = MPT_SCANDV_ISSUE_SENSE;
3481 else
3482 completionCode = MPT_SCANDV_DID_RESET;
3484 else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS)
3485 completionCode = MPT_SCANDV_DID_RESET;
3486 else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3487 completionCode = MPT_SCANDV_DID_RESET;
3488 else {
3489 completionCode = MPT_SCANDV_GOOD;
3490 hd->pLocal->scsiStatus = scsi_status;
3492 break;
3494 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
3495 if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
3496 completionCode = MPT_SCANDV_DID_RESET;
3497 else
3498 completionCode = MPT_SCANDV_SOME_ERROR;
3499 break;
3501 default:
3502 completionCode = MPT_SCANDV_SOME_ERROR;
3503 break;
3505 } /* switch(status) */
3507 ddvtprintk((KERN_NOTICE " completionCode set to %08xh\n",
3508 completionCode));
3509 } /* end of address reply case */
3511 hd->pLocal->completion = completionCode;
3513 /* MF and RF are freed in mpt_interrupt
3515 wakeup:
3516 /* Free Chain buffers (will never chain) in scan or dv */
3517 //mptscsih_freeChainBuffers(ioc, req_idx);
3520 * Wake up the original calling thread
3522 hd->scandv_wait_done = 1;
3523 wake_up(&hd->scandv_waitq);
3525 return 1;
3528 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3529 /* mptscsih_timer_expired - Call back for timer process.
3530 * Used only for dv functionality.
3531 * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
3534 void
3535 mptscsih_timer_expired(unsigned long data)
3537 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
3539 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr));
3541 if (hd->cmdPtr) {
3542 MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr;
3544 if (cmd->Function == MPI_FUNCTION_SCSI_IO_REQUEST) {
3545 /* Desire to issue a task management request here.
3546 * TM requests MUST be single threaded.
3547 * If old eh code and no TM current, issue request.
3548 * If new eh code, do nothing. Wait for OS cmd timeout
3549 * for bus reset.
3551 ddvtprintk((MYIOC_s_NOTE_FMT "DV Cmd Timeout: NoOp\n", hd->ioc->name));
3552 } else {
3553 /* Perform a FW reload */
3554 if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) {
3555 printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name);
3558 } else {
3559 /* This should NEVER happen */
3560 printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name);
3563 /* No more processing.
3564 * TM call will generate an interrupt for SCSI TM Management.
3565 * The FW will reply to all outstanding commands, callback will finish cleanup.
3566 * Hard reset clean-up will free all resources.
3568 ddvprintk((MYIOC_s_WARN_FMT "Timer Expired Complete!\n", hd->ioc->name));
3570 return;
3573 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
3574 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3575 /* mptscsih_do_raid - Format and Issue a RAID volume request message.
3576 * @hd: Pointer to scsi host structure
3577 * @action: What do be done.
3578 * @id: Logical target id.
3579 * @bus: Target locations bus.
3581 * Returns: < 0 on a fatal error
3582 * 0 on success
3584 * Remark: Wait to return until reply processed by the ISR.
3586 static int
3587 mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
3589 MpiRaidActionRequest_t *pReq;
3590 MPT_FRAME_HDR *mf;
3591 int in_isr;
3593 in_isr = in_interrupt();
3594 if (in_isr) {
3595 dprintk((MYIOC_s_WARN_FMT "Internal raid request not allowed in ISR context!\n",
3596 hd->ioc->name));
3597 return -EPERM;
3600 /* Get and Populate a free Frame
3602 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3603 ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
3604 hd->ioc->name));
3605 return -EAGAIN;
3607 pReq = (MpiRaidActionRequest_t *)mf;
3608 pReq->Action = action;
3609 pReq->Reserved1 = 0;
3610 pReq->ChainOffset = 0;
3611 pReq->Function = MPI_FUNCTION_RAID_ACTION;
3612 pReq->VolumeID = io->id;
3613 pReq->VolumeBus = io->bus;
3614 pReq->PhysDiskNum = io->physDiskNum;
3615 pReq->MsgFlags = 0;
3616 pReq->Reserved2 = 0;
3617 pReq->ActionDataWord = 0; /* Reserved for this action */
3618 //pReq->ActionDataSGE = 0;
3620 mpt_add_sge((char *)&pReq->ActionDataSGE,
3621 MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);
3623 ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n",
3624 hd->ioc->name, action, io->id));
3626 hd->pLocal = NULL;
3627 hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
3628 hd->scandv_wait_done = 0;
3630 /* Save cmd pointer, for resource free if timeout or
3631 * FW reload occurs
3633 hd->cmdPtr = mf;
3635 add_timer(&hd->timer);
3636 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3637 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3639 if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
3640 return -1;
3642 return 0;
3644 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
3646 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3648 * mptscsih_do_cmd - Do internal command.
3649 * @hd: MPT_SCSI_HOST pointer
3650 * @io: INTERNAL_CMD pointer.
3652 * Issue the specified internally generated command and do command
3653 * specific cleanup. For bus scan / DV only.
3654 * NOTES: If command is Inquiry and status is good,
3655 * initialize a target structure, save the data
3657 * Remark: Single threaded access only.
3659 * Return:
3660 * < 0 if an illegal command or no resources
3662 * 0 if good
3664 * > 0 if command complete but some type of completion error.
3666 static int
3667 mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
3669 MPT_FRAME_HDR *mf;
3670 SCSIIORequest_t *pScsiReq;
3671 SCSIIORequest_t ReqCopy;
3672 int my_idx, ii, dir;
3673 int rc, cmdTimeout;
3674 int in_isr;
3675 char cmdLen;
3676 char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
3677 char cmd = io->cmd;
3679 in_isr = in_interrupt();
3680 if (in_isr) {
3681 dprintk((MYIOC_s_WARN_FMT "Internal SCSI IO request not allowed in ISR context!\n",
3682 hd->ioc->name));
3683 return -EPERM;
3687 /* Set command specific information
3689 switch (cmd) {
3690 case INQUIRY:
3691 cmdLen = 6;
3692 dir = MPI_SCSIIO_CONTROL_READ;
3693 CDB[0] = cmd;
3694 CDB[4] = io->size;
3695 cmdTimeout = 10;
3696 break;
3698 case TEST_UNIT_READY:
3699 cmdLen = 6;
3700 dir = MPI_SCSIIO_CONTROL_READ;
3701 cmdTimeout = 10;
3702 break;
3704 case START_STOP:
3705 cmdLen = 6;
3706 dir = MPI_SCSIIO_CONTROL_READ;
3707 CDB[0] = cmd;
3708 CDB[4] = 1; /*Spin up the disk */
3709 cmdTimeout = 15;
3710 break;
3712 case REQUEST_SENSE:
3713 cmdLen = 6;
3714 CDB[0] = cmd;
3715 CDB[4] = io->size;
3716 dir = MPI_SCSIIO_CONTROL_READ;
3717 cmdTimeout = 10;
3718 break;
3720 case READ_BUFFER:
3721 cmdLen = 10;
3722 dir = MPI_SCSIIO_CONTROL_READ;
3723 CDB[0] = cmd;
3724 if (io->flags & MPT_ICFLAG_ECHO) {
3725 CDB[1] = 0x0A;
3726 } else {
3727 CDB[1] = 0x02;
3730 if (io->flags & MPT_ICFLAG_BUF_CAP) {
3731 CDB[1] |= 0x01;
3733 CDB[6] = (io->size >> 16) & 0xFF;
3734 CDB[7] = (io->size >> 8) & 0xFF;
3735 CDB[8] = io->size & 0xFF;
3736 cmdTimeout = 10;
3737 break;
3739 case WRITE_BUFFER:
3740 cmdLen = 10;
3741 dir = MPI_SCSIIO_CONTROL_WRITE;
3742 CDB[0] = cmd;
3743 if (io->flags & MPT_ICFLAG_ECHO) {
3744 CDB[1] = 0x0A;
3745 } else {
3746 CDB[1] = 0x02;
3748 CDB[6] = (io->size >> 16) & 0xFF;
3749 CDB[7] = (io->size >> 8) & 0xFF;
3750 CDB[8] = io->size & 0xFF;
3751 cmdTimeout = 10;
3752 break;
3754 case RESERVE:
3755 cmdLen = 6;
3756 dir = MPI_SCSIIO_CONTROL_READ;
3757 CDB[0] = cmd;
3758 cmdTimeout = 10;
3759 break;
3761 case RELEASE:
3762 cmdLen = 6;
3763 dir = MPI_SCSIIO_CONTROL_READ;
3764 CDB[0] = cmd;
3765 cmdTimeout = 10;
3766 break;
3768 case SYNCHRONIZE_CACHE:
3769 cmdLen = 10;
3770 dir = MPI_SCSIIO_CONTROL_READ;
3771 CDB[0] = cmd;
3772 // CDB[1] = 0x02; /* set immediate bit */
3773 cmdTimeout = 10;
3774 break;
3776 default:
3777 /* Error Case */
3778 return -EFAULT;
3781 /* Get and Populate a free Frame
3783 if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
3784 ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
3785 hd->ioc->name));
3786 return -EBUSY;
3789 pScsiReq = (SCSIIORequest_t *) mf;
3791 /* Get the request index */
3792 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
3793 ADD_INDEX_LOG(my_idx); /* for debug */
3795 if (io->flags & MPT_ICFLAG_PHYS_DISK) {
3796 pScsiReq->TargetID = io->physDiskNum;
3797 pScsiReq->Bus = 0;
3798 pScsiReq->ChainOffset = 0;
3799 pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3800 } else {
3801 pScsiReq->TargetID = io->id;
3802 pScsiReq->Bus = io->bus;
3803 pScsiReq->ChainOffset = 0;
3804 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
3807 pScsiReq->CDBLength = cmdLen;
3808 pScsiReq->SenseBufferLength = MPT_SENSE_BUFFER_SIZE;
3810 pScsiReq->Reserved = 0;
3812 pScsiReq->MsgFlags = mpt_msg_flags();
3813 /* MsgContext set in mpt_get_msg_fram call */
3815 for (ii=0; ii < 8; ii++)
3816 pScsiReq->LUN[ii] = 0;
3817 pScsiReq->LUN[1] = io->lun;
3819 if (io->flags & MPT_ICFLAG_TAGGED_CMD)
3820 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_SIMPLEQ);
3821 else
3822 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3824 if (cmd == REQUEST_SENSE) {
3825 pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
3826 ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
3827 hd->ioc->name, cmd));
3830 for (ii=0; ii < 16; ii++)
3831 pScsiReq->CDB[ii] = CDB[ii];
3833 pScsiReq->DataLength = cpu_to_le32(io->size);
3834 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma
3835 + (my_idx * MPT_SENSE_BUFFER_ALLOC));
3837 ddvprintk((MYIOC_s_INFO_FMT "Sending Command 0x%x for (%d:%d:%d)\n",
3838 hd->ioc->name, cmd, io->bus, io->id, io->lun));
3840 if (dir == MPI_SCSIIO_CONTROL_READ) {
3841 mpt_add_sge((char *) &pScsiReq->SGL,
3842 MPT_SGE_FLAGS_SSIMPLE_READ | io->size,
3843 io->data_dma);
3844 } else {
3845 mpt_add_sge((char *) &pScsiReq->SGL,
3846 MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size,
3847 io->data_dma);
3850 /* The ISR will free the request frame, but we need
3851 * the information to initialize the target. Duplicate.
3853 memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t));
3855 /* Issue this command after:
3856 * finish init
3857 * add timer
3858 * Wait until the reply has been received
3859 * ScsiScanDvCtx callback function will
3860 * set hd->pLocal;
3861 * set scandv_wait_done and call wake_up
3863 hd->pLocal = NULL;
3864 hd->timer.expires = jiffies + HZ*cmdTimeout;
3865 hd->scandv_wait_done = 0;
3867 /* Save cmd pointer, for resource free if timeout or
3868 * FW reload occurs
3870 hd->cmdPtr = mf;
3872 add_timer(&hd->timer);
3873 mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
3874 wait_event(hd->scandv_waitq, hd->scandv_wait_done);
3876 if (hd->pLocal) {
3877 rc = hd->pLocal->completion;
3878 hd->pLocal->skip = 0;
3880 /* Always set fatal error codes in some cases.
3882 if (rc == MPT_SCANDV_SELECTION_TIMEOUT)
3883 rc = -ENXIO;
3884 else if (rc == MPT_SCANDV_SOME_ERROR)
3885 rc = -rc;
3886 } else {
3887 rc = -EFAULT;
3888 /* This should never happen. */
3889 ddvprintk((MYIOC_s_INFO_FMT "_do_cmd: Null pLocal!!!\n",
3890 hd->ioc->name));
3893 return rc;
3896 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
3898 * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
3899 * @hd: Pointer to MPT_SCSI_HOST structure
3900 * @portnum: IOC port number
3902 * Uses the ISR, but with special processing.
3903 * MUST be single-threaded.
3905 * Return: 0 on completion
3907 static int
3908 mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
3910 MPT_ADAPTER *ioc= hd->ioc;
3911 VirtDevice *pTarget;
3912 SCSIDevicePage1_t *pcfg1Data = NULL;
3913 INTERNAL_CMD iocmd;
3914 CONFIGPARMS cfg;
3915 dma_addr_t cfg1_dma_addr = -1;
3916 ConfigPageHeader_t header1;
3917 int bus = 0;
3918 int id = 0;
3919 int lun;
3920 int indexed_lun, lun_index;
3921 int hostId = ioc->pfacts[portnum].PortSCSIID;
3922 int max_id;
3923 int requested, configuration, data;
3924 int doConfig = 0;
3925 u8 flags, factor;
3927 max_id = ioc->sh->max_id - 1;
3929 /* Following parameters will not change
3930 * in this routine.
3932 iocmd.cmd = SYNCHRONIZE_CACHE;
3933 iocmd.flags = 0;
3934 iocmd.physDiskNum = -1;
3935 iocmd.data = NULL;
3936 iocmd.data_dma = -1;
3937 iocmd.size = 0;
3938 iocmd.rsvd = iocmd.rsvd2 = 0;
3940 /* No SCSI hosts
3942 if (hd->Targets == NULL)
3943 return 0;
3945 /* Skip the host
3947 if (id == hostId)
3948 id++;
3950 /* Write SDP1 for all SCSI devices
3951 * Alloc memory and set up config buffer
3953 if (ioc->bus_type == SCSI) {
3954 if (ioc->spi_data.sdp1length > 0) {
3955 pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
3956 ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
3958 if (pcfg1Data != NULL) {
3959 doConfig = 1;
3960 header1.PageVersion = ioc->spi_data.sdp1version;
3961 header1.PageLength = ioc->spi_data.sdp1length;
3962 header1.PageNumber = 1;
3963 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
3964 cfg.cfghdr.hdr = &header1;
3965 cfg.physAddr = cfg1_dma_addr;
3966 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
3967 cfg.dir = 1;
3968 cfg.timeout = 0;
3973 /* loop through all devices on this port
3975 while (bus < MPT_MAX_BUS) {
3976 iocmd.bus = bus;
3977 iocmd.id = id;
3978 pTarget = hd->Targets[(int)id];
3980 if (doConfig) {
3982 /* Set the negotiation flags */
3983 if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
3984 flags = pTarget->negoFlags;
3985 } else {
3986 flags = hd->ioc->spi_data.noQas;
3987 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
3988 data = hd->ioc->spi_data.nvram[id];
3990 if (data & MPT_NVRAM_WIDE_DISABLE)
3991 flags |= MPT_TARGET_NO_NEGO_WIDE;
3993 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
3994 if ((factor == 0) || (factor == MPT_ASYNC))
3995 flags |= MPT_TARGET_NO_NEGO_SYNC;
3999 /* Force to async, narrow */
4000 mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
4001 &configuration, flags);
4002 dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
4003 "offset=0 negoFlags=%x request=%x config=%x\n",
4004 id, flags, requested, configuration));
4005 pcfg1Data->RequestedParameters = cpu_to_le32(requested);
4006 pcfg1Data->Reserved = 0;
4007 pcfg1Data->Configuration = cpu_to_le32(configuration);
4008 cfg.pageAddr = (bus<<8) | id;
4009 mpt_config(hd->ioc, &cfg);
4012 /* If target Ptr NULL or if this target is NOT a disk, skip.
4014 if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){
4015 for (lun=0; lun <= MPT_LAST_LUN; lun++) {
4016 /* If LUN present, issue the command
4018 lun_index = (lun >> 5); /* 32 luns per lun_index */
4019 indexed_lun = (lun % 32);
4020 if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
4021 iocmd.lun = lun;
4022 (void) mptscsih_do_cmd(hd, &iocmd);
4027 /* get next relevant device */
4028 id++;
4030 if (id == hostId)
4031 id++;
4033 if (id > max_id) {
4034 id = 0;
4035 bus++;
4039 if (pcfg1Data) {
4040 pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
4043 return 0;
4046 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
4047 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4049 * mptscsih_domainValidation - Top level handler for domain validation.
4050 * @hd: Pointer to MPT_SCSI_HOST structure.
4052 * Uses the ISR, but with special processing.
4053 * Called from schedule, should not be in interrupt mode.
4054 * While thread alive, do dv for all devices needing dv
4056 * Return: None.
4058 static void
4059 mptscsih_domainValidation(void *arg)
4061 MPT_SCSI_HOST *hd;
4062 MPT_ADAPTER *ioc;
4063 unsigned long flags;
4064 int id, maxid, dvStatus, did;
4065 int ii, isPhysDisk;
4067 spin_lock_irqsave(&dvtaskQ_lock, flags);
4068 dvtaskQ_active = 1;
4069 if (dvtaskQ_release) {
4070 dvtaskQ_active = 0;
4071 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4072 return;
4074 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4076 /* For this ioc, loop through all devices and do dv to each device.
4077 * When complete with this ioc, search through the ioc list, and
4078 * for each scsi ioc found, do dv for all devices. Exit when no
4079 * device needs dv.
4081 did = 1;
4082 while (did) {
4083 did = 0;
4084 list_for_each_entry(ioc, &ioc_list, list) {
4085 spin_lock_irqsave(&dvtaskQ_lock, flags);
4086 if (dvtaskQ_release) {
4087 dvtaskQ_active = 0;
4088 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4089 return;
4091 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4093 msleep(250);
4095 /* DV only to SCSI adapters */
4096 if (ioc->bus_type != SCSI)
4097 continue;
4099 /* Make sure everything looks ok */
4100 if (ioc->sh == NULL)
4101 continue;
4103 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
4104 if (hd == NULL)
4105 continue;
4107 if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) {
4108 mpt_read_ioc_pg_3(ioc);
4109 if (ioc->spi_data.pIocPg3) {
4110 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4111 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4113 while (numPDisk) {
4114 if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE)
4115 ioc->spi_data.dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
4117 pPDisk++;
4118 numPDisk--;
4121 ioc->spi_data.forceDv &= ~MPT_SCSICFG_RELOAD_IOC_PG3;
4124 maxid = min_t(int, ioc->sh->max_id, MPT_MAX_SCSI_DEVICES);
4126 for (id = 0; id < maxid; id++) {
4127 spin_lock_irqsave(&dvtaskQ_lock, flags);
4128 if (dvtaskQ_release) {
4129 dvtaskQ_active = 0;
4130 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4131 return;
4133 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4134 dvStatus = hd->ioc->spi_data.dvStatus[id];
4136 if (dvStatus & MPT_SCSICFG_NEED_DV) {
4137 did++;
4138 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
4139 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
4141 msleep(250);
4143 /* If hidden phys disk, block IO's to all
4144 * raid volumes
4145 * else, process normally
4147 isPhysDisk = mptscsih_is_phys_disk(ioc, id);
4148 if (isPhysDisk) {
4149 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4150 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
4151 hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING;
4156 if (mptscsih_doDv(hd, 0, id) == 1) {
4157 /* Untagged device was busy, try again
4159 hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_NEED_DV;
4160 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_PENDING;
4161 } else {
4162 /* DV is complete. Clear flags.
4164 hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
4167 if (isPhysDisk) {
4168 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4169 if (hd->ioc->spi_data.isRaid & (1 << ii)) {
4170 hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING;
4175 if (hd->ioc->spi_data.noQas)
4176 mptscsih_qas_check(hd, id);
4182 spin_lock_irqsave(&dvtaskQ_lock, flags);
4183 dvtaskQ_active = 0;
4184 spin_unlock_irqrestore(&dvtaskQ_lock, flags);
4186 return;
4189 /* Search IOC page 3 to determine if this is hidden physical disk
4191 static int
4192 mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
4194 if (ioc->spi_data.pIocPg3) {
4195 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4196 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4198 while (numPDisk) {
4199 if (pPDisk->PhysDiskID == id) {
4200 return 1;
4202 pPDisk++;
4203 numPDisk--;
4206 return 0;
4209 /* Write SDP1 if no QAS has been enabled
4211 static void
4212 mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
4214 VirtDevice *pTarget;
4215 int ii;
4217 if (hd->Targets == NULL)
4218 return;
4220 for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
4221 if (ii == id)
4222 continue;
4224 if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
4225 continue;
4227 pTarget = hd->Targets[ii];
4229 if ((pTarget != NULL) && (!pTarget->raidVolume)) {
4230 if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
4231 pTarget->negoFlags |= hd->ioc->spi_data.noQas;
4232 dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
4233 mptscsih_writeSDP1(hd, 0, ii, 0);
4235 } else {
4236 if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
4237 dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
4238 mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
4242 return;
4247 #define MPT_GET_NVRAM_VALS 0x01
4248 #define MPT_UPDATE_MAX 0x02
4249 #define MPT_SET_MAX 0x04
4250 #define MPT_SET_MIN 0x08
4251 #define MPT_FALLBACK 0x10
4252 #define MPT_SAVE 0x20
4254 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
4256 * mptscsih_doDv - Perform domain validation to a target.
4257 * @hd: Pointer to MPT_SCSI_HOST structure.
4258 * @portnum: IOC port number.
4259 * @target: Physical ID of this target
4261 * Uses the ISR, but with special processing.
4262 * MUST be single-threaded.
4263 * Test will exit if target is at async & narrow.
4265 * Return: None.
4267 static int
4268 mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
4270 MPT_ADAPTER *ioc = hd->ioc;
4271 VirtDevice *pTarget;
4272 SCSIDevicePage1_t *pcfg1Data;
4273 SCSIDevicePage0_t *pcfg0Data;
4274 u8 *pbuf1;
4275 u8 *pbuf2;
4276 u8 *pDvBuf;
4277 dma_addr_t dvbuf_dma = -1;
4278 dma_addr_t buf1_dma = -1;
4279 dma_addr_t buf2_dma = -1;
4280 dma_addr_t cfg1_dma_addr = -1;
4281 dma_addr_t cfg0_dma_addr = -1;
4282 ConfigPageHeader_t header1;
4283 ConfigPageHeader_t header0;
4284 DVPARAMETERS dv;
4285 INTERNAL_CMD iocmd;
4286 CONFIGPARMS cfg;
4287 int dv_alloc = 0;
4288 int rc, sz = 0;
4289 int bufsize = 0;
4290 int dataBufSize = 0;
4291 int echoBufSize = 0;
4292 int notDone;
4293 int patt;
4294 int repeat;
4295 int retcode = 0;
4296 int nfactor = MPT_ULTRA320;
4297 char firstPass = 1;
4298 char doFallback = 0;
4299 char readPage0;
4300 char bus, lun;
4301 char inq0 = 0;
4303 if (ioc->spi_data.sdp1length == 0)
4304 return 0;
4306 if (ioc->spi_data.sdp0length == 0)
4307 return 0;
4309 /* If multiple buses are used, require that the initiator
4310 * id be the same on all buses.
4312 if (id == ioc->pfacts[0].PortSCSIID)
4313 return 0;
4315 lun = 0;
4316 bus = (u8) bus_number;
4317 ddvtprintk((MYIOC_s_NOTE_FMT
4318 "DV started: bus=%d, id=%d dv @ %p\n",
4319 ioc->name, bus, id, &dv));
4321 /* Prep DV structure
4323 memset (&dv, 0, sizeof(DVPARAMETERS));
4324 dv.id = id;
4326 /* Populate tmax with the current maximum
4327 * transfer parameters for this target.
4328 * Exit if narrow and async.
4330 dv.cmd = MPT_GET_NVRAM_VALS;
4331 mptscsih_dv_parms(hd, &dv, NULL);
4333 /* Prep SCSI IO structure
4335 iocmd.id = id;
4336 iocmd.bus = bus;
4337 iocmd.lun = lun;
4338 iocmd.flags = 0;
4339 iocmd.physDiskNum = -1;
4340 iocmd.rsvd = iocmd.rsvd2 = 0;
4342 pTarget = hd->Targets[id];
4344 /* Use tagged commands if possible.
4346 if (pTarget) {
4347 if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
4348 iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
4349 else {
4350 if (hd->ioc->facts.FWVersion.Word < 0x01000600)
4351 return 0;
4353 if ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4354 (hd->ioc->facts.FWVersion.Word < 0x01010B00))
4355 return 0;
4359 /* Prep cfg structure
4361 cfg.pageAddr = (bus<<8) | id;
4362 cfg.cfghdr.hdr = NULL;
4364 /* Prep SDP0 header
4366 header0.PageVersion = ioc->spi_data.sdp0version;
4367 header0.PageLength = ioc->spi_data.sdp0length;
4368 header0.PageNumber = 0;
4369 header0.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4371 /* Prep SDP1 header
4373 header1.PageVersion = ioc->spi_data.sdp1version;
4374 header1.PageLength = ioc->spi_data.sdp1length;
4375 header1.PageNumber = 1;
4376 header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
4378 if (header0.PageLength & 1)
4379 dv_alloc = (header0.PageLength * 4) + 4;
4381 dv_alloc += (2048 + (header1.PageLength * 4));
4383 pDvBuf = pci_alloc_consistent(ioc->pcidev, dv_alloc, &dvbuf_dma);
4384 if (pDvBuf == NULL)
4385 return 0;
4387 sz = 0;
4388 pbuf1 = (u8 *)pDvBuf;
4389 buf1_dma = dvbuf_dma;
4390 sz +=1024;
4392 pbuf2 = (u8 *) (pDvBuf + sz);
4393 buf2_dma = dvbuf_dma + sz;
4394 sz +=1024;
4396 pcfg0Data = (SCSIDevicePage0_t *) (pDvBuf + sz);
4397 cfg0_dma_addr = dvbuf_dma + sz;
4398 sz += header0.PageLength * 4;
4400 /* 8-byte alignment
4402 if (header0.PageLength & 1)
4403 sz += 4;
4405 pcfg1Data = (SCSIDevicePage1_t *) (pDvBuf + sz);
4406 cfg1_dma_addr = dvbuf_dma + sz;
4408 /* Skip this ID? Set cfg.cfghdr.hdr to force config page write
4411 ScsiCfgData *pspi_data = &hd->ioc->spi_data;
4412 if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
4413 /* Set the factor from nvram */
4414 nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8;
4415 if (nfactor < pspi_data->minSyncFactor )
4416 nfactor = pspi_data->minSyncFactor;
4418 if (!(pspi_data->nvram[id] & MPT_NVRAM_ID_SCAN_ENABLE) ||
4419 (pspi_data->PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV) ) {
4421 ddvprintk((MYIOC_s_NOTE_FMT "DV Skipped: bus, id, lun (%d, %d, %d)\n",
4422 ioc->name, bus, id, lun));
4424 dv.cmd = MPT_SET_MAX;
4425 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4426 cfg.cfghdr.hdr = &header1;
4428 /* Save the final negotiated settings to
4429 * SCSI device page 1.
4431 cfg.physAddr = cfg1_dma_addr;
4432 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4433 cfg.dir = 1;
4434 mpt_config(hd->ioc, &cfg);
4435 goto target_done;
4440 /* Finish iocmd inititialization - hidden or visible disk? */
4441 if (ioc->spi_data.pIocPg3) {
4442 /* Search IOC page 3 for matching id
4444 Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
4445 int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
4447 while (numPDisk) {
4448 if (pPDisk->PhysDiskID == id) {
4449 /* match */
4450 iocmd.flags |= MPT_ICFLAG_PHYS_DISK;
4451 iocmd.physDiskNum = pPDisk->PhysDiskNum;
4453 /* Quiesce the IM
4455 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_QUIESCE_PHYS_IO, &iocmd) < 0) {
4456 ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name));
4457 goto target_done;
4459 break;
4461 pPDisk++;
4462 numPDisk--;
4466 /* RAID Volume ID's may double for a physical device. If RAID but
4467 * not a physical ID as well, skip DV.
4469 if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK))
4470 goto target_done;
4473 /* Basic Test.
4474 * Async & Narrow - Inquiry
4475 * Async & Narrow - Inquiry
4476 * Maximum transfer rate - Inquiry
4477 * Compare buffers:
4478 * If compare, test complete.
4479 * If miscompare and first pass, repeat
4480 * If miscompare and not first pass, fall back and repeat
4482 hd->pLocal = NULL;
4483 readPage0 = 0;
4484 sz = SCSI_MAX_INQUIRY_BYTES;
4485 rc = MPT_SCANDV_GOOD;
4486 while (1) {
4487 ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
4488 retcode = 0;
4489 dv.cmd = MPT_SET_MIN;
4490 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4492 cfg.cfghdr.hdr = &header1;
4493 cfg.physAddr = cfg1_dma_addr;
4494 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4495 cfg.dir = 1;
4496 if (mpt_config(hd->ioc, &cfg) != 0)
4497 goto target_done;
4499 /* Wide - narrow - wide workaround case
4501 if ((rc == MPT_SCANDV_ISSUE_SENSE) && dv.max.width) {
4502 /* Send an untagged command to reset disk Qs corrupted
4503 * when a parity error occurs on a Request Sense.
4505 if ((hd->ioc->facts.FWVersion.Word >= 0x01000600) ||
4506 ((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
4507 (hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
4509 iocmd.cmd = REQUEST_SENSE;
4510 iocmd.data_dma = buf1_dma;
4511 iocmd.data = pbuf1;
4512 iocmd.size = 0x12;
4513 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4514 goto target_done;
4515 else {
4516 if (hd->pLocal == NULL)
4517 goto target_done;
4518 rc = hd->pLocal->completion;
4519 if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) {
4520 dv.max.width = 0;
4521 doFallback = 0;
4522 } else
4523 goto target_done;
4525 } else
4526 goto target_done;
4529 iocmd.cmd = INQUIRY;
4530 iocmd.data_dma = buf1_dma;
4531 iocmd.data = pbuf1;
4532 iocmd.size = sz;
4533 memset(pbuf1, 0x00, sz);
4534 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4535 goto target_done;
4536 else {
4537 if (hd->pLocal == NULL)
4538 goto target_done;
4539 rc = hd->pLocal->completion;
4540 if (rc == MPT_SCANDV_GOOD) {
4541 if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
4542 if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
4543 retcode = 1;
4544 else
4545 retcode = 0;
4547 goto target_done;
4549 } else if (rc == MPT_SCANDV_SENSE) {
4551 } else {
4552 /* If first command doesn't complete
4553 * with a good status or with a check condition,
4554 * exit.
4556 goto target_done;
4560 /* Reset the size for disks
4562 inq0 = (*pbuf1) & 0x1F;
4563 if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
4564 sz = 0x40;
4565 iocmd.size = sz;
4568 /* Another GEM workaround. Check peripheral device type,
4569 * if PROCESSOR, quit DV.
4571 if (inq0 == TYPE_PROCESSOR) {
4572 mptscsih_initTarget(hd,
4573 bus,
4575 lun,
4576 pbuf1,
4577 sz);
4578 goto target_done;
4581 if (inq0 > 0x08)
4582 goto target_done;
4584 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4585 goto target_done;
4587 if (sz == 0x40) {
4588 if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
4589 && (pTarget->minSyncFactor > 0x09)) {
4590 if ((pbuf1[56] & 0x04) == 0)
4592 else if ((pbuf1[56] & 0x01) == 1) {
4593 pTarget->minSyncFactor =
4594 nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
4595 } else {
4596 pTarget->minSyncFactor =
4597 nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
4600 dv.max.factor = pTarget->minSyncFactor;
4602 if ((pbuf1[56] & 0x02) == 0) {
4603 pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
4604 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
4605 ddvprintk((MYIOC_s_NOTE_FMT
4606 "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n",
4607 ioc->name, id, pbuf1[56]));
4612 if (doFallback)
4613 dv.cmd = MPT_FALLBACK;
4614 else
4615 dv.cmd = MPT_SET_MAX;
4617 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4618 if (mpt_config(hd->ioc, &cfg) != 0)
4619 goto target_done;
4621 if ((!dv.now.width) && (!dv.now.offset))
4622 goto target_done;
4624 iocmd.cmd = INQUIRY;
4625 iocmd.data_dma = buf2_dma;
4626 iocmd.data = pbuf2;
4627 iocmd.size = sz;
4628 memset(pbuf2, 0x00, sz);
4629 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4630 goto target_done;
4631 else if (hd->pLocal == NULL)
4632 goto target_done;
4633 else {
4634 /* Save the return code.
4635 * If this is the first pass,
4636 * read SCSI Device Page 0
4637 * and update the target max parameters.
4639 rc = hd->pLocal->completion;
4640 doFallback = 0;
4641 if (rc == MPT_SCANDV_GOOD) {
4642 if (!readPage0) {
4643 u32 sdp0_info;
4644 u32 sdp0_nego;
4646 cfg.cfghdr.hdr = &header0;
4647 cfg.physAddr = cfg0_dma_addr;
4648 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4649 cfg.dir = 0;
4651 if (mpt_config(hd->ioc, &cfg) != 0)
4652 goto target_done;
4654 sdp0_info = le32_to_cpu(pcfg0Data->Information) & 0x0E;
4655 sdp0_nego = (le32_to_cpu(pcfg0Data->NegotiatedParameters) & 0xFF00 ) >> 8;
4657 /* Quantum and Fujitsu workarounds.
4658 * Quantum: PPR U320 -> PPR reply with Ultra2 and wide
4659 * Fujitsu: PPR U320 -> Msg Reject and Ultra2 and wide
4660 * Resetart with a request for U160.
4662 if ((dv.now.factor == MPT_ULTRA320) && (sdp0_nego == MPT_ULTRA2)) {
4663 doFallback = 1;
4664 } else {
4665 dv.cmd = MPT_UPDATE_MAX;
4666 mptscsih_dv_parms(hd, &dv, (void *)pcfg0Data);
4667 /* Update the SCSI device page 1 area
4669 pcfg1Data->RequestedParameters = pcfg0Data->NegotiatedParameters;
4670 readPage0 = 1;
4674 /* Quantum workaround. Restart this test will the fallback
4675 * flag set.
4677 if (doFallback == 0) {
4678 if (memcmp(pbuf1, pbuf2, sz) != 0) {
4679 if (!firstPass)
4680 doFallback = 1;
4681 } else {
4682 ddvprintk((MYIOC_s_NOTE_FMT
4683 "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
4684 hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
4685 mptscsih_initTarget(hd,
4686 bus,
4688 lun,
4689 pbuf1,
4690 sz);
4691 break; /* test complete */
4696 } else if (rc == MPT_SCANDV_ISSUE_SENSE)
4697 doFallback = 1; /* set fallback flag */
4698 else if ((rc == MPT_SCANDV_DID_RESET) ||
4699 (rc == MPT_SCANDV_SENSE) ||
4700 (rc == MPT_SCANDV_FALLBACK))
4701 doFallback = 1; /* set fallback flag */
4702 else
4703 goto target_done;
4705 firstPass = 0;
4708 ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
4710 if (ioc->spi_data.mpt_dv == 0)
4711 goto target_done;
4713 inq0 = (*pbuf1) & 0x1F;
4715 /* Continue only for disks
4717 if (inq0 != 0)
4718 goto target_done;
4720 if ( ioc->spi_data.PortFlags == MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY )
4721 goto target_done;
4723 /* Start the Enhanced Test.
4724 * 0) issue TUR to clear out check conditions
4725 * 1) read capacity of echo (regular) buffer
4726 * 2) reserve device
4727 * 3) do write-read-compare data pattern test
4728 * 4) release
4729 * 5) update nego parms to target struct
4731 cfg.cfghdr.hdr = &header1;
4732 cfg.physAddr = cfg1_dma_addr;
4733 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
4734 cfg.dir = 1;
4736 iocmd.cmd = TEST_UNIT_READY;
4737 iocmd.data_dma = -1;
4738 iocmd.data = NULL;
4739 iocmd.size = 0;
4740 notDone = 1;
4741 while (notDone) {
4742 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4743 goto target_done;
4745 if (hd->pLocal == NULL)
4746 goto target_done;
4748 rc = hd->pLocal->completion;
4749 if (rc == MPT_SCANDV_GOOD)
4750 notDone = 0;
4751 else if (rc == MPT_SCANDV_SENSE) {
4752 u8 skey = hd->pLocal->sense[2] & 0x0F;
4753 u8 asc = hd->pLocal->sense[12];
4754 u8 ascq = hd->pLocal->sense[13];
4755 ddvprintk((MYIOC_s_INFO_FMT
4756 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4757 ioc->name, skey, asc, ascq));
4759 if (skey == UNIT_ATTENTION)
4760 notDone++; /* repeat */
4761 else if ((skey == NOT_READY) &&
4762 (asc == 0x04)&&(ascq == 0x01)) {
4763 /* wait then repeat */
4764 mdelay (2000);
4765 notDone++;
4766 } else if ((skey == NOT_READY) && (asc == 0x3A)) {
4767 /* no medium, try read test anyway */
4768 notDone = 0;
4769 } else {
4770 /* All other errors are fatal.
4772 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4773 ioc->name));
4774 goto target_done;
4776 } else
4777 goto target_done;
4780 iocmd.cmd = READ_BUFFER;
4781 iocmd.data_dma = buf1_dma;
4782 iocmd.data = pbuf1;
4783 iocmd.size = 4;
4784 iocmd.flags |= MPT_ICFLAG_BUF_CAP;
4786 dataBufSize = 0;
4787 echoBufSize = 0;
4788 for (patt = 0; patt < 2; patt++) {
4789 if (patt == 0)
4790 iocmd.flags |= MPT_ICFLAG_ECHO;
4791 else
4792 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4794 notDone = 1;
4795 while (notDone) {
4796 bufsize = 0;
4798 /* If not ready after 8 trials,
4799 * give up on this device.
4801 if (notDone > 8)
4802 goto target_done;
4804 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4805 goto target_done;
4806 else if (hd->pLocal == NULL)
4807 goto target_done;
4808 else {
4809 rc = hd->pLocal->completion;
4810 ddvprintk(("ReadBuffer Comp Code %d", rc));
4811 ddvprintk((" buff: %0x %0x %0x %0x\n",
4812 pbuf1[0], pbuf1[1], pbuf1[2], pbuf1[3]));
4814 if (rc == MPT_SCANDV_GOOD) {
4815 notDone = 0;
4816 if (iocmd.flags & MPT_ICFLAG_ECHO) {
4817 bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3];
4818 } else {
4819 bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3];
4821 } else if (rc == MPT_SCANDV_SENSE) {
4822 u8 skey = hd->pLocal->sense[2] & 0x0F;
4823 u8 asc = hd->pLocal->sense[12];
4824 u8 ascq = hd->pLocal->sense[13];
4825 ddvprintk((MYIOC_s_INFO_FMT
4826 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4827 ioc->name, skey, asc, ascq));
4828 if (skey == ILLEGAL_REQUEST) {
4829 notDone = 0;
4830 } else if (skey == UNIT_ATTENTION) {
4831 notDone++; /* repeat */
4832 } else if ((skey == NOT_READY) &&
4833 (asc == 0x04)&&(ascq == 0x01)) {
4834 /* wait then repeat */
4835 mdelay (2000);
4836 notDone++;
4837 } else {
4838 /* All other errors are fatal.
4840 ddvprintk((MYIOC_s_INFO_FMT "DV: fatal error.",
4841 ioc->name));
4842 goto target_done;
4844 } else {
4845 /* All other errors are fatal
4847 goto target_done;
4852 if (iocmd.flags & MPT_ICFLAG_ECHO)
4853 echoBufSize = bufsize;
4854 else
4855 dataBufSize = bufsize;
4857 sz = 0;
4858 iocmd.flags &= ~MPT_ICFLAG_BUF_CAP;
4860 /* Use echo buffers if possible,
4861 * Exit if both buffers are 0.
4863 if (echoBufSize > 0) {
4864 iocmd.flags |= MPT_ICFLAG_ECHO;
4865 if (dataBufSize > 0)
4866 bufsize = min(echoBufSize, dataBufSize);
4867 else
4868 bufsize = echoBufSize;
4869 } else if (dataBufSize == 0)
4870 goto target_done;
4872 ddvprintk((MYIOC_s_INFO_FMT "%s Buffer Capacity %d\n", ioc->name,
4873 (iocmd.flags & MPT_ICFLAG_ECHO) ? "Echo" : " ", bufsize));
4875 /* Data buffers for write-read-compare test max 1K.
4877 sz = min(bufsize, 1024);
4879 /* --- loop ----
4880 * On first pass, always issue a reserve.
4881 * On additional loops, only if a reset has occurred.
4882 * iocmd.flags indicates if echo or regular buffer
4884 for (patt = 0; patt < 4; patt++) {
4885 ddvprintk(("Pattern %d\n", patt));
4886 if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
4887 iocmd.cmd = TEST_UNIT_READY;
4888 iocmd.data_dma = -1;
4889 iocmd.data = NULL;
4890 iocmd.size = 0;
4891 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4892 goto target_done;
4894 iocmd.cmd = RELEASE;
4895 iocmd.data_dma = -1;
4896 iocmd.data = NULL;
4897 iocmd.size = 0;
4898 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4899 goto target_done;
4900 else if (hd->pLocal == NULL)
4901 goto target_done;
4902 else {
4903 rc = hd->pLocal->completion;
4904 ddvprintk(("Release rc %d\n", rc));
4905 if (rc == MPT_SCANDV_GOOD)
4906 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4907 else
4908 goto target_done;
4910 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
4912 iocmd.flags &= ~MPT_ICFLAG_DID_RESET;
4914 repeat = 5;
4915 while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
4916 iocmd.cmd = RESERVE;
4917 iocmd.data_dma = -1;
4918 iocmd.data = NULL;
4919 iocmd.size = 0;
4920 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4921 goto target_done;
4922 else if (hd->pLocal == NULL)
4923 goto target_done;
4924 else {
4925 rc = hd->pLocal->completion;
4926 if (rc == MPT_SCANDV_GOOD) {
4927 iocmd.flags |= MPT_ICFLAG_RESERVED;
4928 } else if (rc == MPT_SCANDV_SENSE) {
4929 /* Wait if coming ready
4931 u8 skey = hd->pLocal->sense[2] & 0x0F;
4932 u8 asc = hd->pLocal->sense[12];
4933 u8 ascq = hd->pLocal->sense[13];
4934 ddvprintk((MYIOC_s_INFO_FMT
4935 "DV: Reserve Failed: ", ioc->name));
4936 ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
4937 skey, asc, ascq));
4939 if ((skey == NOT_READY) && (asc == 0x04)&&
4940 (ascq == 0x01)) {
4941 /* wait then repeat */
4942 mdelay (2000);
4943 notDone++;
4944 } else {
4945 ddvprintk((MYIOC_s_INFO_FMT
4946 "DV: Reserved Failed.", ioc->name));
4947 goto target_done;
4949 } else {
4950 ddvprintk((MYIOC_s_INFO_FMT "DV: Reserved Failed.",
4951 ioc->name));
4952 goto target_done;
4957 mptscsih_fillbuf(pbuf1, sz, patt, 1);
4958 iocmd.cmd = WRITE_BUFFER;
4959 iocmd.data_dma = buf1_dma;
4960 iocmd.data = pbuf1;
4961 iocmd.size = sz;
4962 if (mptscsih_do_cmd(hd, &iocmd) < 0)
4963 goto target_done;
4964 else if (hd->pLocal == NULL)
4965 goto target_done;
4966 else {
4967 rc = hd->pLocal->completion;
4968 if (rc == MPT_SCANDV_GOOD)
4969 ; /* Issue read buffer */
4970 else if (rc == MPT_SCANDV_DID_RESET) {
4971 /* If using echo buffers, reset to data buffers.
4972 * Else do Fallback and restart
4973 * this test (re-issue reserve
4974 * because of bus reset).
4976 if ((iocmd.flags & MPT_ICFLAG_ECHO) && (dataBufSize >= bufsize)) {
4977 iocmd.flags &= ~MPT_ICFLAG_ECHO;
4978 } else {
4979 dv.cmd = MPT_FALLBACK;
4980 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
4982 if (mpt_config(hd->ioc, &cfg) != 0)
4983 goto target_done;
4985 if ((!dv.now.width) && (!dv.now.offset))
4986 goto target_done;
4989 iocmd.flags |= MPT_ICFLAG_DID_RESET;
4990 patt = -1;
4991 continue;
4992 } else if (rc == MPT_SCANDV_SENSE) {
4993 /* Restart data test if UA, else quit.
4995 u8 skey = hd->pLocal->sense[2] & 0x0F;
4996 ddvprintk((MYIOC_s_INFO_FMT
4997 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
4998 hd->pLocal->sense[12], hd->pLocal->sense[13]));
4999 if (skey == UNIT_ATTENTION) {
5000 patt = -1;
5001 continue;
5002 } else if (skey == ILLEGAL_REQUEST) {
5003 if (iocmd.flags & MPT_ICFLAG_ECHO) {
5004 if (dataBufSize >= bufsize) {
5005 iocmd.flags &= ~MPT_ICFLAG_ECHO;
5006 patt = -1;
5007 continue;
5010 goto target_done;
5012 else
5013 goto target_done;
5014 } else {
5015 /* fatal error */
5016 goto target_done;
5020 iocmd.cmd = READ_BUFFER;
5021 iocmd.data_dma = buf2_dma;
5022 iocmd.data = pbuf2;
5023 iocmd.size = sz;
5024 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5025 goto target_done;
5026 else if (hd->pLocal == NULL)
5027 goto target_done;
5028 else {
5029 rc = hd->pLocal->completion;
5030 if (rc == MPT_SCANDV_GOOD) {
5031 /* If buffers compare,
5032 * go to next pattern,
5033 * else, do a fallback and restart
5034 * data transfer test.
5036 if (memcmp (pbuf1, pbuf2, sz) == 0) {
5037 ; /* goto next pattern */
5038 } else {
5039 /* Miscompare with Echo buffer, go to data buffer,
5040 * if that buffer exists.
5041 * Miscompare with Data buffer, check first 4 bytes,
5042 * some devices return capacity. Exit in this case.
5044 if (iocmd.flags & MPT_ICFLAG_ECHO) {
5045 if (dataBufSize >= bufsize)
5046 iocmd.flags &= ~MPT_ICFLAG_ECHO;
5047 else
5048 goto target_done;
5049 } else {
5050 if (dataBufSize == (pbuf2[1]<<16 | pbuf2[2]<<8 | pbuf2[3])) {
5051 /* Argh. Device returning wrong data.
5052 * Quit DV for this device.
5054 goto target_done;
5057 /* Had an actual miscompare. Slow down.*/
5058 dv.cmd = MPT_FALLBACK;
5059 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5061 if (mpt_config(hd->ioc, &cfg) != 0)
5062 goto target_done;
5064 if ((!dv.now.width) && (!dv.now.offset))
5065 goto target_done;
5068 patt = -1;
5069 continue;
5071 } else if (rc == MPT_SCANDV_DID_RESET) {
5072 /* Do Fallback and restart
5073 * this test (re-issue reserve
5074 * because of bus reset).
5076 dv.cmd = MPT_FALLBACK;
5077 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5079 if (mpt_config(hd->ioc, &cfg) != 0)
5080 goto target_done;
5082 if ((!dv.now.width) && (!dv.now.offset))
5083 goto target_done;
5085 iocmd.flags |= MPT_ICFLAG_DID_RESET;
5086 patt = -1;
5087 continue;
5088 } else if (rc == MPT_SCANDV_SENSE) {
5089 /* Restart data test if UA, else quit.
5091 u8 skey = hd->pLocal->sense[2] & 0x0F;
5092 ddvprintk((MYIOC_s_INFO_FMT
5093 "SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
5094 hd->pLocal->sense[12], hd->pLocal->sense[13]));
5095 if (skey == UNIT_ATTENTION) {
5096 patt = -1;
5097 continue;
5099 else
5100 goto target_done;
5101 } else {
5102 /* fatal error */
5103 goto target_done;
5107 } /* --- end of patt loop ---- */
5109 target_done:
5110 if (iocmd.flags & MPT_ICFLAG_RESERVED) {
5111 iocmd.cmd = RELEASE;
5112 iocmd.data_dma = -1;
5113 iocmd.data = NULL;
5114 iocmd.size = 0;
5115 if (mptscsih_do_cmd(hd, &iocmd) < 0)
5116 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5117 ioc->name, id);
5118 else if (hd->pLocal) {
5119 if (hd->pLocal->completion == MPT_SCANDV_GOOD)
5120 iocmd.flags &= ~MPT_ICFLAG_RESERVED;
5121 } else {
5122 printk(MYIOC_s_INFO_FMT "DV: Release failed. id %d",
5123 ioc->name, id);
5128 /* Set if cfg1_dma_addr contents is valid
5130 if ((cfg.cfghdr.hdr != NULL) && (retcode == 0)){
5131 /* If disk, not U320, disable QAS
5133 if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
5134 hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
5135 ddvprintk((MYIOC_s_NOTE_FMT
5136 "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
5139 dv.cmd = MPT_SAVE;
5140 mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
5142 /* Double writes to SDP1 can cause problems,
5143 * skip save of the final negotiated settings to
5144 * SCSI device page 1.
5146 cfg.cfghdr.hdr = &header1;
5147 cfg.physAddr = cfg1_dma_addr;
5148 cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
5149 cfg.dir = 1;
5150 mpt_config(hd->ioc, &cfg);
5154 /* If this is a RAID Passthrough, enable internal IOs
5156 if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) {
5157 if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0)
5158 ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name));
5161 /* Done with the DV scan of the current target
5163 if (pDvBuf)
5164 pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
5166 ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
5167 ioc->name, id));
5169 return retcode;
5172 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5173 /* mptscsih_dv_parms - perform a variety of operations on the
5174 * parameters used for negotiation.
5175 * @hd: Pointer to a SCSI host.
5176 * @dv: Pointer to a structure that contains the maximum and current
5177 * negotiated parameters.
5179 static void
5180 mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
5182 VirtDevice *pTarget;
5183 SCSIDevicePage0_t *pPage0;
5184 SCSIDevicePage1_t *pPage1;
5185 int val = 0, data, configuration;
5186 u8 width = 0;
5187 u8 offset = 0;
5188 u8 factor = 0;
5189 u8 negoFlags = 0;
5190 u8 cmd = dv->cmd;
5191 u8 id = dv->id;
5193 switch (cmd) {
5194 case MPT_GET_NVRAM_VALS:
5195 ddvprintk((MYIOC_s_NOTE_FMT "Getting NVRAM: ",
5196 hd->ioc->name));
5197 /* Get the NVRAM values and save in tmax
5198 * If not an LVD bus, the adapter minSyncFactor has been
5199 * already throttled back.
5201 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
5202 width = pTarget->maxWidth;
5203 offset = pTarget->maxOffset;
5204 factor = pTarget->minSyncFactor;
5205 negoFlags = pTarget->negoFlags;
5206 } else {
5207 if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
5208 data = hd->ioc->spi_data.nvram[id];
5209 width = data & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
5210 if ((offset = hd->ioc->spi_data.maxSyncOffset) == 0)
5211 factor = MPT_ASYNC;
5212 else {
5213 factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
5214 if ((factor == 0) || (factor == MPT_ASYNC)){
5215 factor = MPT_ASYNC;
5216 offset = 0;
5219 } else {
5220 width = MPT_NARROW;
5221 offset = 0;
5222 factor = MPT_ASYNC;
5225 /* Set the negotiation flags */
5226 negoFlags = hd->ioc->spi_data.noQas;
5227 if (!width)
5228 negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
5230 if (!offset)
5231 negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
5234 /* limit by adapter capabilities */
5235 width = min(width, hd->ioc->spi_data.maxBusWidth);
5236 offset = min(offset, hd->ioc->spi_data.maxSyncOffset);
5237 factor = max(factor, hd->ioc->spi_data.minSyncFactor);
5239 /* Check Consistency */
5240 if (offset && (factor < MPT_ULTRA2) && !width)
5241 factor = MPT_ULTRA2;
5243 dv->max.width = width;
5244 dv->max.offset = offset;
5245 dv->max.factor = factor;
5246 dv->max.flags = negoFlags;
5247 ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
5248 id, width, factor, offset, negoFlags));
5249 break;
5251 case MPT_UPDATE_MAX:
5252 ddvprintk((MYIOC_s_NOTE_FMT
5253 "Updating with SDP0 Data: ", hd->ioc->name));
5254 /* Update tmax values with those from Device Page 0.*/
5255 pPage0 = (SCSIDevicePage0_t *) pPage;
5256 if (pPage0) {
5257 val = le32_to_cpu(pPage0->NegotiatedParameters);
5258 dv->max.width = val & MPI_SCSIDEVPAGE0_NP_WIDE ? 1 : 0;
5259 dv->max.offset = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> 16;
5260 dv->max.factor = (val&MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8;
5263 dv->now.width = dv->max.width;
5264 dv->now.offset = dv->max.offset;
5265 dv->now.factor = dv->max.factor;
5266 ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
5267 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5268 break;
5270 case MPT_SET_MAX:
5271 ddvprintk((MYIOC_s_NOTE_FMT "Setting Max: ",
5272 hd->ioc->name));
5273 /* Set current to the max values. Update the config page.*/
5274 dv->now.width = dv->max.width;
5275 dv->now.offset = dv->max.offset;
5276 dv->now.factor = dv->max.factor;
5277 dv->now.flags = dv->max.flags;
5279 pPage1 = (SCSIDevicePage1_t *)pPage;
5280 if (pPage1) {
5281 mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
5282 dv->now.offset, &val, &configuration, dv->now.flags);
5283 dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5284 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5285 pPage1->RequestedParameters = cpu_to_le32(val);
5286 pPage1->Reserved = 0;
5287 pPage1->Configuration = cpu_to_le32(configuration);
5290 ddvprintk(("id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x configuration=%x\n",
5291 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
5292 break;
5294 case MPT_SET_MIN:
5295 ddvprintk((MYIOC_s_NOTE_FMT "Setting Min: ",
5296 hd->ioc->name));
5297 /* Set page to asynchronous and narrow
5298 * Do not update now, breaks fallback routine. */
5299 width = MPT_NARROW;
5300 offset = 0;
5301 factor = MPT_ASYNC;
5302 negoFlags = dv->max.flags;
5304 pPage1 = (SCSIDevicePage1_t *)pPage;
5305 if (pPage1) {
5306 mptscsih_setDevicePage1Flags (width, factor,
5307 offset, &val, &configuration, negoFlags);
5308 dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
5309 id, width, factor, offset, negoFlags, val, configuration));
5310 pPage1->RequestedParameters = cpu_to_le32(val);
5311 pPage1->Reserved = 0;
5312 pPage1->Configuration = cpu_to_le32(configuration);
5314 ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
5315 id, width, factor, offset, val, configuration, negoFlags));
5316 break;
5318 case MPT_FALLBACK:
5319 ddvprintk((MYIOC_s_NOTE_FMT
5320 "Fallback: Start: offset %d, factor %x, width %d \n",
5321 hd->ioc->name, dv->now.offset,
5322 dv->now.factor, dv->now.width));
5323 width = dv->now.width;
5324 offset = dv->now.offset;
5325 factor = dv->now.factor;
5326 if ((offset) && (dv->max.width)) {
5327 if (factor < MPT_ULTRA160)
5328 factor = MPT_ULTRA160;
5329 else if (factor < MPT_ULTRA2) {
5330 factor = MPT_ULTRA2;
5331 width = MPT_WIDE;
5332 } else if ((factor == MPT_ULTRA2) && width) {
5333 factor = MPT_ULTRA2;
5334 width = MPT_NARROW;
5335 } else if (factor < MPT_ULTRA) {
5336 factor = MPT_ULTRA;
5337 width = MPT_WIDE;
5338 } else if ((factor == MPT_ULTRA) && width) {
5339 width = MPT_NARROW;
5340 } else if (factor < MPT_FAST) {
5341 factor = MPT_FAST;
5342 width = MPT_WIDE;
5343 } else if ((factor == MPT_FAST) && width) {
5344 factor = MPT_FAST;
5345 width = MPT_NARROW;
5346 } else if (factor < MPT_SCSI) {
5347 factor = MPT_SCSI;
5348 width = MPT_WIDE;
5349 } else if ((factor == MPT_SCSI) && width) {
5350 factor = MPT_SCSI;
5351 width = MPT_NARROW;
5352 } else {
5353 factor = MPT_ASYNC;
5354 offset = 0;
5357 } else if (offset) {
5358 width = MPT_NARROW;
5359 if (factor < MPT_ULTRA)
5360 factor = MPT_ULTRA;
5361 else if (factor < MPT_FAST)
5362 factor = MPT_FAST;
5363 else if (factor < MPT_SCSI)
5364 factor = MPT_SCSI;
5365 else {
5366 factor = MPT_ASYNC;
5367 offset = 0;
5370 } else {
5371 width = MPT_NARROW;
5372 factor = MPT_ASYNC;
5374 dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
5375 dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
5377 dv->now.width = width;
5378 dv->now.offset = offset;
5379 dv->now.factor = factor;
5380 dv->now.flags = dv->max.flags;
5382 pPage1 = (SCSIDevicePage1_t *)pPage;
5383 if (pPage1) {
5384 mptscsih_setDevicePage1Flags (width, factor, offset, &val,
5385 &configuration, dv->now.flags);
5386 dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x negoFlags=%x request=%x config=%x\n",
5387 id, width, offset, factor, dv->now.flags, val, configuration));
5389 pPage1->RequestedParameters = cpu_to_le32(val);
5390 pPage1->Reserved = 0;
5391 pPage1->Configuration = cpu_to_le32(configuration);
5394 ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
5395 id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
5396 break;
5398 case MPT_SAVE:
5399 ddvprintk((MYIOC_s_NOTE_FMT
5400 "Saving to Target structure: ", hd->ioc->name));
5401 ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
5402 id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
5404 /* Save these values to target structures
5405 * or overwrite nvram (phys disks only).
5408 if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
5409 pTarget->maxWidth = dv->now.width;
5410 pTarget->maxOffset = dv->now.offset;
5411 pTarget->minSyncFactor = dv->now.factor;
5412 pTarget->negoFlags = dv->now.flags;
5413 } else {
5414 /* Preserv all flags, use
5415 * read-modify-write algorithm
5417 if (hd->ioc->spi_data.nvram) {
5418 data = hd->ioc->spi_data.nvram[id];
5420 if (dv->now.width)
5421 data &= ~MPT_NVRAM_WIDE_DISABLE;
5422 else
5423 data |= MPT_NVRAM_WIDE_DISABLE;
5425 if (!dv->now.offset)
5426 factor = MPT_ASYNC;
5428 data &= ~MPT_NVRAM_SYNC_MASK;
5429 data |= (dv->now.factor << MPT_NVRAM_SYNC_SHIFT) & MPT_NVRAM_SYNC_MASK;
5431 hd->ioc->spi_data.nvram[id] = data;
5434 break;
5438 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
5439 /* mptscsih_fillbuf - fill a buffer with a special data pattern
5440 * cleanup. For bus scan only.
5442 * @buffer: Pointer to data buffer to be filled.
5443 * @size: Number of bytes to fill
5444 * @index: Pattern index
5445 * @width: bus width, 0 (8 bits) or 1 (16 bits)
5447 static void
5448 mptscsih_fillbuf(char *buffer, int size, int index, int width)
5450 char *ptr = buffer;
5451 int ii;
5452 char byte;
5453 short val;
5455 switch (index) {
5456 case 0:
5458 if (width) {
5459 /* Pattern: 0000 FFFF 0000 FFFF
5461 for (ii=0; ii < size; ii++, ptr++) {
5462 if (ii & 0x02)
5463 *ptr = 0xFF;
5464 else
5465 *ptr = 0x00;
5467 } else {
5468 /* Pattern: 00 FF 00 FF
5470 for (ii=0; ii < size; ii++, ptr++) {
5471 if (ii & 0x01)
5472 *ptr = 0xFF;
5473 else
5474 *ptr = 0x00;
5477 break;
5479 case 1:
5480 if (width) {
5481 /* Pattern: 5555 AAAA 5555 AAAA 5555
5483 for (ii=0; ii < size; ii++, ptr++) {
5484 if (ii & 0x02)
5485 *ptr = 0xAA;
5486 else
5487 *ptr = 0x55;
5489 } else {
5490 /* Pattern: 55 AA 55 AA 55
5492 for (ii=0; ii < size; ii++, ptr++) {
5493 if (ii & 0x01)
5494 *ptr = 0xAA;
5495 else
5496 *ptr = 0x55;
5499 break;
5501 case 2:
5502 /* Pattern: 00 01 02 03 04 05
5503 * ... FE FF 00 01..
5505 for (ii=0; ii < size; ii++, ptr++)
5506 *ptr = (char) ii;
5507 break;
5509 case 3:
5510 if (width) {
5511 /* Wide Pattern: FFFE 0001 FFFD 0002
5512 * ... 4000 DFFF 8000 EFFF
5514 byte = 0;
5515 for (ii=0; ii < size/2; ii++) {
5516 /* Create the base pattern
5518 val = (1 << byte);
5519 /* every 64 (0x40) bytes flip the pattern
5520 * since we fill 2 bytes / iteration,
5521 * test for ii = 0x20
5523 if (ii & 0x20)
5524 val = ~(val);
5526 if (ii & 0x01) {
5527 *ptr = (char)( (val & 0xFF00) >> 8);
5528 ptr++;
5529 *ptr = (char)(val & 0xFF);
5530 byte++;
5531 byte &= 0x0F;
5532 } else {
5533 val = ~val;
5534 *ptr = (char)( (val & 0xFF00) >> 8);
5535 ptr++;
5536 *ptr = (char)(val & 0xFF);
5539 ptr++;
5541 } else {
5542 /* Narrow Pattern: FE 01 FD 02 FB 04
5543 * .. 7F 80 01 FE 02 FD ... 80 7F
5545 byte = 0;
5546 for (ii=0; ii < size; ii++, ptr++) {
5547 /* Base pattern - first 32 bytes
5549 if (ii & 0x01) {
5550 *ptr = (1 << byte);
5551 byte++;
5552 byte &= 0x07;
5553 } else {
5554 *ptr = (char) (~(1 << byte));
5557 /* Flip the pattern every 32 bytes
5559 if (ii & 0x20)
5560 *ptr = ~(*ptr);
5563 break;
5566 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
5568 EXPORT_SYMBOL(mptscsih_remove);
5569 EXPORT_SYMBOL(mptscsih_shutdown);
5570 #ifdef CONFIG_PM
5571 EXPORT_SYMBOL(mptscsih_suspend);
5572 EXPORT_SYMBOL(mptscsih_resume);
5573 #endif
5574 EXPORT_SYMBOL(mptscsih_proc_info);
5575 EXPORT_SYMBOL(mptscsih_info);
5576 EXPORT_SYMBOL(mptscsih_qcmd);
5577 EXPORT_SYMBOL(mptscsih_slave_alloc);
5578 EXPORT_SYMBOL(mptscsih_slave_destroy);
5579 EXPORT_SYMBOL(mptscsih_slave_configure);
5580 EXPORT_SYMBOL(mptscsih_abort);
5581 EXPORT_SYMBOL(mptscsih_dev_reset);
5582 EXPORT_SYMBOL(mptscsih_bus_reset);
5583 EXPORT_SYMBOL(mptscsih_host_reset);
5584 EXPORT_SYMBOL(mptscsih_bios_param);
5585 EXPORT_SYMBOL(mptscsih_io_done);
5586 EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
5587 EXPORT_SYMBOL(mptscsih_scandv_complete);
5588 EXPORT_SYMBOL(mptscsih_event_process);
5589 EXPORT_SYMBOL(mptscsih_ioc_reset);
5590 EXPORT_SYMBOL(mptscsih_change_queue_depth);
5591 EXPORT_SYMBOL(mptscsih_timer_expired);
5593 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/