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