File: /usr/src/linux/drivers/message/fusion/mptscsih.c
1 /*
2 * linux/drivers/message/fusion/mptscsih.c
3 * High performance SCSI / Fibre Channel SCSI Host device driver.
4 * For use with PCI chip/adapter(s):
5 * LSIFC9xx/LSI409xx Fibre Channel
6 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
7 *
8 * Credits:
9 * This driver would not exist if not for Alan Cox's development
10 * of the linux i2o driver.
11 *
12 * A huge debt of gratitude is owed to David S. Miller (DaveM)
13 * for fixing much of the stupid and broken stuff in the early
14 * driver while porting to sparc64 platform. THANK YOU!
15 *
16 * (see mptbase.c)
17 *
18 * Copyright (c) 1999-2001 LSI Logic Corporation
19 * Original author: Steven J. Ralston
20 * (mailto:Steve.Ralston@lsil.com)
21 *
22 * $Id: mptscsih.c,v 1.29 2001/06/18 18:59:05 sralston Exp $
23 */
24 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
25 /*
26 This program is free software; you can redistribute it and/or modify
27 it under the terms of the GNU General Public License as published by
28 the Free Software Foundation; version 2 of the License.
29
30 This program is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
34
35 NO WARRANTY
36 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
37 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
38 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
39 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
40 solely responsible for determining the appropriateness of using and
41 distributing the Program and assumes all risks associated with its
42 exercise of rights under this Agreement, including but not limited to
43 the risks and costs of program errors, damage to or loss of data,
44 programs or equipment, and unavailability or interruption of operations.
45
46 DISCLAIMER OF LIABILITY
47 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
48 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
50 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
51 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
52 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
53 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
54
55 You should have received a copy of the GNU General Public License
56 along with this program; if not, write to the Free Software
57 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
58 */
59 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
60
61 #include <linux/module.h>
62 #include <linux/version.h>
63 #include <linux/kernel.h>
64 #include <linux/init.h>
65 #include <linux/errno.h>
66 #include <linux/kdev_t.h>
67 #include <linux/blkdev.h>
68 #include <linux/blk.h> /* for io_request_lock (spinlock) decl */
69 #include "../../scsi/scsi.h"
70 #include "../../scsi/hosts.h"
71 #include "../../scsi/sd.h"
72
73 #include "mptbase.h"
74 #include "mptscsih.h"
75 #include "isense.h"
76
77 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
78 #define my_NAME "Fusion MPT SCSI Host driver"
79 #define my_VERSION MPT_LINUX_VERSION_COMMON
80 #define MYNAM "mptscsih"
81
82 MODULE_AUTHOR(MODULEAUTHOR);
83 MODULE_DESCRIPTION(my_NAME);
84
85 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
86
87 typedef struct _BIG_SENSE_BUF {
88 u8 data[256];
89 } BIG_SENSE_BUF;
90
91 typedef struct _MPT_SCSI_HOST {
92 MPT_ADAPTER *ioc;
93 int port;
94 struct scsi_cmnd **ScsiLookup;
95 u8 *SgHunks;
96 dma_addr_t SgHunksDMA;
97 u32 qtag_tick;
98 } MPT_SCSI_HOST;
99
100 typedef struct _MPT_SCSI_DEV {
101 struct _MPT_SCSI_DEV *forw;
102 struct _MPT_SCSI_DEV *back;
103 MPT_ADAPTER *ioc;
104 int sense_sz;
105 BIG_SENSE_BUF CachedSense;
106 unsigned long io_cnt;
107 unsigned long read_cnt;
108 } MPT_SCSI_DEV;
109
110 /*
111 * Other private/forward protos...
112 */
113
114 static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
115 static void mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
116 static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
117 static int mptscsih_io_direction(Scsi_Cmnd *cmd);
118 static void copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
119 static u32 SCPNT_TO_MSGCTX(Scsi_Cmnd *sc);
120
121 static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
122 static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
123
124
125 static int mpt_scsi_hosts = 0;
126 static atomic_t queue_depth;
127
128 static int ScsiDoneCtx = -1;
129 static int ScsiTaskCtx = -1;
130
131 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,28)
132 static struct proc_dir_entry proc_mpt_scsihost =
133 {
134 low_ino: PROC_SCSI_MPT,
135 namelen: 8,
136 name: "mptscsih",
137 mode: S_IFDIR | S_IRUGO | S_IXUGO,
138 nlink: 2,
139 };
140 #endif
141
142 #define SNS_LEN(scp) sizeof((scp)->sense_buffer)
143
144 #ifndef MPT_SCSI_USE_NEW_EH
145 /*
146 * Stuff to handle single-threading SCSI TaskMgmt
147 * (abort/reset) requests...
148 */
149 static spinlock_t mpt_scsih_taskQ_lock = SPIN_LOCK_UNLOCKED;
150 static MPT_Q_TRACKER mpt_scsih_taskQ = {
151 (MPT_FRAME_HDR*) &mpt_scsih_taskQ,
152 (MPT_FRAME_HDR*) &mpt_scsih_taskQ
153 };
154 static int mpt_scsih_taskQ_cnt = 0;
155 static int mpt_scsih_taskQ_bh_active = 0;
156 static MPT_FRAME_HDR *mpt_scsih_active_taskmgmt_mf = NULL;
157 #endif
158
159 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
160 /*
161 * mptscsih_io_done - Main SCSI IO callback routine registered to
162 * Fusion MPT (base) driver
163 * @ioc: Pointer to MPT_ADAPTER structure
164 * @mf: Pointer to original MPT request frame
165 * @r: Pointer to MPT reply frame (NULL if TurboReply)
166 *
167 * This routine is called from mpt.c::mpt_interrupt() at the completion
168 * of any SCSI IO request.
169 * This routine is registered with the Fusion MPT (base) driver at driver
170 * load/init time via the mpt_register() API call.
171 *
172 * Returns 1 indicating alloc'd request frame ptr should be freed.
173 */
174 static int
175 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r)
176 {
177 Scsi_Cmnd *sc;
178 MPT_SCSI_HOST *hd;
179 MPT_SCSI_DEV *mpt_sdev = NULL;
180 u16 req_idx;
181
182 if ((mf == NULL) ||
183 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
184 printk(KERN_ERR MYNAM ": ERROR! NULL or BAD req frame ptr (=%p)!\n", mf);
185 return 1;
186 }
187
188 hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
189 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
190 sc = hd->ScsiLookup[req_idx];
191 hd->ScsiLookup[req_idx] = NULL;
192
193 dmfprintk((KERN_INFO MYNAM ": ScsiDone (req:sc:reply=%p:%p:%p)\n", mf, sc, r));
194
195 atomic_dec(&queue_depth);
196
197 /*
198 * Check for {1st} {IO} completion to "new" device.
199 * How do we know it's a new device?
200 * If we haven't set SDpnt->hostdata I guess...
201 */
202 if (sc && sc->device) {
203 mpt_sdev = (MPT_SCSI_DEV*)sc->device->hostdata;
204 if (!mpt_sdev) {
205 dprintk((KERN_INFO MYNAM ": *NEW* SCSI device (%d:%d:%d)!\n",
206 sc->device->id, sc->device->lun, sc->device->channel));
207 if ((sc->device->hostdata = kmalloc(sizeof(MPT_SCSI_DEV), GFP_ATOMIC)) == NULL) {
208 printk(KERN_ERR MYNAM ": ERROR - kmalloc(%d) FAILED!\n", (int)sizeof(MPT_SCSI_DEV));
209 } else {
210 memset(sc->device->hostdata, 0, sizeof(MPT_SCSI_DEV));
211 mpt_sdev = (MPT_SCSI_DEV *) sc->device->hostdata;
212 mpt_sdev->ioc = ioc;
213 }
214 } else {
215 if (++mpt_sdev->io_cnt && mptscsih_io_direction(sc) < 0) {
216 if (++mpt_sdev->read_cnt == 3) {
217 dprintk((KERN_INFO MYNAM ": 3rd DATA_IN, CDB[0]=%02x\n",
218 sc->cmnd[0]));
219 }
220 }
221 #if 0
222 if (mpt_sdev->sense_sz) {
223 /*
224 * Completion of first IO down this path
225 * *should* invalidate device SenseData...
226 */
227 mpt_sdev->sense_sz = 0;
228 }
229 #endif
230 }
231 }
232
233 #if 0
234 {
235 MPT_FRAME_HDR *mf_chk;
236
237 /* This, I imagine, is a costly check, but...
238 * If abort/reset active, check to see if this is a IO
239 * that completed while ABORT/RESET for it is waiting
240 * on our taskQ!
241 */
242 if (! Q_IS_EMPTY(&mpt_scsih_taskQ)) {
243 /* If ABORT for this IO is queued, zap it! */
244 mf_chk = search_taskQ(1,sc,MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
245 if (mf_chk != NULL) {
246 sc->result = DID_ABORT << 16;
247 spin_lock_irqsave(&io_request_lock, flags);
248 sc->scsi_done(sc);
249 spin_unlock_irqrestore(&io_request_lock, flags);
250 return 1;
251 }
252 }
253 }
254 #endif
255
256 if (r != NULL && sc != NULL) {
257 SCSIIOReply_t *pScsiReply;
258 SCSIIORequest_t *pScsiReq;
259 u16 status;
260
261 pScsiReply = (SCSIIOReply_t *) r;
262 pScsiReq = (SCSIIORequest_t *) mf;
263
264 status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
265
266 dprintk((KERN_NOTICE MYNAM ": Uh-Oh! (req:sc:reply=%p:%p:%p)\n", mf, sc, r));
267 dprintk((KERN_NOTICE " IOCStatus=%04xh, SCSIState=%02xh"
268 ", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
269 status, pScsiReply->SCSIState, pScsiReply->SCSIStatus,
270 le32_to_cpu(pScsiReply->IOCLogInfo)));
271
272 /*
273 * Look for + dump FCP ResponseInfo[]!
274 */
275 if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
276 dprintk((KERN_NOTICE " FCP_ResponseInfo=%08xh\n",
277 le32_to_cpu(pScsiReply->ResponseInfo)));
278 }
279
280 switch(status) {
281 case MPI_IOCSTATUS_BUSY: /* 0x0002 */
282 /*sc->result = DID_BUS_BUSY << 16;*/ /* YIKES! - Seems to
283 * kill linux interrupt
284 * handler
285 */
286 sc->result = STS_BUSY; /* Try SCSI BUSY! */
287 break;
288
289 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
290 /* Not real sure here... */
291 sc->result = DID_OK << 16;
292 break;
293
294 case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */
295 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */
296 sc->result = DID_BAD_TARGET << 16;
297 break;
298
299 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */
300 /* Spoof to SCSI Selection Timeout! */
301 sc->result = DID_NO_CONNECT << 16;
302 break;
303
304 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
305 /*
306 * YIKES! I just discovered that SCSI IO which
307 * returns check condition, SenseKey=05 (ILLEGAL REQUEST)
308 * and ASC/ASCQ=94/01 (LSI Logic RAID vendor specific),
309 * comes down this path!
310 * Do upfront check for valid SenseData and give it
311 * precedence!
312 */
313 if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
314 copy_sense_data(sc, hd, mf, pScsiReply);
315 sc->result = pScsiReply->SCSIStatus;
316 break;
317 }
318
319 dprintk((KERN_NOTICE MYNAM ": sc->underflow={report ERR if < %02xh bytes xfer'd}\n", sc->underflow));
320 dprintk((KERN_NOTICE MYNAM ": ActBytesXferd=%02xh\n", le32_to_cpu(pScsiReply->TransferCount)));
321
322 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
323 sc->resid = sc->request_bufflen - le32_to_cpu(pScsiReply->TransferCount);
324 dprintk((KERN_NOTICE MYNAM ": SET sc->resid=%02xh\n", sc->resid));
325 #endif
326
327 #if 0
328 if (sc->underflow && (le32_to_cpu(pScsiReply->TransferCount) < sc->underflow)) {
329 sc->result = DID_ERROR << 16;
330 sc->resid = sc->request_bufflen - le32_to_cpu(pScsiReply->TransferCount);
331 } else {
332 sc->result = 0;
333 }
334 #endif
335
336 /* workaround attempts... */
337 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
338 if (sc->resid >= 0x200) {
339 /* GRRRRR...
340 * //sc->result = DID_SOFT_ERROR << 16;
341 * Try spoofing to BUSY
342 */
343 sc->result = STS_BUSY;
344 } else {
345 sc->result = 0;
346 }
347 #else
348 sc->result = 0;
349 #endif
350 break;
351
352 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */
353 sc->result = DID_ABORT << 16;
354 break;
355
356 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */
357 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
358 sc->result = DID_RESET << 16;
359 break;
360
361 case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */
362 sc->result = pScsiReply->SCSIStatus;
363
364 if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) {
365 copy_sense_data(sc, hd, mf, pScsiReply);
366
367 /* If running agains circa 200003dd 909 MPT f/w,
368 * may get this (AUTOSENSE_VALID) for actual TASK_SET_FULL
369 * (QUEUE_FULL) returned from device! --> get 0x0000?128
370 * and with SenseBytes set to 0.
371 */
372 if (pScsiReply->SCSIStatus == MPI_SCSI_STATUS_TASK_SET_FULL)
373 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
374 }
375 else if (pScsiReply->SCSIState & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
376 /*
377 * What to do?
378 */
379 sc->result = DID_SOFT_ERROR << 16;
380 }
381 else if (pScsiReply->SCSIState & MPI_SCSI_STATE_TERMINATED) {
382 /* Not real sure here either... */
383 sc->result = DID_ABORT << 16;
384 }
385
386 if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
387 mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
388
389 break;
390
391 case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */
392 case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */
393 case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */
394 case MPI_IOCSTATUS_RESERVED: /* 0x0005 */
395 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */
396 case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */
397 case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */
398 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */
399 case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */
400 case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */
401 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
402 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */
403 default:
404 /*
405 * What to do?
406 */
407 sc->result = DID_SOFT_ERROR << 16;
408 break;
409
410 } /* switch(status) */
411
412 dprintk((KERN_NOTICE MYNAM ": sc->result set to %08xh\n", sc->result));
413 }
414
415 if (sc != NULL) {
416 unsigned long flags;
417
418 /* Unmap the DMA buffers, if any. */
419 if (sc->use_sg) {
420 pci_unmap_sg(ioc->pcidev,
421 (struct scatterlist *) sc->request_buffer,
422 sc->use_sg,
423 scsi_to_pci_dma_dir(sc->sc_data_direction));
424 } else if (sc->request_bufflen) {
425 pci_unmap_single(ioc->pcidev,
426 (dma_addr_t)((long)sc->SCp.ptr),
427 sc->request_bufflen,
428 scsi_to_pci_dma_dir(sc->sc_data_direction));
429 }
430
431 spin_lock_irqsave(&io_request_lock, flags);
432 sc->scsi_done(sc);
433 spin_unlock_irqrestore(&io_request_lock, flags);
434 }
435
436 return 1;
437 }
438
439 #ifndef MPT_SCSI_USE_NEW_EH
440 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
441 /*
442 * search_taskQ - Search SCSI task mgmt request queue for specific
443 * request type
444 * @remove: (Boolean) Should request be removed if found?
445 * @sc: Pointer to Scsi_Cmnd structure
446 * @task_type: Task type to search for
447 *
448 * Returns pointer to MPT request frame if found, or %NULL if request
449 * was not found.
450 */
451 static MPT_FRAME_HDR *
452 search_taskQ(int remove, Scsi_Cmnd *sc, u8 task_type)
453 {
454 MPT_FRAME_HDR *mf = NULL;
455 unsigned long flags;
456 int count = 0;
457 int list_sz;
458
459 dslprintk((KERN_INFO MYNAM ": spinlock#1\n"));
460 spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
461 list_sz = mpt_scsih_taskQ_cnt;
462 if (! Q_IS_EMPTY(&mpt_scsih_taskQ)) {
463 mf = mpt_scsih_taskQ.head;
464 do {
465 count++;
466 if (mf->u.frame.linkage.argp1 == sc &&
467 mf->u.frame.linkage.arg1 == task_type) {
468 if (remove) {
469 Q_DEL_ITEM(&mf->u.frame.linkage);
470 mpt_scsih_taskQ_cnt--;
471 }
472 break;
473 }
474 } while ((mf = mf->u.frame.linkage.forw) != (MPT_FRAME_HDR*)&mpt_scsih_taskQ);
475 if (mf == (MPT_FRAME_HDR*)&mpt_scsih_taskQ) {
476 mf = NULL;
477 }
478 }
479 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
480
481 if (list_sz) {
482 dprintk((KERN_INFO MYNAM ": search_taskQ(%d,%p,%d) results=%p (%sFOUND%s)!\n",
483 remove, sc, task_type,
484 mf,
485 mf ? "" : "NOT_",
486 (mf && remove) ? "+REMOVED" : "" ));
487 dprintk((KERN_INFO MYNAM ": (searched thru %d of %d items on taskQ)\n",
488 count,
489 list_sz ));
490 }
491
492 return mf;
493 }
494
495 #endif
496
497 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
498
499 /*
500 * Hack! I'd like to report if a device is returning QUEUE_FULL
501 * but maybe not each and every time...
502 */
503 static long last_queue_full = 0;
504
505 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
506 /*
507 * mptscsih_report_queue_full - Report QUEUE_FULL status returned
508 * from a SCSI target device.
509 * @sc: Pointer to Scsi_Cmnd structure
510 * @pScsiReply: Pointer to SCSIIOReply_t
511 * @pScsiReq: Pointer to original SCSI request
512 *
513 * This routine periodically reports QUEUE_FULL status returned from a
514 * SCSI target device. It reports this to the console via kernel
515 * printk() API call, not more than once every 10 seconds.
516 */
517 static void
518 mptscsih_report_queue_full(Scsi_Cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
519 {
520 long time = jiffies;
521
522 if (time - last_queue_full > 10 * HZ) {
523 printk(KERN_WARNING MYNAM ": Device reported QUEUE_FULL! SCSI bus:target:lun = %d:%d:%d\n",
524 0, sc->target, sc->lun);
525 last_queue_full = time;
526 }
527 }
528
529 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
530 static int BeenHereDoneThat = 0;
531
532 /* SCSI fops start here... */
533 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
534 /**
535 * mptscsih_detect - Register MPT adapter(s) as SCSI host(s) with
536 * linux scsi mid-layer.
537 * @tpnt: Pointer to Scsi_Host_Template structure
538 *
539 * (linux Scsi_Host_Template.detect routine)
540 *
541 * Returns number of SCSI host adapters that were successfully
542 * registered with the linux scsi mid-layer via the scsi_register()
543 * API call.
544 */
545 int
546 mptscsih_detect(Scsi_Host_Template *tpnt)
547 {
548 struct Scsi_Host *sh = NULL;
549 MPT_SCSI_HOST *hd = NULL;
550 MPT_ADAPTER *this;
551 unsigned long flags;
552 int sz;
553 u8 *mem;
554
555 if (! BeenHereDoneThat++) {
556 show_mptmod_ver(my_NAME, my_VERSION);
557
558 if ((ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER)) <= 0) {
559 printk(KERN_ERR MYNAM ": Failed to register callback1 with MPT base driver\n");
560 return mpt_scsi_hosts;
561 }
562 if ((ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER)) <= 0) {
563 printk(KERN_ERR MYNAM ": Failed to register callback2 with MPT base driver\n");
564 return mpt_scsi_hosts;
565 }
566
567 #ifndef MPT_SCSI_USE_NEW_EH
568 Q_INIT(&mpt_scsih_taskQ, MPT_FRAME_HDR);
569 spin_lock_init(&mpt_scsih_taskQ_lock);
570 #endif
571
572 if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
573 dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n"));
574 } else {
575 /* FIXME! */
576 }
577
578 if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
579 dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
580 } else {
581 /* FIXME! */
582 }
583 }
584
585 dprintk((KERN_INFO MYNAM ": mpt_scsih_detect()\n"));
586
587 this = mpt_adapter_find_first();
588 while (this != NULL) {
589 /* FIXME! Multi-port (aka FC929) support...
590 * for (i = 0; i < this->facts.NumberOfPorts; i++)
591 */
592
593 /* 20010215 -sralston
594 * Added sanity check on SCSI Initiator-mode enabled
595 * for this MPT adapter.
596 */
597 if (!(this->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
598 printk(KERN_ERR MYNAM ": Skipping %s because SCSI Initiator mode is NOT enabled!\n",
599 this->name);
600 this = mpt_adapter_find_next(this);
601 continue;
602 }
603
604 /* 20010202 -sralston
605 * Added sanity check on readiness of the MPT adapter.
606 */
607 if (this->last_state != MPI_IOC_STATE_OPERATIONAL) {
608 printk(KERN_ERR MYNAM ": ERROR - Skipping %s because it's not operational!\n",
609 this->name);
610 this = mpt_adapter_find_next(this);
611 continue;
612 }
613
614 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
615 tpnt->proc_dir = &proc_mpt_scsihost;
616 #endif
617 sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));
618 if (sh != NULL) {
619 save_flags(flags);
620 cli();
621 sh->io_port = 0;
622 sh->n_io_port = 0;
623 sh->irq = 0;
624
625 /* Yikes! This is important!
626 * Otherwise, by default, linux only scans target IDs 0-7!
627 *
628 * BUG FIX! 20010618 -sralston & pdelaney
629 * FC919 testing was encountering "duplicate" FC devices,
630 * as it turns out because the 919 was returning 512
631 * for PortFacts.MaxDevices, causing a wraparound effect
632 * in SCSI IO requests. So instead of using:
633 * sh->max_id = this->pfacts[0].MaxDevices - 1
634 * we'll use a definitive max here.
635 */
636 sh->max_id = MPT_MAX_FC_DEVICES;
637
638 sh->this_id = this->pfacts[0].PortSCSIID;
639
640 restore_flags(flags);
641
642 hd = (MPT_SCSI_HOST *) sh->hostdata;
643 hd->ioc = this;
644 hd->port = 0; /* FIXME! */
645
646 /* SCSI needs Scsi_Cmnd lookup table!
647 * (with size equal to req_depth*PtrSz!)
648 */
649 sz = hd->ioc->req_depth * sizeof(void *);
650 mem = kmalloc(sz, GFP_KERNEL);
651 if (mem == NULL)
652 return mpt_scsi_hosts;
653
654 memset(mem, 0, sz);
655 hd->ScsiLookup = (struct scsi_cmnd **) mem;
656
657 dprintk((KERN_INFO MYNAM ": ScsiLookup @ %p, sz=%d\n",
658 hd->ScsiLookup, sz));
659
660 /* SCSI also needs SG buckets/hunk management!
661 * (with size equal to N * req_sz * req_depth!)
662 * (where N is number of SG buckets per hunk)
663 */
664 sz = MPT_SG_BUCKETS_PER_HUNK * hd->ioc->req_sz * hd->ioc->req_depth;
665 mem = pci_alloc_consistent(hd->ioc->pcidev, sz,
666 &hd->SgHunksDMA);
667 if (mem == NULL)
668 return mpt_scsi_hosts;
669
670 memset(mem, 0, sz);
671 hd->SgHunks = (u8*)mem;
672
673 dprintk((KERN_INFO MYNAM ": SgHunks @ %p(%08x), sz=%d\n",
674 hd->SgHunks, hd->SgHunksDMA, sz));
675
676 hd->qtag_tick = jiffies;
677
678 this->sh = sh;
679 mpt_scsi_hosts++;
680 }
681 this = mpt_adapter_find_next(this);
682 }
683
684 return mpt_scsi_hosts;
685 }
686
687 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
688 static char *info_kbuf = NULL;
689 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
690 /**
691 * mptscsih_release - Unregister SCSI host from linux scsi mid-layer
692 * @host: Pointer to Scsi_Host structure
693 *
694 * (linux Scsi_Host_Template.release routine)
695 * This routine releases all resources associated with the SCSI host
696 * adapter.
697 *
698 * Returns 0 for success.
699 */
700 int
701 mptscsih_release(struct Scsi_Host *host)
702 {
703 MPT_SCSI_HOST *hd;
704 #ifndef MPT_SCSI_USE_NEW_EH
705 unsigned long flags;
706
707 spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
708 if (mpt_scsih_taskQ_bh_active) {
709 int count = 10 * HZ;
710
711 dprintk((KERN_INFO MYNAM ": Info: Zapping TaskMgmt thread!\n"));
712
713 /* Zap the taskQ! */
714 Q_INIT(&mpt_scsih_taskQ, MPT_FRAME_HDR);
715 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
716
717 while(mpt_scsih_taskQ_bh_active && --count) {
718 current->state = TASK_INTERRUPTIBLE;
719 schedule_timeout(1);
720 }
721 if (!count)
722 printk(KERN_ERR MYNAM ": ERROR! TaskMgmt thread still active!\n");
723 }
724 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
725 #endif
726
727 hd = (MPT_SCSI_HOST *) host->hostdata;
728 if (hd != NULL) {
729 int sz1, sz2;
730
731 sz1 = sz2 = 0;
732 if (hd->ScsiLookup != NULL) {
733 sz1 = hd->ioc->req_depth * sizeof(void *);
734 kfree(hd->ScsiLookup);
735 hd->ScsiLookup = NULL;
736 }
737
738 if (hd->SgHunks != NULL) {
739
740 sz2 = MPT_SG_BUCKETS_PER_HUNK * hd->ioc->req_sz * hd->ioc->req_depth;
741 pci_free_consistent(hd->ioc->pcidev, sz2,
742 hd->SgHunks, hd->SgHunksDMA);
743 hd->SgHunks = NULL;
744 }
745 dprintk((KERN_INFO MYNAM ": Free'd ScsiLookup (%d) and SgHunks (%d) memory\n", sz1, sz2));
746 }
747
748 if (mpt_scsi_hosts) {
749 if (--mpt_scsi_hosts == 0) {
750 #if 0
751 mptscsih_flush_pending();
752 #endif
753 mpt_reset_deregister(ScsiDoneCtx);
754 dprintk((KERN_INFO MYNAM ": Deregistered for IOC reset notifications\n"));
755
756 mpt_event_deregister(ScsiDoneCtx);
757 dprintk((KERN_INFO MYNAM ": Deregistered for IOC event notifications\n"));
758
759 mpt_deregister(ScsiDoneCtx);
760 mpt_deregister(ScsiTaskCtx);
761
762 if (info_kbuf != NULL)
763 kfree(info_kbuf);
764 }
765 }
766
767 return 0;
768 }
769
770 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
771 /**
772 * mptscsih_info - Return information about MPT adapter
773 * @SChost: Pointer to Scsi_Host structure
774 *
775 * (linux Scsi_Host_Template.info routine)
776 *
777 * Returns pointer to buffer where information was written.
778 */
779 const char *
780 mptscsih_info(struct Scsi_Host *SChost)
781 {
782 MPT_SCSI_HOST *h;
783 int size = 0;
784
785 if (info_kbuf == NULL)
786 if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
787 return info_kbuf;
788
789 h = (MPT_SCSI_HOST *)SChost->hostdata;
790 info_kbuf[0] = '\0';
791 mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
792 info_kbuf[size-1] = '\0';
793
794 return info_kbuf;
795 }
796
797 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
798 static int max_qd = 1;
799 #ifdef MPT_DEBUG
800 static int max_sges = 0;
801 static int max_xfer = 0;
802 #endif
803 #if 0
804 static int max_num_sges = 0;
805 static int max_sgent_len = 0;
806 #endif
807 #if 0
808 static int index_log[128];
809 static int index_ent = 0;
810 static __inline__ void ADD_INDEX_LOG(int req_ent)
811 {
812 int i = index_ent++;
813
814 index_log[i & (128 - 1)] = req_ent;
815 }
816 #else
817 #define ADD_INDEX_LOG(req_ent) do { } while(0)
818 #endif
819 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
820 /**
821 * mptscsih_qcmd - Primary Fusion MPT SCSI initiator IO start routine.
822 * @SCpnt: Pointer to Scsi_Cmnd structure
823 * @done: Pointer SCSI mid-layer IO completion function
824 *
825 * (linux Scsi_Host_Template.queuecommand routine)
826 * This is the primary SCSI IO start routine. Create a MPI SCSIIORequest
827 * from a linux Scsi_Cmnd request and send it to the IOC.
828 *
829 * Returns 0. (rtn value discarded by linux scsi mid-layer)
830 */
831 int
832 mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
833 {
834 struct Scsi_Host *host;
835 MPT_SCSI_HOST *hd;
836 MPT_FRAME_HDR *mf;
837 SCSIIORequest_t *pScsiReq;
838 int datadir;
839 u32 len;
840 u32 sgdir;
841 u32 scsictl;
842 u32 scsidir;
843 u32 qtag;
844 u32 *mptr;
845 int sge_spill1;
846 int frm_sz;
847 int sges_left;
848 u32 chain_offset;
849 int my_idx;
850 int i;
851
852 dmfprintk((KERN_INFO MYNAM "_qcmd: SCpnt=%p, done()=%p\n",
853 SCpnt, done));
854
855 host = SCpnt->host;
856 hd = (MPT_SCSI_HOST *) host->hostdata;
857
858 #if 0
859 if (host->host_busy >= 60) {
860 MPT_ADAPTER *ioc = hd->ioc;
861 u16 pci_command, pci_status;
862
863 /* The IOC is probably hung, investigate status. */
864 printk("MPI: IOC probably hung IOCSTAT[%08x] INTSTAT[%08x] REPLYFIFO[%08x]\n",
865 readl(&ioc->chip.fc9xx->DoorbellValue),
866 readl(&ioc->chip.fc9xx->IntStatus),
867 readl(&ioc->chip.fc9xx->ReplyFifo));
868 pci_read_config_word(ioc->pcidev, PCI_COMMAND, &pci_command);
869 pci_read_config_word(ioc->pcidev, PCI_STATUS, &pci_status);
870 printk("MPI: PCI command[%04x] status[%04x]\n", pci_command, pci_status);
871 {
872 /* DUMP req index logger. */
873 int begin, end;
874
875 begin = (index_ent - 65) & (128 - 1);
876 end = index_ent & (128 - 1);
877 printk("MPI: REQ_INDEX_HIST[");
878 while (begin != end) {
879 printk("(%04x)", index_log[begin]);
880 begin = (begin + 1) & (128 - 1);
881 }
882 printk("\n");
883 }
884 sti();
885 while(1)
886 barrier();
887 }
888 #endif
889
890 SCpnt->scsi_done = done;
891
892 /* 20000617 -sralston
893 * GRRRRR... Shouldn't have to do this but...
894 * Do explicit check for REQUEST_SENSE and cached SenseData.
895 * If yes, return cached SenseData.
896 */
897 #ifdef MPT_SCSI_CACHE_AUTOSENSE
898 {
899 MPT_SCSI_DEV *mpt_sdev;
900
901 mpt_sdev = (MPT_SCSI_DEV *) SCpnt->device->hostdata;
902 if (mpt_sdev && SCpnt->cmnd[0] == REQUEST_SENSE) {
903 u8 *dest = NULL;
904
905 if (!SCpnt->use_sg)
906 dest = SCpnt->request_buffer;
907 else {
908 struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
909 if (sg)
910 dest = (u8 *) (unsigned long)sg_dma_address(sg);
911 }
912
913 if (dest && mpt_sdev->sense_sz) {
914 memcpy(dest, mpt_sdev->CachedSense.data, mpt_sdev->sense_sz);
915 #ifdef MPT_DEBUG
916 {
917 int i;
918 u8 *sb;
919
920 sb = mpt_sdev->CachedSense.data;
921 if (sb && ((sb[0] & 0x70) == 0x70)) {
922 printk(KERN_WARNING MYNAM ": Returning last cached SCSI (hex) SenseData:\n");
923 printk(KERN_WARNING " ");
924 for (i = 0; i < (8 + sb[7]); i++)
925 printk("%s%02x", i == 13 ? "-" : " ", sb[i]);
926 printk("\n");
927 }
928 }
929 #endif
930 }
931 SCpnt->resid = SCpnt->request_bufflen - mpt_sdev->sense_sz;
932 SCpnt->result = 0;
933 /* spin_lock(&io_request_lock); */
934 SCpnt->scsi_done(SCpnt);
935 /* spin_unlock(&io_request_lock); */
936 return 0;
937 }
938 }
939 #endif
940
941 if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc->id)) == NULL) {
942 /* SCpnt->result = DID_SOFT_ERROR << 16; */
943 SCpnt->result = STS_BUSY;
944 SCpnt->scsi_done(SCpnt);
945 /* return 1; */
946 return 0;
947 }
948 pScsiReq = (SCSIIORequest_t *) mf;
949
950 my_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
951
952 ADD_INDEX_LOG(my_idx);
953
954 /* Map the data portion, if any. */
955 sges_left = SCpnt->use_sg;
956 if (sges_left) {
957 sges_left = pci_map_sg(hd->ioc->pcidev,
958 (struct scatterlist *) SCpnt->request_buffer,
959 sges_left,
960 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
961 } else if (SCpnt->request_bufflen) {
962 dma_addr_t buf_dma_addr;
963
964 buf_dma_addr = pci_map_single(hd->ioc->pcidev,
965 SCpnt->request_buffer,
966 SCpnt->request_bufflen,
967 scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
968
969 /* We hide it here for later unmap. */
970 SCpnt->SCp.ptr = (char *)(unsigned long) buf_dma_addr;
971 }
972
973 /*
974 * Put together a MPT SCSI request...
975 */
976
977 /* Assume SimpleQ, NO DATA XFER for now */
978
979 len = SCpnt->request_bufflen;
980 sgdir = 0x00000000; /* SGL IN (host<--ioc) */
981 scsidir = MPI_SCSIIO_CONTROL_NODATATRANSFER;
982
983 /*
984 * The scsi layer should be handling this stuff
985 * (In 2.3.x it does -DaveM)
986 */
987
988 /* BUG FIX! 19991030 -sralston
989 * TUR's being issued with scsictl=0x02000000 (DATA_IN)!
990 * Seems we may receive a buffer (len>0) even when there
991 * will be no data transfer! GRRRRR...
992 */
993 datadir = mptscsih_io_direction(SCpnt);
994 if (datadir < 0) {
995 scsidir = MPI_SCSIIO_CONTROL_READ; /* DATA IN (host<--ioc<--dev) */
996 } else if (datadir > 0) {
997 sgdir = 0x04000000; /* SGL OUT (host-->ioc) */
998 scsidir = MPI_SCSIIO_CONTROL_WRITE; /* DATA OUT (host-->ioc-->dev) */
999 } else {
1000 len = 0;
1001 }
1002
1003 qtag = MPI_SCSIIO_CONTROL_SIMPLEQ;
1004
1005 /*
1006 * Attach tags to the devices
1007 */
1008 if (SCpnt->device->tagged_supported) {
1009 /*
1010 * Some drives are too stupid to handle fairness issues
1011 * with tagged queueing. We throw in the odd ordered
1012 * tag to stop them starving themselves.
1013 */
1014 if ((jiffies - hd->qtag_tick) > (5*HZ)) {
1015 qtag = MPI_SCSIIO_CONTROL_ORDEREDQ;
1016 hd->qtag_tick = jiffies;
1017
1018 #if 0
1019 /* These are ALWAYS zero!
1020 * (Because this is a place for the device driver to dynamically
1021 * assign tag numbers any way it sees fit. That's why -DaveM)
1022 */
1023 dprintk((KERN_DEBUG MYNAM ": sc->device->current_tag = %08x\n",
1024 SCpnt->device->current_tag));
1025 dprintk((KERN_DEBUG MYNAM ": sc->tag = %08x\n",
1026 SCpnt->tag));
1027 #endif
1028 }
1029 #if 0
1030 else {
1031 /* Hmmm... I always see value of 0 here,
1032 * of which {HEAD_OF, ORDERED, SIMPLE} are NOT! -sralston
1033 * (Because this is a place for the device driver to dynamically
1034 * assign tag numbers any way it sees fit. That's why -DaveM)
1035 *
1036 * if (SCpnt->tag == HEAD_OF_QUEUE_TAG)
1037 */
1038 if (SCpnt->device->current_tag == HEAD_OF_QUEUE_TAG)
1039 qtag = MPI_SCSIIO_CONTROL_HEADOFQ;
1040 else if (SCpnt->tag == ORDERED_QUEUE_TAG)
1041 qtag = MPI_SCSIIO_CONTROL_ORDEREDQ;
1042 }
1043 #endif
1044 }
1045
1046 scsictl = scsidir | qtag;
1047
1048 frm_sz = hd->ioc->req_sz;
1049
1050 /* Ack!
1051 * sge_spill1 = 9;
1052 */
1053 sge_spill1 = (frm_sz - (sizeof(SCSIIORequest_t) - sizeof(SGEIOUnion_t) + sizeof(SGEChain32_t))) / 8;
1054 /* spill1: for req_sz == 128 (128-48==80, 80/8==10 SGEs max, first time!), --> use 9
1055 * spill1: for req_sz == 96 ( 96-48==48, 48/8== 6 SGEs max, first time!), --> use 5
1056 */
1057 dsgprintk((KERN_INFO MYNAM ": SG: %x spill1 = %d\n",
1058 my_idx, sge_spill1));
1059
1060 #ifdef MPT_DEBUG
1061 if (sges_left > max_sges) {
1062 max_sges = sges_left;
1063 dprintk((KERN_INFO MYNAM ": MPT_MaxSges = %d\n", max_sges));
1064 }
1065 #endif
1066 #if 0
1067 if (sges_left > max_num_sges) {
1068 max_num_sges = sges_left;
1069 printk(KERN_INFO MYNAM ": MPT_MaxNumSges = %d\n", max_num_sges);
1070 }
1071 #endif
1072
1073 dsgprintk((KERN_INFO MYNAM ": SG: %x sges_left = %d (initially)\n",
1074 my_idx, sges_left));
1075
1076 chain_offset = 0;
1077 if (sges_left > (sge_spill1+1)) {
1078 #if 0
1079 chain_offset = 0x1E;
1080 #endif
1081 chain_offset = (frm_sz - 8) / 4;
1082 }
1083
1084 pScsiReq->TargetID = SCpnt->target;
1085 pScsiReq->Bus = hd->port;
1086 pScsiReq->ChainOffset = chain_offset;
1087 pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
1088 pScsiReq->CDBLength = SCpnt->cmd_len;
1089
1090 /* We have 256 bytes alloc'd per IO; let's use it. */
1091 /* pScsiReq->SenseBufferLength = SNS_LEN(SCpnt); */
1092 pScsiReq->SenseBufferLength = 255;
1093
1094 pScsiReq->Reserved = 0;
1095 pScsiReq->MsgFlags = 0;
1096 pScsiReq->LUN[0] = 0;
1097 pScsiReq->LUN[1] = SCpnt->lun;
1098 pScsiReq->LUN[2] = 0;
1099 pScsiReq->LUN[3] = 0;
1100 pScsiReq->LUN[4] = 0;
1101 pScsiReq->LUN[5] = 0;
1102 pScsiReq->LUN[6] = 0;
1103 pScsiReq->LUN[7] = 0;
1104 pScsiReq->Control = cpu_to_le32(scsictl);
1105
1106 /*
1107 * Write SCSI CDB into the message
1108 */
1109 for (i = 0; i < 12; i++)
1110 pScsiReq->CDB[i] = SCpnt->cmnd[i];
1111 for (i = 12; i < 16; i++)
1112 pScsiReq->CDB[i] = 0;
1113
1114 /* DataLength */
1115 pScsiReq->DataLength = cpu_to_le32(len);
1116
1117 /* SenseBuffer low address */
1118 pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_pool_dma + (my_idx * 256));
1119
1120 mptr = (u32 *) &pScsiReq->SGL;
1121
1122 /*
1123 * Now fill in the SGList...
1124 * NOTES: For 128 byte req_sz, we can hold up to 10 simple SGE's
1125 * in the remaining request frame. We -could- do unlimited chains
1126 * but each chain buffer can only be req_sz bytes in size, and
1127 * we lose one SGE whenever we chain.
1128 * For 128 req_sz, we can hold up to 16 SGE's per chain buffer.
1129 * For practical reasons, limit ourselves to 1 overflow chain buffer;
1130 * giving us 9 + 16 == 25 SGE's max.
1131 * At 4 Kb per SGE, that yields 100 Kb max transfer.
1132 *
1133 * (This code needs to be completely changed when/if 64-bit DMA
1134 * addressing is used, since we will be able to fit much less than
1135 * 10 embedded SG entries. -DaveM)
1136 */
1137 if (sges_left) {
1138 struct scatterlist *sg = (struct scatterlist *) SCpnt->request_buffer;
1139 u32 v1, v2;
1140 int sge_spill2;
1141 int sge_cur_spill;
1142 int sgCnt;
1143 u8 *pSgBucket;
1144 int chain_sz;
1145
1146 len = 0;
1147
1148 /* sge_spill2 = 15;
1149 * spill2: for req_sz == 128 (128/8==16 SGEs max, first time!), --> use 15
1150 * spill2: for req_sz == 96 ( 96/8==12 SGEs max, first time!), --> use 11
1151 */
1152 sge_spill2 = frm_sz / 8 - 1;
1153 dsgprintk((KERN_INFO MYNAM ": SG: %x spill2 = %d\n",
1154 my_idx, sge_spill2));
1155
1156 pSgBucket = NULL;
1157 sgCnt = 0;
1158 sge_cur_spill = sge_spill1;
1159 while (sges_left) {
1160 #if 0
1161 if (sg_dma_len(sg) > max_sgent_len) {
1162 max_sgent_len = sg_dma_len(sg);
1163 printk(KERN_INFO MYNAM ": MPT_MaxSgentLen = %d\n", max_sgent_len);
1164 }
1165 #endif
1166 /* Write one simple SGE */
1167 v1 = sgdir | 0x10000000 | sg_dma_len(sg);
1168 len += sg_dma_len(sg);
1169 v2 = sg_dma_address(sg);
1170 dsgprintk((KERN_INFO MYNAM ": SG: %x Writing SGE @%p: %08x %08x, sges_left=%d\n",
1171 my_idx, mptr, v1, v2, sges_left));
1172 *mptr++ = cpu_to_le32(v1);
1173 *mptr++ = cpu_to_le32(v2);
1174 sg++;
1175 sgCnt++;
1176
1177 if (--sges_left == 0) {
1178 /* re-write 1st word of previous SGE with SIMPLE,
1179 * LE, EOB, and EOL bits!
1180 */
1181 v1 = 0xD1000000 | sgdir | sg_dma_len(sg-1);
1182 dsgprintk((KERN_INFO MYNAM ": SG: %x (re)Writing SGE @%p: %08x (VERY LAST SGE!)\n",
1183 my_idx, mptr-2, v1));
1184 *(mptr - 2) = cpu_to_le32(v1);
1185 } else {
1186 if ((sges_left > 1) && ((sgCnt % sge_cur_spill) == 0)) {
1187 dsgprintk((KERN_INFO MYNAM ": SG: %x SG spill at modulo 0!\n",
1188 my_idx));
1189
1190 /* Fixup previous SGE with LE bit! */
1191 v1 = sgdir | 0x90000000 | sg_dma_len(sg-1);
1192 dsgprintk((KERN_INFO MYNAM ": SG: %x (re)Writing SGE @%p: %08x (LAST BUCKET SGE!)\n",
1193 my_idx, mptr-2, v1));
1194 *(mptr - 2) = cpu_to_le32(v1);
1195
1196 chain_offset = 0;
1197 /* Going to need another chain? */
1198 if (sges_left > (sge_spill2+1)) {
1199 #if 0
1200 chain_offset = 0x1E;
1201 #endif
1202 chain_offset = (frm_sz - 8) / 4;
1203 chain_sz = frm_sz;
1204 } else {
1205 chain_sz = sges_left * 8;
1206 }
1207
1208 /* write chain SGE at mptr. */
1209 v1 = 0x30000000 | chain_offset<<16 | chain_sz;
1210 if (pSgBucket == NULL) {
1211 pSgBucket = hd->SgHunks
1212 + (my_idx * frm_sz * MPT_SG_BUCKETS_PER_HUNK);
1213 } else {
1214 pSgBucket += frm_sz;
1215 }
1216 v2 = (hd->SgHunksDMA +
1217 ((u8 *)pSgBucket - (u8 *)hd->SgHunks));
1218 dsgprintk((KERN_INFO MYNAM ": SG: %x Writing SGE @%p: %08x %08x (CHAIN!)\n",
1219 my_idx, mptr, v1, v2));
1220 *(mptr++) = cpu_to_le32(v1);
1221 *(mptr) = cpu_to_le32(v2);
1222
1223 mptr = (u32 *) pSgBucket;
1224 sgCnt = 0;
1225 sge_cur_spill = sge_spill2;
1226 }
1227 }
1228 }
1229 } else {
1230 dsgprintk((KERN_INFO MYNAM ": SG: non-SG for %p, len=%d\n",
1231 SCpnt, SCpnt->request_bufflen));
1232
1233 if (len > 0) {
1234 dma_addr_t buf_dma_addr;
1235
1236 buf_dma_addr = (dma_addr_t) (unsigned long)SCpnt->SCp.ptr;
1237 *(mptr++) = cpu_to_le32(0xD1000000|sgdir|SCpnt->request_bufflen);
1238 *(mptr++) = cpu_to_le32(buf_dma_addr);
1239 }
1240 }
1241
1242 #ifdef MPT_DEBUG
1243 /* if (SCpnt->request_bufflen > max_xfer) */
1244 if (len > max_xfer) {
1245 max_xfer = len;
1246 dprintk((KERN_INFO MYNAM ": MPT_MaxXfer = %d\n", max_xfer));
1247 }
1248 #endif
1249
1250 hd->ScsiLookup[my_idx] = SCpnt;
1251
1252 /* Main banana... */
1253 mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
1254
1255 atomic_inc(&queue_depth);
1256 if (atomic_read(&queue_depth) > max_qd) {
1257 max_qd = atomic_read(&queue_depth);
1258 dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd));
1259 }
1260
1261 dmfprintk((KERN_INFO MYNAM ": Issued SCSI cmd (%p)\n", SCpnt));
1262
1263 return 0;
1264 }
1265
1266 #ifdef MPT_SCSI_USE_NEW_EH /* { */
1267 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1268 /*
1269 mptscsih_abort
1270 Returns: 0=SUCCESS, else FAILED
1271 */
1272 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1273 /**
1274 * mptscsih_abort - Abort linux Scsi_Cmnd routine, new_eh variant
1275 * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
1276 *
1277 * (linux Scsi_Host_Template.eh_abort_handler routine)
1278 *
1279 * Returns SUCCESS or FAILED.
1280 */
1281 int
1282 mptscsih_abort(Scsi_Cmnd * SCpnt)
1283 {
1284 MPT_FRAME_HDR *mf;
1285 SCSITaskMgmt_t *pScsiTm;
1286 MPT_SCSI_HOST *hd;
1287 u32 *msg;
1288 u32 ctx2abort;
1289 int i;
1290 unsigned long flags;
1291
1292 printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO (=%p)\n", SCpnt);
1293 printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
1294
1295 hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
1296
1297 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
1298 /* SCpnt->result = DID_SOFT_ERROR << 16; */
1299 SCpnt->result = STS_BUSY;
1300 SCpnt->scsi_done(SCpnt);
1301 return FAILED;
1302 }
1303
1304 pScsiTm = (SCSITaskMgmt_t *) mf;
1305 msg = (u32 *) mf;
1306
1307 pScsiTm->TargetID = SCpnt->target;
1308 pScsiTm->Bus = hd->port;
1309 pScsiTm->ChainOffset = 0;
1310 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1311
1312 pScsiTm->Reserved = 0;
1313 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
1314 pScsiTm->Reserved1 = 0;
1315 pScsiTm->MsgFlags = 0;
1316
1317 for (i = 0; i < 8; i++) {
1318 u8 val = 0;
1319 if (i == 1)
1320 val = SCpnt->lun;
1321 pScsiTm->LUN[i] = val;
1322 }
1323
1324 for (i = 0; i < 7; i++)
1325 pScsiTm->Reserved2[i] = 0;
1326
1327 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1328 * (the IO to be ABORT'd)
1329 *
1330 * NOTE: Since we do not byteswap MsgContext, we do not
1331 * swap it here either. It is an opaque cookie to
1332 * the controller, so it does not matter. -DaveM
1333 */
1334 ctx2abort = SCPNT_TO_MSGCTX(SCpnt);
1335 if (ctx2abort == -1) {
1336 printk(KERN_ERR MYNAM ": ERROR - ScsiLookup fail(#2) for SCpnt=%p\n", SCpnt);
1337 SCpnt->result = DID_SOFT_ERROR << 16;
1338 spin_lock_irqsave(&io_request_lock, flags);
1339 SCpnt->scsi_done(SCpnt);
1340 spin_unlock_irqrestore(&io_request_lock, flags);
1341 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
1342 } else {
1343 dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort));
1344 pScsiTm->TaskMsgContext = ctx2abort;
1345
1346
1347 /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
1348 mpt_put_msg_frame(hd->ioc->id, mf);
1349 */
1350 if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
1351 sizeof(SCSITaskMgmt_t), msg))
1352 != 0) {
1353 printk(KERN_WARNING MYNAM
1354 ": WARNING[2] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n",
1355 i, mf, SCpnt);
1356 SCpnt->result = DID_SOFT_ERROR << 16;
1357 spin_lock_irqsave(&io_request_lock, flags);
1358 SCpnt->scsi_done(SCpnt);
1359 spin_unlock_irqrestore(&io_request_lock, flags);
1360 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
1361 }
1362 }
1363
1364 //return SUCCESS;
1365 return FAILED;
1366 }
1367
1368 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1369 /**
1370 * mptscsih_dev_reset - Perform a SCSI TARGET_RESET! new_eh variant
1371 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
1372 *
1373 * (linux Scsi_Host_Template.eh_dev_reset_handler routine)
1374 *
1375 * Returns SUCCESS or FAILED.
1376 */
1377 int
1378 mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
1379 {
1380 MPT_FRAME_HDR *mf;
1381 SCSITaskMgmt_t *pScsiTm;
1382 MPT_SCSI_HOST *hd;
1383 u32 *msg;
1384 int i;
1385 unsigned long flags;
1386
1387 printk(KERN_WARNING MYNAM ": Attempting _TARGET_RESET (%p)\n", SCpnt);
1388 printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
1389
1390 hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
1391
1392 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
1393 /* SCpnt->result = DID_SOFT_ERROR << 16; */
1394 SCpnt->result = STS_BUSY;
1395 SCpnt->scsi_done(SCpnt);
1396 return FAILED;
1397 }
1398
1399 pScsiTm = (SCSITaskMgmt_t *) mf;
1400 msg = (u32*)mf;
1401
1402 pScsiTm->TargetID = SCpnt->target;
1403 pScsiTm->Bus = hd->port;
1404 pScsiTm->ChainOffset = 0;
1405 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1406
1407 pScsiTm->Reserved = 0;
1408 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
1409 pScsiTm->Reserved1 = 0;
1410 pScsiTm->MsgFlags = 0;
1411
1412 /* _TARGET_RESET goes to LUN 0 always! */
1413 for (i = 0; i < 8; i++)
1414 pScsiTm->LUN[i] = 0;
1415
1416 /* Control: No data direction, set task mgmt bit? */
1417 for (i = 0; i < 7; i++)
1418 pScsiTm->Reserved2[i] = 0;
1419
1420 pScsiTm->TaskMsgContext = cpu_to_le32(0);
1421
1422 /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
1423 mpt_put_msg_frame(hd->ioc->id, mf);
1424 */
1425 /* FIXME! Check return status! */
1426 if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
1427 sizeof(SCSITaskMgmt_t), msg))
1428 != 0) {
1429 printk(KERN_WARNING MYNAM
1430 ": WARNING[3] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n",
1431 i, mf, SCpnt);
1432 SCpnt->result = DID_SOFT_ERROR << 16;
1433 spin_lock_irqsave(&io_request_lock, flags);
1434 SCpnt->scsi_done(SCpnt);
1435 spin_unlock_irqrestore(&io_request_lock, flags);
1436 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
1437 }
1438
1439 //return SUCCESS;
1440 return FAILED;
1441 }
1442
1443 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1444 /**
1445 * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant
1446 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
1447 *
1448 * (linux Scsi_Host_Template.eh_bus_reset_handler routine)
1449 *
1450 * Returns SUCCESS or FAILED.
1451 */
1452 int
1453 mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
1454 {
1455 MPT_FRAME_HDR *mf;
1456 SCSITaskMgmt_t *pScsiTm;
1457 MPT_SCSI_HOST *hd;
1458 u32 *msg;
1459 int i;
1460 unsigned long flags;
1461
1462 printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET (%p)\n", SCpnt);
1463 printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
1464
1465 hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
1466
1467 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
1468 /* SCpnt->result = DID_SOFT_ERROR << 16; */
1469 SCpnt->result = STS_BUSY;
1470 SCpnt->scsi_done(SCpnt);
1471 return FAILED;
1472 }
1473
1474 pScsiTm = (SCSITaskMgmt_t *) mf;
1475 msg = (u32 *) mf;
1476
1477 pScsiTm->TargetID = SCpnt->target;
1478 pScsiTm->Bus = hd->port;
1479 pScsiTm->ChainOffset = 0;
1480 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1481
1482 pScsiTm->Reserved = 0;
1483 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
1484 pScsiTm->Reserved1 = 0;
1485 pScsiTm->MsgFlags = 0;
1486
1487 for (i = 0; i < 8; i++)
1488 pScsiTm->LUN[i] = 0;
1489
1490 /* Control: No data direction, set task mgmt bit? */
1491 for (i = 0; i < 7; i++)
1492 pScsiTm->Reserved2[i] = 0;
1493
1494 pScsiTm->TaskMsgContext = cpu_to_le32(0);
1495
1496 /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
1497 mpt_put_msg_frame(hd->ioc->id, mf);
1498 */
1499 /* FIXME! Check return status! */
1500 if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
1501 sizeof(SCSITaskMgmt_t), msg))
1502 != 0) {
1503 printk(KERN_WARNING MYNAM
1504 ": WARNING[4] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n",
1505 i, mf, SCpnt);
1506 SCpnt->result = DID_SOFT_ERROR << 16;
1507 spin_lock_irqsave(&io_request_lock, flags);
1508 SCpnt->scsi_done(SCpnt);
1509 spin_unlock_irqrestore(&io_request_lock, flags);
1510 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
1511 }
1512
1513 return SUCCESS;
1514 }
1515
1516 #if 0 /* { */
1517 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1518 /**
1519 * mptscsih_host_reset - Perform a SCSI host adapter RESET!
1520 * new_eh variant
1521 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
1522 *
1523 * (linux Scsi_Host_Template.eh_host_reset_handler routine)
1524 *
1525 * Returns SUCCESS or FAILED.
1526 */
1527 int
1528 mptscsih_host_reset(Scsi_Cmnd * SCpnt)
1529 {
1530 return FAILED;
1531 }
1532 #endif /* } */
1533
1534 #else /* MPT_SCSI old EH stuff... */
1535 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1536 /**
1537 * mptscsih_old_abort - Abort linux Scsi_Cmnd routine
1538 * @SCpnt: Pointer to Scsi_Cmnd structure, IO to be aborted
1539 *
1540 * (linux Scsi_Host_Template.abort routine)
1541 *
1542 * Returns SCSI_ABORT_{SUCCESS,BUSY,PENDING}.
1543 */
1544 int
1545 mptscsih_old_abort(Scsi_Cmnd *SCpnt)
1546 {
1547 MPT_SCSI_HOST *hd;
1548 MPT_FRAME_HDR *mf;
1549 struct tq_struct *ptaskfoo;
1550 unsigned long flags;
1551
1552 printk(KERN_WARNING MYNAM ": Scheduling _ABORT SCSI IO (=%p)\n", SCpnt);
1553 printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
1554
1555 if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
1556 SCpnt->result = DID_ABORT << 16;
1557 SCpnt->scsi_done(SCpnt);
1558 return SCSI_ABORT_SUCCESS;
1559 }
1560
1561 /*
1562 * Check to see if there's already an ABORT queued for this guy.
1563 */
1564 mf = search_taskQ(0,SCpnt,MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK);
1565 if (mf != NULL) {
1566 return SCSI_ABORT_PENDING;
1567 }
1568
1569 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
1570 /* SCpnt->result = DID_SOFT_ERROR << 16; */
1571 SCpnt->result = STS_BUSY;
1572 SCpnt->scsi_done(SCpnt);
1573 return SCSI_ABORT_BUSY;
1574 }
1575
1576 /*
1577 * Add ourselves to (end of) mpt_scsih_taskQ.
1578 * Check to see if our _bh is running. If NOT, schedule it.
1579 */
1580 dslprintk((KERN_INFO MYNAM ": spinlock#2\n"));
1581 spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
1582 Q_ADD_TAIL(&mpt_scsih_taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
1583 mpt_scsih_taskQ_cnt++;
1584 /* Yikes - linkage! */
1585 /* SCpnt->host_scribble = (unsigned char *)mf; */
1586 mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
1587 mf->u.frame.linkage.argp1 = SCpnt;
1588 if (! mpt_scsih_taskQ_bh_active) {
1589 mpt_scsih_taskQ_bh_active = 1;
1590 /*
1591 * Oh how cute, no alloc/free/mgmt needed if we use
1592 * (bottom/unused portion of) MPT request frame.
1593 */
1594 ptaskfoo = (struct tq_struct *) ((u8*)mf + hd->ioc->req_sz - sizeof(*ptaskfoo));
1595 ptaskfoo->sync = 0;
1596 ptaskfoo->routine = mptscsih_taskmgmt_bh;
1597 ptaskfoo->data = SCpnt;
1598
1599 SCHEDULE_TASK(ptaskfoo);
1600 }
1601 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1602
1603 return SCSI_ABORT_PENDING;
1604 }
1605
1606 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1607 /**
1608 * mptscsih_old_reset - Perform a SCSI BUS_RESET!
1609 * @SCpnt: Pointer to Scsi_Cmnd structure, IO which reset is due to
1610 * @reset_flags: (not used?)
1611 *
1612 * (linux Scsi_Host_Template.reset routine)
1613 *
1614 * Returns SCSI_RESET_{SUCCESS,PUNT,PENDING}.
1615 */
1616 int
1617 mptscsih_old_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
1618 {
1619 MPT_SCSI_HOST *hd;
1620 MPT_FRAME_HDR *mf;
1621 struct tq_struct *ptaskfoo;
1622 unsigned long flags;
1623
1624 printk(KERN_WARNING MYNAM ": Scheduling _BUS_RESET (=%p)\n", SCpnt);
1625 printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
1626
1627 if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
1628 SCpnt->result = DID_RESET << 16;
1629 SCpnt->scsi_done(SCpnt);
1630 return SCSI_RESET_SUCCESS;
1631 }
1632
1633 /*
1634 * Check to see if there's already a BUS_RESET queued for this guy.
1635 */
1636 mf = search_taskQ(0,SCpnt,MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS);
1637 if (mf != NULL) {
1638 return SCSI_RESET_PENDING;
1639 }
1640
1641 if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc->id)) == NULL) {
1642 /* SCpnt->result = DID_SOFT_ERROR << 16; */
1643 SCpnt->result = STS_BUSY;
1644 SCpnt->scsi_done(SCpnt);
1645 return SCSI_RESET_PUNT;
1646 }
1647
1648 /*
1649 * Add ourselves to (end of) mpt_scsih_taskQ.
1650 * Check to see if our _bh is running. If NOT, schedule it.
1651 */
1652 dslprintk((KERN_INFO MYNAM ": spinlock#3\n"));
1653 spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
1654 Q_ADD_TAIL(&mpt_scsih_taskQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
1655 mpt_scsih_taskQ_cnt++;
1656 /* Yikes - linkage! */
1657 /* SCpnt->host_scribble = (unsigned char *)mf; */
1658 mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS;
1659 mf->u.frame.linkage.argp1 = SCpnt;
1660 if (! mpt_scsih_taskQ_bh_active) {
1661 mpt_scsih_taskQ_bh_active = 1;
1662 /*
1663 * Oh how cute, no alloc/free/mgmt needed if we use
1664 * (bottom/unused portion of) MPT request frame.
1665 */
1666 ptaskfoo = (struct tq_struct *) ((u8*)mf + hd->ioc->req_sz - sizeof(*ptaskfoo));
1667 ptaskfoo->sync = 0;
1668 ptaskfoo->routine = mptscsih_taskmgmt_bh;
1669 ptaskfoo->data = SCpnt;
1670
1671 SCHEDULE_TASK(ptaskfoo);
1672 }
1673 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1674
1675 return SCSI_RESET_PENDING;
1676 }
1677
1678 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1679 /*
1680 * mptscsih_taskmgmt_bh - SCSI task mgmt bottom half handler
1681 * @sc: (unused)
1682 *
1683 * This routine (thread) is active whenever there are any outstanding
1684 * SCSI task management requests for a SCSI host adapter.
1685 * IMPORTANT! This routine is scheduled therefore should never be
1686 * running in ISR context. i.e., it's safe to sleep here.
1687 */
1688 void
1689 mptscsih_taskmgmt_bh(void *sc)
1690 {
1691 Scsi_Cmnd *SCpnt;
1692 MPT_FRAME_HDR *mf;
1693 SCSITaskMgmt_t *pScsiTm;
1694 MPT_SCSI_HOST *hd;
1695 u32 ctx2abort = 0;
1696 int i;
1697 unsigned long flags;
1698 u8 task_type;
1699
1700 dslprintk((KERN_INFO MYNAM ": spinlock#4\n"));
1701 spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
1702 mpt_scsih_taskQ_bh_active = 1;
1703 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1704
1705 while (1) {
1706 current->state = TASK_INTERRUPTIBLE;
1707 schedule_timeout(HZ/4);
1708
1709 /*
1710 * We MUST remove item from taskQ *before* we format the
1711 * frame as a SCSITaskMgmt request and send it down to the IOC.
1712 */
1713 dslprintk((KERN_INFO MYNAM ": spinlock#5\n"));
1714 spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
1715 if (Q_IS_EMPTY(&mpt_scsih_taskQ)) {
1716 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1717 break;
1718 }
1719 mf = mpt_scsih_taskQ.head;
1720 Q_DEL_ITEM(&mf->u.frame.linkage);
1721 mpt_scsih_taskQ_cnt--;
1722 mpt_scsih_active_taskmgmt_mf = mf;
1723 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1724
1725 SCpnt = (Scsi_Cmnd*)mf->u.frame.linkage.argp1;
1726 if (SCpnt == NULL) {
1727 printk(KERN_ERR MYNAM ": ERROR - TaskMgmt has NULL SCpnt! (%p:%p)\n", mf, SCpnt);
1728 continue;
1729 }
1730 hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata;
1731 pScsiTm = (SCSITaskMgmt_t *) mf;
1732
1733 for (i = 0; i < 8; i++) {
1734 pScsiTm->LUN[i] = 0;
1735 }
1736
1737 task_type = mf->u.frame.linkage.arg1;
1738 if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
1739 printk(KERN_WARNING MYNAM ": Attempting _ABORT SCSI IO! (mf=%p:sc=%p)\n",
1740 mf, SCpnt);
1741
1742 /* Most important! Set TaskMsgContext to SCpnt's MsgContext!
1743 * (the IO to be ABORT'd)
1744 *
1745 * NOTE: Since we do not byteswap MsgContext, we do not
1746 * swap it here either. It is an opaque cookie to
1747 * the controller, so it does not matter. -DaveM
1748 */
1749 ctx2abort = SCPNT_TO_MSGCTX(SCpnt);
1750 if (ctx2abort == -1) {
1751 printk(KERN_ERR MYNAM ": ERROR - ScsiLookup fail(#1) for SCpnt=%p\n", SCpnt);
1752 SCpnt->result = DID_SOFT_ERROR << 16;
1753 spin_lock_irqsave(&io_request_lock, flags);
1754 SCpnt->scsi_done(SCpnt);
1755 spin_unlock_irqrestore(&io_request_lock, flags);
1756 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
1757 continue;
1758 }
1759 pScsiTm->LUN[1] = SCpnt->lun;
1760 }
1761 else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
1762 {
1763 printk(KERN_WARNING MYNAM ": Attempting _BUS_RESET! (against SCSI IO mf=%p:sc=%p)\n", mf, SCpnt);
1764 }
1765 #if 0
1766 else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {}
1767 else if (task_type == MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET) {}
1768 #endif
1769
1770 printk(KERN_WARNING MYNAM ": IOs outstanding = %d\n", atomic_read(&queue_depth));
1771
1772 pScsiTm->TargetID = SCpnt->target;
1773 pScsiTm->Bus = hd->port;
1774 pScsiTm->ChainOffset = 0;
1775 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1776
1777 pScsiTm->Reserved = 0;
1778 pScsiTm->TaskType = task_type;
1779 pScsiTm->Reserved1 = 0;
1780 pScsiTm->MsgFlags = 0;
1781
1782 for (i = 0; i < 7; i++)
1783 pScsiTm->Reserved2[i] = 0;
1784
1785 dprintk((KERN_INFO MYNAM ":DbG: ctx2abort = %08x\n", ctx2abort));
1786 pScsiTm->TaskMsgContext = ctx2abort;
1787
1788 /* Control: No data direction, set task mgmt bit? */
1789
1790 /*
1791 * As of MPI v0.10 this request can NOT be sent (normally)
1792 * via FIFOs. So we can't:
1793 * mpt_put_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
1794 * SCSITaskMgmt requests MUST be sent ONLY via
1795 * Doorbell/handshake now. :-(
1796 */
1797 if ((i = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc->id,
1798 sizeof(SCSITaskMgmt_t), (u32*) mf))
1799 != 0) {
1800 printk(KERN_WARNING MYNAM ": WARNING[1] - IOC error (%d) processing TaskMgmt request (mf=%p:sc=%p)\n", i, mf, SCpnt);
1801 SCpnt->result = DID_SOFT_ERROR << 16;
1802 spin_lock_irqsave(&io_request_lock, flags);
1803 SCpnt->scsi_done(SCpnt);
1804 spin_unlock_irqrestore(&io_request_lock, flags);
1805 mpt_free_msg_frame(ScsiTaskCtx, hd->ioc->id, mf);
1806 } else {
1807 /* Spin-Wait for TaskMgmt complete!!! */
1808 while (mpt_scsih_active_taskmgmt_mf != NULL) {
1809 current->state = TASK_INTERRUPTIBLE;
1810 schedule_timeout(HZ/4);
1811 }
1812 }
1813 }
1814
1815 dslprintk((KERN_INFO MYNAM ": spinlock#6\n"));
1816 spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
1817 mpt_scsih_taskQ_bh_active = 0;
1818 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1819
1820 return;
1821 }
1822
1823 #endif /* } */
1824
1825 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1826 /**
1827 * mptscsih_taskmgmt_complete - Callback routine, gets registered to
1828 * Fusion MPT base driver
1829 * @ioc: Pointer to MPT_ADAPTER structure
1830 * @mf: Pointer to SCSI task mgmt request frame
1831 * @r: Pointer to SCSI task mgmt reply frame
1832 *
1833 * This routine is called from mptbase.c::mpt_interrupt() at the completion
1834 * of any SCSI task management request.
1835 * This routine is registered with the MPT (base) driver at driver
1836 * load/init time via the mpt_register() API call.
1837 *
1838 * Returns 1 indicating alloc'd request frame ptr should be freed.
1839 */
1840 static int
1841 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r)
1842 {
1843 SCSITaskMgmtReply_t *pScsiTmReply;
1844 SCSITaskMgmt_t *pScsiTmReq;
1845 u8 tmType;
1846 #ifndef MPT_SCSI_USE_NEW_EH
1847 unsigned long flags;
1848 #endif
1849
1850 dprintk((KERN_INFO MYNAM ": SCSI TaskMgmt completed mf=%p, r=%p\n",
1851 mf, r));
1852
1853 #ifndef MPT_SCSI_USE_NEW_EH
1854 dslprintk((KERN_INFO MYNAM ": spinlock#7\n"));
1855 spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
1856 /* It better be the active one! */
1857 if (mf != mpt_scsih_active_taskmgmt_mf) {
1858 printk(KERN_ERR MYNAM ": ERROR! Non-active TaskMgmt (=%p) completed!\n", mf);
1859 mpt_scsih_active_taskmgmt_mf = NULL;
1860 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1861 return 1;
1862 }
1863
1864 #ifdef MPT_DEBUG
1865 if ((mf == NULL) ||
1866 (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
1867 printk(KERN_ERR MYNAM ": ERROR! NULL or BAD TaskMgmt ptr (=%p)!\n", mf);
1868 mpt_scsih_active_taskmgmt_mf = NULL;
1869 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1870 return 1;
1871 }
1872 #endif
1873 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1874 #endif
1875
1876 if (r != NULL) {
1877 pScsiTmReply = (SCSITaskMgmtReply_t*)r;
1878 pScsiTmReq = (SCSITaskMgmt_t*)mf;
1879
1880 /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
1881 tmType = pScsiTmReq->TaskType;
1882
1883 dprintk((KERN_INFO MYNAM ": TaskType = %d\n", tmType));
1884 dprintk((KERN_INFO MYNAM ": TerminationCount = %d\n",
1885 le32_to_cpu(pScsiTmReply->TerminationCount)));
1886
1887 /* Error? (anything non-zero?) */
1888 if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
1889 dprintk((KERN_INFO MYNAM ": SCSI TaskMgmt (%d) - Oops!\n", tmType));
1890 dprintk((KERN_INFO MYNAM ": IOCStatus = %04xh\n",
1891 le16_to_cpu(pScsiTmReply->IOCStatus)));
1892 dprintk((KERN_INFO MYNAM ": IOCLogInfo = %08xh\n",
1893 le32_to_cpu(pScsiTmReply->IOCLogInfo)));
1894 } else {
1895 dprintk((KERN_INFO MYNAM ": SCSI TaskMgmt (%d) SUCCESS!\n", tmType));
1896 }
1897 }
1898
1899 #ifndef MPT_SCSI_USE_NEW_EH
1900 /*
1901 * Signal to _bh thread that we finished.
1902 */
1903 dslprintk((KERN_INFO MYNAM ": spinlock#8\n"));
1904 spin_lock_irqsave(&mpt_scsih_taskQ_lock, flags);
1905 mpt_scsih_active_taskmgmt_mf = NULL;
1906 spin_unlock_irqrestore(&mpt_scsih_taskQ_lock, flags);
1907 #endif
1908
1909 return 1;
1910 }
1911
1912 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1913 /*
1914 * This is anyones guess quite frankly.
1915 */
1916
1917 int
1918 mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip)
1919 {
1920 int size;
1921
1922 size = disk->capacity;
1923 ip[0] = 64; /* heads */
1924 ip[1] = 32; /* sectors */
1925 if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */
1926 ip[0] = 255; /* heads */
1927 ip[1] = 63; /* sectors */
1928 ip[2] = size / (255 * 63); /* cylinders */
1929 }
1930 return 0;
1931 }
1932
1933 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1934 /*
1935 * Private routines...
1936 */
1937 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1938 /* 19991030 -sralston
1939 * Return absolute SCSI data direction:
1940 * 1 = _DATA_OUT
1941 * 0 = _DIR_NONE
1942 * -1 = _DATA_IN
1943 */
1944 static int
1945 mptscsih_io_direction(Scsi_Cmnd *cmd)
1946 {
1947 switch (cmd->cmnd[0]) {
1948 /* _DATA_OUT commands */
1949 case WRITE_6: case WRITE_10: case WRITE_12:
1950 case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER:
1951 case WRITE_VERIFY: case WRITE_VERIFY_12:
1952 case COMPARE: case COPY: case COPY_VERIFY:
1953 case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
1954 case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12:
1955 case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT:
1956 case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK:
1957 case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG:
1958 case REASSIGN_BLOCKS:
1959 case PERSISTENT_RESERVE_OUT:
1960 case 0xea:
1961 return 1;
1962
1963 /* No data transfer commands */
1964 case SEEK_6: case SEEK_10:
1965 case RESERVE: case RELEASE:
1966 case TEST_UNIT_READY:
1967 case START_STOP:
1968 case ALLOW_MEDIUM_REMOVAL:
1969 return 0;
1970
1971 /* Conditional data transfer commands */
1972 case FORMAT_UNIT:
1973 if (cmd->cmnd[1] & 0x10) /* FmtData (data out phase)? */
1974 return 1;
1975 else
1976 return 0;
1977
1978 case VERIFY:
1979 if (cmd->cmnd[1] & 0x02) /* VERIFY:BYTCHK (data out phase)? */
1980 return 1;
1981 else
1982 return 0;
1983
1984 case RESERVE_10:
1985 if (cmd->cmnd[1] & 0x03) /* RESERSE:{LongID|Extent} (data out phase)? */
1986 return 1;
1987 else
1988 return 0;
1989
1990 #if 0
1991 case REZERO_UNIT: /* (or REWIND) */
1992 case SPACE:
1993 case ERASE: case ERASE_10:
1994 case SYNCHRONIZE_CACHE:
1995 case LOCK_UNLOCK_CACHE:
1996 #endif
1997
1998 /* Must be data _IN! */
1999 default:
2000 return -1;
2001 }
2002 }
2003
2004 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2005 static void
2006 copy_sense_data(Scsi_Cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
2007 {
2008 MPT_SCSI_DEV *mpt_sdev = NULL;
2009 u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
2010 char devFoo[32];
2011 IO_Info_t thisIo;
2012
2013 if (sc && sc->device)
2014 mpt_sdev = (MPT_SCSI_DEV*) sc->device->hostdata;
2015
2016 if (sense_count) {
2017 u8 *sense_data;
2018 int req_index;
2019
2020 /* Copy the sense received into the scsi command block. */
2021 req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
2022 sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * 256));
2023 memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
2024 /* Cache SenseData for this SCSI device! */
2025 if (mpt_sdev) {
2026 memcpy(mpt_sdev->CachedSense.data, sense_data, sense_count);
2027 mpt_sdev->sense_sz = sense_count;
2028 }
2029 } else {
2030 dprintk((KERN_INFO MYNAM ": Hmmm... SenseData len=0! (?)\n"));
2031 }
2032
2033
2034 thisIo.cdbPtr = sc->cmnd;
2035 thisIo.sensePtr = sc->sense_buffer;
2036 thisIo.SCSIStatus = pScsiReply->SCSIStatus;
2037 thisIo.DoDisplay = 1;
2038 sprintf(devFoo, "ioc%d,scsi%d:%d", hd->ioc->id, sc->target, sc->lun);
2039 thisIo.DevIDStr = devFoo;
2040 /* fubar */
2041 thisIo.dataPtr = NULL;
2042 thisIo.inqPtr = NULL;
2043 if (sc->device) {
2044 thisIo.inqPtr = sc->device->vendor-8; /* FIXME!!! */
2045 }
2046 (void) mpt_ScsiHost_ErrorReport(&thisIo);
2047
2048 return;
2049 }
2050
2051 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2052 static u32
2053 SCPNT_TO_MSGCTX(Scsi_Cmnd *sc)
2054 {
2055 MPT_SCSI_HOST *hd;
2056 MPT_FRAME_HDR *mf;
2057 int i;
2058
2059 hd = (MPT_SCSI_HOST *) sc->host->hostdata;
2060
2061 for (i = 0; i < hd->ioc->req_depth; i++) {
2062 if (hd->ScsiLookup[i] == sc) {
2063 mf = MPT_INDEX_2_MFPTR(hd->ioc, i);
2064 return mf->u.frame.hwhdr.msgctxu.MsgContext;
2065 }
2066 }
2067
2068 return -1;
2069 }
2070
2071 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2072
2073 /* see mptscsih.h */
2074
2075 #ifdef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS
2076 static Scsi_Host_Template driver_template = MPT_SCSIHOST;
2077 # include "../../scsi/scsi_module.c"
2078 #endif
2079
2080
2081 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2082 static int
2083 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
2084 {
2085 dprintk((KERN_INFO MYNAM ": IOC %s_reset routed to SCSI host driver!\n",
2086 reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"));
2087
2088 if (reset_phase == MPT_IOC_PRE_RESET) {
2089 /* FIXME! Do pre-reset cleanup */
2090 } else {
2091 /* FIXME! Do post-reset cleanup */
2092 }
2093
2094 return 1; /* currently means nothing really */
2095 }
2096
2097 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2098 static int
2099 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
2100 {
2101 u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
2102
2103 dprintk((KERN_INFO MYNAM ": MPT event (=%02Xh) routed to SCSI host driver!\n", event));
2104
2105 switch (event) {
2106 case MPI_EVENT_UNIT_ATTENTION: /* 03 */
2107 /* FIXME! */
2108 break;
2109 case MPI_EVENT_IOC_BUS_RESET: /* 04 */
2110 /* FIXME! */
2111 break;
2112 case MPI_EVENT_EXT_BUS_RESET: /* 05 */
2113 /* FIXME! */
2114 break;
2115 case MPI_EVENT_LOGOUT: /* 09 */
2116 /* FIXME! */
2117 break;
2118
2119 /*
2120 * CHECKME! Don't think we need to do
2121 * anything for these, but...
2122 */
2123 case MPI_EVENT_RESCAN: /* 06 */
2124 case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
2125 case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
2126 /*
2127 * CHECKME! Falling thru...
2128 */
2129
2130 case MPI_EVENT_NONE: /* 00 */
2131 case MPI_EVENT_LOG_DATA: /* 01 */
2132 case MPI_EVENT_STATE_CHANGE: /* 02 */
2133 case MPI_EVENT_EVENT_CHANGE: /* 0A */
2134 default:
2135 dprintk((KERN_INFO MYNAM ": Ignoring event (=%02Xh)\n", event));
2136 break;
2137 }
2138
2139 return 1; /* currently means nothing really */
2140 }
2141
2142 #if 0 /* { */
2143 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2144 /*
2145 * scsiherr.c - Fusion MPT SCSI Host driver error handling/reporting.
2146 *
2147 * drivers/message/fusion/scsiherr.c
2148 */
2149
2150 //extern const char **mpt_ScsiOpcodesPtr; /* needed by mptscsih.c */
2151 //extern ASCQ_Table_t *mpt_ASCQ_TablePtr;
2152 //extern int mpt_ASCQ_TableSz;
2153
2154 /* Lie! */
2155 #define MYNAM "mptscsih"
2156
2157 #endif /* } */
2158
2159 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2160 /*
2161 * Private data...
2162 */
2163 static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
2164
2165 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2166 /* old symsense.c stuff... */
2167 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2168 /*
2169 * Private data...
2170 * To protect ourselves against those that would pass us bogus pointers
2171 */
2172 static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
2173 = { 0x1F, 0x00, 0x00, 0x00,
2174 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2178 static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
2179 = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
2180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2181 0x00, 0x00 };
2182 static u8 dummyCDB[16]
2183 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2185 static u8 dummyScsiData[16]
2186 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2188
2189 #if 0
2190 static const char *PeripheralDeviceTypeString[32] = {
2191 "Direct-access", /* 00h */
2192 "Sequential-access", /* 01h */
2193 "Printer", /* 02h */
2194 "Processor", /* 03h */
2195 /*"Write-Once-Read-Multiple",*/ /* 04h */
2196 "WORM", /* 04h */
2197 "CD-ROM", /* 05h */
2198 "Scanner", /* 06h */
2199 "Optical memory", /* 07h */
2200 "Media Changer", /* 08h */
2201 "Communications", /* 09h */
2202 "(Graphics arts pre-press)", /* 0Ah */
2203 "(Graphics arts pre-press)", /* 0Bh */
2204 "Array controller", /* 0Ch */
2205 "Enclosure services", /* 0Dh */
2206 "Simplified direct-access", /* 0Eh */
2207 "Reserved-0Fh", /* 0Fh */
2208 "Reserved-10h", /* 10h */
2209 "Reserved-11h", /* 11h */
2210 "Reserved-12h", /* 12h */
2211 "Reserved-13h", /* 13h */
2212 "Reserved-14h", /* 14h */
2213 "Reserved-15h", /* 15h */
2214 "Reserved-16h", /* 16h */
2215 "Reserved-17h", /* 17h */
2216 "Reserved-18h", /* 18h */
2217 "Reserved-19h", /* 19h */
2218 "Reserved-1Ah", /* 1Ah */
2219 "Reserved-1Bh", /* 1Bh */
2220 "Reserved-1Ch", /* 1Ch */
2221 "Reserved-1Dh", /* 1Dh */
2222 "Reserved-1Eh", /* 1Eh */
2223 "Unknown" /* 1Fh */
2224 };
2225 #endif
2226
2227 static char *ScsiStatusString[] = {
2228 "GOOD", /* 00h */
2229 NULL, /* 01h */
2230 "CHECK CONDITION", /* 02h */
2231 NULL, /* 03h */
2232 "CONDITION MET", /* 04h */
2233 NULL, /* 05h */
2234 NULL, /* 06h */
2235 NULL, /* 07h */
2236 "BUSY", /* 08h */
2237 NULL, /* 09h */
2238 NULL, /* 0Ah */
2239 NULL, /* 0Bh */
2240 NULL, /* 0Ch */
2241 NULL, /* 0Dh */
2242 NULL, /* 0Eh */
2243 NULL, /* 0Fh */
2244 "INTERMEDIATE", /* 10h */
2245 NULL, /* 11h */
2246 NULL, /* 12h */
2247 NULL, /* 13h */
2248 "INTERMEDIATE-CONDITION MET", /* 14h */
2249 NULL, /* 15h */
2250 NULL, /* 16h */
2251 NULL, /* 17h */
2252 "RESERVATION CONFLICT", /* 18h */
2253 NULL, /* 19h */
2254 NULL, /* 1Ah */
2255 NULL, /* 1Bh */
2256 NULL, /* 1Ch */
2257 NULL, /* 1Dh */
2258 NULL, /* 1Eh */
2259 NULL, /* 1Fh */
2260 NULL, /* 20h */
2261 NULL, /* 21h */
2262 "COMMAND TERMINATED", /* 22h */
2263 NULL, /* 23h */
2264 NULL, /* 24h */
2265 NULL, /* 25h */
2266 NULL, /* 26h */
2267 NULL, /* 27h */
2268 "TASK SET FULL", /* 28h */
2269 NULL, /* 29h */
2270 NULL, /* 2Ah */
2271 NULL, /* 2Bh */
2272 NULL, /* 2Ch */
2273 NULL, /* 2Dh */
2274 NULL, /* 2Eh */
2275 NULL, /* 2Fh */
2276 "ACA ACTIVE", /* 30h */
2277 NULL
2278 };
2279
2280 static const char *ScsiCommonOpString[] = {
2281 "TEST UNIT READY", /* 00h */
2282 "REZERO UNIT (REWIND)", /* 01h */
2283 NULL, /* 02h */
2284 "REQUEST_SENSE", /* 03h */
2285 "FORMAT UNIT (MEDIUM)", /* 04h */
2286 "READ BLOCK LIMITS", /* 05h */
2287 NULL, /* 06h */
2288 "REASSIGN BLOCKS", /* 07h */
2289 "READ(6)", /* 08h */
2290 NULL, /* 09h */
2291 "WRITE(6)", /* 0Ah */
2292 "SEEK(6)", /* 0Bh */
2293 NULL, /* 0Ch */
2294 NULL, /* 0Dh */
2295 NULL, /* 0Eh */
2296 "READ REVERSE", /* 0Fh */
2297 "WRITE_FILEMARKS", /* 10h */
2298 "SPACE(6)", /* 11h */
2299 "INQUIRY", /* 12h */
2300 NULL
2301 };
2302
2303 static const char *SenseKeyString[] = {
2304 "NO SENSE", /* 0h */
2305 "RECOVERED ERROR", /* 1h */
2306 "NOT READY", /* 2h */
2307 "MEDIUM ERROR", /* 3h */
2308 "HARDWARE ERROR", /* 4h */
2309 "ILLEGAL REQUEST", /* 5h */
2310 "UNIT ATTENTION", /* 6h */
2311 "DATA PROTECT", /* 7h */
2312 "BLANK CHECK", /* 8h */
2313 "VENDOR-SPECIFIC", /* 9h */
2314 "ABORTED COPY", /* Ah */
2315 "ABORTED COMMAND", /* Bh */
2316 "EQUAL (obsolete)", /* Ch */
2317 "VOLUME OVERFLOW", /* Dh */
2318 "MISCOMPARE", /* Eh */
2319 "RESERVED", /* Fh */
2320 NULL
2321 };
2322
2323 #define SPECIAL_ASCQ(c,q) \
2324 (((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
2325
2326 #if 0
2327 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2328 /*
2329 * Sense_Key_Specific() - If Sense_Key_Specific_Valid bit is set,
2330 * then print additional information via
2331 * a call to SDMS_SystemAlert().
2332 *
2333 * Return: nothing
2334 */
2335 static void Sense_Key_Specific(IO_Info_t *ioop, char *msg1)
2336 {
2337 u8 *sd;
2338 u8 BadValue;
2339 u8 SenseKey;
2340 int Offset;
2341 int len = strlen(msg1);
2342
2343 sd = ioop->sensePtr;
2344 if (SD_Additional_Sense_Length(sd) < 8)
2345 return;
2346
2347 SenseKey = SD_Sense_Key(sd);
2348
2349 if (SD_Sense_Key_Specific_Valid(sd)) {
2350 if (SenseKey == SK_ILLEGAL_REQUEST) {
2351 Offset = SD_Bad_Byte(sd);
2352 if (SD_Was_Illegal_Request(sd)) {
2353 BadValue = ioop->cdbPtr[Offset];
2354 len += sprintf(msg1+len, "\n Illegal CDB value=%02Xh found at CDB ",
2355 BadValue);
2356 } else {
2357 BadValue = ioop->dataPtr[Offset];
2358 len += sprintf(msg1+len, "\n Illegal DATA value=%02Xh found at DATA ",
2359 BadValue);
2360 }
2361 len += sprintf(msg1+len, "byte=%02Xh", Offset);
2362 if (SD_SKS_Bit_Pointer_Valid(sd))
2363 len += sprintf(msg1+len, "/bit=%1Xh", SD_SKS_Bit_Pointer(sd));
2364 } else if ((SenseKey == SK_RECOVERED_ERROR) ||
2365 (SenseKey == SK_HARDWARE_ERROR) ||
2366 (SenseKey == SK_MEDIUM_ERROR)) {
2367 len += sprintf(msg1+len, "\n Recovery algorithm Actual_Retry_Count=%02Xh",
2368 SD_Actual_Retry_Count(sd));
2369 }
2370 }
2371 }
2372 #endif
2373
2374 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2375 static int dump_cdb(char *foo, unsigned char *cdb)
2376 {
2377 int i, grpCode, cdbLen;
2378 int l = 0;
2379
2380 grpCode = cdb[0] >> 5;
2381 if (grpCode < 1)
2382 cdbLen = 6;
2383 else if (grpCode < 3)
2384 cdbLen = 10;
2385 else if (grpCode == 5)
2386 cdbLen = 12;
2387 else
2388 cdbLen = 16;
2389
2390 for (i=0; i < cdbLen; i++)
2391 l += sprintf(foo+l, " %02X", cdb[i]);
2392
2393 return l;
2394 }
2395
2396 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2397 static int dump_sd(char *foo, unsigned char *sd)
2398 {
2399 int snsLen = 8 + SD_Additional_Sense_Length(sd);
2400 int l = 0;
2401 int i;
2402
2403 for (i=0; i < MIN(snsLen,18); i++)
2404 l += sprintf(foo+l, " %02X", sd[i]);
2405 l += sprintf(foo+l, "%s", snsLen>18 ? " ..." : "");
2406
2407 return l;
2408 }
2409
2410 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2411 /* Do ASC/ASCQ lookup/grindage to English readable string(s) */
2412 static const char * ascq_set_strings_4max(
2413 u8 ASC, u8 ASCQ,
2414 const char **s1, const char **s2, const char **s3, const char **s4)
2415 {
2416 static const char *asc_04_part1_string = "LOGICAL UNIT ";
2417 static const char *asc_04_part2a_string = "NOT READY, ";
2418 static const char *asc_04_part2b_string = "IS ";
2419 static const char *asc_04_ascq_NN_part3_strings[] = { /* ASC ASCQ (hex) */
2420 "CAUSE NOT REPORTABLE", /* 04 00 */
2421 "IN PROCESS OF BECOMING READY", /* 04 01 */
2422 "INITIALIZING CMD. REQUIRED", /* 04 02 */
2423 "MANUAL INTERVENTION REQUIRED", /* 04 03 */
2424 /* Add " IN PROGRESS" to all the following... */
2425 "FORMAT", /* 04 04 */
2426 "REBUILD", /* 04 05 */
2427 "RECALCULATION", /* 04 06 */
2428 "OPERATION", /* 04 07 */
2429 "LONG WRITE", /* 04 08 */
2430 "SELF-TEST", /* 04 09 */
2431 NULL
2432 };
2433 static char *asc_04_part4_string = " IN PROGRESS";
2434
2435 static char *asc_29_ascq_NN_strings[] = { /* ASC ASCQ (hex) */
2436 "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED", /* 29 00 */
2437 "POWER ON OCCURRED", /* 29 01 */
2438 "SCSI BUS RESET OCCURRED", /* 29 02 */
2439 "BUS DEVICE RESET FUNCTION OCCURRED", /* 29 03 */
2440 "DEVICE INTERNAL RESET", /* 29 04 */
2441 "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED", /* 29 05 */
2442 "TRANSCEIVER MODE CHANGED TO LVD", /* 29 06 */
2443 NULL
2444 };
2445 static char *ascq_vendor_uniq = "(Vendor Unique)";
2446 static char *ascq_noone = "(no matching ASC/ASCQ description found)";
2447 int idx;
2448
2449 *s1 = *s2 = *s3 = *s4 = ""; /* set'em all to the empty "" string */
2450
2451 /* CHECKME! Need lock/sem?
2452 * Update and examine for isense module presense.
2453 */
2454 mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
2455
2456 if (mptscsih_ASCQ_TablePtr == NULL) {
2457 /* 2nd chances... */
2458 if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
2459 *s1 = asc_04_part1_string;
2460 *s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
2461 *s3 = asc_04_ascq_NN_part3_strings[ASCQ];
2462 /* check for " IN PROGRESS" ones */
2463 if (ASCQ >= 0x04)
2464 *s4 = asc_04_part4_string;
2465 } else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
2466 *s1 = asc_29_ascq_NN_strings[ASCQ];
2467 /*
2468 * else { leave all *s[1-4] values pointing to the empty "" string }
2469 */
2470 return *s1;
2471 }
2472
2473 /*
2474 * Need to check ASC here; if it is "special," then
2475 * the ASCQ is variable, and indicates failed component number.
2476 * We must treat the ASCQ as a "don't care" while searching the
2477 * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
2478 * on when we actually need to identify the failed component.
2479 */
2480 if (SPECIAL_ASCQ(ASC,ASCQ))
2481 ASCQ = 0xFF;
2482
2483 /* OK, now search mptscsih_ASCQ_Table[] for a matching entry */
2484 for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
2485 if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ))
2486 return (*s1 = mptscsih_ASCQ_TablePtr[idx].Description);
2487
2488 if ((ASC >= 0x80) || (ASCQ >= 0x80))
2489 *s1 = ascq_vendor_uniq;
2490 else
2491 *s1 = ascq_noone;
2492
2493 return *s1;
2494 }
2495
2496 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2497 /*
2498 * SCSI Error Report; desired output format...
2499 *---
2500 SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
2501 SCSI_Status=02h (CHECK CONDITION)
2502 Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
2503 SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
2504 SenseKey=6h (UNIT ATTENTION); FRU=03h
2505 ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
2506 *---
2507 */
2508
2509 int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
2510 {
2511 char foo[512];
2512 char buf2[32];
2513 char *statstr;
2514 const char *opstr;
2515 int sk = SD_Sense_Key(ioop->sensePtr);
2516 const char *skstr = SenseKeyString[sk];
2517 unsigned char asc = SD_ASC(ioop->sensePtr);
2518 unsigned char ascq = SD_ASCQ(ioop->sensePtr);
2519 int l;
2520
2521 /*
2522 * More quiet mode.
2523 * Filter out common, repetitive, warning-type errors... like:
2524 * POWER ON (06,29/00 or 06,29/01),
2525 * SPINNING UP (02,04/01),
2526 * LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
2527 */
2528 if ( (sk==SK_UNIT_ATTENTION && asc==0x29 && (ascq==0x00 || ascq==0x01))
2529 || (sk==SK_NOT_READY && asc==0x04 && ascq==0x01)
2530 || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
2531 )
2532 {
2533 /* Do nothing! */
2534 return 0;
2535 }
2536
2537 /*
2538 * Protect ourselves...
2539 */
2540 if (ioop->cdbPtr == NULL)
2541 ioop->cdbPtr = dummyCDB;
2542 if (ioop->sensePtr == NULL)
2543 ioop->sensePtr = dummySenseData;
2544 if (ioop->inqPtr == NULL)
2545 ioop->inqPtr = dummyInqData;
2546 if (ioop->dataPtr == NULL)
2547 ioop->dataPtr = dummyScsiData;
2548
2549 statstr = NULL;
2550 if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
2551 ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
2552 (void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
2553 statstr = buf2;
2554 }
2555
2556 opstr = NULL;
2557 if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
2558 opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
2559 else if (mpt_ScsiOpcodesPtr)
2560 opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
2561
2562 l = sprintf(foo, "SCSI Error Report =-=-= (%s)\n"
2563 " SCSI_Status=%02Xh (%s)\n"
2564 " Original_CDB[]:",
2565 ioop->DevIDStr,
2566 ioop->SCSIStatus,
2567 statstr);
2568 l += dump_cdb(foo+l, ioop->cdbPtr);
2569 if (opstr)
2570 l += sprintf(foo+l, " - \"%s\"", opstr);
2571 l += sprintf(foo+l, "\n SenseData[%02Xh]:", 8+SD_Additional_Sense_Length(ioop->sensePtr));
2572 l += dump_sd(foo+l, ioop->sensePtr);
2573 l += sprintf(foo+l, "\n SenseKey=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh",
2574 sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
2575
2576 {
2577 const char *x1, *x2, *x3, *x4;
2578 x1 = x2 = x3 = x4 = "";
2579 x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
2580 if (x1 != NULL) {
2581 if (x1[0] != '(')
2582 l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
2583 else
2584 l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
2585 }
2586 }
2587
2588 #if 0
2589 if (SPECIAL_ASCQ(asc,ascq))
2590 l += sprintf(foo+l, " (%02Xh)", ascq);
2591 #endif
2592
2593 PrintF(("%s\n", foo));
2594
2595 return l;
2596 }
2597
2598 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
2599
2600